From cfca4f1ab48476176e81965e09782f9608d7039c Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 21 Aug 2010 13:01:41 +0300 Subject: [PATCH] 2300b12 --- akiko.cpp | 6 +- blkdev.cpp | 271 +++++++++++++----- blkdev_cdimage.cpp | 209 +++++++++----- cdtv.cpp | 6 +- cfgfile.cpp | 29 +- cia.cpp | 6 +- disk.cpp | 26 +- include/disk.h | 2 +- include/execio.h | 42 +-- include/gui.h | 2 +- include/inputdevice.h | 4 +- include/rommgr.h | 6 +- inputdevice.cpp | 64 +++-- od-win32/blkdev_win32_ioctl.cpp | 182 +++++++----- od-win32/cloanto/RetroPlatformIPC.h | 102 ++++--- .../cloanto/RetroPlatformIPC_doc_draft.txt | 72 ++++- od-win32/dinput.cpp | 28 +- od-win32/direct3d.cpp | 6 +- od-win32/lib/prowizard.lib | Bin 1138408 -> 1140766 bytes od-win32/posixemu.cpp | 2 +- od-win32/rp.cpp | 91 +++++- od-win32/rp.h | 20 +- od-win32/threaddep/thread.h | 2 +- od-win32/win32.cpp | 22 +- od-win32/win32.h | 4 +- od-win32/win32_scaler.cpp | 2 + od-win32/win32gfx.cpp | 2 +- od-win32/win32gui.cpp | 8 +- od-win32/winuaechangelog.txt | 32 +++ prowizard/rippers/ProPacker10.c | 171 +++++++---- prowizard/rippers/ProPacker21.c | 24 +- prowizard/rippers/ProPacker30.c | 210 +++++++------- rommgr.cpp | 8 +- scsiemul.cpp | 4 +- 34 files changed, 1095 insertions(+), 570 deletions(-) mode change 100644 => 100755 od-win32/cloanto/RetroPlatformIPC.h mode change 100644 => 100755 od-win32/cloanto/RetroPlatformIPC_doc_draft.txt diff --git a/akiko.cpp b/akiko.cpp index 294d2354..77d059c2 100644 --- a/akiko.cpp +++ b/akiko.cpp @@ -503,8 +503,10 @@ static void subfunc (uae_u8 *data, int cnt) static int statusfunc (int status) { - if (status < 0) - return 1000; + if (status == -1) + return 0; + if (status == -2) + return 150; if (cdrom_audiostatus != status) { if (status == AUDIO_STATUS_IN_PROGRESS) { cdrom_playing = 1; diff --git a/blkdev.cpp b/blkdev.cpp index c62e43d6..585a3b70 100644 --- a/blkdev.cpp +++ b/blkdev.cpp @@ -16,10 +16,14 @@ #include "scsidev.h" #include "savestate.h" #include "crc32.h" +#include "threaddep/thread.h" +#include "execio.h" #ifdef RETROPLATFORM #include "rp.h" #endif +int log_scsiemu = 0; + #define PRE_INSERT_DELAY (3 * (currprefs.ntscmode ? 60 : 50)) static int scsiemu[MAX_TOTAL_SCSI_DEVICES]; @@ -28,6 +32,8 @@ static struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES]; static int openlist[MAX_TOTAL_SCSI_DEVICES]; static int waspaused[MAX_TOTAL_SCSI_DEVICES]; static int delayed[MAX_TOTAL_SCSI_DEVICES]; +static uae_sem_t unitsem[MAX_TOTAL_SCSI_DEVICES]; +static int unitsem_cnt[MAX_TOTAL_SCSI_DEVICES]; /* convert minutes, seconds and frames -> logical sector number */ int msf2lsn (int msf) @@ -222,9 +228,58 @@ void blkdev_fix_prefs (struct uae_prefs *p) } +static bool getsem (int unitnum, bool dowait) +{ + if (unitsem[unitnum] == NULL) + uae_sem_init (&unitsem[unitnum], 0, 1); + bool gotit = false; + if (dowait) { + uae_sem_wait (&unitsem[unitnum]); + gotit = true; + } else { + gotit = uae_sem_trywait (&unitsem[unitnum]) == 0; + } + if (gotit) + unitsem_cnt[unitnum]++; + if (unitsem_cnt[unitnum] > 1) + write_log (L"CD: unitsem%d acquire mismatch! cnt=%d\n", unitnum, unitsem_cnt[unitnum]); + return gotit; +} +static bool getsem (int unitnum) +{ + return getsem (unitnum, false); +} +static void freesem (int unitnum) +{ + unitsem_cnt[unitnum]--; + if (unitsem_cnt[unitnum] < 0) + write_log (L"CD: unitsem%d release mismatch! cnt=%d\n", unitnum, unitsem_cnt[unitnum]); + uae_sem_post (&unitsem[unitnum]); +} +static void sys_command_close_internal (int unitnum) +{ + getsem (unitnum, true); + waspaused[unitnum] = 0; + if (openlist[unitnum] <= 0) + write_log (L"BUG unit %d close: opencnt=%d!\n", unitnum, openlist[unitnum]); + if (device_func[unitnum]) { + device_func[unitnum]->closedev (unitnum); + if (openlist[unitnum] > 0) + openlist[unitnum]--; + } + freesem (unitnum); + if (openlist[unitnum] == 0) { + uae_sem_destroy (&unitsem[unitnum]); + unitsem[unitnum] = NULL; + } +} + static int sys_command_open_internal (int unitnum, const TCHAR *ident, cd_standard_unit csu) { int ret = 0; + if (unitsem[unitnum] == NULL) + uae_sem_init (&unitsem[unitnum], 0, 1); + getsem (unitnum, true); if (openlist[unitnum]) write_log (L"BUG unit %d open: opencnt=%d!\n", unitnum, openlist[unitnum]); if (device_func[unitnum]) { @@ -232,6 +287,7 @@ static int sys_command_open_internal (int unitnum, const TCHAR *ident, cd_standa if (ret) openlist[unitnum]++; } + freesem (unitnum); return ret; } @@ -345,17 +401,9 @@ int sys_command_open (int unitnum) return sys_command_open_internal (unitnum, currprefs.cdslots[unitnum].name[0] ? currprefs.cdslots[unitnum].name : NULL, CD_STANDARD_UNIT_DEFAULT); } - void sys_command_close (int unitnum) { - waspaused[unitnum] = 0; - if (openlist[unitnum] <= 0) - write_log (L"BUG unit %d close: opencnt=%d!\n", unitnum, openlist[unitnum]); - if (device_func[unitnum]) { - device_func[unitnum]->closedev (unitnum); - if (openlist[unitnum] > 0) - openlist[unitnum]--; - } + sys_command_close_internal (unitnum); } void blkdev_cd_change (int unitnum, const TCHAR *name) @@ -430,6 +478,8 @@ static void check_changes (int unitnum) changed = true; if (changed) { + if (unitsem[unitnum]) + getsem (unitnum, true); cdimagefileinuse[unitnum] = changed_prefs.cdslots[unitnum].inuse; _tcscpy (newimagefiles[unitnum], changed_prefs.cdslots[unitnum].name); changed_prefs.cdslots[unitnum].name[0] = currprefs.cdslots[unitnum].name[0] = 0; @@ -451,12 +501,16 @@ static void check_changes (int unitnum) #ifdef RETROPLATFORM rp_cd_image_change (unitnum, NULL); #endif + if (unitsem[unitnum]) + freesem (unitnum); } if (imagechangetime[unitnum] == 0) return; imagechangetime[unitnum]--; if (imagechangetime[unitnum] > 0) return; + if (unitsem[unitnum]) + getsem (unitnum, true); _tcscpy (currprefs.cdslots[unitnum].name, newimagefiles[unitnum]); _tcscpy (changed_prefs.cdslots[unitnum].name, newimagefiles[unitnum]); currprefs.cdslots[unitnum].inuse = changed_prefs.cdslots[unitnum].inuse = cdimagefileinuse[unitnum]; @@ -478,6 +532,9 @@ static void check_changes (int unitnum) #ifdef RETROPLATFORM rp_cd_image_change (unitnum, currprefs.cdslots[unitnum].name); #endif + if (unitsem[unitnum]) + freesem (unitnum); + config_changed = 1; } @@ -508,8 +565,11 @@ static int failunit (int unitnum) static int audiostatus (int unitnum) { + if (!getsem (unitnum)) + return 0; uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(DEVICE_SCSI_BUFSIZE>>8),(uae_u8)(DEVICE_SCSI_BUFSIZE&0xff),0}; uae_u8 *p = device_func[unitnum]->exec_in (unitnum, cmd, sizeof (cmd), 0); + freesem (unitnum); if (!p) return 0; return p[1]; @@ -520,13 +580,19 @@ int sys_command_cd_pause (int unitnum, int paused) { if (failunit (unitnum)) return -1; + if (!getsem (unitnum)) + return 0; + int v; if (device_func[unitnum]->pause == NULL) { int as = audiostatus (unitnum); uae_u8 cmd[10] = {0x4b,0,0,0,0,0,0,0,paused?0:1,0}; do_scsi (unitnum, cmd, sizeof cmd); - return as == AUDIO_STATUS_PAUSED; + v = as == AUDIO_STATUS_PAUSED; + } else { + v = device_func[unitnum]->pause (unitnum, paused); } - return device_func[unitnum]->pause (unitnum, paused); + freesem (unitnum); + return v; } /* stop CD audio */ @@ -534,48 +600,26 @@ void sys_command_cd_stop (int unitnum) { if (failunit (unitnum)) return; + if (!getsem (unitnum)) + return; if (device_func[unitnum]->stop == NULL) { int as = audiostatus (unitnum); uae_u8 cmd[6] = {0x4e,0,0,0,0,0}; do_scsi (unitnum, cmd, sizeof cmd); - return; - } - device_func[unitnum]->stop (unitnum); -} - -#if 0 -static int adjustplaypos (int unitnum, int startlsn) -{ - uae_u8 q[SUBQ_SIZE]; - if (!device_func[unitnum]->qcode (unitnum, q, startlsn - 1)) - return startlsn; - int otrack = frombcd (q[4 + 1]); - int lsn = startlsn; - int max = 150; - while (max-- > 0 && startlsn > 0) { - if (!device_func[unitnum]->qcode (unitnum, q, startlsn - 1)) - break; - int track = frombcd (q[4 + 1]); - int idx = frombcd (q[4 + 2]); - //write_log (L"%d %d\n", track, idx); - if (idx != 0 || otrack != track) - break; - startlsn--; + } else { + device_func[unitnum]->stop (unitnum); } - if (lsn != startlsn) - write_log (L"CD play adjust %d -> %d\n", lsn, startlsn); - startlsn -= 10; - if (startlsn < 0) - startlsn = 0; - return startlsn; + freesem (unitnum); } -#endif /* play CD audio */ int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan) { + int v; if (failunit (unitnum)) return 0; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum]->play == NULL) { uae_u8 cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; int startmsf = lsn2msf (startlsn); @@ -587,145 +631,209 @@ int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan) cmd[6] = (uae_u8)(endmsf >> 16); cmd[7] = (uae_u8)(endmsf >> 8); cmd[8] = (uae_u8)(endmsf >> 0); - return do_scsi (unitnum, cmd, sizeof cmd) ? 0 : 1; + v = do_scsi (unitnum, cmd, sizeof cmd) ? 0 : 1; + } else { + v = device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, NULL, NULL); } - //startlsn = adjustplaypos (unitnum, startlsn); - return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, NULL, NULL); + freesem (unitnum); + return v; } /* play CD audio with subchannels */ int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc) { + int v; if (failunit (unitnum)) return 0; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum]->play == NULL) - return sys_command_cd_play (unitnum, startlsn, endlsn, scan); - //startlsn = adjustplaypos (unitnum, startlsn); - return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, statusfunc, subfunc); + v = sys_command_cd_play (unitnum, startlsn, endlsn, scan); + else + v = device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, statusfunc, subfunc); + freesem (unitnum); + return v; } /* set CD audio volume */ uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right) { + int v; if (failunit (unitnum)) return 0; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum]->volume == NULL) - return -1; - return device_func[unitnum]->volume (unitnum, volume_left, volume_right); + v = -1; + else + v = device_func[unitnum]->volume (unitnum, volume_left, volume_right); + freesem (unitnum); + return v; } /* read qcode */ int sys_command_cd_qcode (int unitnum, uae_u8 *buf) { + int v; if (failunit (unitnum)) return 0; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum]->qcode == NULL) { uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(SUBQ_SIZE>>8),(uae_u8)(SUBQ_SIZE&0xff),0}; - return do_scsi (unitnum, cmd, sizeof cmd, buf, SUBQ_SIZE); + v = do_scsi (unitnum, cmd, sizeof cmd, buf, SUBQ_SIZE); + } else { + v = device_func[unitnum]->qcode (unitnum, buf, -1); } - return device_func[unitnum]->qcode (unitnum, buf, -1); + freesem (unitnum); + return v; }; /* read table of contents */ int sys_command_cd_toc (int unitnum, struct cd_toc_head *toc) { + int v; if (failunit (unitnum)) return 0; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum]->toc == NULL) { uae_u8 buf[4 + 8 * 103]; int size = sizeof buf; uae_u8 cmd [10] = { 0x43,0,2,0,0,0,0,(uae_u8)(size>>8),(uae_u8)(size&0xff),0}; if (do_scsi (unitnum, cmd, sizeof cmd, buf, size)) { // toc parse to do - return 0; + v = 0; } - return 0; + v = 0; + } else { + v = device_func[unitnum]->toc (unitnum, toc); } - return device_func[unitnum]->toc (unitnum, toc); + freesem (unitnum); + return v; } /* read one cd sector */ int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size) { + int v; if (failunit (unitnum)) return 0; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum]->read == NULL) { uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 }; cmd[1] = 2 << 3; // 2048 if (!do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048)) cmd[1] = 4 << 3; // 2048 mode2 - return do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048); + v = do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048); + } else { + v = device_func[unitnum]->read (unitnum, data, block, size); } - return device_func[unitnum]->read (unitnum, data, block, size); + freesem (unitnum); + return v; } int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int sectorsize) { + int v; if (failunit (unitnum)) return -1; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum]->rawread == NULL) { uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 }; - return do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize); + v = do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize); + } else { + v = device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, 0xffffffff); } - return device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, 0xffffffff); + freesem (unitnum); + return v; } int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int sectorsize, uae_u8 sectortype, uae_u8 scsicmd9, uae_u8 subs) { + int v; if (failunit (unitnum)) return -1; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum]->rawread == NULL) { uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 }; - return do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize); + v = do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize); + } else { + v = device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, (sectortype << 16) | (scsicmd9 << 8) | subs); } - return device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, (sectortype << 16) | (scsicmd9 << 8) | subs); + freesem (unitnum); + return v; } /* read block */ int sys_command_read (int unitnum, uae_u8 *data, int block, int size) { + int v; if (failunit (unitnum)) return 0; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum]->read == NULL) { uae_u8 cmd[12] = { 0xa8, 0, 0, 0, 0, 0, size >> 24, size >> 16, size >> 8, size >> 0, 0, 0 }; cmd[2] = (uae_u8)(block >> 24); cmd[3] = (uae_u8)(block >> 16); cmd[4] = (uae_u8)(block >> 8); cmd[5] = (uae_u8)(block >> 0); - return do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048); + v = do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048); + } else { + v = device_func[unitnum]->read (unitnum, data, block, size); } - return device_func[unitnum]->read (unitnum, data, block, size); + freesem (unitnum); + return v; } /* write block */ int sys_command_write (int unitnum, uae_u8 *data, int offset, int size) { + int v; if (failunit (unitnum)) return 0; - if (device_func[unitnum]->write == NULL) + if (!getsem (unitnum)) return 0; - return device_func[unitnum]->write (unitnum, data, offset, size); + if (device_func[unitnum]->write == NULL) { + v = 0; + } else { + v = device_func[unitnum]->write (unitnum, data, offset, size); + } + freesem (unitnum); + return v; } int sys_command_ismedia (int unitnum, int quick) { + int v; if (failunit (unitnum)) return -1; if (delayed[unitnum]) return 0; + if (!getsem (unitnum)) + return 0; if (device_func[unitnum] == NULL) { uae_u8 cmd[6] = { 0, 0, 0, 0, 0, 0 }; - return do_scsi (unitnum, cmd, sizeof cmd); + v = do_scsi (unitnum, cmd, sizeof cmd); } else { - return device_func[unitnum]->ismedia (unitnum, quick); + v = device_func[unitnum]->ismedia (unitnum, quick); } + freesem (unitnum); + return v; } struct device_info *sys_command_info (int unitnum, struct device_info *di, int quick) { if (failunit (unitnum)) return NULL; + if (!getsem (unitnum)) + return 0; struct device_info *di2 = device_func[unitnum]->info (unitnum, di, quick); if (di2 && delayed[unitnum]) di2->media_inserted = 0; + freesem (unitnum); return di2; } @@ -857,10 +965,13 @@ static bool nodisk (struct device_info *di) } static uae_u64 cmd_readx (int unitnum, uae_u8 *dataptr, int offset, int len) { - if (device_func[unitnum]->read (unitnum, dataptr, offset, len)) - return len; - else + if (!getsem (unitnum)) return 0; + int v = device_func[unitnum]->read (unitnum, dataptr, offset, len); + freesem (unitnum); + if (v) + return len; + return 0; } static void wl (uae_u8 *p, int v) @@ -963,10 +1074,11 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, scsi_len = 0; goto end; } - write_log (L"SCSIEMU %d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X CMDLEN=%d DATA=%08X LEN=%d\n", unitnum, - cmdbuf[0], cmdbuf[1], cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], - cmdbuf[7], cmdbuf[8], cmdbuf[9], cmdbuf[10], cmdbuf[11], - scsi_cmd_len, scsi_data, *data_len); + if (log_scsiemu) + write_log (L"SCSIEMU %d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X CMDLEN=%d DATA=%08X LEN=%d\n", unitnum, + cmdbuf[0], cmdbuf[1], cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6], + cmdbuf[7], cmdbuf[8], cmdbuf[9], cmdbuf[10], cmdbuf[11], + scsi_cmd_len, scsi_data, *data_len); switch (cmdbuf[0]) { case 0x12: /* INQUIRY */ @@ -1037,7 +1149,8 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, int dbd = cmdbuf[1] & 8; if (cmdbuf[0] == 0x5a) dbd = 1; - write_log (L"MODE SENSE PC=%d CODE=%d DBD=%d\n", pc, pcode, dbd); + if (log_scsiemu) + write_log (L"MODE SENSE PC=%d CODE=%d DBD=%d\n", pc, pcode, dbd); p = r; if (cmdbuf[0] == 0x5a) { p[0] = 8 - 1; @@ -1512,7 +1625,7 @@ end: *data_len = scsi_len; *reply_len = lr; *sense_len = ls; - if (cmdbuf[0]) + if (cmdbuf[0] && log_scsiemu) write_log (L"-> DATAOUT=%d ST=%d SENSELEN=%d\n", scsi_len, status, ls); return status; } @@ -1538,7 +1651,7 @@ static int execscsicmd_direct (int unitnum, struct amigascsi *as) as->cmdactual = as->status != 0 ? 0 : as->cmd_len; /* fake scsi_CmdActual */ if (as->status) { - io_error = 45; /* HFERR_BadStatus */ + io_error = IOERR_BadStatus; as->sense_len = senselen; as->actual = 0; /* scsi_Actual */ } else { @@ -1552,7 +1665,7 @@ static int execscsicmd_direct (int unitnum, struct amigascsi *as) as->sensedata[i] = 0; sactual = 0; if (datalen < 0) { - io_error = 20; /* io_Error, but not specified */ + io_error = IOERR_NotSpecified; as->actual = 0; /* scsi_Actual */ } else { as->len = datalen; @@ -1591,11 +1704,13 @@ int sys_command_scsi_direct (int unitnum, uaecptr acmd) bank = &get_mem_bank (ap); if (!bank || !bank->check(ap, as.len)) - return -5; + return IOERR_BADADDRESS; as.data = bank->xlateaddr (ap); ap = get_long (acmd + 12); as.cmd_len = get_word (acmd + 16); + if (as.cmd_len > sizeof as.cmd) + return IOERR_BADLENGTH; for (i = 0; i < as.cmd_len; i++) as.cmd[i] = get_byte (ap++); while (i < sizeof as.cmd) diff --git a/blkdev_cdimage.cpp b/blkdev_cdimage.cpp index 7918de3d..9012df8f 100644 --- a/blkdev_cdimage.cpp +++ b/blkdev_cdimage.cpp @@ -76,7 +76,7 @@ struct cdunit { int cdda_start, cdda_end; play_subchannel_callback cdda_subfunc; play_status_callback cdda_statusfunc; - int cdda_delay; + int cdda_delay, cdda_delay_frames; int imagechange; TCHAR newfile[MAX_DPATH]; @@ -98,11 +98,14 @@ static struct cdunit *unitisopen (int unitnum) return NULL; } + static struct cdtoc *findtoc (struct cdunit *cdu, int *sectorp) { int i; int sector; + if (*sectorp < 0) + return NULL; sector = *sectorp; for (i = 0; i <= cdu->tracks; i++) { struct cdtoc *t = &cdu->toc[i]; @@ -266,7 +269,7 @@ static void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d) } } -static int getsub (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector) +static int getsub_deinterleaved (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector) { int ret = 0; uae_sem_wait (&cdu->sub_sem); @@ -309,29 +312,20 @@ static int getsub (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector) return ret; } -static void dosub (struct cdunit *cdu, struct cdtoc *t, int sector) +static void dosub (struct cdunit *cdu, uae_u8 *subbuf) { - uae_u8 *d; - uae_u8 subbuf[SUB_CHANNEL_SIZE]; uae_u8 subbuf2[SUB_CHANNEL_SIZE]; if (!cdu->cdda_subfunc) return; - if (!t) { - memset (subbuf, 0, sizeof subbuf); - cdu->cdda_subfunc (subbuf, 1); + if (!subbuf) { + memset (subbuf2, 0, sizeof subbuf2); + cdu->cdda_subfunc (subbuf2, 1); return; } - memset (subbuf, 0, SUB_CHANNEL_SIZE); - int mode = getsub (subbuf, cdu, t, sector); - if (mode == 2) { // deinterleaved -> interleaved - sub_to_interleaved (subbuf, subbuf2); - d = subbuf2; - } else { - d = subbuf; - } - cdu->cdda_subfunc (d, 1); + sub_to_interleaved (subbuf, subbuf2); + cdu->cdda_subfunc (subbuf2, 1); } static int setstate (struct cdunit *cdu, int state) @@ -400,6 +394,8 @@ static void *cdda_play_func (void *v) MMRESULT mmr; int volume[2], volume_main; int oldplay; + int idleframes; + bool foundsub; struct cdunit *cdu = (struct cdunit*)v; for (i = 0; i < 2; i++) { @@ -441,11 +437,12 @@ static void *cdda_play_func (void *v) int sector, diff; struct _timeb tb1, tb2; + idleframes = 0; + foundsub = false; _ftime (&tb1); cdda_pos = cdu->cdda_start; oldplay = cdu->cdda_play; - cdu->cd_last_pos = cdda_pos; - sector = cdu->cdda_start; + sector = cdu->cd_last_pos = cdda_pos; t = findtoc (cdu, §or); if (!t) { write_log (L"IMAGE CDDA: illegal sector number %d\n", cdu->cdda_start); @@ -463,10 +460,44 @@ static void *cdda_play_func (void *v) while (cdimage_unpack_active == 0) Sleep (10); } + idleframes = cdu->cdda_delay_frames; + while (cdu->cdda_paused && cdu->cdda_play > 0) { + Sleep (10); + idleframes = -1; + } + + if (cdu->cdda_scan == 0) { + // find possible P-subchannel=1 and fudge starting point so that + // buggy CD32/CDTV software CD+G handling does not miss any frames + bool seenindex = false; + for (sector = cdda_pos - 200; sector < cdda_pos; sector++) { + int sec = sector; + t = findtoc (cdu, &sec); + if (t) { + uae_u8 subbuf[SUB_CHANNEL_SIZE]; + getsub_deinterleaved (subbuf, cdu, t, sector); + if (seenindex) { + for (int i = 2 * SUB_ENTRY_SIZE; i < SUB_CHANNEL_SIZE; i++) { + if (subbuf[i]) { // non-zero R-W subchannels + int diff = cdda_pos - sector + 2; + write_log (L"-> CD+G start pos fudge -> %d (%d)\n", sector, -diff); + idleframes -= diff; + cdda_pos = sector; + break; + } + } + } else if (subbuf[0] == 0xff) { // P == 1? + seenindex = true; + } + } + } + } + cdda_pos -= idleframes; + _ftime (&tb2); diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm); diff -= cdu->cdda_delay; - if (diff < 0 && cdu->cdda_play > 0) + if (idleframes >= 0 && diff < 0 && cdu->cdda_play > 0) Sleep (-diff); setstate (cdu, AUDIO_STATUS_IN_PROGRESS); } @@ -478,7 +509,7 @@ static void *cdda_play_func (void *v) } bufon[bufnum] = 0; - if (!isaudiotrack (&cdu->di.toc, cdda_pos)) { + if (idleframes <= 0 && !isaudiotrack (&cdu->di.toc, cdda_pos)) { setstate (cdu, AUDIO_STATUS_PLAY_ERROR); goto end; // data track? } @@ -493,22 +524,15 @@ static void *cdda_play_func (void *v) memset (px[bufnum], 0, num_sectors * 2352); for (cnt = 0; cnt < num_sectors; cnt++) { + uae_u8 *dst = px[bufnum] + cnt * 2352; + uae_u8 subbuf[SUB_CHANNEL_SIZE]; sector = cdda_pos; - if (cdu->cdda_scan) { - cdda_pos += cdu->cdda_scan; - if (cdda_pos < 0) - cdda_pos = 0; - } else { - cdda_pos++; - } - if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end) - dofinish = 1; + memset (subbuf, 0, SUB_CHANNEL_SIZE); t = findtoc (cdu, §or); if (t) { if (t->handle && !(t->ctrl & 4)) { - uae_u8 *dst = px[bufnum] + cnt * t->size; int totalsize = t->size + t->skipsize; if ((t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC) && t->data) { if (t->filesize >= sector * totalsize + t->offset + t->size) @@ -520,10 +544,36 @@ static void *cdda_play_func (void *v) } } } - dosub (cdu, t, cdda_pos); + getsub_deinterleaved (subbuf, cdu, t, cdda_pos); + } + + if (idleframes > 0) { + idleframes--; + memset (dst, 0, 2352); + memset (subbuf, 0, SUB_CHANNEL_SIZE); + } + + if (cdda_pos < cdu->cdda_start && cdu->cdda_scan == 0) + memset (dst, 0, 2352); + + dosub (cdu, subbuf); + + if (cdu->cdda_scan) { + cdda_pos += cdu->cdda_scan; + if (cdda_pos < 0) + cdda_pos = 0; + } else { + cdda_pos++; } + + if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end) + dofinish = 1; + } + if (idleframes <= 0) + cdu->cd_last_pos = cdda_pos; + volume_main = currprefs.sound_volume; int vol_mult[2]; for (int j = 0; j < 2; j++) { @@ -547,8 +597,6 @@ static void *cdda_play_func (void *v) break; } - cdu->cd_last_pos = cdda_pos; - if (dofinish) { setstate (cdu, AUDIO_STATUS_PLAY_COMPLETE); cdu->cdda_play = -1; @@ -597,6 +645,7 @@ static void cdda_stop (struct cdunit *cdu) } } cdu->cdda_paused = 0; + cdu->cdda_play_state = 0; } @@ -631,6 +680,7 @@ static int command_play (int unitnum, int startlsn, int endlsn, int scan, play_s cdu->cdda_statusfunc = statusfunc; cdu->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0); cdu->cdda_delay = setstate (cdu, -1); + cdu->cdda_delay_frames = setstate (cdu, -2); setstate (cdu, AUDIO_STATUS_NOT_SUPPORTED); if (!isaudiotrack (&cdu->di.toc, startlsn)) { setstate (cdu, AUDIO_STATUS_PLAY_ERROR); @@ -684,7 +734,7 @@ static int command_qcode (int unitnum, uae_u8 *buf, int sector) } if (!td) return 0; - getsub (subbuf, cdu, td, pos); + getsub_deinterleaved (subbuf, cdu, td, pos); memcpy (p, subbuf + 12, 12); // write_log (L"%6d %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n", // pos, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]); @@ -713,7 +763,8 @@ static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int struct cdtoc *t = findtoc (cdu, §or); if (!t || t->handle == NULL) - return 0; + goto end; + cdda_stop (cdu); if (sectorsize > 0) { if (sectorsize == 2352 && t->size == 2048) { @@ -765,21 +816,27 @@ static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int int edcecc = (cmd9 >> 3) & 1; int errorfield = (cmd9 >> 1) & 3; uae_u8 subs = extra & 7; - if (subs != 0 && subs != 1 && subs != 2 && subs != 4) - return -1; + if (subs != 0 && subs != 1 && subs != 2 && subs != 4) { + ret = -1; + goto end; + } if (isaudiotrack (&cdu->di.toc, sector)) { - if (sectortype != 0 && sectortype != 1) - return -2; - if (t->size != 2352) - return -1; + if (sectortype != 0 && sectortype != 1) { + ret = -2; + goto end; + } + if (t->size != 2352) { + ret = -1; + goto end; + } for (int i = 0; i < size; i++) { zfile_fseek (t->handle, t->offset + sector * t->size, SEEK_SET); zfile_fread (data, t->size, 1, t->handle); uae_u8 *p = data + t->size; if (subs) { uae_u8 subdata[SUB_CHANNEL_SIZE]; - getsub (subdata, cdu, t, sector); + getsub_deinterleaved (subdata, cdu, t, sector); if (subs == 4) { // all, de-interleaved memcpy (p, subdata, SUB_CHANNEL_SIZE); p += SUB_CHANNEL_SIZE; @@ -797,6 +854,7 @@ static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int } } } +end: return ret; } @@ -810,7 +868,7 @@ static int command_read (int unitnum, uae_u8 *data, int sector, int size) struct cdtoc *t = findtoc (cdu, §or); if (!t || t->handle == NULL) - return NULL; + return 0; cdda_stop (cdu); if (t->size == 2048) { zfile_fseek (t->handle, t->offset + sector * t->size, SEEK_SET); @@ -1556,7 +1614,6 @@ static int parse_image (struct cdunit *cdu, const TCHAR *img) return 1; } - static int ismedia (int unitnum, int quick) { struct cdunit *cdu = &cdunits[unitnum]; @@ -1623,44 +1680,46 @@ static void unload_image (struct cdunit *cdu) static int open_device (int unitnum, const TCHAR *ident, int flags) { struct cdunit *cdu = &cdunits[unitnum]; + int ret = 0; - if (cdu->open) - return 0; - uae_sem_init (&cdu->sub_sem, 0, 1); - parse_image (cdu, ident); - cdu->open = true; - cdu->enabled = true; - cdu->cdda_volume[0] = 0x7fff; - cdu->cdda_volume[1] = 0x7fff; - blkdev_cd_change (unitnum, currprefs.cdslots[unitnum].name); - if (cdimage_unpack_thread == 0) { - init_comm_pipe (&unpack_pipe, 10, 1); - uae_start_thread (L"cdimage_unpack", cdda_unpack_func, NULL, NULL); - while (cdimage_unpack_thread == 0) - Sleep (10); + if (!cdu->open) { + uae_sem_init (&cdu->sub_sem, 0, 1); + parse_image (cdu, ident); + cdu->open = true; + cdu->enabled = true; + cdu->cdda_volume[0] = 0x7fff; + cdu->cdda_volume[1] = 0x7fff; + if (cdimage_unpack_thread == 0) { + init_comm_pipe (&unpack_pipe, 10, 1); + uae_start_thread (L"cdimage_unpack", cdda_unpack_func, NULL, NULL); + while (cdimage_unpack_thread == 0) + Sleep (10); + } + ret = 1; } - return 1; + blkdev_cd_change (unitnum, currprefs.cdslots[unitnum].name); + return ret; } static void close_device (int unitnum) { struct cdunit *cdu = &cdunits[unitnum]; - if (cdu->open == false) - return; - cdda_stop (cdu); - unload_image (cdu); - uae_sem_destroy (&cdu->sub_sem); - cdu->open = false; - blkdev_cd_change (unitnum, currprefs.cdslots[unitnum].name); - if (cdimage_unpack_thread) { - cdimage_unpack_thread = 0; - write_comm_pipe_u32 (&unpack_pipe, -1, 0); - write_comm_pipe_u32 (&unpack_pipe, -1, 1); - while (cdimage_unpack_thread == 0) - Sleep (10); - cdimage_unpack_thread = 0; - destroy_comm_pipe (&unpack_pipe); + if (cdu->open) { + cdda_stop (cdu); + unload_image (cdu); + uae_sem_destroy (&cdu->sub_sem); + cdu->open = false; + if (cdimage_unpack_thread) { + cdimage_unpack_thread = 0; + write_comm_pipe_u32 (&unpack_pipe, -1, 0); + write_comm_pipe_u32 (&unpack_pipe, -1, 1); + while (cdimage_unpack_thread == 0) + Sleep (10); + cdimage_unpack_thread = 0; + destroy_comm_pipe (&unpack_pipe); + } } + blkdev_cd_change (unitnum, currprefs.cdslots[unitnum].name); } static void close_bus (void) diff --git a/cdtv.cpp b/cdtv.cpp index 2daf2bf6..268ba4fd 100644 --- a/cdtv.cpp +++ b/cdtv.cpp @@ -268,8 +268,10 @@ static void subfunc (uae_u8 *data, int cnt) } static int statusfunc (int status) { - if (status < 0) + if (status == -1) return 500; + if (status == -2) + return 75; if (cd_audio_status != status) { if (status == AUDIO_STATUS_PLAY_COMPLETE || status == AUDIO_STATUS_PLAY_ERROR) { cd_audio_finished = 1; @@ -515,6 +517,8 @@ static void cdrom_command_thread (uae_u8 b) if (cdrom_command_cnt_in == 7) { cdrom_command_accepted (0, s, &cdrom_command_cnt_in); cd_finished = 1; + sleep_millis (500); + activate_stch = 1; } break; case 0x02: /* read */ diff --git a/cfgfile.cpp b/cfgfile.cpp index d0dfd982..3fcea0ab 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -1194,7 +1194,8 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) *next2++ = 0; cfgfile_intval (option, next, tmp, &unitnum, 1); } - _tcsncpy (p->cdslots[i].name, value, sizeof p->cdslots[i].name / sizeof (TCHAR)); + if (_tcslen (value) > 0) + _tcsncpy (p->cdslots[i].name, value, sizeof p->cdslots[i].name / sizeof (TCHAR)); p->cdslots[i].name[sizeof p->cdslots[i].name - 1] = 0; p->cdslots[i].inuse = true; p->cdslots[i].type = type; @@ -1650,9 +1651,9 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) return 0; } -static void decode_rom_ident (TCHAR *romfile, int maxlen, TCHAR *ident) +static void decode_rom_ident (TCHAR *romfile, int maxlen, const TCHAR *ident, int romflags) { - TCHAR *p; + const TCHAR *p; int ver, rev, subver, subrev, round, i; TCHAR model[64], *modelp; struct romlist **rl; @@ -1670,29 +1671,29 @@ static void decode_rom_ident (TCHAR *romfile, int maxlen, TCHAR *ident) while (*p) { TCHAR c = *p++; int *pp1 = NULL, *pp2 = NULL; - if (_totupper(c) == 'V' && _istdigit(*p)) { + if (_totupper (c) == 'V' && _istdigit (*p)) { pp1 = &ver; pp2 = &rev; - } else if (_totupper(c) == 'R' && _istdigit(*p)) { + } else if (_totupper (c) == 'R' && _istdigit (*p)) { pp1 = &subver; pp2 = &subrev; - } else if (!_istdigit(c) && c != ' ') { - _tcsncpy (model, p - 1, (sizeof model) - 1); + } else if (!_istdigit (c) && c != ' ') { + _tcsncpy (model, p - 1, (sizeof model) / sizeof (TCHAR) - 1); p += _tcslen (model); modelp = model; } if (pp1) { - *pp1 = _tstol(p); + *pp1 = _tstol (p); while (*p != 0 && *p != '.' && *p != ' ') p++; if (*p == '.') { p++; if (pp2) - *pp2 = _tstol(p); + *pp2 = _tstol (p); } } if (*p == 0 || *p == ';') { - rl = getromlistbyident (ver, rev, subver, subrev, modelp, round); + rl = getromlistbyident (ver, rev, subver, subrev, modelp, romflags, round > 0); if (rl) { for (i = 0; rl[i]; i++) { if (round) { @@ -1812,7 +1813,7 @@ static void parse_addmem (struct uae_prefs *p, TCHAR *buf, int num) p->custom_memory_sizes[num] = size; } -static int cfgfile_parse_hardware (struct uae_prefs *p, TCHAR *option, TCHAR *value) +static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCHAR *value) { int tmpval, dummyint, i; bool tmpbool, dummybool; @@ -1964,15 +1965,15 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, TCHAR *option, TCHAR *va return 1; } if (cfgfile_string (option, value, L"kickstart_rom", p->romident, sizeof p->romident / sizeof (TCHAR))) { - decode_rom_ident (p->romfile, sizeof p->romfile / sizeof (TCHAR), p->romident); + decode_rom_ident (p->romfile, sizeof p->romfile / sizeof (TCHAR), p->romident, ROMTYPE_ALL_KICK); return 1; } if (cfgfile_string (option, value, L"kickstart_ext_rom", p->romextident, sizeof p->romextident / sizeof (TCHAR))) { - decode_rom_ident (p->romextfile, sizeof p->romextfile / sizeof (TCHAR), p->romextident); + decode_rom_ident (p->romextfile, sizeof p->romextfile / sizeof (TCHAR), p->romextident, ROMTYPE_ALL_EXT); return 1; } if (cfgfile_string (option, value, L"cart", p->cartident, sizeof p->cartident / sizeof (TCHAR))) { - decode_rom_ident (p->cartfile, sizeof p->cartfile / sizeof (TCHAR), p->cartident); + decode_rom_ident (p->cartfile, sizeof p->cartfile / sizeof (TCHAR), p->cartident, ROMTYPE_ALL_CART); return 1; } diff --git a/cia.cpp b/cia.cpp index f7e205a6..03d7fcdb 100644 --- a/cia.cpp +++ b/cia.cpp @@ -625,12 +625,8 @@ static uae_u8 ReadCIAA (unsigned int addr) action_replay_ciaread (); #endif tmp = DISK_status() & 0x3c; - tmp |= handle_joystick_buttons (ciaadra); + tmp |= handle_joystick_buttons (ciaapra, ciaadra); tmp |= (ciaapra | (ciaadra ^ 3)) & 0x03; - if (ciaadra & 0x40) - tmp = (tmp & ~0x40) | (ciaapra & 0x40); - if (ciaadra & 0x80) - tmp = (tmp & ~0x80) | (ciaapra & 0x80); tmp = dongle_cia_read (0, reg, tmp); #if DONGLE_DEBUG > 0 if (notinrom()) diff --git a/disk.cpp b/disk.cpp index 2ef4e976..1c7c0343 100644 --- a/disk.cpp +++ b/disk.cpp @@ -876,7 +876,6 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR int canauto; const TCHAR *ext; - gui_disk_image_change (dnum, fname); drive_image_free (drv); DISK_validate_filename (fname, 1, &drv->wrprot, &drv->crc32, &drv->diskfile); drv->ddhd = 1; @@ -886,6 +885,8 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR drv->useturbo = 0; drv->indexoffset = 0; + gui_disk_image_change (dnum, fname, drv->wrprot); + canauto = 0; ext = _tcsrchr (fname, '.'); if (ext) { @@ -2005,7 +2006,7 @@ static void drive_eject (drive * drv) #ifdef DRIVESOUND driveclick_insert (drv - floppy, 1); #endif - gui_disk_image_change (drv - floppy, NULL); + gui_disk_image_change (drv - floppy, NULL, drv->wrprot); drive_image_free (drv); drv->dskchange = 1; drv->ddhd = 1; @@ -2134,7 +2135,7 @@ int disk_getwriteprotect (const TCHAR *name) return diskfile_iswriteprotect (name, &needwritefile, &drvtype); } -static void diskfile_readonly (const TCHAR *name, int readonly) +static void diskfile_readonly (const TCHAR *name, bool readonly) { struct _stat64 st; int mode, oldmode; @@ -2143,7 +2144,8 @@ static void diskfile_readonly (const TCHAR *name, int readonly) return; oldmode = mode = st.st_mode; mode &= ~FILEFLAG_WRITE; - if (!readonly) mode |= FILEFLAG_WRITE; + if (!readonly) + mode |= FILEFLAG_WRITE; if (mode != oldmode) chmod (name, mode); } @@ -2170,7 +2172,7 @@ void DISK_reinsert (int num) setdskchangetime (&floppy[num], 20); } -int disk_setwriteprotect (int num, const TCHAR *name, int protect) +int disk_setwriteprotect (int num, const TCHAR *name, bool writeprotected) { int needwritefile, oldprotect; struct zfile *zf1, *zf2; @@ -2192,7 +2194,7 @@ int disk_setwriteprotect (int num, const TCHAR *name, int protect) if (needwritefile && zf2 == 0) disk_creatediskfile (name2, 1, drvtype, NULL); zfile_fclose (zf2); - if (protect && iswritefileempty (name)) { + if (writeprotected && iswritefileempty (name)) { for (i = 0; i < MAX_FLOPPY_DRIVES; i++) { if (!_tcscmp (name, floppy[i].newname)) drive_eject (&floppy[i]); @@ -2201,8 +2203,8 @@ int disk_setwriteprotect (int num, const TCHAR *name, int protect) } if (!needwritefile) - diskfile_readonly (name, protect); - diskfile_readonly (name2, protect); + diskfile_readonly (name, writeprotected); + diskfile_readonly (name2, writeprotected); DISK_reinsert (num); return 1; } @@ -3125,14 +3127,14 @@ void DSKLEN (uae_u16 v, int hpos) break; } if (dr == 4) { - write_log (L"disk %s DMA started, drvmask=%x motormask=%x\n", - dskdmaen == 3 ? L"write" : L"read", selected ^ 15, motormask); + write_log (L"disk %s DMA started, drvmask=%x motormask=%x PC=%08x\n", + dskdmaen == 3 ? L"write" : L"read", selected ^ 15, motormask, M68K_GETPC); noselected = 1; } else { if (disk_debug_logging > 0) { - write_log (L"disk %s DMA started, drvmask=%x track %d mfmpos %d dmaen=%d\n", + write_log (L"disk %s DMA started, drvmask=%x track %d mfmpos %d dmaen=%d PC=%08X\n", dskdmaen == 3 ? L"write" : L"read", selected ^ 15, - floppy[dr].cyl * 2 + side, floppy[dr].mfmpos, dma_enable); + floppy[dr].cyl * 2 + side, floppy[dr].mfmpos, dma_enable, M68K_GETPC); disk_dma_debugmsg (); } } diff --git a/include/disk.h b/include/disk.h index a6a38f9b..4ec56ac4 100644 --- a/include/disk.h +++ b/include/disk.h @@ -27,7 +27,7 @@ extern void DISK_update_adkcon (int hpos, uae_u16 v); extern void DISK_hsync (void); extern void DISK_reset (void); extern int disk_getwriteprotect (const TCHAR *name); -extern int disk_setwriteprotect (int num, const TCHAR *name, int protect); +extern int disk_setwriteprotect (int num, const TCHAR *name, bool writeprotected); extern void disk_creatediskfile (TCHAR *name, int type, drive_type adftype, TCHAR *disk_name); extern void dumpdisk (void); extern int DISK_history_add (const TCHAR *name, int idx, int type, int donotcheck); diff --git a/include/execio.h b/include/execio.h index 8e5f3854..6a0465a8 100644 --- a/include/execio.h +++ b/include/execio.h @@ -7,27 +7,27 @@ #define IOERR_UNITBUSY -6 #define IOERR_SELFTEST -7 -#define CDERR_NotSpecified 20 /* general catchall */ -#define CDERR_NoSecHdr 21 /* couldn't even find a sector */ -#define CDERR_BadSecPreamble 22 /* sector looked wrong */ -#define CDERR_BadSecID 23 /* ditto */ -#define CDERR_BadHdrSum 24 /* header had incorrect checksum */ -#define CDERR_BadSecSum 25 /* data had incorrect checksum */ -#define CDERR_TooFewSecs 26 /* couldn't find enough sectors */ -#define CDERR_BadSecHdr 27 /* another "sector looked wrong" */ -#define CDERR_WriteProt 28 /* can't write to a protected disk */ -#define CDERR_NoDisk 29 /* no disk in the drive */ -#define CDERR_SeekError 30 /* couldn't find track 0 */ -#define CDERR_NoMem 31 /* ran out of memory */ -#define CDERR_BadUnitNum 32 /* asked for a unit > NUMUNITS */ -#define CDERR_BadDriveType 33 /* not a drive cd.device understands */ -#define CDERR_DriveInUse 34 /* someone else allocated the drive */ -#define CDERR_PostReset 35 /* user hit reset; awaiting doom */ -#define CDERR_BadDataType 36 /* data on disk is wrong type */ -#define CDERR_InvalidState 37 /* invalid cmd under current conditions */ - -#define CDERR_Phase 42 /* illegal or unexpected SCSI phase */ -#define CDERR_NoBoard 50 /* open failed for non-existant board */ +#define IOERR_NotSpecified 20 /* general catchall */ +#define IOERR_NoSecHdr 21 /* couldn't even find a sector */ +#define IOERR_BadSecPreamble 22 /* sector looked wrong */ +#define IOERR_BadSecID 23 /* ditto */ +#define IOERR_BadHdrSum 24 /* header had incorrect checksum */ +#define IOERR_BadSecSum 25 /* data had incorrect checksum */ +#define IOERR_TooFewSecs 26 /* couldn't find enough sectors */ +#define IOERR_BadSecHdr 27 /* another "sector looked wrong" */ +#define IOERR_WriteProt 28 /* can't write to a protected disk */ +#define IOERR_NoDisk 29 /* no disk in the drive */ +#define IOERR_SeekError 30 /* couldn't find track 0 */ +#define IOERR_NoMem 31 /* ran out of memory */ +#define IOERR_BadUnitNum 32 /* asked for a unit > NUMUNITS */ +#define IOERR_BadDriveType 33 /* not a drive cd.device understands */ +#define IOERR_DriveInUse 34 /* someone else allocated the drive */ +#define IOERR_PostReset 35 /* user hit reset; awaiting doom */ +#define IOERR_BadDataType 36 /* data on disk is wrong type */ +#define IOERR_InvalidState 37 /* invalid cmd under current conditions */ +#define IOERR_BadStatus 45 +#define IOERR_Phase 42 /* illegal or unexpected SCSI phase */ +#define IOERR_NoBoard 50 /* open failed for non-existant board */ #define TDERR_DiskChanged 29 diff --git a/include/gui.h b/include/gui.h index ac65ba66..e28e24e1 100644 --- a/include/gui.h +++ b/include/gui.h @@ -17,7 +17,7 @@ extern void gui_changesettings (void); extern void gui_lock (void); extern void gui_unlock (void); extern void gui_flicker_led (int, int, int); -extern void gui_disk_image_change (int, const TCHAR *); +extern void gui_disk_image_change (int, const TCHAR *, bool writeprotected); extern unsigned int gui_ledstate; extern void gui_display (int shortcut); diff --git a/include/inputdevice.h b/include/inputdevice.h index af909049..9bedd0ea 100644 --- a/include/inputdevice.h +++ b/include/inputdevice.h @@ -106,7 +106,7 @@ INPUTEVENT_END extern void handle_cd32_joystick_cia (uae_u8, uae_u8); extern uae_u8 handle_parport_joystick (int port, uae_u8 pra, uae_u8 dra); -extern uae_u8 handle_joystick_buttons (uae_u8); +extern uae_u8 handle_joystick_buttons (uae_u8, uae_u8); extern int getbuttonstate (int joy, int button); extern int getjoystate (int joy); @@ -162,7 +162,7 @@ extern void inputdevice_hsync (void); extern void inputdevice_reset (void); extern void write_inputdevice_config (struct uae_prefs *p, struct zfile *f); -extern void read_inputdevice_config (struct uae_prefs *p, TCHAR *option, TCHAR *value); +extern void read_inputdevice_config (struct uae_prefs *p, const TCHAR *option, TCHAR *value); extern void reset_inputdevice_config (struct uae_prefs *pr); extern int inputdevice_joyport_config (struct uae_prefs *p, TCHAR *value, int portnum, int mode, int type); extern int inputdevice_getjoyportdevice (int port, int val); diff --git a/include/rommgr.h b/include/rommgr.h index b62c75da..cd0458c3 100644 --- a/include/rommgr.h +++ b/include/rommgr.h @@ -24,6 +24,10 @@ extern int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size); #define ROMTYPE_CD32 0x200000 #define ROMTYPE_SCRAMBLED 0x400000 +#define ROMTYPE_ALL_KICK (ROMTYPE_KICK | ROMTYPE_KICKCD32 | ROMTYPE_CD32) +#define ROMTYPE_ALL_EXT (ROMTYPE_EXTCD32 | ROMTYPE_EXTCDTV) +#define ROMTYPE_ALL_CART (ROMTYPE_AR | ROMTYPE_HRTMON | ROMTYPE_NORDIC | ROMTYPE_XPOWER | ROMTYPE_CD32CART) + struct romheader { TCHAR *name; int id; @@ -60,7 +64,7 @@ extern struct romdata *getromdatabyidgroup (int id, int group, int subitem); extern struct romdata *getromdatabyzfile (struct zfile *f); extern struct romlist **getarcadiaroms (void); extern struct romdata *getarcadiarombyname (const TCHAR *name); -extern struct romlist **getromlistbyident (int ver, int rev, int subver, int subrev, const TCHAR *model, int all); +extern struct romlist **getromlistbyident (int ver, int rev, int subver, int subrev, const TCHAR *model, int romflags, bool all); extern void getromname (const struct romdata*, TCHAR*); extern struct romdata *getromdatabyname (const TCHAR*); extern struct romlist *getromlistbyids (const int *ids); diff --git a/inputdevice.cpp b/inputdevice.cpp index 15074d00..19c8f8cd 100644 --- a/inputdevice.cpp +++ b/inputdevice.cpp @@ -48,6 +48,10 @@ #include "rp.h" #include "dongle.h" #include "cdtv.h" +#ifdef RETROPLATFORM +#include "rp.h" +#include "cloanto/RetroPlatformIPC.h" +#endif extern int bootrom_header, bootrom_items; @@ -774,9 +778,9 @@ void write_inputdevice_config (struct uae_prefs *p, struct zfile *f) } } -static int getnum (TCHAR **pp) +static int getnum (const TCHAR **pp) { - TCHAR *p = *pp; + const TCHAR *p = *pp; int v; if (!_tcsnicmp (p, L"false", 5)) @@ -793,11 +797,11 @@ static int getnum (TCHAR **pp) *pp = p; return v; } -static TCHAR *getstring (TCHAR **pp) +static TCHAR *getstring (const TCHAR **pp) { int i; static TCHAR str[1000]; - TCHAR *p = *pp; + const TCHAR *p = *pp; if (*p == 0) return 0; @@ -960,7 +964,7 @@ static bool readslot (TCHAR *parm, int num, int joystick, int button, struct uae return true; } -static struct inputevent *readevent (TCHAR *name, TCHAR **customp) +static struct inputevent *readevent (const TCHAR *name, TCHAR **customp) { int i = 1; while (events[i].name) { @@ -976,12 +980,13 @@ static struct inputevent *readevent (TCHAR *name, TCHAR **customp) return &events[0]; } -void read_inputdevice_config (struct uae_prefs *pr, TCHAR *option, TCHAR *value) +void read_inputdevice_config (struct uae_prefs *pr, const TCHAR *option, TCHAR *value) { struct uae_input_device *id = 0; struct inputevent *ie; int devnum, num, button, joystick, subnum, idnum, keynum; - TCHAR *p, *p2, *custom; + const TCHAR *p; + TCHAR *p2, *custom; option += 6; /* "input." */ p = getstring (&option); @@ -2104,12 +2109,13 @@ static void cap_check (void) int isbutton = getbuttonstate (joy, i == 0 ? JOYBUTTON_3 : JOYBUTTON_2); if (cd32_pad_enabled[joy]) { - if (i == 0) // 3rd button? - continue; - if (cd32padmode (p5dir, p5dat)) - continue; // only red and blue can be read if CD32 pad and only if it is in normal pad mode isbutton |= getbuttonstate (joy, JOYBUTTON_CD32_BLUE); + // CD32 pad 3rd button line (P5) is always floating + if (i == 0) + isbutton = 0; + if (cd32padmode (p5dir, p5dat)) + continue; } dong = dongle_analogjoy (joy, i); @@ -2164,6 +2170,10 @@ static void cap_check (void) if (!(potgo_value & pdir) && i == 1 && charge == 0) charge = 2; } + // CD32 pad in 2-button mode: blue button is not floating + if (cd32_pad_enabled[joy] && i == 1 && charge == 0) + charge = 2; + /* official Commodore mouse has pull-up resistors in button lines * NOTE: 3rd party mice may not have pullups! */ if (dong < 0 && (mouse_pullup && mouse_port[joy] && digital_port[joy][i]) && charge == 0) @@ -2181,7 +2191,7 @@ static void cap_check (void) } -uae_u8 handle_joystick_buttons (uae_u8 dra) +uae_u8 handle_joystick_buttons (uae_u8 pra, uae_u8 dra) { uae_u8 but = 0; int i; @@ -2192,9 +2202,9 @@ uae_u8 handle_joystick_buttons (uae_u8 dra) if (cd32_pad_enabled[i]) { uae_u16 p5dir = 0x0200 << (i * 4); uae_u16 p5dat = 0x0100 << (i * 4); - but |= 0x40 << i; + but |= mask; if (!cd32padmode (p5dir, p5dat)) { - if (getbuttonstate (i, JOYBUTTON_CD32_RED)) + if (getbuttonstate (i, JOYBUTTON_CD32_RED) || getbuttonstate (i, JOYBUTTON_1)) but &= ~mask; } } else { @@ -2205,11 +2215,11 @@ uae_u8 handle_joystick_buttons (uae_u8 dra) if (uaerand () & 1) but |= mask; } - + if (dra & mask) + but = (but & ~mask) | (pra & mask); } } - if (inputdevice_logging & 4) write_log (L"BFE001: %02X:%02X %x\n", dra, but, M68K_GETPC); return but; @@ -2836,10 +2846,17 @@ int handle_input_event (int nr, int state, int max, int autofire) if (ie->type & 4) { int old = joybutton[joy] & (1 << ie->data); - if (state) + if (state) { joybutton[joy] |= 1 << ie->data; - else +#ifdef RETROPLATFORM + rp_update_gameport (joy, RP_JOYSTICK_BUTTON1 << ie->data, 1); +#endif + } else { joybutton[joy] &= ~(1 << ie->data); +#ifdef RETROPLATFORM + rp_update_gameport (joy, RP_JOYSTICK_BUTTON1 << ie->data, 0); +#endif + } if (ie->data == 0 && old != (joybutton[joy] & (1 << ie->data)) && currprefs.cpu_cycle_exact) { // emulate contact bounce, 1st button only, others have capacitors @@ -2971,7 +2988,12 @@ int handle_input_event (int nr, int state, int max, int autofire) joydir[joy] |= DIR_UP; if (bot) joydir[joy] |= DIR_DOWN; - +#ifdef RETROPLATFORM + rp_update_gameport (joy, RP_JOYSTICK_LEFT, left); + rp_update_gameport (joy, RP_JOYSTICK_RIGHT, right); + rp_update_gameport (joy, RP_JOYSTICK_DOWN, bot); + rp_update_gameport (joy, RP_JOYSTICK_UP, top); +#endif } break; case 0: /* ->KEY */ @@ -4441,6 +4463,8 @@ void inputdevice_updateconfig (struct uae_prefs *prefs) rp_input_change (1); rp_input_change (2); rp_input_change (3); + for (i = 0; i < MAX_JPORTS; i++) + rp_update_gameport (i, -1, 0); #endif joybutton[0] = joybutton[1] = 0; @@ -5457,7 +5481,7 @@ void setjoystickstate (int joy, int axis, int state, int max) return; } for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) - handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], state, max, id->flags[ID_AXIS_OFFSET + axis][i]); + handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], state, max, id->flags[ID_AXIS_OFFSET + axis][i] & ID_FLAG_AUTOFIRE); id2->states[axis] = state; } int getjoystickstate (int joy) diff --git a/od-win32/blkdev_win32_ioctl.cpp b/od-win32/blkdev_win32_ioctl.cpp index b9081bbe..85154bec 100644 --- a/od-win32/blkdev_win32_ioctl.cpp +++ b/od-win32/blkdev_win32_ioctl.cpp @@ -55,7 +55,7 @@ struct dev_info_ioctl { int cdda_volume[2]; int cdda_scan; int cdda_volume_main; - uae_u32 cd_last_pos; + int cd_last_pos; HWAVEOUT cdda_wavehandle; int cdda_start, cdda_end; uae_u8 subcode[SUB_CHANNEL_SIZE * CDDA_BUFFERS]; @@ -64,7 +64,7 @@ struct dev_info_ioctl { play_subchannel_callback cdda_subfunc; play_status_callback cdda_statusfunc; int cdda_play_state; - int cdda_delay; + int cdda_delay, cdda_delay_frames; struct device_info di; uae_sem_t sub_sem, sub_sem2; bool open; @@ -263,6 +263,34 @@ static int spti_inquiry (struct dev_info_ioctl *ciw, int unitnum, uae_u8 *data) return 1; } +static void sub_deinterleave (const uae_u8 *s, uae_u8 *d) +{ + for (int i = 0; i < 8 * 12; i ++) { + int dmask = 0x80; + int smask = 1 << (7 - (i / 12)); + (*d) = 0; + for (int j = 0; j < 8; j++) { + (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0; + dmask >>= 1; + } + d++; + } +} + +static void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d) +{ + for (int i = 0; i < 8 * 12; i ++) { + int dmask = 0x80; + int smask = 1 << (7 - (i / 12)); + (*d) = 0; + for (int j = 0; j < 8; j++) { + (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0; + dmask >>= 1; + } + d++; + } +} + static int spti_read (struct dev_info_ioctl *ciw, int unitnum, uae_u8 *data, int sector, int sectorsize) { uae_u8 cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }; @@ -282,7 +310,6 @@ static int spti_read (struct dev_info_ioctl *ciw, int unitnum, uae_u8 *data, int cmd[9] |= 0x2 << 1; // C2 } } - ciw->cd_last_pos = sector; cmd[3] = (uae_u8)(sector >> 16); cmd[4] = (uae_u8)(sector >> 8); cmd[5] = (uae_u8)(sector >> 0); @@ -338,7 +365,6 @@ retry: data += sectorsize; ret += sectorsize; } - ciw->cd_last_pos = sector; got = true; } } @@ -363,7 +389,6 @@ retry: ret += sectorsize; } } - ciw->cd_last_pos = sector; got = true; } else { reseterrormode (ciw); @@ -391,7 +416,6 @@ retry: ret += sectorsize; } } - ciw->cd_last_pos = sector; got = true; } } @@ -473,8 +497,8 @@ static void *cdda_play (void *v) MMRESULT mmr; int volume[2], volume_main; int oldplay; + int idleframes; int readblocksize = 2352 + 96; - int current_sector = -1; for (i = 0; i < 2; i++) { memset (&whdr[i], 0, sizeof (WAVEHDR)); @@ -518,30 +542,61 @@ static void *cdda_play (void *v) bufon[bufnum] = 0; if (oldplay != ciw->cdda_play) { + idleframes = 0; struct _timeb tb1, tb2; - current_sector = -1; _ftime (&tb1); cdda_pos = ciw->cdda_start; + ciw->cd_last_pos = cdda_pos; oldplay = ciw->cdda_play; write_log (L"IOCTL%s CDDA: playing from %d to %d\n", ciw->usesptiread ? L"(SPTI)" : L"", ciw->cdda_start, ciw->cdda_end); ciw->subcodevalid = false; - while (ciw->cdda_paused && ciw->cdda_play > 0) + idleframes = ciw->cdda_delay_frames; + while (ciw->cdda_paused && ciw->cdda_play > 0) { Sleep (10); - // pre-load first sectors - if (read_block (ciw, -1, px[bufnum], cdda_pos, num_sectors, readblocksize)) - current_sector = cdda_pos; + idleframes = -1; + } + // force spin up + read_block (ciw, -1, px[bufnum], cdda_pos, num_sectors, readblocksize); + + if (ciw->cdda_scan == 0) { + // find possible P-subchannel=1 and fudge starting point so that + // buggy CD32/CDTV software CD+G handling does not miss any frames + bool seenindex = false; + for (int sector = cdda_pos - 200; sector < cdda_pos; sector++) { + uae_u8 *dst = px[bufnum]; + if (sector >= 0 && read_block (ciw, -1, dst, sector, 1, readblocksize)) { + uae_u8 subbuf[SUB_CHANNEL_SIZE]; + sub_deinterleave (dst + 2352, subbuf); + if (seenindex) { + for (int i = 2 * SUB_ENTRY_SIZE; i < SUB_CHANNEL_SIZE; i++) { + if (subbuf[i]) { // non-zero R-W subchannels + int diff = cdda_pos - sector + 2; + write_log (L"-> CD+G start pos fudge -> %d (%d)\n", sector, -diff); + idleframes -= diff; + cdda_pos = sector; + break; + } + } + } else if (subbuf[0] == 0xff) { // P == 1? + seenindex = true; + } + } + } + } + cdda_pos -= idleframes; + _ftime (&tb2); int diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm); diff -= ciw->cdda_delay; - if (diff < 0 && ciw->cdda_play > 0) + if (idleframes >= 0 && diff < 0 && ciw->cdda_play > 0) Sleep (-diff); setstate (ciw, AUDIO_STATUS_IN_PROGRESS); } if ((cdda_pos < ciw->cdda_end || ciw->cdda_end == 0xffffffff) && !ciw->cdda_paused && ciw->cdda_play) { - if (!isaudiotrack (&ciw->di.toc, cdda_pos)) { + if (idleframes <= 0 && !isaudiotrack (&ciw->di.toc, cdda_pos)) { setstate (ciw, AUDIO_STATUS_PLAY_ERROR); goto end; // data track? } @@ -549,32 +604,37 @@ static void *cdda_play (void *v) gui_flicker_led (LED_CD, ciw->di.unitnum - 1, LED_CD_AUDIO); uae_sem_wait (&ciw->sub_sem); + ciw->subcodevalid = false; memset (ciw->subcode, 0, sizeof ciw->subcode); - - bool readerr = false; - if (current_sector != cdda_pos) { - current_sector = -1; - memset (px[bufnum], 0, num_sectors * readblocksize); - readerr = read_block (ciw, -1, px[bufnum], cdda_pos, num_sectors, readblocksize) == 0; - if (!readerr) - current_sector = cdda_pos; - } - if (readerr) { - if (ciw->cdda_subfunc) - ciw->cdda_subfunc (ciw->subcode, num_sectors); - } else { - for (i = 0; i < num_sectors; i++) { - memcpy (ciw->subcode + i * SUB_CHANNEL_SIZE, px[bufnum] + readblocksize * i + 2352, SUB_CHANNEL_SIZE); + memset (px[bufnum], 0, num_sectors * readblocksize); + + if (cdda_pos >= 0) { + if (read_block (ciw, -1, px[bufnum], cdda_pos, num_sectors, readblocksize)) { + for (i = 0; i < num_sectors; i++) { + memcpy (ciw->subcode + i * SUB_CHANNEL_SIZE, px[bufnum] + readblocksize * i + 2352, SUB_CHANNEL_SIZE); + } + for (i = 1; i < num_sectors; i++) { + memmove (px[bufnum] + 2352 * i, px[bufnum] + readblocksize * i, 2352); + } + ciw->subcodevalid = true; } - if (ciw->cdda_subfunc) - ciw->cdda_subfunc (ciw->subcode, num_sectors); - for (i = 1; i < num_sectors; i++) { - memmove (px[bufnum] + 2352 * i, px[bufnum] + readblocksize * i, 2352); + } + + for (i = 0; i < num_sectors; i++) { + if (idleframes > 0) { + idleframes--; + memset (px[bufnum] + 2352 * i, 0, 2352); + memset (ciw->subcode + i * SUB_CHANNEL_SIZE, 0, SUB_CHANNEL_SIZE); + } else if (cdda_pos < ciw->cdda_start && ciw->cdda_scan == 0) { + memset (px[bufnum] + 2352 * i, 0, 2352); } - ciw->subcodevalid = true; } - reseterrormode (ciw); + if (idleframes > 0) + ciw->subcodevalid = false; + + if (ciw->cdda_subfunc) + ciw->cdda_subfunc (ciw->subcode, num_sectors); uae_sem_post (&ciw->sub_sem); @@ -612,16 +672,21 @@ static void *cdda_play (void *v) if (cdda_pos < 0) cdda_pos = 0; } else { - cdda_pos += num_sectors; - } - if (cdda_pos - num_sectors < ciw->cdda_end && cdda_pos >= ciw->cdda_end) { - setstate (ciw, AUDIO_STATUS_PLAY_COMPLETE); - ciw->cdda_play_finished = 1; - ciw->cdda_play = -1; - cdda_pos = ciw->cdda_end; + if (cdda_pos < 0 && cdda_pos + num_sectors >= 0) + cdda_pos = 0; + else + cdda_pos += num_sectors; } - ciw->cd_last_pos = cdda_pos; + if (idleframes <= 0) { + if (cdda_pos - num_sectors < ciw->cdda_end && cdda_pos >= ciw->cdda_end) { + setstate (ciw, AUDIO_STATUS_PLAY_COMPLETE); + ciw->cdda_play_finished = 1; + ciw->cdda_play = -1; + cdda_pos = ciw->cdda_end; + } + ciw->cd_last_pos = cdda_pos; + } } if (bufon[0] == 0 && bufon[1] == 0) { @@ -710,6 +775,7 @@ static int ioctl_command_play (int unitnum, int startlsn, int endlsn, int scan, ciw->cdda_statusfunc = statusfunc; ciw->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0); ciw->cdda_delay = setstate (ciw, -1); + ciw->cdda_delay_frames = setstate (ciw, -2); setstate (ciw, AUDIO_STATUS_NOT_SUPPORTED); if (!open_createfile (ciw, 0)) { @@ -731,34 +797,6 @@ static int ioctl_command_play (int unitnum, int startlsn, int endlsn, int scan, return 1; } -static void sub_deinterleave (const uae_u8 *s, uae_u8 *d) -{ - for (int i = 0; i < 8 * 12; i ++) { - int dmask = 0x80; - int smask = 1 << (7 - (i / 12)); - (*d) = 0; - for (int j = 0; j < 8; j++) { - (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0; - dmask >>= 1; - } - d++; - } -} - -static void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d) -{ - for (int i = 0; i < 8 * 12; i ++) { - int dmask = 0x80; - int smask = 1 << (7 - (i / 12)); - (*d) = 0; - for (int j = 0; j < 8; j++) { - (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0; - dmask >>= 1; - } - d++; - } -} - /* read qcode */ static int ioctl_command_qcode (int unitnum, uae_u8 *buf, int sector) { @@ -875,6 +913,7 @@ static int ioctl_command_rawread (int unitnum, uae_u8 *data, int sector, int siz while (size-- > 0) { if (!read_block (ciw, unitnum, data, sector, 1, sectorsize)) break; + ciw->cd_last_pos = sector; data += sectorsize; ret += sectorsize; sector++; @@ -908,6 +947,7 @@ static int ioctl_command_rawread (int unitnum, uae_u8 *data, int sector, int siz reseterrormode (ciw); return ret; } + ciw->cd_last_pos = sector; if (subs == 0) { memcpy (data, p, blocksize); diff --git a/od-win32/cloanto/RetroPlatformIPC.h b/od-win32/cloanto/RetroPlatformIPC.h old mode 100644 new mode 100755 index be6b9efd..9d54969c --- a/od-win32/cloanto/RetroPlatformIPC.h +++ b/od-win32/cloanto/RetroPlatformIPC.h @@ -2,12 +2,13 @@ Name : RetroPlatformIPC.h Project : RetroPlatform Player Client : Cloanto Italia srl - Legal : Copyright 2007, 2008 Cloanto Italia srl - All rights reserved. This + Support : http://www.retroplatform.com + Legal : Copyright 2007-2010 Cloanto Italia srl - All rights reserved. This : file is made available under the terms of the GNU General Public : License version 2 as published by the Free Software Foundation. Authors : os, mcb Created : 2007-08-27 13:55:49 - Updated : 2008-12-19 12:38:00 + Updated : 2010-08-17 19:01:00 Comment : RP Player interprocess communication include file *****************************************************************************/ @@ -16,9 +17,9 @@ #include -#define RPLATFORM_API_VER "1.1" +#define RPLATFORM_API_VER "1.2" #define RPLATFORM_API_VER_MAJOR 1 -#define RPLATFORM_API_VER_MINOR 1 +#define RPLATFORM_API_VER_MINOR 2 #define RPIPC_HostWndClass "RetroPlatformHost%s" #define RPIPC_GuestWndClass "RetroPlatformGuest%d" @@ -50,46 +51,48 @@ #define RPIPCGM_PARENT (WM_APP + 21) #define RPIPCGM_DEVICESEEK (WM_APP + 22) #define RPIPCGM_CLOSE (WM_APP + 23) - +#define RPIPCGM_DEVICEREADWRITE (WM_APP + 24) +#define RPIPCGM_HOSTVERSION (WM_APP + 25) // **************************************************************************** // Host-to-Guest Messages // **************************************************************************** -#define RPIPCHM_CLOSE (WM_APP + 200) -#define RPIPCHM_SCREENMODE (WM_APP + 202) -#define RPIPCHM_SCREENCAPTURE (WM_APP + 203) -#define RPIPCHM_PAUSE (WM_APP + 204) -#define RPIPCHM_DEVICECONTENT (WM_APP + 205) -#define RPIPCHM_RESET (WM_APP + 206) -#define RPIPCHM_TURBO (WM_APP + 207) -#define RPIPCHM_PING (WM_APP + 208) -#define RPIPCHM_VOLUME (WM_APP + 209) -#define RPIPCHM_ESCAPEKEY (WM_APP + 210) -#define RPIPCHM_EVENT (WM_APP + 211) -#define RPIPCHM_MOUSECAPTURE (WM_APP + 212) -#define RPIPCHM_SAVESTATE (WM_APP + 213) -#define RPIPCHM_LOADSTATE (WM_APP + 214) -#define RPIPCHM_FLUSH (WM_APP + 215) - +#define RPIPCHM_CLOSE (WM_APP + 200) +#define RPIPCHM_SCREENMODE (WM_APP + 202) +#define RPIPCHM_SCREENCAPTURE (WM_APP + 203) +#define RPIPCHM_PAUSE (WM_APP + 204) +#define RPIPCHM_DEVICECONTENT (WM_APP + 205) +#define RPIPCHM_RESET (WM_APP + 206) +#define RPIPCHM_TURBO (WM_APP + 207) +#define RPIPCHM_PING (WM_APP + 208) +#define RPIPCHM_VOLUME (WM_APP + 209) +#define RPIPCHM_ESCAPEKEY (WM_APP + 210) +#define RPIPCHM_EVENT (WM_APP + 211) +#define RPIPCHM_MOUSECAPTURE (WM_APP + 212) +#define RPIPCHM_SAVESTATE (WM_APP + 213) +#define RPIPCHM_LOADSTATE (WM_APP + 214) +#define RPIPCHM_FLUSH (WM_APP + 215) +#define RPIPCHM_DEVICEREADWRITE (WM_APP + 216) // **************************************************************************** // Message Data Structures and Defines // **************************************************************************** // Guest Features -#define RP_FEATURE_POWERLED 0x00000001 // a power LED is emulated -#define RP_FEATURE_SCREEN1X 0x00000002 // 1x mode is available -#define RP_FEATURE_SCREEN2X 0x00000004 // 2x mode is available -#define RP_FEATURE_SCREEN3X 0x00000008 // 3x mode is available -#define RP_FEATURE_SCREEN4X 0x00000010 // 4x mode is available -#define RP_FEATURE_FULLSCREEN 0x00000020 // full screen display is available -#define RP_FEATURE_SCREENCAPTURE 0x00000040 // screen capture functionality is available (see RPIPCHM_SCREENCAPTURE message) -#define RP_FEATURE_PAUSE 0x00000080 // pause functionality is available (see RPIPCHM_PAUSE message) -#define RP_FEATURE_TURBO 0x00000100 // turbo mode functionality is available (see RPIPCHM_TURBO message) -#define RP_FEATURE_VOLUME 0x00000200 // volume adjustment is possible (see RPIPCHM_VOLUME message) -#define RP_FEATURE_STATE 0x00000400 // loading and saving of emulation state is supported (see RPIPCHM_SAVESTATE/RPIPCHM_LOADSTATE message) -#define RP_FEATURE_SCANLINES 0x00000800 // scan lines video effect is available +#define RP_FEATURE_POWERLED 0x00000001 // a power LED is emulated +#define RP_FEATURE_SCREEN1X 0x00000002 // 1x mode is available +#define RP_FEATURE_SCREEN2X 0x00000004 // 2x mode is available +#define RP_FEATURE_SCREEN3X 0x00000008 // 3x mode is available +#define RP_FEATURE_SCREEN4X 0x00000010 // 4x mode is available +#define RP_FEATURE_FULLSCREEN 0x00000020 // full screen display is available +#define RP_FEATURE_SCREENCAPTURE 0x00000040 // screen capture functionality is available (see RPIPCHM_SCREENCAPTURE message) +#define RP_FEATURE_PAUSE 0x00000080 // pause functionality is available (see RPIPCHM_PAUSE message) +#define RP_FEATURE_TURBO 0x00000100 // turbo mode functionality is available (see RPIPCHM_TURBO message) +#define RP_FEATURE_VOLUME 0x00000200 // volume adjustment is possible (see RPIPCHM_VOLUME message) +#define RP_FEATURE_STATE 0x00000400 // loading and saving of emulation state is supported (see RPIPCHM_SAVESTATE/RPIPCHM_LOADSTATE message) +#define RP_FEATURE_SCANLINES 0x00000800 // scan lines video effect is available +#define RP_FEATURE_DEVICEREADWRITE 0x00001000 // device read/write can be set at runtime on floppy and hard disks // Screen Modes #define RP_SCREENMODE_1X 0x00000000 // 1x window or full-screen mode ("CGA mode") @@ -152,6 +155,23 @@ typedef struct RPDeviceContent #define RP_IPD_KEYBDL2 L"KeyboardLayout2" // second joystick emulation keyboard layout (e.g. Keyboard Layout B for WinUAE) #define RP_IPD_KEYBDL3 L"KeyboardLayout3" // third joystick emulation keyboard layout (e.g. Keyboard Layout C for WinUAE) +// Joystick status flags +#define RP_JOYSTICK_RIGHT 0x00000001 // right direction +#define RP_JOYSTICK_LEFT 0x00000002 // left direction +#define RP_JOYSTICK_DOWN 0x00000004 // down direction +#define RP_JOYSTICK_UP 0x00000008 // up direction +#define RP_JOYSTICK_BUTTON1 0x00000010 // button 1 - Fire 1 - CD32 Red +#define RP_JOYSTICK_BUTTON2 0x00000020 // button 2 - Fire 2 - CD32 Blue +#define RP_JOYSTICK_BUTTON3 0x00000040 // button 3 - Fire 3 - CD32 Yellow +#define RP_JOYSTICK_BUTTON4 0x00000080 // button 4 - Fire 4 - CD32 Green +#define RP_JOYSTICK_BUTTON5 0x00000100 // button 5 - CD32 Play +#define RP_JOYSTICK_BUTTON6 0x00000200 // button 6 - CD32 Reverse +#define RP_JOYSTICK_BUTTON7 0x00000400 // button 7 - CD32 Forward + +// Device Read/Write status +#define RP_DEVICE_READONLY 0 // the medium is write-protected +#define RP_DEVICE_READWRITE 1 // the medium is read/write + // Turbo Mode Functionalities #define RP_TURBO_CPU 0x00000001 // CPU #define RP_TURBO_FLOPPY 0x00000002 // floppy disk drive @@ -168,7 +188,19 @@ typedef struct RPDeviceContent // RPIPCGM_DEVICEACTIVITY #define RP_DEVICEACTIVITY_GREEN 0x0000 // green led #define RP_DEVICEACTIVITY_RED 0x0001 // red led -#define RP_DEVICEACTIVITY_READ RP_DEVICEACTIVITY_GREEN // the device activity is about a read operation -#define RP_DEVICEACTIVITY_WRITE RP_DEVICEACTIVITY_RED // the device activity is about a write operation +#define RP_DEVICEACTIVITY_READ RP_DEVICEACTIVITY_GREEN // device activity is a read operation +#define RP_DEVICEACTIVITY_WRITE RP_DEVICEACTIVITY_RED // device activity is a write operation + +// RPIPCGM_HOSTVERSION +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-----------------------+-------------------+-------------------+ +// | major | minor | build | +// +-----------------------+-------------------+-------------------+ +#define RP_HOSTVERSION_MAJOR(ver) (((ver) >> 20) & 0xFFF) +#define RP_HOSTVERSION_MINOR(ver) (((ver) >> 10) & 0x3FF) +#define RP_HOSTVERSION_BUILD(ver) ((ver) & 0x3FF) +#define RP_MAKE_HOSTVERSION(major,minor,build) ((LPARAM) (((LPARAM)((major) & 0xFFF)<<20) | ((LPARAM)((minor) & 0x3FF)<<10) | ((LPARAM)((build) & 0x3FF)))) + #endif // __CLOANTO_RETROPLATFORMIPC_H__ diff --git a/od-win32/cloanto/RetroPlatformIPC_doc_draft.txt b/od-win32/cloanto/RetroPlatformIPC_doc_draft.txt old mode 100644 new mode 100755 index 823db414..406925ae --- a/od-win32/cloanto/RetroPlatformIPC_doc_draft.txt +++ b/od-win32/cloanto/RetroPlatformIPC_doc_draft.txt @@ -2,8 +2,9 @@ Name : RetroPlatformIPC_doc.txt Project : RPSampleGuest Client : Cloanto Italia srl + Support : http://www.retroplatform.com Legal : CONFIDENTIAL TRADE SECRET PROPERTY OF CLOANTO ITALIA SRL - : Copyright © Cloanto Italia srl 2007-2008. + : Copyright © Cloanto Italia srl 2007-2009. : All rights reserved, except where licensed, : assigned or transferred by contract. Authors : os, mcb @@ -38,6 +39,7 @@ Description: RPIPCGM_POWERLED (turns on the power LED in the GUI), RPIPCGM_DEVICES (one for each device category: tells the number of emulated devices), RPIPCGM_DEVICECONTENT (one for each device with an image file or peripheral attached), + RPIPCGM_DEVICEREADWRITE (one for each device with an image file or peripheral attached - optional for non-floppy/non-hard disk which are always read-only), RPIPCGM_TURBO (tells if some of the turbo modes are activated from the start), RPIPCGM_VOLUME (reports about starting volume level), RPIPCGM_SCREENMODE (communicates the screen mode, the clipping coordinates and the guest window handle); @@ -45,7 +47,12 @@ Description: and send its handle using a RPIPCGM_SCREENMODE message, which must be the last of the initialization messages, since it displays the guest window and the host "frame window" (the part of the player user interface - with command and status icons which can be used to drag the guest window, etc.) + with command and status icons which can be used to drag the guest window, etc.); + in some circumstances the host may decide not to display the guest window + when receiving the RPIPCGM_SCREENMODE message (e.g. in Express mode + the guest may be immediately paused and an intro banner may be displayed; + when the intro banner is dismissed the guest is resumed from pause mode + and its window is displayed) Data sent: WPARAM = RP_FEATURE_* flags Response: @@ -164,7 +171,8 @@ Message: RPIPCGM_DEVICEACTIVITY Description: this message can be used to turn on or off the activity indicator - of a specified device (like a LED on the original hardware); + of a specified device (like a LED on the original hardware) + or to notify the host about the status of a joystick; the indicator can also be "blinked", i.e. the host will turn the LED on and then off again after the specified amount of time Data sent: @@ -180,7 +188,10 @@ Data sent: or to a value to turn on the activity LED for the specified amount of time (blink); the Flags value can be set - using one or more of the RP_DEVICEACTIVITY_* defines + using one or more of the RP_DEVICEACTIVITY_* defines; + in case the message references a RP_DEVICE_INPUTPORT device + connected to a joystick, the data sent via LPARAM + is a combination of RP_JOYSTICK_* values Response: none @@ -224,6 +235,18 @@ Response: (e.g. LOWORD(lr) = major version; HIWORD(lr) = minor version) +Message: + RPIPCGM_HOSTVERSION +Description: + the guest can send a RPIPCGM_HOSTVERSION + to query the host about its version +Data sent: + none +Response: + LRESULT = major, minor and build versions combined into a single 32 bit value; + the RP_HOSTVERSION_* macros can be used to get specific information + + Message: RPIPCGM_PAUSE Description: @@ -254,7 +277,32 @@ Data sent: pData = a RPDEVICECONTENT structure (see RetroPlatformIPC.h); the szContent field of the structure contains an empty string when the guest - is ejecting something from the device + is ejecting something from the device; + szContent examples for CD and other physical drives supported by the guest: + - "D:\" = mount physical drive D: (full or empty, does not matter) + - "C:\test.iso" = mount ISO image + - "" = empty image drive ("image mode without image") + - there is no specific message to indicate "empty physical drive" (what counts is that there is an association with the physical drive) +Response: + none + + +Message: + RPIPCGM_DEVICEREADWRITE +Description: + the guest sends a RPIPCGM_DEVICEREADWRITE message + to notify the host about an initial status or a change in + the read/write protection status; + this notification is optional if the event + was requested by the host (see the RPIPCHM_DEVICEREADWRITE message); + if no initial status is sent, the status is assumed to be read/write + for floppy and hard disks, and read-only for all other devices + (CDs, cartridges, tapes, etc.) +Data sent: + WPARAM = device category (RP_DEVICE_* value) and device number + combined with the MAKEWORD macro; + e.g. MAKEWORD(RP_DEVICE_FLOPPY, 0) + LPARAM = current device read/write status flags (RP_DEVICE_READONLY/RP_DEVICE_READWRITE) Response: none @@ -450,6 +498,20 @@ Response: LRESULT = 1 if the guest successfully executed the command or 0 otherwise +Message: + RPIPCHM_DEVICEREADWRITE +Description: + the host sends a RPIPCHM_DEVICEREADWRITE message + to set the read/write protection status +Data sent: + WPARAM = device category (RP_DEVICE_* value) and device number + combined with the MAKEWORD macro; + e.g. MAKEWORD(RP_DEVICE_FLOPPY, 0) + LPARAM = current device read/write status flags (RP_DEVICE_READONLY/RP_DEVICE_READWRITE) +Response: + LRESULT = 1 if the guest successfully executed the command or 0 otherwise (for example, because the image file itself is read-only, so that writing is not possible) + + Message: RPIPCHM_RESET Description: diff --git a/od-win32/dinput.cpp b/od-win32/dinput.cpp index fac2e5d8..4e705a70 100644 --- a/od-win32/dinput.cpp +++ b/od-win32/dinput.cpp @@ -114,6 +114,7 @@ static int oldleds, oldusedleds, newleds, oldusbleds; static int normalmouse, supermouse, rawmouse, winmouse, winmousenumber, winmousemode, winmousewheelbuttonstart; static int normalkb, superkb, rawkb; static bool rawinput_enabled_mouse, rawinput_enabled_keyboard; +static bool rawinput_decided; int no_rawinput = 0; int dinput_enum_all; @@ -813,18 +814,11 @@ static void getvidpid (const TCHAR *devname, int *vid, int *pid, int *mi) static void addrkblabels (struct didata *did) { - int j = 0; for (int k = 0; k < 254; k++) { TCHAR tmp[100]; tmp[0] = 0; - if (rawkeyboardlabels[j] != NULL) { - if (rawkeyboardlabels[j][0]) { - _tcscpy (tmp, rawkeyboardlabels[j]); - j++; - } - } else { - j++; - } + if (rawkeyboardlabels[k] != NULL && rawkeyboardlabels[k][0]) + _tcscpy (tmp, rawkeyboardlabels[k]); if (!tmp[0]) _stprintf (tmp, L"KEY_%02X", k + 1); did->buttonname[k] = my_strdup (tmp); @@ -889,6 +883,14 @@ static int initialize_rawinput (void) PRID_DEVICE_INFO rdi; int v, j; + if (rawinput_decided) { + // must not enable rawinput later, even if rawinput capable device was plugged in + if (type == RIM_TYPEKEYBOARD && !rawinput_enabled_keyboard) + continue; + if (type == RIM_TYPEMOUSE && !rawinput_enabled_mouse) + continue; + } + if (GetRawInputDeviceInfo (h, RIDI_DEVICENAME, NULL, &vtmp) == -1) continue; if (vtmp >= bufsize) @@ -1598,8 +1600,12 @@ static int di_do_init (void) write_log (L"RawInput enumeration..\n"); initialize_rawinput (); } - rawinput_enabled_keyboard = num_keyboard > 0; - rawinput_enabled_mouse = num_mouse > 0; + + if (!rawinput_decided) { + rawinput_enabled_keyboard = num_keyboard > 0; + rawinput_enabled_mouse = num_mouse > 0; + rawinput_decided = true; + } hr = DirectInput8Create (hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID *)&g_lpdi, NULL); if (FAILED(hr)) { diff --git a/od-win32/direct3d.cpp b/od-win32/direct3d.cpp index 63570387..f92f3507 100644 --- a/od-win32/direct3d.cpp +++ b/od-win32/direct3d.cpp @@ -2149,7 +2149,7 @@ void D3D_clear (void) static void D3D_render22 (void) { HRESULT hr; - LPDIRECT3DTEXTURE9 srctex; + LPDIRECT3DTEXTURE9 srctex = texture; UINT uPasses, uPass; if (!isd3d ()) @@ -2238,10 +2238,6 @@ static void D3D_render22 (void) #endif srctex = lpTempTexture; - } else { - - srctex = texture; - } } diff --git a/od-win32/lib/prowizard.lib b/od-win32/lib/prowizard.lib index 46893986b29ce1ab37692f7b85ad71f85feded90..0ae8ca6501bbc5f9d44e90792c5e933162b5ec1a 100644 GIT binary patch delta 21869 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 delta 19372 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 MAX_JPORTS) + if (num < 0 || num >= maxjports) return FALSE; if (_tcslen (name) == 0) { inputdevice_joyport_config (&changed_prefs, L"none", num, 0, 0); @@ -685,6 +692,18 @@ static LRESULT CALLBACK RPHostMsgFunction2 (UINT uMessage, WPARAM wParam, LPARAM } return ret; } + case RPIPCHM_DEVICEREADWRITE: + { + DWORD ret = FALSE; + int device = LOBYTE(wParam); + if (device == RP_DEVICE_FLOPPY) { + int num = HIBYTE(wParam); + if (lParam == RP_DEVICE_READONLY || lParam == RP_DEVICE_READWRITE) { + ret = disk_setwriteprotect (num, currprefs.floppyslots[num].df, lParam == RP_DEVICE_READONLY); + } + } + return ret ? (LPARAM)1 : 0; + } } return FALSE; } @@ -699,6 +718,17 @@ static LRESULT CALLBACK RPHostMsgFunction (UINT uMessage, WPARAM wParam, LPARAM return lr; } +static int rp_hostversion (int *ver, int *rev, int *build) +{ + LRESULT lr = 0; + if (!RPSendMessagex (RPIPCGM_HOSTVERSION, 0, 0, NULL, 0, &guestinfo, &lr)) + return 0; + *ver = RP_HOSTVERSION_MAJOR(lr); + *rev = RP_HOSTVERSION_MINOR(lr); + *build = RP_HOSTVERSION_BUILD(lr); + return 1; +} + HRESULT rp_init (void) { HRESULT hr; @@ -706,7 +736,9 @@ HRESULT rp_init (void) hr = RPInitializeGuest (&guestinfo, hInst, rp_param, RPHostMsgFunction, 0); if (SUCCEEDED (hr)) { initialized = TRUE; - write_log (L"rp_init('%s') succeeded\n", rp_param); + rp_version = rp_revision = rp_build = -1; + rp_hostversion (&rp_version, &rp_revision, &rp_build); + write_log (L"rp_init('%s') succeeded. Version: %d.%d.%d\n", rp_param, rp_version, rp_revision, rp_build); } else { write_log (L"rp_init('%s') failed, error code %08x\n", rp_param, hr); } @@ -727,6 +759,7 @@ void rp_free (void) RPUninitializeGuest (&guestinfo); } + int rp_close (void) { if (!cando ()) @@ -750,7 +783,7 @@ static void sendfeatures (void) feat = RP_FEATURE_POWERLED | RP_FEATURE_SCREEN1X | RP_FEATURE_FULLSCREEN; feat |= RP_FEATURE_PAUSE | RP_FEATURE_TURBO | RP_FEATURE_VOLUME | RP_FEATURE_SCREENCAPTURE; - feat |= RP_FEATURE_STATE | RP_FEATURE_SCANLINES; + feat |= RP_FEATURE_STATE | RP_FEATURE_SCANLINES | RP_FEATURE_DEVICEREADWRITE; if (!WIN32GFX_IsPicassoScreen ()) feat |= RP_FEATURE_SCREEN2X | RP_FEATURE_SCREEN4X; RPSendMessagex (RPIPCGM_FEATURES, feat, 0, NULL, 0, &guestinfo, NULL); @@ -788,6 +821,7 @@ void rp_fixup_options (struct uae_prefs *p) max_horiz_dbl = currprefs.gfx_max_horizontal; max_vert_dbl = currprefs.gfx_max_vertical; + maxjports = (rp_version * 256 + rp_revision) >= 2 * 256 + 3 ? MAX_JPORTS : 2; changed_prefs.win32_borderless = currprefs.win32_borderless = 1; rp_filter_default = rp_filter = currprefs.gfx_filter; @@ -810,11 +844,12 @@ void rp_fixup_options (struct uae_prefs *p) } RPSendMessagex (RPIPCGM_DEVICES, RP_DEVICE_FLOPPY, floppy_mask, NULL, 0, &guestinfo, NULL); - RPSendMessagex (RPIPCGM_DEVICES, RP_DEVICE_INPUTPORT, (1 << MAX_JPORTS) - 1, NULL, 0, &guestinfo, NULL); + RPSendMessagex (RPIPCGM_DEVICES, RP_DEVICE_INPUTPORT, (1 << maxjports) - 1, NULL, 0, &guestinfo, NULL); rp_input_change (0); rp_input_change (1); rp_input_change (2); rp_input_change (3); + gameportmask[0] = gameportmask[1] = gameportmask[2] = gameportmask[3] = 0; hd_mask = 0; cd_mask = 0; @@ -845,7 +880,6 @@ void rp_fixup_options (struct uae_prefs *p) } } - rp_update_volume (&currprefs); rp_turbo (currprefs.turbo_emulation); for (i = 0; i <= 4; i++) @@ -853,6 +887,15 @@ void rp_fixup_options (struct uae_prefs *p) config_changed = 1; } +static void rp_device_writeprotect (int dev, int num, bool writeprotected) +{ + if (!cando ()) + return; + if (rp_version * 256 + rp_revision < 2 * 256 + 3) + return; + RPSendMessagex (RPIPCGM_DEVICEREADWRITE, MAKEWORD(dev, num), writeprotected ? RP_DEVICE_READONLY : RP_DEVICE_READWRITE, NULL, 0, &guestinfo, NULL); +} + static void rp_device_change (int dev, int num, const TCHAR *name) { struct RPDeviceContent *dc; @@ -883,6 +926,9 @@ void rp_input_change (int num) TCHAR name[MAX_DPATH]; TCHAR *name2 = NULL, *name3 = NULL; + if (num >= maxjports) + return; + name[0] = 0; if (JSEM_ISXARCADE1 (num, &currprefs)) { j = 2; @@ -914,9 +960,10 @@ void rp_input_change (int num) } rp_device_change (RP_DEVICE_INPUTPORT, num, name); } -void rp_disk_image_change (int num, const TCHAR *name) +void rp_disk_image_change (int num, const TCHAR *name, bool writeprotected) { rp_device_change (RP_DEVICE_FLOPPY, num, name); + rp_device_writeprotect (RP_DEVICE_FLOPPY, num, writeprotected); } void rp_harddrive_image_change (int num, const TCHAR *name) { @@ -988,6 +1035,24 @@ void rp_update_leds (int led, int onoff, int write) } } +void rp_update_gameport (int port, int mask, int onoff) +{ + if (!cando ()) + return; + if (port < 0 || port >= maxjports) + return; + if (rp_version * 256 + rp_revision < 2 * 256 + 3) + return; + int old = gameportmask[port]; + if (onoff) + gameportmask[port] |= mask; + else + gameportmask[port] &= ~mask; + if (old != gameportmask[port]) + RPPostMessagex (RPIPCGM_DEVICEACTIVITY, MAKEWORD (RP_DEVICE_INPUTPORT, port), + gameportmask[port], &guestinfo); +} + void rp_hd_activity (int num, int onoff, int write) { if (!cando ()) diff --git a/od-win32/rp.h b/od-win32/rp.h index 42564193..bce81613 100644 --- a/od-win32/rp.h +++ b/od-win32/rp.h @@ -3,15 +3,7 @@ extern HRESULT rp_init (void); extern void rp_free (void); extern int rp_close (void); extern void rp_fixup_options (struct uae_prefs*); -extern void rp_update_volume (struct uae_prefs*); extern void rp_pause (int paused); -extern void rp_update_leds (int, int, int); -extern void rp_floppy_track (int floppy, int track); -extern void rp_floppydrive_change (int num, int removed); -extern void rp_hd_activity (int, int, int); -extern void rp_hd_change (int, int); -extern void rp_cd_activity (int, int); -extern void rp_cd_change (int, int); extern void rp_activate (int, LPARAM); extern void rp_mouse_capture (int); extern void rp_mouse_magic (int); @@ -32,6 +24,16 @@ extern int rp_inputmode; extern int log_rp; extern void rp_input_change (int num); -extern void rp_disk_image_change (int num, const TCHAR *name); +extern void rp_disk_image_change (int num, const TCHAR *name, bool writeprotected); extern void rp_harddrive_image_change (int num, const TCHAR *name); extern void rp_cd_image_change (int num, const TCHAR *name); + +extern void rp_update_gameport (int port, int mask, int onoff); +extern void rp_update_volume (struct uae_prefs*); +extern void rp_update_leds (int, int, int); +extern void rp_floppy_track (int floppy, int track); +extern void rp_floppydrive_change (int num, int removed); +extern void rp_hd_activity (int, int, int); +extern void rp_hd_change (int, int); +extern void rp_cd_activity (int, int); +extern void rp_cd_change (int, int); diff --git a/od-win32/threaddep/thread.h b/od-win32/threaddep/thread.h index 6d786b31..11428971 100644 --- a/od-win32/threaddep/thread.h +++ b/od-win32/threaddep/thread.h @@ -7,7 +7,7 @@ extern int uae_sem_trywait (uae_sem_t*); extern void uae_sem_post (uae_sem_t*); extern void uae_sem_wait (uae_sem_t*t); extern void uae_sem_init (uae_sem_t*, int manual_reset, int initial_state); -extern int uae_start_thread (TCHAR *name, void *(*f)(void *), void *arg, uae_thread_id *thread); +extern int uae_start_thread (const TCHAR *name, void *(*f)(void *), void *arg, uae_thread_id *thread); extern int uae_start_thread_fast (void *(*f)(void *), void *arg, uae_thread_id *thread); extern void uae_end_thread (uae_thread_id *thread); extern void uae_set_thread_priority (uae_thread_id *, int); diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 212d285e..6b572367 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -1477,7 +1477,7 @@ static LRESULT CALLBACK MainWindowProc (HWND hWnd, UINT message, WPARAM wParam, } else { oc = SetTextColor (lpDIS->hDC, GetSysColor ((tflags & 2) ? COLOR_BTNTEXT : COLOR_GRAYTEXT)); } - flags = DT_VCENTER | DT_SINGLELINE ; + flags = DT_VCENTER | DT_SINGLELINE; if (tflags & 1) { flags |= DT_CENTER; lpDIS->rcItem.left++; @@ -1668,39 +1668,39 @@ static int WIN32_RegisterClasses (void) g_dwBackgroundColor = RGB (255, 0, 255); ReleaseDC (NULL, hDC); - wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_DBLCLKS | CS_OWNDC; + wc.style = CS_DBLCLKS | CS_OWNDC; wc.lpfnWndProc = AmigaWindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; wc.hInstance = hInst; wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE (IDI_APPICON)); - wc.hCursor = NULL; //LoadCursor (NULL, IDC_ARROW); + wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.lpszMenuName = 0; wc.lpszClassName = L"AmigaPowah"; wc.hbrBackground = CreateSolidBrush (g_dwBackgroundColor); if (!RegisterClass (&wc)) return 0; - wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = MainWindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; wc.hInstance = hInst; wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE (IDI_APPICON)); - wc.hCursor = NULL; //LoadCursor (NULL, IDC_ARROW); + wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground = CreateSolidBrush (black); wc.lpszMenuName = 0; wc.lpszClassName = L"PCsuxRox"; if (!RegisterClass (&wc)) return 0; - wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW; + wc.style = 0; wc.lpfnWndProc = HiddenWindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; wc.hInstance = hInst; wc.hIcon = LoadIcon (GetModuleHandle (NULL), MAKEINTRESOURCE (IDI_APPICON)); - wc.hCursor = NULL; //LoadCursor (NULL, IDC_ARROW); + wc.hCursor = NULL; wc.hbrBackground = CreateSolidBrush (g_dwBackgroundColor); wc.lpszMenuName = 0; wc.lpszClassName = L"Useless"; @@ -2101,6 +2101,9 @@ void fullpath (TCHAR *path, int size) { if (path[0] == 0 || (path[0] == '\\' && path[1] == '\\') || path[0] == ':') return; + /* : is supposed to mean same as :\ */ + if (_istalpha (path[0]) && path[1] == ':' && path[2] == 0) + _tcscat (path, L"\\"); if (relativepaths) { TCHAR tmp1[MAX_DPATH], tmp2[MAX_DPATH]; tmp1[0] = 0; @@ -4267,6 +4270,11 @@ static int parseargs (const TCHAR *argx, const TCHAR *np, const TCHAR *np2) log_scsi = 1; return 1; } + if (!_tcscmp (arg, L"scsiemulog")) { + extern int log_scsiemu; + log_scsiemu = 1; + return 1; + } if (!_tcscmp (arg, L"netlog")) { log_net = 1; return 1; diff --git a/od-win32/win32.h b/od-win32/win32.h index 80613cfb..28e7a8f4 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"10" -#define WINUAEDATE MAKEBD(2010, 8, 11) +#define WINUAEBETA L"12" +#define WINUAEDATE MAKEBD(2010, 8, 21) #define WINUAEEXTRA L"" #define WINUAEREV L"" diff --git a/od-win32/win32_scaler.cpp b/od-win32/win32_scaler.cpp index f38347e9..0828033e 100644 --- a/od-win32/win32_scaler.cpp +++ b/od-win32/win32_scaler.cpp @@ -796,6 +796,8 @@ int S2X_getmult (void) { if (!usedfilter) return 1; + if (screen_is_picasso) + return 1; return usedfilter->intmul; } diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index d7a5c249..a72e1731 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -2524,7 +2524,7 @@ static BOOL doInit (void) #ifdef D3D if (currentmode->flags & DM_D3D) { const TCHAR *err = D3D_init (hAmigaWnd, currentmode->native_width, currentmode->native_height, - currentmode->amiga_width, currentmode->amiga_height, currentmode->current_depth, currprefs.gfx_filter_filtermode + 1); + currentmode->amiga_width, currentmode->amiga_height, currentmode->current_depth, screen_is_picasso ? 1 : currprefs.gfx_filter_filtermode + 1); if (err) { D3D_free (); gui_message (err); diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 25cde563..3efe556d 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -9709,10 +9709,10 @@ static void addallfloppies (HWND hDlg) addfloppyhistory (hDlg); } -static void floppysetwriteprotect (HWND hDlg, int n, int protect) +static void floppysetwriteprotect (HWND hDlg, int n, bool writeprotected) { if (!iscd (n)) { - disk_setwriteprotect (n, workprefs.floppyslots[n].df, protect); + disk_setwriteprotect (n, workprefs.floppyslots[n].df, writeprotected); addfloppytype (hDlg, n); } } @@ -14208,10 +14208,10 @@ void check_prefs_changed_gui (void) { } -void gui_disk_image_change (int unitnum, const TCHAR *name) +void gui_disk_image_change (int unitnum, const TCHAR *name, bool writeprotected) { #ifdef RETROPLATFORM - rp_disk_image_change (unitnum, name); + rp_disk_image_change (unitnum, name, writeprotected); #endif } diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 0d7c2a09..6ed957fc 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,4 +1,36 @@ +Beta 12: + +- : without '\' in harddrive paths was detected as a relative path, + automatically add missing '\', it was commonly used in old config files +- CD32 pad in 2-button mode usually returned non-existing 3rd button pressed +- CD32 pad in 2-button mode didn't have pullup resistor emulation (was lost when + joystick pullups were removed in 2.2) +- autocorrect CD32/CDTV CDA starting position if R-W subchannel data is detected, workaround + for a bug (happens on real CD32 and CDTV too) that can cause missed subchannel frames at + play startup causing corrupt or missing CD+G graphics +- CD thread safety critical sections moved to common part from image mounter +- CD image mounter in play state while replacing image: state was still reported as playing +- do not enable rawinput if rawinput capable device is inserted after winuae has been started +- 2x or larger filters changed RTG hardware mouse cursor size.. (D3D + hardware RTG cursor only) +- scsi emulation always-on logging disabled, added -scsiemulog command line parameter + +Beta 11: + +- internal CD audio handling update, status change (starting, started, end, error) callback + added, CD32 and CDTV emulation does not poll for state changes anymore, better accuracy + in audio start and end timing. CD handling rewrite should be complete now. +- CD image mounter is now thread safe, no more weird and random behavior if mounted image was + in use and image was ejected or replaced +- fixed rare crash in display emulation (introduced when right border blanking update was added) +- improved CD32 CD sound/animation timing +- CD32 CD timing now works correctly in NTSC mode (previously used hardcoded PAL values) +- "non-path" kickstart rom configuration file selection now only allows normal KS roms in + kickstart_rom variable and extended roms in kickstart_rom_ext variable +- fixed D3D non-shader mode crash introduced in b9 +- bogus autofire mode was enabled if same joystick was custom configured in input panel and in gameports panel + (missing masking of flags variable, time to wear brown paper bag again..) + Beta 10: - archive dragndrop worked too well, it unpacked everything, including adf filesystem etc.. diff --git a/prowizard/rippers/ProPacker10.c b/prowizard/rippers/ProPacker10.c index 7de0711b..22386296 100644 --- a/prowizard/rippers/ProPacker10.c +++ b/prowizard/rippers/ProPacker10.c @@ -32,7 +32,7 @@ short testPP10 ( void ) PW_l = (((in_data[PW_Start_Address+PW_j*8+4]*256)+in_data[PW_Start_Address+5+PW_j*8])*2); /* loop size */ PW_m = (((in_data[PW_Start_Address+PW_j*8+6]*256)+in_data[PW_Start_Address+7+PW_j*8])*2); - if ( (PW_m == 0) || (PW_m == PW_l) ) + if ( PW_m == 0 ) { /*printf ( "#1,98 (start:%ld) (PW_k:%ld) (PW_l:%ld) (PW_m:%ld)\n" , PW_Start_Address,PW_k,PW_l,PW_m );*/ return BAD; @@ -78,6 +78,7 @@ short testPP10 ( void ) return BAD; } } + if ( PW_WholeSampleSize <= 2 ) { /*printf ( "#2,4 (start:%ld)\n" , PW_Start_Address );*/ @@ -107,9 +108,9 @@ short testPP10 ( void ) if ( PW_Start_Address + 762 + (PW_k*4) > PW_in_size ) { +/*printf ( "#4 (start:%ld)\n" , PW_Start_Address );*/ return BAD; } - /* track data test */ PW_l=0; for ( PW_j=0 ; PW_j Max ) - Max = Tracks_Numbers[j][i]; - } + ReadPat[i] = (in_data[Where+i]*256*256*256) + + (in_data[Where+i+128]*256*256) + + (in_data[Where+i+256]*256) + + in_data[Where+i+384]; + ReadTrkPat[i][0] = in_data[Where+i]; + ReadTrkPat[i][1] = in_data[Where+i+128]; + ReadTrkPat[i][2] = in_data[Where+i+256]; + ReadTrkPat[i][3] = in_data[Where+i+384]; + if (ReadTrkPat[i][0] > Highest_Track) + Highest_Track = ReadTrkPat[i][0]; + if (ReadTrkPat[i][1] > Highest_Track) + Highest_Track = ReadTrkPat[i][1]; + if (ReadTrkPat[i][2] > Highest_Track) + Highest_Track = ReadTrkPat[i][2]; + if (ReadTrkPat[i][3] > Highest_Track) + Highest_Track = ReadTrkPat[i][3]; + /*printf ("%x-%x-%x-%x\n",ReadTrkPat[i][0],ReadTrkPat[i][1],ReadTrkPat[i][2],ReadTrkPat[i][3]);*/ + } + /*printf ( "Number of tracks : %d\n" , Highest_Track+1 );*/ + + /* sorting ?*/ + k = 0; /* next min */ + l = 0; + + /* put the first pattern number */ + /* could be stored several times */ + for (j=0; jk)) + m = ReadPat[i]; + /* if k == m then an already existing ref was found */ + if (k==m) + continue; + /* m is the next minimum */ + k = m; + for (i=0; i Highest_Track) Highest_Track = ReadTrkPat[i][3]; - /*printf ("%x-%x-%x-%x\n",ReadTrkPat[i][0],ReadTrkPat[i][1],ReadTrkPat[i][2],ReadTrkPat[i][3]);*/ + /*fprintf (info,"%x-%x-%x-%x (%ld)\n",ReadTrkPat[i][0],ReadTrkPat[i][1],ReadTrkPat[i][2],ReadTrkPat[i][3],ReadPat[i]);*/ } - /*printf ( "Number of tracks : %d\n" , Highest_Track+1 );*/ + /*fprintf ( info,"Number of tracks : %d\n\n" , Highest_Track+1 );*/ /* sorting ?*/ k = 0; /* next min */ @@ -234,7 +238,10 @@ void Depack_PP21 ( void ) Header[952+i] = (unsigned char)l; l++; } - + if ( l != Header[950] ) + l -= 1; + /*fprintf (info,"number of pattern stored : %ld\n\n",l);*/ + //fflush (info); /* write ptk's ID */ Header[1080] = 'M'; @@ -251,10 +258,11 @@ void Depack_PP21 ( void ) /* l is the number of stored patterns */ /* rebuild pattern data now */ whereTableRef = ((Highest_Track + 1)*128) + 4 + Where; - printf ( "\nwhereTableRef : %ld\n",whereTableRef); - for (i=0;i Max ) - Max = Tracks_Numbers[j][i]; - } + ReadPat[i] = (in_data[Where+i]*256*256*256) + + (in_data[Where+i+128]*256*256) + + (in_data[Where+i+256]*256) + + in_data[Where+i+384]; + ReadTrkPat[i][0] = in_data[Where+i]; + ReadTrkPat[i][1] = in_data[Where+i+128]; + ReadTrkPat[i][2] = in_data[Where+i+256]; + ReadTrkPat[i][3] = in_data[Where+i+384]; + if (ReadTrkPat[i][0] > Highest_Track) + Highest_Track = ReadTrkPat[i][0]; + if (ReadTrkPat[i][1] > Highest_Track) + Highest_Track = ReadTrkPat[i][1]; + if (ReadTrkPat[i][2] > Highest_Track) + Highest_Track = ReadTrkPat[i][2]; + if (ReadTrkPat[i][3] > Highest_Track) + Highest_Track = ReadTrkPat[i][3]; + /*printf ("%x-%x-%x-%x\n",ReadTrkPat[i][0],ReadTrkPat[i][1],ReadTrkPat[i][2],ReadTrkPat[i][3]);*/ } + /*printf ( "Number of tracks : %d\n" , Highest_Track+1 );*/ - /* write pattern table without any optimizing ! */ - for ( c1=0x00 ; c1k)) + m = ReadPat[i]; + /* if k == m then an already existing ref was found */ + if (k==m) + continue; + /* m is the next minimum */ + k = m; + for (i=0; iname)) ok = 2; - if (rd->ver == ver && (rev < 0 || rd->rev == rev)) { + if ((ver < 0 || rd->ver == ver) && (rev < 0 || rd->rev == rev)) { if (subver >= 0) { if (rd->subver == subver && (subrev < 0 || rd->subrev == subrev) && rd->subver > 0) ok = 1; @@ -419,7 +419,7 @@ struct romlist **getromlistbyident (int ver, int rev, int subver, int subrev, co if (model && ok < 2) { TCHAR *p = rd->model; ok = 0; - while (*p) { + while (p && *p) { if (!_tcscmp(rd->model, model)) { ok = 1; break; @@ -427,7 +427,7 @@ struct romlist **getromlistbyident (int ver, int rev, int subver, int subrev, co p = p + _tcslen(p) + 1; } } - if (!model && rd->type != ROMTYPE_KICK) + if (romflags && (rd->type & romflags) == 0) ok = 0; if (ok) { if (all) { diff --git a/scsiemul.cpp b/scsiemul.cpp index 07661857..082d0df9 100644 --- a/scsiemul.cpp +++ b/scsiemul.cpp @@ -707,7 +707,7 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) } } } else { - io_error = CDERR_NotSpecified; + io_error = IOERR_NotSpecified; } } break; @@ -846,7 +846,7 @@ static int dev_do_io (struct devstruct *dev, uaecptr request) put_long (io_data + 8, diskpos); io_actual = 12; } else { - io_error = CDERR_InvalidState; + io_error = IOERR_InvalidState; } } else { io_error = IOERR_BADADDRESS; -- 2.47.3