]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
2600b2
authorToni Wilen <twilen@winuae.net>
Sun, 20 Jan 2013 13:37:53 +0000 (15:37 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 20 Jan 2013 13:37:53 +0000 (15:37 +0200)
40 files changed:
a2091.cpp
blkdev.cpp
blkdev_cdimage.cpp
cdtv.cpp
cfgfile.cpp
consolehook.cpp
cpummu.cpp
cpummu30.cpp
custom.cpp
debug.cpp
expansion.cpp
filesys.cpp
gayle.cpp
gencpu.cpp
hardfile.cpp
include/a2091.h
include/autoconf.h
include/blkdev.h
include/cdtv.h
include/cpummu.h
include/cpummu030.h
include/gui.h
include/mmu_common.h
include/options.h
include/scsi.h
memory.cpp
newcpu.cpp
od-win32/gencomp_msvc/gencomp_msvc.vcxproj
od-win32/mman.cpp
od-win32/resources/RCa02620 [new file with mode: 0644]
od-win32/resources/RCa06412 [new file with mode: 0644]
od-win32/resources/RCb02620 [new file with mode: 0644]
od-win32/resources/RCb06412 [new file with mode: 0644]
od-win32/resources/resource.h
od-win32/resources/winuae.rc
od-win32/win32.h
od-win32/win32gui.cpp
od-win32/winuaechangelog.txt
rommgr.cpp
scsi.cpp

index d19dcfcf417971e4f2f7958067856f2fc1e185ef..e9b1c3b68db422ccdf4a5ac025bc4254e5594698 100644 (file)
--- a/a2091.cpp
+++ b/a2091.cpp
@@ -9,7 +9,7 @@
 
 #define A2091_DEBUG 0
 #define A3000_DEBUG 0
-#define WD33C93_DEBUG 1
+#define WD33C93_DEBUG 0
 #define WD33C93_DEBUG_PIO 0
 
 #include "sysconfig.h"
@@ -340,7 +340,7 @@ static TCHAR *scsitostring (void)
 
        p = buf;
        p[0] = 0;
-       for (i = 0; i < gettc () && i < sizeof wd_data; i++) {
+       for (i = 0; i < scsi->offset && i < sizeof wd_data; i++) {
                if (i > 0) {
                        _tcscat (p, _T("."));
                        p++;
@@ -418,7 +418,7 @@ static bool do_dma (void)
 static bool wd_do_transfer_out (void)
 {
 #if WD33C93_DEBUG > 0
-       write_log (_T("%s SCSI O [%02X] %d/%d %s\n"), WD33C93, wdregs[WD_COMMAND_PHASE], wd_dataoffset, gettc (), scsitostring ());
+       write_log (_T("%s SCSI O [%02X] %d/%d TC=%d %s\n"), WD33C93, wdregs[WD_COMMAND_PHASE], scsi->offset, scsi->data_len, gettc (), scsitostring ());
 #endif
        if (wdregs[WD_COMMAND_PHASE] < 0x20) {
                /* message was sent */
@@ -775,6 +775,9 @@ static void wd_cmd_reset (bool irq)
                wdregs[0] &= ~(0x08 | 0x10);
        sasr = 0;
        wd_selected = false;
+       scsi = NULL;
+       scsidelay_irq[0] = 0;
+       scsidelay_irq[1] = 0;
        if (irq)
                set_status ((wdregs[0] & 0x08) ? 1 : 0, 200);
 }
@@ -840,7 +843,7 @@ void wdscsi_put (uae_u8 d)
 #endif
        } else if (sasr == WD_DATA) {
 #if WD33C93_DEBUG_PIO
-               write_log (_T("%s WD_DATA WRITE %02x %d/%d,%d\n"), WD33C93, d, wd_dataoffset, scsi->len, scsi->data_len);
+               write_log (_T("%s WD_DATA WRITE %02x %d/%d\n"), WD33C93, d, scsi->offset, scsi->data_len);
 #endif
                if (!wd_data_avail) {
                        write_log (_T("%s WD_DATA WRITE without data request!?\n"), WD33C93);
@@ -913,7 +916,7 @@ uae_u8 wdscsi_get (void)
                }
                int status = scsi_receive_data (scsi, &v);
 #if WD33C93_DEBUG_PIO
-               write_log (_T("%s WD_DATA READ %02x %d/%d,%d\n"), WD33C93, v, wd_dataoffset, scsi->len, scsi->data_len);
+               write_log (_T("%s WD_DATA READ %02x %d/%d\n"), WD33C93, v, scsi->offset, scsi->data_len);
 #endif
                if (wd_dataoffset < sizeof wd_data)
                        wd_data[wd_dataoffset] = v;
@@ -1532,7 +1535,7 @@ static void freescsi (struct scsi_data *sd)
        scsi_free (sd);
 }
 
-int addscsi (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int scsi_level)
+int add_scsi_hd (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int scsi_level)
 {
        freescsi (scsis[ch]);
        scsis[ch] = NULL;
@@ -1543,7 +1546,15 @@ int addscsi (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci,
        if (!hdf_hd_open (hfd))
                return 0;
        hfd->ansi_version = scsi_level;
-       scsis[ch] = scsi_alloc (ch, hfd);
+       scsis[ch] = scsi_alloc_hd (ch, hfd);
+       return scsis[ch] ? 1 : 0;
+}
+
+int add_scsi_cd (int ch, int unitnum)
+{
+       device_func_init (0);
+       freescsi (scsis[ch]);
+       scsis[ch] = scsi_alloc_cd (ch, unitnum);
        return scsis[ch] ? 1 : 0;
 }
 
@@ -1605,7 +1616,10 @@ static void addnativescsi (void)
 
 int a3000_add_scsi_unit (int ch, struct uaedev_config_info *ci)
 {
-       return addscsi (ch, NULL, ci, 2);
+       if (ci->cd_emu_unit >= 0)
+               return add_scsi_cd (ch, ci->cd_emu_unit);
+       else
+               return add_scsi_hd (ch, NULL, ci, 2);
 }
 
 void a3000scsi_reset (void)
@@ -1621,7 +1635,10 @@ void a3000scsi_free (void)
 
 int a2091_add_scsi_unit (int ch, struct uaedev_config_info *ci)
 {
-       return addscsi (ch, NULL, ci, 1);
+       if (ci->cd_emu_unit >= 0)
+               return add_scsi_cd (ch, ci->cd_emu_unit);
+       else
+               return add_scsi_hd (ch, NULL, ci, 1);
 }
 
 
@@ -1759,6 +1776,8 @@ uae_u8 *save_scsi_hd (int num, int *len, uae_u8 *dstptr)
        if (!scsis[num])
                return NULL;
        s = scsis[num];
+       if (s->hfd == NULL)
+               return NULL;
        if (dstptr)
                dstbak = dst = dstptr;
        else
@@ -1794,7 +1813,7 @@ uae_u8 *restore_scsi_hd (uae_u8 *src)
        num = restore_u32 ();
 
        hfd = xcalloc (struct hd_hardfiledata, 1);
-       s = scsis[num] = scsi_alloc (num, hfd);
+       s = scsis[num] = scsi_alloc_hd (num, hfd);
        restore_u32 ();
        size = restore_u64 ();
        path = restore_string ();
@@ -1812,7 +1831,7 @@ uae_u8 *restore_scsi_hd (uae_u8 *src)
        s->hfd->ansi_version = restore_u32 ();
 
        if (size) {
-               addscsi (num, hfd, NULL, s->hfd->ansi_version);
+               add_scsi_hd (num, hfd, NULL, s->hfd->ansi_version);
        }
        xfree (path);
        return src;
index a8d62c042f789dcab4f07c363af81c3c1ac9046a..3b1490b93019f1ed4af3cbb9899e82964e2ba8e6 100644 (file)
@@ -43,6 +43,7 @@ static TCHAR newimagefiles[MAX_TOTAL_SCSI_DEVICES][256];
 static int imagechangetime[MAX_TOTAL_SCSI_DEVICES];
 static bool cdimagefileinuse[MAX_TOTAL_SCSI_DEVICES];
 static int wasopen[MAX_TOTAL_SCSI_DEVICES];
+static bool dev_init;
 
 /* convert minutes, seconds and frames -> logical sector number */
 int msf2lsn (int msf)
@@ -324,16 +325,16 @@ static int getunitinfo (int unitnum, int drive, cd_standard_unit csu, int *isaud
        return 0;
 }
 
-static int get_standard_cd_unit2 (cd_standard_unit csu)
+static int get_standard_cd_unit2 (struct uae_prefs *p, cd_standard_unit csu)
 {
        int unitnum = 0;
        int isaudio = 0;
-       if (currprefs.cdslots[unitnum].name[0] || currprefs.cdslots[unitnum].inuse) {
-               if (currprefs.cdslots[unitnum].name[0]) {
+       if (p->cdslots[unitnum].name[0] || p->cdslots[unitnum].inuse) {
+               if (p->cdslots[unitnum].name[0]) {
                        device_func_init (SCSI_UNIT_IOCTL);
-                       if (!sys_command_open_internal (unitnum, currprefs.cdslots[unitnum].name, csu)) {
+                       if (!sys_command_open_internal (unitnum, p->cdslots[unitnum].name, csu)) {
                                device_func_init (SCSI_UNIT_IMAGE);
-                               if (!sys_command_open_internal (unitnum, currprefs.cdslots[unitnum].name, csu))
+                               if (!sys_command_open_internal (unitnum, p->cdslots[unitnum].name, csu))
                                        goto fallback;
                        }
                } else {
@@ -371,7 +372,7 @@ fallback:
 
 int get_standard_cd_unit (cd_standard_unit csu)
 {
-       int unitnum = get_standard_cd_unit2 (csu);
+       int unitnum = get_standard_cd_unit2 (&currprefs, csu);
        if (unitnum < 0)
                return -1;
 #ifdef RETROPLATFORM
@@ -396,6 +397,12 @@ int sys_command_isopen (int unitnum)
 
 int sys_command_open (int unitnum)
 {
+       blkdev_fix_prefs (&currprefs);
+       if (!dev_init) {
+               device_func_init (0);
+               dev_init = true;
+       }
+
        if (openlist[unitnum]) {
                openlist[unitnum]++;
                return -1;
@@ -449,6 +456,23 @@ int device_func_init (int flags)
        return 1;
 }
 
+bool blkdev_get_info (struct uae_prefs *p, int unitnum, struct device_info *di)
+{
+       bool open = true, opened = true, ok = false;
+       if (!openlist[unitnum]) {
+               blkdev_fix_prefs (p);
+               install_driver (0);
+               opened = true;
+               open = sys_command_open_internal (unitnum, p->cdslots[unitnum].name[0] ? p->cdslots[unitnum].name : NULL, CD_STANDARD_UNIT_DEFAULT) != 0;
+       }
+       if (open) {
+               ok = sys_command_info (unitnum, di, true) != 0;
+       }
+       if (open && opened)
+               sys_command_close_internal (unitnum);
+       return ok;
+}
+
 void blkdev_entergui (void)
 {
        for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
@@ -1121,7 +1145,7 @@ static int scsi_read_cd (int unitnum, uae_u8 *cmd, uae_u8 *data, struct device_i
        return sys_command_cd_rawread (unitnum, data, start, len, 0, (cmd[1] >> 2) & 7, cmd[9], subs);
 }
 
-static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
+int scsi_cd_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
        uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len)
 {
        uae_u64 len, offset;
@@ -1150,14 +1174,21 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
                        scsi_cmd_len, scsi_data, *data_len);
        switch (cmdbuf[0])
        {
+       case 0x03: /* REQUEST SENSE */
+               break;
+       case 0x1e: /* PREVENT/ALLOW MEDIUM REMOVAL */
+               scsi_len = 0;
+               break;
        case 0x12: /* INQUIRY */
        {
                if ((cmdbuf[1] & 1) || cmdbuf[2] != 0)
                        goto err;
                len = cmdbuf[4];
-               if (cmdbuf[1] >> 5)
-                       goto err;
-               r[0] = 5; // CDROM
+               if (cmdbuf[1] >> 5) {
+                       r[0] = 0x7f;
+               } else {
+                       r[0] = 5; // CDROM
+               }
                r[1] |= 0x80; // removable
                r[2] = 2; /* supports SCSI-2 */
                r[3] = 2; /* response data format */
@@ -1414,6 +1445,61 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
        break;
        case 0xaa: /* WRITE (12) */
                goto readprot;
+       case 0x51: /* READ DISC INFORMATION */
+               {
+                       struct cd_toc_head ttoc;
+                       int maxlen = (cmdbuf[7] << 8) | cmdbuf[8];
+                       if (nodisk (&di))
+                               goto nodisk;
+                       if (!sys_command_cd_toc (unitnum, &ttoc))
+                               goto readerr;
+                       struct cd_toc_head *toc = &ttoc;
+                       uae_u8 *p = scsi_data;
+                       p[0] = 0;
+                       p[1] = 34 - 2;
+                       p[2] = 2 | (3 << 2); // complete cd rom, last session is complete
+                       p[3] = toc->first_track;
+                       p[4] = 1;
+                       p[5] = toc->first_track;
+                       p[6] = toc->last_track;
+                       wl (p + 16, lsn2msf (toc->lastaddress));
+                       wl (p + 20, 0x00ffffff);
+                       scsi_len = p[1] + 2;
+                       if (scsi_len > maxlen)
+                               scsi_len = maxlen;
+               }
+               break;
+       case 0x52: /* READ TRACK INFORMATION */
+               {
+                       struct cd_toc_head ttoc;
+                       int maxlen = (cmdbuf[7] << 8) | cmdbuf[8];
+                       if (nodisk (&di))
+                               goto nodisk;
+                       if (!sys_command_cd_toc (unitnum, &ttoc))
+                               goto readerr;
+                       struct cd_toc_head *toc = &ttoc;
+                       uae_u8 *p = scsi_data;
+                       int lsn;
+                       if (cmdbuf[1] & 1) {
+                               int track = cmdbuf[5];
+                               lsn = toc->toc[track].address;
+                       } else {
+                               lsn = rl (p + 2);
+                       }
+                       struct cd_toc *t = gettoc (toc, lsn);
+                       p[0] = 0;
+                       p[1] = 28 - 2;
+                       p[2] = t->track;
+                       p[3] = 1;
+                       p[5] = t->control;
+                       p[6] = 0; // data mode, fixme
+                       wl (p + 8, t->address);
+                       wl (p + 24, t[1].address - t->address);
+                       scsi_len = p[1] + 2;
+                       if (scsi_len > maxlen)
+                               scsi_len = maxlen;
+               }
+               break;
        case 0x43: // READ TOC
                {
                        if (nodisk (&di))
@@ -1425,6 +1511,7 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
                        if (format >= 3)
                                goto errreq;
                        int maxlen = (cmdbuf[7] << 8) | cmdbuf[8];
+                       int maxlen2 = maxlen;
                        struct cd_toc_head ttoc;
                        if (!sys_command_cd_toc (unitnum, &ttoc))
                                goto readerr;
@@ -1458,23 +1545,24 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
                                maxlen -= 4;
                                if (format == 2) {
                                        if (!addtocentry (&p2, &maxlen, 0xa0, -1, msf, p, toc))
-                                               goto errreq;
+                                               break;
                                        if (!addtocentry (&p2, &maxlen, 0xa1, -1, msf, p, toc))
-                                               goto errreq;
+                                               break;
                                        if (!addtocentry (&p2, &maxlen, 0xa2, -1, msf, p, toc))
-                                               goto errreq;
+                                               break;
                                }
                                while (strack < 100) {
                                        if (!addtocentry (&p2, &maxlen, strack, -1, msf, p, toc))
-                                               goto errreq;
+                                               break;
                                        strack++;
                                }
-                               if (!addtocentry (&p2, &maxlen, 0xa2, 0xaa, msf, p, toc))
-                                       goto errreq;
+                               addtocentry (&p2, &maxlen, 0xa2, 0xaa, msf, p, toc);                            
                                int tlen = p2 - (p + 2);
                                p[0] = tlen >> 8;
                                p[1] = tlen >> 0;
-                               scsi_len = tlen + 2 + 4;
+                               scsi_len = tlen + 2;
+                               if (scsi_len > maxlen2)
+                                       scsi_len = maxlen2;
                        }
                }
                break;
@@ -1524,10 +1612,6 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
                        scsiemudrv (unitnum, cmdbuf);
                        scsi_len = 0;
                break;
-               case 0x1e: // PREVENT/ALLOW MEDIA REMOVAL
-                       // do nothing
-                       scsi_len = 0;
-               break;
                case 0x4e: // STOP PLAY/SCAN
                        if (nodisk (&di))
                                goto nodisk;
@@ -1635,7 +1719,7 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
                                goto nodisk;
                        int start = rl (cmdbuf + 2);
                        int len;
-                       if (cmd = 0xa5)
+                       if (cmd == 0xa5)
                                len = rl (cmdbuf + 6);
                        else
                                len = rw (cmdbuf + 7);
@@ -1762,7 +1846,7 @@ static int execscsicmd_direct (int unitnum, struct amigascsi *as)
        if (as->sense_len > 32)
                as->sense_len = 32;
 
-       as->status = scsi_emulate (unitnum, cmd, as->cmd_len, scsi_datap, &datalen, replydata, &replylen, as->sensedata, &senselen);
+       as->status = scsi_cd_emulate (unitnum, cmd, as->cmd_len, scsi_datap, &datalen, replydata, &replylen, as->sensedata, &senselen);
 
        as->cmdactual = as->status != 0 ? 0 : as->cmd_len; /* fake scsi_CmdActual */
        if (as->status) {
index 23c527a27129d1554b8378f2014d297291a1c7ce..ffdbfafe233e3047e67784d61b9009569ff621f0 100644 (file)
@@ -86,8 +86,7 @@ struct cdunit {
        play_status_callback cdda_statusfunc;
        int cdda_delay, cdda_delay_frames;
 
-       int imagechange;
-       TCHAR newfile[MAX_DPATH];
+       TCHAR imgname[MAX_DPATH];
        uae_sem_t sub_sem;
        struct device_info di;
        chd_file *chd_f;
@@ -1705,7 +1704,7 @@ static struct device_info *info_device (int unitnum, struct device_info *di, int
        di->sectorspertrack = (int)(cdu->cdsize / di->bytespersector);
        if (ismedia (unitnum, 1)) {
                di->media_inserted = 1;
-               _tcscpy (di->mediapath, currprefs.cdslots[unitnum].name);
+               _tcscpy (di->mediapath, cdu->imgname);
        }
        memset (&di->toc, 0, sizeof (struct cd_toc_head));
        command_toc (unitnum, &di->toc);
@@ -1718,6 +1717,9 @@ static struct device_info *info_device (int unitnum, struct device_info *di, int
        } else {
                _tcscpy (di->label, _T("IMG:<EMPTY>"));
        }
+       _tcscpy (di->vendorid, _T("UAE"));
+       _stprintf (di->productid, _T("SCSICD%d"), unitnum);
+       _tcscpy (di->revision, _T("1.0"));
        di->backend = _T("IMAGE");
        return di;
 }
@@ -1737,8 +1739,10 @@ static void unload_image (struct cdunit *cdu)
                xfree (t->extrainfo);
        }
        cdrom_close (cdu->chd_cdf);
+       cdu->chd_cdf = NULL;
        if (cdu->chd_f)
                cdu->chd_f->close();
+       cdu->chd_f = NULL;
        memset (cdu->toc, 0, sizeof cdu->toc);
        cdu->tracks = 0;
        cdu->cdsize = 0;
@@ -1752,6 +1756,7 @@ static int open_device (int unitnum, const TCHAR *ident, int flags)
 
        if (!cdu->open) {
                uae_sem_init (&cdu->sub_sem, 0, 1);
+               _tcscpy (cdu->imgname, ident);
                parse_image (cdu, ident);
                cdu->open = true;
                cdu->enabled = true;
index d8254914dd26a2d1ac81968392cae001bd911215..e49c9a80c5e57ed7f19f06cc73cdb76f796e45b4 100644 (file)
--- a/cdtv.cpp
+++ b/cdtv.cpp
@@ -1656,9 +1656,9 @@ uae_u8 cdtv_battram_read (int addr)
        return v;
 }
 
-int cdtv_add_scsi_unit (int ch, struct uaedev_config_info *ci)
+int cdtv_add_scsi_hd_unit (int ch, struct uaedev_config_info *ci)
 {
-       return addscsi (ch, NULL, ci, 1);
+       return add_scsi_hd (ch, NULL, ci, 1);
 }
 
 void cdtv_free (void)
index 09e4acea39ade732258a6b0032753421a6bd95e5..b9437a637eaf12daa449d8d639a1748eff28149d 100644 (file)
@@ -533,7 +533,7 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
                if (ci->donotmount)
                        bp = -129;
                str = cfgfile_put_multipath (&p->path_hardfile, ci->rootdir);
-               if (!uci->ishdf) {
+               if (ci->type == UAEDEV_DIR) {
                        _stprintf (tmp, _T("%s,%s:%s:%s,%d"), ci->readonly ? _T("ro") : _T("rw"),
                                ci->devname ? ci->devname : _T(""), ci->volname, str, bp);
                        cfgfile_write_str (f, _T("filesystem2"), tmp);
@@ -542,7 +542,7 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
                                uci->volname, str);
                        zfile_fputs (f, tmp2);
 #endif
-               } else {
+               } else if (ci->type == UAEDEV_HDF || ci->type == UAEDEV_CD) {
                        _stprintf (tmp, _T("%s,%s:%s,%d,%d,%d,%d,%d,%s,%s"),
                                ci->readonly ? _T("ro") : _T("rw"),
                                ci->devname ? ci->devname : _T(""), str,
@@ -556,7 +556,8 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
                                        _stprintf (s, _T(",%d/%d/%d"), ci->pcyls, ci->pheads, ci->psecs);
                                }
                        }
-                       cfgfile_write_str (f, _T("hardfile2"), tmp);
+                       if (ci->type == UAEDEV_HDF)
+                               cfgfile_write_str (f, _T("hardfile2"), tmp);
 #if 0
                        _stprintf (tmp2, _T("hardfile=%s,%d,%d,%d,%d,%s"),
                                uci->readonly ? "ro" : "rw", uci->sectors,
@@ -565,7 +566,11 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
 #endif
                }
                _stprintf (tmp2, _T("uaehf%d"), i);
-               cfgfile_write (f, tmp2, _T("%s,%s"), uci->ishdf ? _T("hdf") : _T("dir"), tmp);
+               if (ci->type == UAEDEV_CD) {
+                       cfgfile_write (f, tmp2, _T("cd%d,%s"), ci->cd_emu_unit, tmp);
+               } else {
+                       cfgfile_write (f, tmp2, _T("%s,%s"), ci->type == UAEDEV_HDF ? _T("hdf") : _T("dir"), tmp);
+               }
                xfree (str);
        }
 }
@@ -2309,7 +2314,7 @@ static struct uaedev_config_data *getuci (struct uae_prefs *p)
        return NULL;
 }
 
-struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, struct uaedev_config_info *ci, bool hdf)
+struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, struct uaedev_config_info *ci)
 {
        struct uaedev_config_data *uci;
        int i;
@@ -2320,8 +2325,18 @@ struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, s
                                return 0;
                }
        }
+       if (ci->type == UAEDEV_CD) {
+               if (ci->controller > HD_CONTROLLER_SCSI6 || ci->controller < HD_CONTROLLER_IDE0)
+                       return NULL;
+       }
 
        if (index < 0) {
+               if (ci->type == UAEDEV_CD) {
+                       for (i = 0; i < p->mountitems; i++) {
+                               if (p->mountconfig[i].ci.type == UAEDEV_CD)
+                                       return 0;
+                       }
+               }
                uci = getuci (p);
                uci->configoffset = -1;
        } else {
@@ -2331,18 +2346,17 @@ struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, s
                return 0;
 
        memcpy (&uci->ci, ci, sizeof (struct uaedev_config_info));
-       uci->ishdf = hdf;
        validatedevicename (uci->ci.devname);
        validatevolumename (uci->ci.volname);
        if (uci->ci.bootpri < -128)
                uci->ci.donotmount = true;
        else if (uci->ci.bootpri >= -127)
                uci->ci.autoboot = true;
-       if (!uci->ci.devname[0]) {
+       if (!uci->ci.devname[0] && ci->type != UAEDEV_CD) {
                TCHAR base[32];
                TCHAR base2[32];
                int num = 0;
-               if (uci->ci.rootdir[0] == 0 && !uci->ishdf)
+               if (uci->ci.rootdir[0] == 0 && ci->type == UAEDEV_DIR)
                        _tcscpy (base, _T("RDH"));
                else
                        _tcscpy (base, _T("DH"));
@@ -2358,7 +2372,7 @@ struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, s
                _tcscpy (uci->ci.devname, base2);
                validatedevicename (uci->ci.devname);
        }
-       if (!uci->ishdf) {
+       if (ci->type == UAEDEV_DIR) {
                TCHAR *s = filesys_createvolname (uci->ci.volname, uci->ci.rootdir, _T("Harddrive"));
                _tcscpy (uci->ci.volname, s);
                xfree (s);
@@ -2496,6 +2510,8 @@ static bool parse_geo (const TCHAR *tname, struct uaedev_config_info *uci, struc
                        uci->flags = v;
                if (!_tcsicmp (key, _T("priority")))
                        uci->priority = v;
+               if (!_tcsicmp (key, _T("forceload")))
+                       uci->forceload = v;
                if (!_tcsicmp (key, _T("bootpri"))) {
                        uci->bootpri = v;
                        uci->donotmount = false;
@@ -2540,7 +2556,7 @@ bool get_hd_geometry (struct uaedev_config_info *uci)
        return false;
 }
 
-static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, bool hdf, TCHAR *value)
+static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, int type, TCHAR *value, int unit, bool uaehfentry)
 {
        struct uaedev_config_info uci;
        TCHAR *tmpp = _tcschr (value, ','), *tmpp2;
@@ -2563,7 +2579,8 @@ static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, bool hdf, TCHA
                goto invalid_fs;
 
        value = tmpp;
-       if (!hdf) {
+       if (type == 0) {
+               uci.type = UAEDEV_DIR;
                tmpp = _tcschr (value, ':');
                if (tmpp == 0)
                        goto empty_fs;
@@ -2585,7 +2602,7 @@ static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, bool hdf, TCHA
                _tcscpy (uci.devname, devname);
                if (! getintval (&tmpp, &uci.bootpri, 0))
                        goto empty_fs;
-       } else {
+       } else if (type == 1 || (type == 2 && uaehfentry)) {
                tmpp = _tcschr (value, ':');
                if (tmpp == 0)
                        goto invalid_fs;
@@ -2624,6 +2641,16 @@ static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, bool hdf, TCHA
                                }
                        }
                }
+               if (type == 2) {
+                       uci.cd_emu_unit = unit;
+                       uci.blocksize = 2048;
+                       uci.readonly = true;
+                       uci.type = UAEDEV_CD;
+               } else {
+                       uci.type = UAEDEV_HDF;
+               }
+       } else {
+               goto invalid_fs;
        }
 empty_fs:
        uci.autoboot = uci.bootpri >= -127; 
@@ -2637,13 +2664,13 @@ empty_fs:
                _tcscpy (uci.rootdir, str);
        }
 #ifdef FILESYS
-       add_filesys_config (p, nr, &uci, hdf);
+       add_filesys_config (p, nr, &uci);
 #endif
        xfree (str);
        return 1;
 
 invalid_fs:
-       write_log (_T("Invalid filesystem/hardfile specification.\n"));
+       write_log (_T("Invalid filesystem/hardfile/cd specification.\n"));
        return 1;
 }
 
@@ -2656,21 +2683,29 @@ static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHA
                _stprintf (tmp, _T("uaehf%d"), i);
                if (_tcscmp (option, tmp) == 0) {
                        for (;;) {
-                               bool hdf = false;
+                               int  type = -1;
+                               int unit = -1;
                                TCHAR *tmpp = _tcschr (value, ',');
                                if (tmpp == NULL)
                                        return 1;
                                *tmpp++ = 0;
-                               if (strcasecmp (value, _T("hdf")) == 0) {
-                                       hdf = true;
-                               } else if (strcasecmp (value, _T("dir")) != 0) {
-                                       return 1;
+                               if (_tcsicmp (value, _T("hdf")) == 0) {
+                                       type = 1;
+                                       return 1; /* ignore for now */
+                               } else if (_tcsnicmp (value, _T("cd"), 2) == 0 && (value[2] == 0 || value[3] == 0)) {
+                                       unit = 0;
+                                       if (value[2] > 0)
+                                               unit = value[2] - '0';
+                                       if (unit >= 0 && unit <= MAX_TOTAL_SCSI_DEVICES) {
+                                               type = 2;
+                                       }
+                               } else if (_tcsicmp (value, _T("dir")) != 0) {
+                                       type = 0;
+                                       return 1;  /* ignore for now */
                                }
-#if 0                  // not yet
-                               return cfgfile_parse_newfilesys (p, i, hdf, tmpp);
-#else
+                               if (type >= 0)
+                                       return cfgfile_parse_newfilesys (p, -1, type, tmpp, unit, true);
                                return 1;
-#endif
                        }
                        return 1;
                } else if (!_tcsncmp (option, tmp, _tcslen (tmp)) && option[_tcslen (tmp)] == '_') {
@@ -2744,7 +2779,8 @@ static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHA
                }
                str = cfgfile_subst_path_load (UNEXPANDED, &p->path_hardfile, uci.rootdir, true);
 #ifdef FILESYS
-               add_filesys_config (p, -1, &uci, hdf);
+               uci.type = hdf ? UAEDEV_HDF : UAEDEV_DIR;
+               add_filesys_config (p, -1, &uci);
 #endif
                xfree (str);
                return 1;
@@ -2755,9 +2791,9 @@ invalid_fs:
        }
 
        if (_tcscmp (option, _T("filesystem2")) == 0)
-               return cfgfile_parse_newfilesys (p, -1, false, value);
+               return cfgfile_parse_newfilesys (p, -1, 0, value, -1, false);
        if (_tcscmp (option, _T("hardfile2")) == 0)
-               return cfgfile_parse_newfilesys (p, -1, true, value);
+               return cfgfile_parse_newfilesys (p, -1, 1, value, -1, false);
 
        return 0;
 }
@@ -3749,7 +3785,8 @@ static void parse_filesys_spec (struct uae_prefs *p, bool readonly, const TCHAR
                _tcscpy (uci.volname, buf);
                _tcscpy (uci.rootdir, s2);
                uci.readonly = readonly;
-               add_filesys_config (p, -1, &uci, false);
+               uci.type = UAEDEV_DIR;
+               add_filesys_config (p, -1, &uci);
 #endif
        } else {
                write_log (_T("Usage: [-m | -M] VOLNAME:mount_point\n"));
index a81f8e1860a5e2da3afe113a97c4999234bacdcf..28f76f44d6f408061ab2f13077812fb6ffd09c7d 100644 (file)
@@ -54,7 +54,8 @@ void consolehook_config (struct uae_prefs *p)
        _tcscpy (ci.volname, _T("CLIBOOT"));
        _tcscpy (ci.devname, _T("DH0"));
        ci.bootpri = 15;
-       add_filesys_config (p, -1, &ci, false);
+       ci.type = UAEDEV_DIR;
+       add_filesys_config (p, -1, &ci);
 }
 
 static void *console_thread (void *v)
index a65db594c4c9e0ae1ea0b14a06aba7e87d9c8ee1..64b52a94040ed55dcf06cacddcdcdbfec3e90e86 100644 (file)
 
 
 uae_u32 mmu_is_super;
-uae_u32 mmu_tagmask, mmu_pagemask;
+uae_u32 mmu_tagmask, mmu_pagemask, mmu_pagemaski;
 struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS];
-int mmu060_state;
 bool mmu_pagesize_8k;
 
+int mmu060_state;
+uae_u16 mmu060_opcode;
+static bool locked_rmw_cycle;
+
+int mmu040_movem;
+uaecptr mmu040_movem_ea;
+
 static void mmu_dump_ttr(const TCHAR * label, uae_u32 ttr)
 {
        DUNUSED(label);
@@ -247,7 +253,7 @@ static void mmu_bus_error(uaecptr addr, int fc, bool write, int size, uae_u32 st
        if (currprefs.mmu_model == 68040) {
                uae_u16 ssw = 0;
 
-               ssw |= fc & MMU_SSW_TM;                         /* Copy TM */
+               ssw |= fc & MMU_SSW_TM;                         /* TM = FC */
                switch (size) {
                case sz_byte:
                        ssw |= MMU_SSW_SIZE_B;
@@ -258,21 +264,45 @@ static void mmu_bus_error(uaecptr addr, int fc, bool write, int size, uae_u32 st
                case sz_long:
                        ssw |= MMU_SSW_SIZE_L;
                        break;
+               case 16: // MOVE16
+                       ssw |= MMU_SSW_SIZE_L; // ??
+                       ssw |= MMU_SSW_TT0;
+                       break;
                }
 
                regs.wb3_status = write ? 0x80 | ssw : 0;
                if (!write)
                        ssw |= MMU_SSW_RW;
 
+               if (mmu040_movem) {
+                       ssw |= MMU_SSW_CM;
+                       addr = mmu040_movem_ea;
+                       mmu040_movem = 0;
+                       write_log (_T("040 MMU_SSW_CM!\n"));
+               }
+               if (locked_rmw_cycle) {
+                       ssw |= MMU_SSW_LK;
+                       locked_rmw_cycle = false;
+                       write_log (_T("040 MMU_SSW_LK!\n"));
+               }
+
                regs.mmu_ssw = ssw | MMU_SSW_ATC;
 
-#if MMUDEBUG > 2
+#if MMUDEBUG > 0
                write_log(_T("040 BUS ERROR: fc=%d w=%d logical=%08x ssw=%04x PC=%08x\n"), fc, write, addr, ssw, m68k_getpc());
 #endif
        } else {
                uae_u32 fslw = 0;
 
                fslw |= write ? MMU_FSLW_W : MMU_FSLW_R;
+#if 0
+               // read-modify-write?
+               if (table68k[mmu060_opcode].rmw) {
+                       fslw |= MMU_FSLW_W | MMU_FSLW_R;
+               }
+#endif
+
+               fslw |= fc << 16; /* MMU_FSLW_TM */
                switch (size) {
                case sz_byte:
                        fslw |= MMU_FSLW_SIZE_B;
@@ -286,24 +316,39 @@ static void mmu_bus_error(uaecptr addr, int fc, bool write, int size, uae_u32 st
                case 16: // MOVE16
                        addr &= ~15;
                        fslw |= MMU_FSLW_SIZE_D;
+                       fslw |= MMU_FSLW_TT_16;
                        break;
                }
-               if (mmu060_state == 0) {
-                       fslw |= MMU_FSLW_IO; // opword fetch
-               } else if ((fc & 2)) {
-                       fslw |= MMU_FSLW_IO | MMU_FSLW_MA; // extension word
+               if ((fc & 3) == 2) {
+                       if (mmu060_state == 0) {
+                               fslw |= MMU_FSLW_IO; // opword fetch
+                       } else {
+                               fslw |= MMU_FSLW_IO | MMU_FSLW_MA; // extension word
+                       }
+               }
+               if (locked_rmw_cycle) {
+                       fslw |= MMU_FSLW_LK;
+                       locked_rmw_cycle = false;
+                       write_log (_T("060 MMU_FSLW_LK!\n"));
                }
                fslw |= status;
                regs.mmu_fslw = fslw;
 
-#if MMUDEBUG > 2
+#if MMUDEBUG > 0
                write_log(_T("060 BUS ERROR: fc=%d w=%d logical=%08x ssw=%08x PC=%08x\n"), fc, write, addr, fslw, m68k_getpc());
 #endif
 
        }
 
        regs.mmu_fault_addr = addr;
+#if 0
+       if (addr == 0x00002180) {
+               write_log (_T("*"));
 
+       extern void activate_debugger(void);
+       activate_debugger ();
+       }
+#endif
        THROW(2);
 }
 
@@ -351,10 +396,7 @@ static uaecptr mmu_fill_atc(uaecptr addr, bool super, bool data, bool write, str
                l->global = 0;
        } else {
                l->valid = 1;
-               if (mmu_pagesize_8k)
-                       l->phys = (desc & ~0x1fff);
-               else
-                       l->phys = (desc & ~0xfff);
+               l->phys = desc & mmu_pagemaski;
                l->global = (desc & MMU_MMUSR_G) != 0;
                l->modified = (desc & MMU_MMUSR_M) != 0;
                l->write_protect = (desc & MMU_MMUSR_W) != 0;
@@ -375,7 +417,7 @@ static ALWAYS_INLINE bool mmu_fill_atc_try(uaecptr addr, bool super, bool data,
        if (write) {
                if (l1->write_protect) {
                        *status |= MMU_FSLW_WP;
-#if MMUDEBUG > 1
+#if MMUDEBUG > 0
                        write_log(_T("MMU: write protected %lx by atc \n"), addr);
 #endif
                        mmu_dump_atc();
@@ -398,14 +440,14 @@ uaecptr REGPARAM2 mmu_translate(uaecptr addr, bool super, bool data, bool write)
        mmu_user_lookup(addr, super, data, write, &l);
 
        mmu_fill_atc(addr, super, data, write, l, &status);
-       if (!l->valid) {
-#if MMUDEBUG > 0
+       if (!l->valid || (write && l->write_protect)) {
+#if MMUDEBUG > 2
                write_log(_T("[MMU] mmu_translate error"));
 #endif
                THROW(2);
        }
 
-    return l->phys | (addr & (mmu_pagesize_8k?0x00001fff:0x00000fff));
+    return l->phys | (addr & mmu_pagemask);
 
 }
 
@@ -536,6 +578,7 @@ uae_u32 REGPARAM2 mmu_get_long_unaligned(uaecptr addr, bool data)
                CATCH(prb) {
                        RESTORE_EXCEPTION;
                        regs.mmu_fault_addr = addr;
+                       regs.mmu_fslw |= MMU_FSLW_MA;
                        regs.mmu_ssw |= MMU_SSW_MA;
                        THROW_AGAIN(prb);
                } ENDTRY
@@ -559,6 +602,63 @@ uae_u32 REGPARAM2 mmu_get_long_unaligned(uaecptr addr, bool data)
        return res;
 }
 
+uae_u16 REGPARAM2 mmu_get_rmw_word_unaligned(uaecptr addr)
+{
+       uae_u16 res;
+
+       res = (uae_u16)mmu_get_user_byte(addr, regs.s != 0, false, true, sz_word) << 8;
+       SAVE_EXCEPTION;
+       TRY(prb) {
+               res |= mmu_get_user_byte(addr + 1, regs.s != 0, false, true, sz_word);
+               RESTORE_EXCEPTION;
+       }
+       CATCH(prb) {
+               RESTORE_EXCEPTION;
+               regs.mmu_fault_addr = addr;
+               regs.mmu_fslw |= MMU_FSLW_MA;
+               regs.mmu_ssw |= MMU_SSW_MA;
+               THROW_AGAIN(prb);
+       } ENDTRY
+       return res;
+}
+
+uae_u32 REGPARAM2 mmu_get_rmw_long_unaligned(uaecptr addr)
+{
+       uae_u32 res;
+
+       if (likely(!(addr & 1))) {
+               res = (uae_u32)mmu_get_user_word(addr, regs.s != 0, false, true, sz_long) << 16;
+               SAVE_EXCEPTION;
+               TRY(prb) {
+                       res |= mmu_get_user_word(addr + 2, regs.s != 0, false, true, sz_long);
+                       RESTORE_EXCEPTION;
+               }
+               CATCH(prb) {
+                       RESTORE_EXCEPTION;
+                       regs.mmu_fault_addr = addr;
+                       regs.mmu_fslw |= MMU_FSLW_MA;
+                       regs.mmu_ssw |= MMU_SSW_MA;
+                       THROW_AGAIN(prb);
+               } ENDTRY
+       } else {
+               res = (uae_u32)mmu_get_user_byte(addr, regs.s != 0, false, true, sz_long) << 8;
+               SAVE_EXCEPTION;
+               TRY(prb) {
+                       res = (res | mmu_get_user_byte(addr + 1, regs.s != 0, false, true, sz_long)) << 8;
+                       res = (res | mmu_get_user_byte(addr + 2, regs.s != 0, false, true, sz_long)) << 8;
+                       res |= mmu_get_user_byte(addr + 3, regs.s != 0, false, true, sz_long);
+                       RESTORE_EXCEPTION;
+               }
+               CATCH(prb) {
+                       RESTORE_EXCEPTION;
+                       regs.mmu_fault_addr = addr;
+                       regs.mmu_fslw |= MMU_FSLW_MA;
+                       regs.mmu_ssw |= MMU_SSW_MA;
+                       THROW_AGAIN(prb);
+               } ENDTRY
+       }
+       return res;
+}
 uae_u8 REGPARAM2 mmu_get_byte_slow(uaecptr addr, bool super, bool data,
                                                 int size, struct mmu_atc_line *cl)
 {
@@ -682,13 +782,13 @@ uae_u32 REGPARAM2 sfc_get_long(uaecptr addr)
        uae_u32 res;
 
        if (likely(!is_unaligned(addr, 4)))
-               return mmu_get_user_long(addr, super, data, sz_long);
+               return mmu_get_user_long(addr, super, data, false, sz_long);
 
        if (likely(!(addr & 1))) {
-               res = (uae_u32)mmu_get_user_word(addr, super, data, sz_long) << 16;
+               res = (uae_u32)mmu_get_user_word(addr, super, data, false, sz_long) << 16;
                SAVE_EXCEPTION;
                TRY(prb) {
-                       res |= mmu_get_user_word(addr + 2, super, data, sz_long);
+                       res |= mmu_get_user_word(addr + 2, super, data, false, sz_long);
                        RESTORE_EXCEPTION;
                }
                CATCH(prb) {
@@ -699,12 +799,12 @@ uae_u32 REGPARAM2 sfc_get_long(uaecptr addr)
                        THROW_AGAIN(prb);
                } ENDTRY
        } else {
-               res = (uae_u32)mmu_get_user_byte(addr, super, data, sz_long) << 8;
+               res = (uae_u32)mmu_get_user_byte(addr, super, data, false, sz_long) << 8;
                SAVE_EXCEPTION;
                TRY(prb) {
-                       res = (res | mmu_get_user_byte(addr + 1, super, data, sz_long)) << 8;
-                       res = (res | mmu_get_user_byte(addr + 2, super, data, sz_long)) << 8;
-                       res |= mmu_get_user_byte(addr + 3, super, data, sz_long);
+                       res = (res | mmu_get_user_byte(addr + 1, super, data, false, sz_long)) << 8;
+                       res = (res | mmu_get_user_byte(addr + 2, super, data, false, sz_long)) << 8;
+                       res |= mmu_get_user_byte(addr + 3, super, data, false, sz_long);
                        RESTORE_EXCEPTION;
                }
                CATCH(prb) {
@@ -725,12 +825,12 @@ uae_u16 REGPARAM2 sfc_get_word(uaecptr addr)
        uae_u16 res;
 
        if (likely(!is_unaligned(addr, 2)))
-               return mmu_get_user_word(addr, super, data, sz_word);
+               return mmu_get_user_word(addr, super, data, false, sz_word);
 
-       res = (uae_u16)mmu_get_user_byte(addr, super, data, sz_word) << 8;
+       res = (uae_u16)mmu_get_user_byte(addr, super, data, false, sz_word) << 8;
        SAVE_EXCEPTION;
        TRY(prb) {
-               res |= mmu_get_user_byte(addr + 1, super, data, sz_word);
+               res |= mmu_get_user_byte(addr + 1, super, data, false, sz_word);
                RESTORE_EXCEPTION;
        }
        CATCH(prb) {
@@ -748,7 +848,7 @@ uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr)
        bool super = (regs.sfc & 4) != 0;
        bool data = (regs.sfc & 3) != 2;
 
-       return mmu_get_user_byte(addr, super, data, sz_byte);
+       return mmu_get_user_byte(addr, super, data, false, sz_byte);
 }
 
 void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val)
@@ -842,13 +942,13 @@ void REGPARAM2 mmu_op_real(uae_u32 opcode, uae_u16 extra)
 
                if (opcode & 16) {
 #if MMUDEBUG > 1
-                       write_log(_T("pflusha(%u,%u)\n"), glob, regs.dfc);
+                       write_log(_T("pflusha(%u,%u) PC=%08x\n"), glob, regs.dfc, m68k_getpc ());
 #endif
                        mmu_flush_atc_all(glob);
                } else {
                        addr = m68k_areg(regs, regno);
 #if MMUDEBUG > 1
-                       write_log(_T("pflush(%u,%u,%x)\n"), glob, regs.dfc, addr);
+                       write_log(_T("pflush(%u,%u,%x) PC=%08x\n"), glob, regs.dfc, addr, m68k_getpc ());
 #endif
                        mmu_flush_atc(addr, super, glob);
                }
@@ -959,8 +1059,9 @@ void REGPARAM2 mmu_set_tc(uae_u16 tc)
 {
        regs.mmu_enabled = (tc & 0x8000) != 0;
        mmu_pagesize_8k = (tc & 0x4000) != 0;
-       mmu_tagmask = mmu_pagesize_8k ? 0xFFFF0000 : 0xFFFF8000;
+       mmu_tagmask  = mmu_pagesize_8k ? 0xFFFF0000 : 0xFFFF8000;
        mmu_pagemask = mmu_pagesize_8k ? 0x00001FFF : 0x00000FFF;
+       mmu_pagemaski = ~mmu_pagemask;
        regs.mmu_page_size = mmu_pagesize_8k ? 8192 : 4096;
 
        mmu_flush_atc_all(true);
@@ -984,6 +1085,10 @@ void m68k_do_rte_mmu040 (uaecptr a7)
                // skip this word
                put_long_mmu040 (dst_a7 + 8, get_long_mmu040 (src_a7 + 8));
        }
+       if (ssr & MMU_SSW_CM) {
+               mmu040_movem = 1;
+               mmu040_movem_ea = get_long_mmu040 (a7 + 8);
+       }
 }
 
 void flush_mmu040 (uaecptr addr, int n)
@@ -1016,6 +1121,47 @@ void m68k_do_bsr_mmu060 (uaecptr oldpc, uae_s32 offset)
        m68k_incpci (offset);
 }
 
+void uae_mmu_put_rmw (uaecptr addr, uae_u32 v, int size, int type)
+{
+       locked_rmw_cycle = true;
+       if (size == sz_byte) {
+               mmu_put_byte(addr, v, true, sz_byte);
+       } else if (size == sz_word) {
+               if (unlikely(is_unaligned(addr, 2))) {
+                       mmu_put_word_unaligned(addr, v, true);
+               } else {
+                       mmu_put_word(addr, v, true, sz_word);
+               }
+       } else {
+               if (unlikely(is_unaligned(addr, 4)))
+                       mmu_put_long_unaligned(addr, v, true);
+               else
+                       mmu_put_long(addr, v, true, sz_long);
+       }
+       locked_rmw_cycle = false;
+}
+uae_u32 uae_mmu_get_rmw (uaecptr addr, int size, int type)
+{
+       uae_u32 v;
+       locked_rmw_cycle = true;
+       if (size == sz_byte) {
+               v = mmu_get_user_byte(addr, regs.s != 0, true, true, sz_byte);
+       } else if (size == sz_word) {
+               if (unlikely(is_unaligned(addr, 2))) {
+                       v = mmu_get_rmw_word_unaligned(addr);
+               } else {
+                       v = mmu_get_user_word(addr, regs.s != 0, true, true, sz_word);
+               }
+       } else {
+               if (unlikely(is_unaligned(addr, 4)))
+                       v = mmu_get_rmw_long_unaligned(addr);
+               else
+                       v = mmu_get_user_long(addr, regs.s != 0, true, true, sz_long);
+       }
+       locked_rmw_cycle = false;
+       return v;
+}
+
 #ifndef __cplusplus
 jmp_buf __exbuf;
 int     __exvalue;
index 584cc25575cfb4f86624962ee4c1eeef5784cadb..a056e6a7235455341f029ddaa4f9325aee3cd3cf 100644 (file)
 #define MMU030_ATC_DBG_MSG 0
 #define MMU030_REG_DBG_MSG 0
 
+#define TT_FC_MASK      0x00000007
+#define TT_FC_BASE      0x00000070
+#define TT_RWM          0x00000100
+#define TT_RW           0x00000200
+#define TT_CI           0x00000400
+#define TT_ENABLE       0x00008000
+
+#define TT_ADDR_MASK    0x00FF0000
+#define TT_ADDR_BASE    0xFF000000
+
 static int bBusErrorReadWrite;
 static int atcindextable[32];
+static int tt_enabled;
 
 int mmu030_idx;
 
@@ -266,6 +277,7 @@ void mmu_op30_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
     if (!fd && !rw && !(preg==0x18)) {
         mmu030_flush_atc_all();
     }
+       tt_enabled = (tt0_030 & TT_ENABLE) || (tt1_030 & TT_ENABLE);
 }
 
 void mmu_op30_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
@@ -488,17 +500,6 @@ void mmu030_flush_atc_all(void) {
  *
  */
 
-
-#define TT_FC_MASK      0x00000007
-#define TT_FC_BASE      0x00000070
-#define TT_RWM          0x00000100
-#define TT_RW           0x00000200
-#define TT_CI           0x00000400
-#define TT_ENABLE       0x00008000
-
-#define TT_ADDR_MASK    0x00FF0000
-#define TT_ADDR_BASE    0xFF000000
-
 /* TT comparision results */
 #define TT_NO_MATCH    0x1
 #define TT_OK_MATCH    0x2
@@ -514,10 +515,12 @@ TT_info mmu030_decode_tt(uae_u32 TT) {
     ret.addr_base = TT & TT_ADDR_BASE;
     ret.addr_mask = ~(((TT&TT_ADDR_MASK)<<8)|0x00FFFFFF);
     
+#if 0
     if ((TT&TT_ENABLE) && !(TT&TT_RWM)) {
         write_log(_T("MMU Warning: Transparent translation of read-modify-write cycle is not correctly handled!\n"));
     }
-    
+#endif
+
 #if MMU030_REG_DBG_MSG /* enable or disable debugging messages */
     write_log(_T("\n"));
     write_log(_T("TRANSPARENT TRANSLATION: %08X\n"), TT);
@@ -571,6 +574,27 @@ int mmu030_match_ttr(uaecptr addr, uae_u32 fc, bool write)
     
     return (tt0|tt1);
 }
+int mmu030_match_ttr_access(uaecptr addr, uae_u32 fc, bool write)
+{
+    int tt0, tt1;
+       if (!tt_enabled)
+               return 0;
+    tt0 = mmu030_do_match_ttr(tt0_030, mmu030.transparent.tt0, addr, fc, write);
+    tt1 = mmu030_do_match_ttr(tt1_030, mmu030.transparent.tt1, addr, fc, write);
+    return (tt0|tt1) & TT_OK_MATCH;
+}
+
+/* Read-Modify-Write */
+int mmu030_match_rmw_ttr_access(uaecptr addr, uae_u32 fc)
+{
+    int tt0, tt1;
+
+       if (!tt_enabled)
+               return 0;
+    tt0 = mmu030_do_match_rmw_ttr(tt0_030, mmu030.transparent.tt0, addr, fc);
+    tt1 = mmu030_do_match_rmw_ttr(tt1_030, mmu030.transparent.tt1, addr, fc);
+    return (tt0|tt1) & TT_OK_MATCH;
+}
 
 /* This function checks if an address matches a transparent
  * translation register */
@@ -604,6 +628,23 @@ int mmu030_do_match_ttr(uae_u32 tt, TT_info comp, uaecptr addr, uae_u32 fc, bool
        return TT_NO_MATCH;
 }
 
+int mmu030_do_match_rmw_ttr(uae_u32 tt, TT_info comp, uaecptr addr, uae_u32 fc)
+{
+       if ((tt & TT_ENABLE) && (tt & TT_RWM))  {       /* transparent translation enabled */
+        
+        /* Compare actual function code with function code base using mask */
+        if ((comp.fc_base&comp.fc_mask)==(fc&comp.fc_mask)) {
+            
+            /* Compare actual address with address base using mask */
+            if ((comp.addr_base&comp.addr_mask)==(addr&comp.addr_mask)) {
+                
+                               return TT_NO_READ; /* TODO: check this! */
+            }
+               }
+       }
+       return TT_NO_MATCH;
+}
+
 
 
 /* Translation Control Register:
@@ -1510,18 +1551,22 @@ uae_u32 mmu030_ptest_table_search(uaecptr logical_addr, uae_u32 fc, bool write,
 #define ATC030_PHYS_CI  0x04000000
 #define ATC030_PHYS_BE  0x08000000
 
-void mmu030_page_fault(uaecptr addr, bool read, int size, uae_u32 fc) {
+static void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc) {
        regs.mmu_fault_addr = addr;
        regs.mmu_ssw = (fc & 1) ? MMU030_SSW_DF | (MMU030_SSW_DF << 1) : (MMU030_SSW_FB | MMU030_SSW_RB);
        regs.mmu_ssw |= read ? MMU030_SSW_RW : 0;
-       regs.mmu_ssw |= size;
+       regs.mmu_ssw |= flags;
        regs.mmu_ssw |= fc;
     bBusErrorReadWrite = read; 
        mm030_stageb_address = addr;
 #if 1
        write_log(_T("MMU: page fault (logical addr=%08X SSW=%04x read=%d size=%d fc=%d pc=%08x)\n"),
-               addr, regs.mmu_ssw, read, (size & MMU030_SSW_SIZE_B) ? 1 : (size & MMU030_SSW_SIZE_W) ? 2 : 4, fc, regs.instruction_pc);
+               addr, regs.mmu_ssw, read, (flags & MMU030_SSW_SIZE_B) ? 1 : (flags & MMU030_SSW_SIZE_W) ? 2 : 4, fc, regs.instruction_pc);
 #endif
+       
+//     extern void activate_debugger(void);
+//     activate_debugger ();
+
        THROW(2);
 }
 
@@ -1537,7 +1582,7 @@ void mmu030_put_long_atc(uaecptr addr, uae_u32 val, int l, uae_u32 fc) {
     physical_addr += page_index;
     
     if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) {
-        mmu030_page_fault(addr, 0, MMU030_SSW_SIZE_L, fc);
+        mmu030_page_fault(addr, false, MMU030_SSW_SIZE_L, fc);
         return;
     }
 
@@ -1556,7 +1601,7 @@ void mmu030_put_word_atc(uaecptr addr, uae_u16 val, int l, uae_u32 fc) {
     physical_addr += page_index;
     
     if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) {
-        mmu030_page_fault(addr, 0, MMU030_SSW_SIZE_W, fc);
+        mmu030_page_fault(addr, false, MMU030_SSW_SIZE_W, fc);
         return;
     }
 
@@ -1575,7 +1620,7 @@ void mmu030_put_byte_atc(uaecptr addr, uae_u8 val, int l, uae_u32 fc) {
     physical_addr += page_index;
     
     if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) {
-        mmu030_page_fault(addr, 0, MMU030_SSW_SIZE_B, fc);
+        mmu030_page_fault(addr, false, MMU030_SSW_SIZE_B, fc);
         return;
     }
 
@@ -1594,7 +1639,7 @@ uae_u32 mmu030_get_long_atc(uaecptr addr, int l, uae_u32 fc) {
     physical_addr += page_index;
     
     if (mmu030.atc[l].physical.bus_error) {
-        mmu030_page_fault(addr, 1, MMU030_SSW_SIZE_L, fc);
+        mmu030_page_fault(addr, true, MMU030_SSW_SIZE_L, fc);
         return 0;
     }
 
@@ -1613,7 +1658,7 @@ uae_u16 mmu030_get_word_atc(uaecptr addr, int l, uae_u32 fc) {
     physical_addr += page_index;
     
     if (mmu030.atc[l].physical.bus_error) {
-        mmu030_page_fault(addr, 1, MMU030_SSW_SIZE_W, fc);
+        mmu030_page_fault(addr, true, MMU030_SSW_SIZE_W, fc);
         return 0;
     }
     
@@ -1632,13 +1677,60 @@ uae_u8 mmu030_get_byte_atc(uaecptr addr, int l, uae_u32 fc) {
     physical_addr += page_index;
     
     if (mmu030.atc[l].physical.bus_error) {
-        mmu030_page_fault(addr, 1, MMU030_SSW_SIZE_B, fc);
+        mmu030_page_fault(addr, true, MMU030_SSW_SIZE_B, fc);
         return 0;
     }
 
     return phys_get_byte(physical_addr);
 }
 
+/* Generic versions of above */
+void mmu030_put_atc_generic(uaecptr addr, uae_u32 val, int l, uae_u32 fc, int size, int flags) {
+    uae_u32 page_index = addr & mmu030.translation.page.mask;
+    uae_u32 addr_mask = mmu030.translation.page.imask;
+    
+    uae_u32 physical_addr = mmu030.atc[l].physical.addr & addr_mask;
+#if MMU030_ATC_DBG_MSG
+    write_log(_T("ATC match(%i): page addr = %08X, index = %08X (bput %02X)\n"),
+              l, physical_addr, page_index, val);
+#endif
+    physical_addr += page_index;
+    
+    if (mmu030.atc[l].physical.write_protect || mmu030.atc[l].physical.bus_error) {
+               mmu030_page_fault(addr, false, flags, fc);
+        return;
+    }
+       if (size == sz_byte)
+           phys_put_byte(physical_addr, val);
+       else if (size == sz_word)
+           phys_put_word(physical_addr, val);
+       else
+           phys_put_long(physical_addr, val);
+
+}
+uae_u32 mmu030_get_atc_generic(uaecptr addr, int l, uae_u32 fc, int size, int flags, bool checkwrite) {
+    uae_u32 page_index = addr & mmu030.translation.page.mask;
+    uae_u32 addr_mask = mmu030.translation.page.imask;
+    
+    uae_u32 physical_addr = mmu030.atc[l].physical.addr & addr_mask;
+#if MMU030_ATC_DBG_MSG
+    write_log(_T("ATC match(%i): page addr = %08X, index = %08X (bget %02X)\n"), l,
+              physical_addr, page_index, phys_get_byte(physical_addr+page_index));
+#endif
+    physical_addr += page_index;
+    
+       if (mmu030.atc[l].physical.bus_error || (checkwrite && mmu030.atc[l].physical.write_protect)) {
+        mmu030_page_fault(addr, true, flags, fc);
+        return 0;
+    }
+       if (size == sz_byte)
+               return phys_get_byte(physical_addr);
+       else if (size == sz_word)
+               return phys_get_word(physical_addr);
+       return phys_get_long(physical_addr);
+}
+
+
 /* This function checks if a certain logical address is in the ATC 
  * by comparing the logical address and function code to the values
  * stored in the ATC entries. If a matching entry is found it sets
@@ -1704,10 +1796,10 @@ void mmu030_atc_handle_history_bit(int entry_num) {
  * create a new ATC entry and then look up the physical address. 
  */
 
-void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc, int size) {
+void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc) {
     
        //                                        addr,super,write
-       if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,true)&TT_OK_MATCH) || (fc==7)) {
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,true)) || (fc==7)) {
                phys_put_long(addr,val);
                return;
     }
@@ -1722,10 +1814,10 @@ void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc, int size) {
     }
 }
 
-void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc, int size) {
+void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc) {
     
        //                                        addr,super,write
-       if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,true)&TT_OK_MATCH) || (fc==7)) {
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,true)) || (fc==7)) {
                phys_put_word(addr,val);
                return;
     }
@@ -1740,10 +1832,10 @@ void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc, int size) {
     }
 }
 
-void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc, int size) {
+void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc) {
     
        //                                        addr,super,write
-       if ((!mmu030.enabled) || (mmu030_match_ttr(addr, fc, true)&TT_OK_MATCH) || (fc==7)) {
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, true)) || (fc==7)) {
                phys_put_byte(addr,val);
                return;
     }
@@ -1758,10 +1850,10 @@ void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc, int size) {
     }
 }
 
-uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc, int size) {
+uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc) {
     
        //                                        addr,super,write
-       if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,false)&TT_OK_MATCH) || (fc==7)) {
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) {
                return phys_get_long(addr);
     }
     
@@ -1775,10 +1867,10 @@ uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc, int size) {
     }
 }
 
-uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc, int size) {
+uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc) {
     
        //                                        addr,super,write
-       if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,false)&TT_OK_MATCH) || (fc==7)) {
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) {
                return phys_get_word(addr);
     }
     
@@ -1792,10 +1884,10 @@ uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc, int size) {
     }
 }
 
-uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc, int size) {
+uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc) {
     
        //                                        addr,super,write
-       if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,false)&TT_OK_MATCH) || (fc==7)) {
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) {
                return phys_get_byte(addr);
     }
     
@@ -1810,14 +1902,128 @@ uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc, int size) {
 }
 
 
-uae_u16 REGPARAM2 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc)
+/* Not commonly used access function */
+void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int accesssize, int flags) {
+    
+       //                                        addr,super,write
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, true)) || (fc==7)) {
+               if (size == sz_byte)
+                       phys_put_byte(addr, val);
+               else if (size == sz_word)
+                       phys_put_word(addr, val);
+               else
+                       phys_put_long(addr, val);
+               return;
+    }
+    
+    int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true);
+    if (atc_line_num>=0) {
+        mmu030_put_atc_generic(addr, val, atc_line_num, fc, size, flags);
+    } else {
+        mmu030_table_search(addr, fc, true, 0);
+               atc_line_num = mmu030_logical_is_in_atc(addr, fc, true);
+               if (accesssize == sz_byte)
+                       flags |= MMU030_SSW_SIZE_B;
+               else if (accesssize == sz_word)
+                       flags |= MMU030_SSW_SIZE_W;
+        mmu030_put_atc_generic(addr, val, atc_line_num, fc, size, flags);
+    }
+}
+static uae_u32 mmu030_get_generic_rmw(uaecptr addr, uae_u32 fc, int size, int accesssize, int flags) {
+    
+       //                                        addr,super,write
+       if ((!mmu030.enabled) || (mmu030_match_rmw_ttr_access(addr,fc)) || (fc==7)) {
+               if (size == sz_byte)
+                       return phys_get_byte(addr);
+               else if (size == sz_word)
+                       return phys_get_word(addr);
+               return phys_get_long(addr);
+    }
+    
+    int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true);
+    if (atc_line_num>=0) {
+        return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, true);
+    } else {
+        mmu030_table_search(addr, fc, true, 0);
+               atc_line_num = mmu030_logical_is_in_atc(addr, fc, true);
+               if (accesssize == sz_byte)
+                       flags |= MMU030_SSW_SIZE_B;
+               else if (accesssize == sz_word)
+                       flags |= MMU030_SSW_SIZE_W;
+        return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, true);
+    }
+}
+uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int accesssize, int flags) {
+       if (flags & MMU030_SSW_RM) {
+               return mmu030_get_generic_rmw(addr, fc, size, accesssize, flags);
+       }
+       //                                        addr,super,write
+       if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) {
+               if (size == sz_byte)
+                       return phys_get_byte(addr);
+               else if (size == sz_word)
+                       return phys_get_word(addr);
+               return phys_get_long(addr);
+    }
+    
+    int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false);
+    if (atc_line_num>=0) {
+        return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, false);
+    } else {
+        mmu030_table_search(addr, fc, false, 0);
+               atc_line_num = mmu030_logical_is_in_atc(addr, fc, false);
+               if (accesssize == sz_byte)
+                       flags |= MMU030_SSW_SIZE_B;
+               else if (accesssize == sz_word)
+                       flags |= MMU030_SSW_SIZE_W;
+        return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, false);
+    }
+}
+
+
+/* RMW is rarely used */
+uae_u32 uae_mmu030_get_rmw(uaecptr addr, int size)
+{
+    uae_u32 fc = (regs.s ? 4 : 0) | 1;
+       if (size == sz_byte) {
+               return mmu030_get_generic(addr, fc, size, size, MMU030_SSW_RM);
+       } else if (size == sz_word) {
+               if (unlikely(is_unaligned(addr, 2)))
+                       return mmu030_get_word_unaligned(addr, fc, MMU030_SSW_RM);
+               else
+                       return mmu030_get_generic(addr, fc, size, size, MMU030_SSW_RM);
+       } else {
+               if (unlikely(is_unaligned(addr, 4)))
+                       return mmu030_get_long_unaligned(addr, fc, MMU030_SSW_RM);
+               else
+                       return mmu030_get_generic(addr, fc, size, size, MMU030_SSW_RM);
+       }
+}
+void uae_mmu030_put_rmw(uaecptr addr, uae_u32 val, int size)
+{
+    uae_u32 fc = (regs.s ? 4 : 0) | 1;
+       if (size == sz_byte) {
+               mmu030_put_generic(addr, val, fc, size, size, MMU030_SSW_RM);
+       } else if (size == sz_word) {
+               if (unlikely(is_unaligned(addr, 2)))
+                       mmu030_put_word_unaligned(addr, val, fc, MMU030_SSW_RM);
+               else
+                       mmu030_put_generic(addr, val, fc, size, size, MMU030_SSW_RM);
+       } else {
+               if (unlikely(is_unaligned(addr, 4)))
+                       mmu030_put_long_unaligned(addr, val, fc, MMU030_SSW_RM);
+               else
+                       mmu030_put_generic(addr, val, fc, size, size, MMU030_SSW_RM);
+       }
+}
+uae_u16 REGPARAM2 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc, int flags)
 {
        uae_u16 res;
     
-       res = (uae_u16)mmu030_get_byte(addr, fc, sz_word) << 8;
+       res = (uae_u16)mmu030_get_generic(addr, fc, sz_byte, sz_word, flags) << 8;
        SAVE_EXCEPTION;
        TRY(prb) {
-               res |= mmu030_get_byte(addr + 1, fc, sz_word);
+               res |= mmu030_get_generic(addr + 1, fc, sz_byte, sz_word, flags);
                RESTORE_EXCEPTION;
        }
        CATCH(prb) {
@@ -1827,15 +2033,15 @@ uae_u16 REGPARAM2 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc)
        return res;
 }
 
-uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc)
+uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc, int flags)
 {
        uae_u32 res;
     
        if (likely(!(addr & 1))) {
-               res = (uae_u32)mmu030_get_word(addr, fc, sz_long) << 16;
+               res = (uae_u32)mmu030_get_generic(addr, fc, sz_word, sz_long, flags) << 16;
                SAVE_EXCEPTION;
                TRY(prb) {
-                       res |= mmu030_get_word(addr + 2, fc, sz_long);
+                       res |= mmu030_get_generic(addr + 2, fc, sz_word, sz_long, flags);
                        RESTORE_EXCEPTION;
                }
                CATCH(prb) {
@@ -1843,12 +2049,12 @@ uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc)
                        THROW_AGAIN(prb);
                } ENDTRY
        } else {
-               res = (uae_u32)mmu030_get_byte(addr, fc, sz_long) << 8;
+               res = (uae_u32)mmu030_get_generic(addr, fc, sz_byte, sz_long, flags) << 8;
                SAVE_EXCEPTION;
                TRY(prb) {
-                       res = (res | mmu030_get_byte(addr + 1, fc, sz_long)) << 8;
-                       res = (res | mmu030_get_byte(addr + 2, fc, sz_long)) << 8;
-                       res |= mmu030_get_byte(addr + 3, fc, sz_long);
+                       res = (res | mmu030_get_generic(addr + 1, fc, sz_byte, sz_long, flags)) << 8;
+                       res = (res | mmu030_get_generic(addr + 2, fc, sz_byte, sz_long, flags)) << 8;
+                       res |= mmu030_get_generic(addr + 3, fc, sz_byte, sz_long, flags);
                        RESTORE_EXCEPTION;
                }
                CATCH(prb) {
@@ -1860,18 +2066,18 @@ uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc)
 }
 
 
-void REGPARAM2 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc)
+void REGPARAM2 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc, int flags)
 {
        SAVE_EXCEPTION;
        TRY(prb) {
                if (likely(!(addr & 1))) {
-                       mmu030_put_word(addr, val >> 16, fc, sz_long);
-                       mmu030_put_word(addr + 2, val, fc, sz_long);
+                       mmu030_put_generic(addr, val >> 16, fc, sz_word, sz_long, flags);
+                       mmu030_put_generic(addr + 2, val, fc, sz_word, sz_long, flags);
                } else {
-                       mmu030_put_byte(addr, val >> 24, fc, sz_long);
-                       mmu030_put_byte(addr + 1, val >> 16, fc, sz_long);
-                       mmu030_put_byte(addr + 2, val >> 8, fc, sz_long);
-                       mmu030_put_byte(addr + 3, val, fc, sz_long);
+                       mmu030_put_generic(addr, val >> 24, fc, sz_byte, sz_long, flags);
+                       mmu030_put_generic(addr + 1, val >> 16, fc, sz_byte, sz_long, flags);
+                       mmu030_put_generic(addr + 2, val >> 8, fc, sz_byte, sz_long, flags);
+                       mmu030_put_generic(addr + 3, val, fc, sz_byte, sz_long, flags);
                }
                RESTORE_EXCEPTION;
        }
@@ -1882,12 +2088,12 @@ void REGPARAM2 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc)
        } ENDTRY
 }
 
-void REGPARAM2 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc)
+void REGPARAM2 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc, int flags)
 {
        SAVE_EXCEPTION;
        TRY(prb) {
-               mmu030_put_byte(addr, val >> 8, fc, sz_word);
-               mmu030_put_byte(addr + 1, val, fc, sz_word);
+               mmu030_put_generic(addr, val >> 8, fc, sz_byte, sz_word, flags);
+               mmu030_put_generic(addr + 1, val, fc, sz_byte, sz_word, flags);
                RESTORE_EXCEPTION;
        }
        CATCH(prb) {
@@ -1906,7 +2112,7 @@ static uaecptr mmu030_get_addr_atc(uaecptr addr, int l, uae_u32 fc, bool write)
     uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask;
     physical_addr += page_index;
     
-    if (mmu030.atc[l].physical.bus_error) {
+       if (mmu030.atc[l].physical.bus_error || (write && mmu030.atc[l].physical.write_protect)) {
         mmu030_page_fault(addr, write == 0, MMU030_SSW_SIZE_B, fc);
         return 0;
     }
@@ -1927,7 +2133,6 @@ uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write)
         mmu030_table_search(addr, fc, false, 0);
         return mmu030_get_addr_atc(addr, mmu030_logical_is_in_atc(addr,fc,write), fc, write);
     }
-
 }
 
 /* MMU Reset */
@@ -1965,6 +2170,9 @@ void m68k_do_rte_mmu030 (uaecptr a7)
        mmu030_disp_store[0] = get_long_mmu030 (a7 + 0x1c);
        mmu030_disp_store[1] = get_long_mmu030 (a7 + 0x1c + 4);
 
+       // Rerun "mmu030_opcode" using restored state.
+       mmu030_retry = true;
+
        if (frame == 0xb) {
                uae_u16 idxsize = get_word_mmu030 (a7 + 0x36);
                for (int i = 0; i < idxsize + 1; i++) {
@@ -1975,7 +2183,11 @@ void m68k_do_rte_mmu030 (uaecptr a7)
                // did we have data fault but DF bit cleared?
                if (ssw & (MMU030_SSW_DF << 1) && !(ssw & MMU030_SSW_DF)) {
                        // DF not set: mark access as done
-                       if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
+                       if (ssw & MMU030_SSW_RM) {
+                               // Read-Modify-Write: whole instruction is considered done
+                               write_log (_T("Read-Modify-Write and DF bit cleared! PC=%08x\n"), regs.instruction_pc);
+                               mmu030_retry = false;
+                       } else if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
                                // if movem, skip next move
                                mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
                        } else {
@@ -2003,8 +2215,6 @@ void m68k_do_rte_mmu030 (uaecptr a7)
        } else {
                m68k_areg (regs, 7) += 32;
        }
-       // Rerun "mmu030_opcode" using restored state.
-       mmu030_retry = true;
 }
 
 void flush_mmu030 (uaecptr addr, int n)
index a1256a44e73e9b624f7b02dd943e9d0e070e60cb..0aec4b1dc9cef3c03c11746c0b28ac8e30ef5e2f 100644 (file)
@@ -2977,7 +2977,7 @@ void compute_framesync (void)
                int start = hbstrt;
                int stop = hbstop;
 
-               gfxvidinfo.drawbuffer.inwidth =  (((start > stop ? (maxhpos - (maxhpos - start + stop)) : (maxhpos - (stop - start) + 2)) * 2) << res2);
+               gfxvidinfo.drawbuffer.inwidth = (((start > stop ? (maxhpos - (maxhpos - start + stop)) : (maxhpos - (stop - start) + 2)) * 2) << res2);
                gfxvidinfo.drawbuffer.inxoffset = ((stop + 1) & ~1) * 2;
                
                gfxvidinfo.drawbuffer.extrawidth = 0;
index cd3416f33963d36f91da34c09de93071e8a24309..42c74411b112ab83b62dd43c442a7183e5ef50bc 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -188,9 +188,9 @@ uae_u32 get_byte_debug (uaecptr addr)
                regs.s = (debug_mmu_mode & 4) != 0;
                TRY(p) {
                        if (currprefs.mmu_model == 68030) {
-                               v = mmu030_get_byte (addr, debug_mmu_mode, sz_byte);
+                               v = mmu030_get_byte (addr, debug_mmu_mode);
                        } else {
-                               v = mmu_get_byte (addr, (debug_mmu_mode & 1) ? true : false, sz_byte);
+                               v = mmu_get_user_byte (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_byte);
                        }
                } CATCH(p) {
                }
@@ -208,9 +208,9 @@ uae_u32 get_word_debug (uaecptr addr)
                regs.s = (debug_mmu_mode & 4) != 0;
                TRY(p) {
                        if (currprefs.mmu_model == 68030) {
-                               v = mmu030_get_word (addr, debug_mmu_mode, sz_word);
+                               v = mmu030_get_word (addr, debug_mmu_mode);
                        } else {
-                               v = mmu_get_word (addr, (debug_mmu_mode & 1) ? true : false, sz_word);
+                               v = mmu_get_user_word (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_word);
                        }
                } CATCH(p) {
                }
@@ -228,9 +228,9 @@ uae_u32 get_long_debug (uaecptr addr)
                regs.s = (debug_mmu_mode & 4) != 0;
                TRY(p) {
                        if (currprefs.mmu_model == 68030) {
-                               v = mmu030_get_long (addr, debug_mmu_mode, sz_long);
+                               v = mmu030_get_long (addr, debug_mmu_mode);
                        } else {
-                               v = mmu_get_long (addr, (debug_mmu_mode & 1) ? true : false, sz_long);
+                               v = mmu_get_user_long (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_long);
                        }
                } CATCH(p) {
                }
index dbeb9cf5363698a74ffed84ff3429b0ec5ac62bc..df2b5472c689ed711ca0078837f16937cdbdcff2 100644 (file)
@@ -953,7 +953,7 @@ static void expamem_map_fastcard (void)
 static void expamem_init_fastcard (void)
 {
        uae_u16 mid = (currprefs.cs_a2091 || currprefs.uae_hide) ? commodore : uae_id;
-       uae_u8 pid = (currprefs.cs_a2091 || currprefs.uae_hide) ? commodore_a2091_ram : 1;
+       uae_u8 pid = (currprefs.cs_a2091 || currprefs.uae_hide) ? commodore_a2091_ram : (currprefs.maprom ? 1 : 81);
 
        expamem_init_clear ();
        if (allocated_fastmem == 0x100000)
index 8f18ba0c7875c1ec703dba8d121d55747f5cf154..73f099da239f934e61aaedd3720ce815a99c210b 100644 (file)
@@ -295,9 +295,10 @@ int get_filesys_unitconfig (struct uae_prefs *p, int index, struct mountedinfo *
 
        memset (mi, 0, sizeof (struct mountedinfo));
        memset (&uitmp, 0, sizeof uitmp);
+       _tcscpy (mi->rootdir, uci->ci.rootdir);
        if (!ui) {
                ui = &uitmp;
-               if (!uci->ishdf) {
+               if (uci->ci.type == UAEDEV_DIR) {
                        mi->ismounted = 1;
                        if (uci->ci.rootdir && _tcslen (uci->ci.rootdir) == 0)
                                return FILESYS_VIRTUAL;
@@ -309,7 +310,7 @@ int get_filesys_unitconfig (struct uae_prefs *p, int index, struct mountedinfo *
                                return -1;
                        mi->ismedia = true;
                        return FILESYS_VIRTUAL;
-               } else {
+               } else if (uci->ci.type == UAEDEV_HDF) {
                        ui->hf.ci.readonly = true;
                        ui->hf.ci.blocksize = uci->ci.blocksize;
                        if (!hdf_open (&ui->hf, uci->ci.rootdir)) {
@@ -326,23 +327,41 @@ int get_filesys_unitconfig (struct uae_prefs *p, int index, struct mountedinfo *
                        if (ui->hf.drive_empty)
                                mi->ismedia = 0;
                        hdf_close (&ui->hf);
+               } else if (uci->ci.type == UAEDEV_CD) {
+                       struct device_info di;
+                       ui->hf.ci.readonly = true;
+                       ui->hf.ci.blocksize = uci->ci.blocksize;
+                       mi->size = -1;
+                       mi->ismounted = true;
+                       if (blkdev_get_info (p, ui->hf.ci.cd_emu_unit, &di)) {
+                               mi->ismedia = di.media_inserted;
+                               _tcscpy (mi->rootdir, di.label);
+                       }
+#if 0
+                       if (ui->hf.ci.cd_emu_unit == 0)
+                               _tcscpy (mi->rootdir, _T("CD"));
+                       else
+                               _stprintf (mi->rootdir, _T("CD %d"), ui->hf.ci.cd_emu_unit);
+#endif
                }
        } else {
                if (!ui->controller || (ui->controller && p->cs_ide)) {
                        mi->ismounted = 1;
-                       if (uci->ishdf)
+                       if (uci->ci.type == UAEDEV_HDF)
                                mi->ismedia = ui->hf.drive_empty ? false : true;
                        else
                                mi->ismedia = true;
                }
        }
+       if (mi->size < 0)
+               return -1;
        mi->size = ui->hf.virtsize;
        if (uci->ci.highcyl) {
                uci->ci.cyls = mi->nrcyls = uci->ci.highcyl;
        } else {
                uci->ci.cyls = mi->nrcyls = (int)(uci->ci.sectors * uci->ci.surfaces ? (ui->hf.virtsize / uci->ci.blocksize) / (uci->ci.sectors * uci->ci.surfaces) : 0);
        }
-       if (!uci->ishdf)
+       if (uci->ci.type == UAEDEV_DIR)
                return FILESYS_VIRTUAL;
        if (uci->ci.reserved == 0 && uci->ci.sectors == 0 && uci->ci.surfaces == 0) {
                if (ui->hf.flags & 1)
@@ -499,6 +518,7 @@ void uci_set_defaults (struct uaedev_config_info *uci, bool rdb)
        uci->stacksize = 4000;
        uci->priority = -129;
        uci->sectorsperblock = 1;
+       uci->cd_emu_unit = -1;
 }
 
 static int set_filesys_unit_1 (int nr, struct uaedev_config_info *ci)
@@ -757,7 +777,7 @@ static void initialize_mountinfo (void)
 #endif
                        } else if (currprefs.cs_cdtvscsi) {
 #ifdef CDTV
-                               cdtv_add_scsi_unit (uci->controller - HD_CONTROLLER_SCSI0, uci);
+                               cdtv_add_scsi_hd_unit (uci->controller - HD_CONTROLLER_SCSI0, uci);
                                allocuci (&currprefs, nr, -1);
 #endif
                        }
@@ -6051,6 +6071,14 @@ static uae_u32 REGPARAM2 filesys_dev_bootfilesys (TrapContext *context)
                }
                fsnode = get_long (fsnode);
        }
+       if (type == FILESYS_HARDFILE) {
+               uae_u32 pf = get_long (parmpacket + PP_FSHDSTART + 8); // fse_PatchFlags
+               for (int i = 0; i < 32; i++) {
+                       if (pf & (1 << i))
+                               put_long (devicenode + 4 + i * 4, get_long (parmpacket + PP_FSHDSTART + 8 + 4 + i * 4));
+               }
+               put_long (devicenode + 4 + 7 * 4, 0); // seglist
+       }
        return 0;
 }
 
@@ -6563,8 +6591,10 @@ static void addfakefilesys (uaecptr parmpacket, uae_u32 dostype, int ver, int re
        flags = 0x180;
        for (i = 0; i < 140; i++)
                put_byte (parmpacket + PP_FSHDSTART + i, 0);
-       put_long (parmpacket + 80, dostype);
-       put_long (parmpacket + PP_FSHDSTART, dostype);
+       if (dostype) {
+               put_long (parmpacket + 80, dostype);
+               put_long (parmpacket + PP_FSHDSTART, dostype);
+       }
        if (ver >= 0 && rev >= 0)
                put_long (parmpacket + PP_FSHDSTART + 4, (ver << 16) | rev);
 
@@ -6603,17 +6633,18 @@ static int dofakefilesys (UnitInfo *uip, uaecptr parmpacket, struct uaedev_confi
        struct zfile *zf;
        int ver = -1, rev = -1;
        uae_u32 dostype;
-       uaecptr seg;
 
        // we already have custom filesystem loaded for earlier hardfile?
-       seg = getfakefilesysseg (uip);
-       if (seg) {
-               // yes, re-use it.
-               put_long (parmpacket + PP_FSSIZE, 0);
-               put_long (parmpacket + PP_FSPTR, seg);
-               put_long (parmpacket + PP_ADDTOFSRES, 0);
-               write_log (_T("HDF: faked RDB filesystem '%s' reused\n"), uip->filesysdir);
-               return FILESYS_HARDFILE;
+       if (!ci->forceload) {
+               uaecptr seg = getfakefilesysseg (uip);
+               if (seg) {
+                       // yes, re-use it.
+                       put_long (parmpacket + PP_FSSIZE, 0);
+                       put_long (parmpacket + PP_FSPTR, seg);
+                       put_long (parmpacket + PP_ADDTOFSRES, 0);
+                       write_log (_T("HDF: faked RDB filesystem '%s' reused\n"), uip->filesysdir);
+                       return FILESYS_HARDFILE;
+               }
        }
 
        if (!ci->dostype) {
@@ -6623,8 +6654,10 @@ static int dofakefilesys (UnitInfo *uip, uaecptr parmpacket, struct uaedev_confi
        } else {
                dostype = ci->dostype;
        }
-       if (dostype == 0)
+       if (dostype == 0) {
+               addfakefilesys (parmpacket, dostype, ver, rev, ci);
                return FILESYS_HARDFILE;
+       }
        tmp[0] = 0;
        if (uip->filesysdir && _tcslen (uip->filesysdir) > 0) {
                _tcscpy (tmp, uip->filesysdir);
@@ -6637,6 +6670,7 @@ static int dofakefilesys (UnitInfo *uip, uaecptr parmpacket, struct uaedev_confi
        }
        if (tmp[0] == 0) {
                write_log (_T("RDB: no filesystem for dostype 0x%08X (%s)\n"), dostype, dostypes (dostype));
+               addfakefilesys (parmpacket, dostype, ver, rev, ci);
                if ((dostype & 0xffffff00) == 0x444f5300)
                        return FILESYS_HARDFILE;
                write_log (_T("RDB: mounted without filesys\n"));
@@ -6645,6 +6679,7 @@ static int dofakefilesys (UnitInfo *uip, uaecptr parmpacket, struct uaedev_confi
        write_log (_T("RDB: fakefilesys, trying to load '%s', dostype 0x%08X (%s)\n"), tmp, dostype, dostypes (dostype));
        zf = zfile_fopen (tmp, _T("rb"), ZFD_NORMAL);
        if (!zf) {
+               addfakefilesys (parmpacket, dostype, ver, rev, ci);
                write_log (_T("RDB: filesys not found\n"));
                if ((dostype & 0xffffff00) == 0x444f5300)
                        return FILESYS_HARDFILE;
@@ -6764,6 +6799,8 @@ static uae_u32 REGPARAM2 filesys_dev_storeinfo (TrapContext *context)
        uaecptr parmpacket = m68k_areg (regs, 0);
        struct uaedev_config_info *ci = &uip[unit_no].hf.ci;
 
+       put_long (parmpacket + PP_ADDTOFSRES, 0);
+       put_long (parmpacket + PP_FSSIZE, 0);
        if (iscd) {
                TCHAR *cdname = NULL;
                uaecptr cdname_amiga;
index 17be285918f1bfc33e5e7c552c88aa65ecd73cd3..a9671e3786937a7145ac1f836d2dc229ea48f071 100644 (file)
--- a/gayle.cpp
+++ b/gayle.cpp
@@ -26,6 +26,8 @@
 #include "gui.h"
 #include "a2091.h"
 #include "ncr_scsi.h"
+#include "blkdev.h"
+#include "scsi.h"
 
 #define PCMCIA_SRAM 1
 #define PCMCIA_IDE 2
@@ -75,7 +77,7 @@ read 1 byte to stop reset */
 /* IDE drive registers */
 #define IDE_DATA       0x00
 #define IDE_ERROR      0x01        /* see err-bits */
-#define IDE_NSECTOR    0x02        /* nr of sectors to read/write */
+#define IDE_NSECTOR    0x02        /* sector count, nr of sectors to read/write */
 #define IDE_SECTOR     0x03        /* starting sector */
 #define IDE_LCYL       0x04        /* starting cylinder */
 #define IDE_HCYL       0x05        /* high byte of starting cyl */
@@ -84,12 +86,13 @@ read 1 byte to stop reset */
 #define IDE_DEVCON     0x0406
 #define IDE_DRVADDR    0x0407
 /* STATUS bits */
-#define IDE_STATUS_ERR 0x01
-#define IDE_STATUS_IDX 0x02
-#define IDE_STATUS_DRQ 0x08
-#define IDE_STATUS_DSC 0x10
-#define IDE_STATUS_DRDY 0x40
-#define IDE_STATUS_BSY 0x80
+#define IDE_STATUS_ERR 0x01            // 0
+#define IDE_STATUS_IDX 0x02            // 1
+#define IDE_STATUS_DRQ 0x08            // 3
+#define IDE_STATUS_DSC 0x10            // 4
+#define IDE_STATUS_DRDY 0x40   // 6
+#define IDE_STATUS_BSY 0x80            // 7
+#define ATAPI_STATUS_CHK IDE_STATUS_ERR
 /* ERROR bits */
 #define IDE_ERR_UNC 0x40
 #define IDE_ERR_MC 0x20
@@ -97,6 +100,11 @@ read 1 byte to stop reset */
 #define IDE_ERR_MCR 0x08
 #define IDE_ERR_ABRT 0x04
 #define IDE_ERR_NM 0x02
+#define ATAPI_ERR_EOM 0x02
+#define ATAPI_ERR_ILI 0x01
+/* ATAPI interrupt reason (Sector Count) */
+#define ATAPI_IO 0x02
+#define ATAPI_CD 0x01
 
 /*
 *  These are at different offsets from the base
@@ -165,13 +173,16 @@ struct ide_registers
 {
        uae_u8 ide_select, ide_nsector, ide_sector, ide_lcyl, ide_hcyl, ide_devcon, ide_error, ide_feat;
        uae_u8 ide_nsector2, ide_sector2, ide_lcyl2, ide_hcyl2, ide_feat2;
-       uae_u8 ide_drv;
+       uae_u8 ide_status;
 };
 
 struct ide_hdf
 {
        struct hd_hardfiledata hdhfd;
-       struct ide_registers *regs;
+       struct ide_registers regs;
+       struct ide_registers *regs0;
+       struct ide_registers *regs1;
+       struct ide_hdf *pair;
 
        uae_u8 secbuf[SECBUF_SIZE];
        int data_offset;
@@ -179,14 +190,19 @@ struct ide_hdf
        int data_multi;
        int lba48;
        uae_u8 multiple_mode;
-       uae_u8 status;
        int irq_delay;
        int irq;
        int num;
        int type;
        int blocksize;
        int maxtransferstate;
+       int ide_drv;
+
        bool atapi;
+       int cd_unit_num;
+       int packet_cnt;
+       int packet_data_size;
+       struct scsi_data scsi;
 };
 
 #define TOTAL_IDE 3
@@ -194,7 +210,7 @@ struct ide_hdf
 #define PCMCIA_IDE_ID 2
 
 static struct ide_hdf *idedrive[TOTAL_IDE * 2];
-static struct ide_registers ideregs[TOTAL_IDE];
+static struct ide_registers ideregs[TOTAL_IDE * 2];
 struct hd_hardfiledata *pcmcia_sram;
 
 static int pcmcia_card;
@@ -251,22 +267,30 @@ static uae_u8 checkpcmciaideirq (void)
        return 0;
 }
 
+static bool isdrive (struct ide_hdf *drv)
+{
+       return drv->hdhfd.size != 0 || drv->atapi;
+}
+
 static uae_u8 checkgayleideirq (void)
 {
        int i;
+       bool irq = false;
+
        if (!idedrive)
                return 0;
        for (i = 0; i < 2; i++) {
-               if (ideregs[i].ide_devcon & 2)
-                       continue;
-               if (idedrive[i]->irq || idedrive[i + 2]->irq) {
-                       /* IDE killer feature. Do not eat interrupt to make booting faster. */
-                       if (idedrive[i]->irq && idedrive[i]->hdhfd.size == 0)
-                               idedrive[i]->irq = 0;
-                       return GAYLE_IRQ_IDE;
+               if (idedrive[i]->ide_drv == i) {
+                       if (!(idedrive[i]->regs.ide_devcon & 2) && (idedrive[i]->irq || idedrive[i + 2]->irq))
+                               irq = true;
                }
+               /* IDE killer feature. Do not eat interrupt to make booting faster. */
+               if (idedrive[i]->irq && !isdrive (idedrive[i]))
+                       idedrive[i]->irq = 0;
+               if (idedrive[i + 2]->irq && !isdrive (idedrive[i + 2]))
+                       idedrive[i + 2]->irq = 0;
        }
-       return 0;
+       return irq ? GAYLE_IRQ_IDE : 0;
 }
 
 void rethink_gayle (void)
@@ -405,26 +429,25 @@ static uae_u8 read_gayle_cs (void)
 
 static void ide_interrupt (void)
 {
-       if (ide->regs->ide_devcon & 2)
-               return;
-       //ide->status |= IDE_STATUS_BSY;
        ide->irq_delay = 2;
 }
 
 static void ide_interrupt_do (struct ide_hdf *ide)
 {
-       ide->status &= ~IDE_STATUS_BSY;
+       ide->regs.ide_status &= ~IDE_STATUS_BSY;
        ide->irq_delay = 0;
+       if (ide->regs.ide_devcon & 2)
+               return;
        ide->irq = 1;
        rethink_gayle ();
 }
 
 static void ide_fail_err (uae_u8 err)
 {
-       ide->regs->ide_error |= err;
-       if (ide->regs->ide_drv == 1 && idedrive[ide2 + 1]->hdhfd.size == 0)
-               idedrive[ide2]->status |= IDE_STATUS_ERR;
-       ide->status |= IDE_STATUS_ERR;
+       ide->regs.ide_error |= err;
+       if (ide->ide_drv == 1 && !isdrive (ide + 1))
+               idedrive[ide2]->regs.ide_status |= IDE_STATUS_ERR;
+       ide->regs.ide_status |= IDE_STATUS_ERR;
        ide_interrupt ();
 }
 static void ide_fail (void)
@@ -436,7 +459,7 @@ static void ide_data_ready (void)
 {
        memset (ide->secbuf, 0, ide->blocksize);
        ide->data_offset = 0;
-       ide->status |= IDE_STATUS_DRQ;
+       ide->regs.ide_status |= IDE_STATUS_DRQ;
        ide->data_size = ide->blocksize;
        ide->data_multi = 1;
        ide_interrupt ();
@@ -445,8 +468,8 @@ static void ide_data_ready (void)
 static void ide_recalibrate (void)
 {
        write_log (_T("IDE%d recalibrate\n"), ide->num);
-       ide->regs->ide_sector = 0;
-       ide->regs->ide_lcyl = ide->regs->ide_hcyl = 0;
+       ide->regs.ide_sector = 0;
+       ide->regs.ide_lcyl = ide->regs.ide_hcyl = 0;
        ide_interrupt ();
 }
 static void ide_identify_drive (void)
@@ -457,7 +480,7 @@ static void ide_identify_drive (void)
        TCHAR tmp[100];
        bool atapi = ide->atapi;
 
-       if (ide->hdhfd.size == 0) {
+       if (!isdrive (ide)) {
                ide_fail ();
                return;
        }
@@ -477,8 +500,11 @@ static void ide_identify_drive (void)
        pw (20, 3);
        pw (21, ide->blocksize);
        pw (22, 4);
-       ps (23, _T("0.4"), 8); /* firmware revision */
-       _stprintf (tmp, _T("UAE-IDE %s"), ide->hdhfd.hfd.product_id);
+       ps (23, _T("0.5"), 8); /* firmware revision */
+       if (ide->atapi)
+               _tcscpy (tmp, _T("UAE-ATAPI"));
+       else
+               _stprintf (tmp, _T("UAE-IDE %s"), ide->hdhfd.hfd.product_id);
        ps (27, tmp, 40); /* model */
        pw (47, MAX_IDE_MULTIPLE_SECTORS >> (ide->blocksize / 512 - 1)); /* max sectors in multiple mode */
        pw (48, 1);
@@ -492,9 +518,9 @@ static void ide_identify_drive (void)
        totalsecs = ide->hdhfd.cyls * ide->hdhfd.heads * ide->hdhfd.secspertrack;
        pw (57, (uae_u16)totalsecs);
        pw (58, (uae_u16)(totalsecs >> 16));
-       v = idedrive[ide->regs->ide_drv]->multiple_mode;
+       v = idedrive[ide->ide_drv]->multiple_mode;
        pw (59, (v > 0 ? 0x100 : 0) | v);
-       totalsecs = ide->hdhfd.size / ide->blocksize;
+       totalsecs = ide->blocksize ? ide->hdhfd.size / ide->blocksize : 0;
        if (totalsecs > 0x0fffffff)
                totalsecs = 0x0fffffff;
        pw (60, (uae_u16)totalsecs);
@@ -527,27 +553,31 @@ static void ide_identify_drive (void)
 
 static void ide_execute_drive_diagnostics (bool irq)
 {
-       ide->regs->ide_error = 1;
+       ide->regs.ide_error = 0x01; // device ok
        if (ide->atapi) {
-               ide->regs->ide_sector = ide->regs->ide_nsector = 1;
-               ide->regs->ide_lcyl = 0x14;
-               ide->regs->ide_hcyl = 0xeb;
+               ide->regs.ide_nsector = 1;
+               ide->regs.ide_sector = 1;
+               ide->regs.ide_lcyl = 0x14;
+               ide->regs.ide_hcyl = 0xeb;
+               ide->regs.ide_status = IDE_STATUS_BSY;
        } else {
-               ide->regs->ide_sector = ide->regs->ide_nsector = 1;
-               ide->regs->ide_select = 0;
-               ide->regs->ide_lcyl = ide->regs->ide_hcyl = 0;
+               ide->regs.ide_nsector = 1;
+               ide->regs.ide_sector = 1;
+               ide->regs.ide_lcyl = 0;
+               ide->regs.ide_hcyl = 0;
+               ide->regs.ide_status = IDE_STATUS_BSY | IDE_STATUS_DRDY;
        }
        if (irq)
                ide_interrupt ();
        else
-               ide->status &= ~IDE_STATUS_BSY;
+               ide->regs.ide_status &= ~IDE_STATUS_BSY;
 }
 
 static void ide_initialize_drive_parameters (void)
 {
        if (ide->hdhfd.size) {
-               ide->hdhfd.secspertrack = ide->regs->ide_nsector == 0 ? 256 : ide->regs->ide_nsector;
-               ide->hdhfd.heads = (ide->regs->ide_select & 15) + 1;
+               ide->hdhfd.secspertrack = ide->regs.ide_nsector == 0 ? 256 : ide->regs.ide_nsector;
+               ide->hdhfd.heads = (ide->regs.ide_select & 15) + 1;
                ide->hdhfd.cyls = (ide->hdhfd.size / ide->blocksize) / (ide->hdhfd.secspertrack * ide->hdhfd.heads);
                if (ide->hdhfd.heads * ide->hdhfd.cyls * ide->hdhfd.secspertrack > 16515072 || ide->lba48) {
                        ide->hdhfd.cyls = ide->hdhfd.cyls_def;
@@ -555,8 +585,8 @@ static void ide_initialize_drive_parameters (void)
                        ide->hdhfd.secspertrack = ide->hdhfd.secspertrack_def;
                }
        } else {
-               ide->regs->ide_error |= IDE_ERR_ABRT;
-               ide->status |= IDE_STATUS_ERR;
+               ide->regs.ide_error |= IDE_ERR_ABRT;
+               ide->regs.ide_status |= IDE_STATUS_ERR;
        }
        write_log (_T("IDE%d initialize drive parameters, CYL=%d,SPT=%d,HEAD=%d\n"),
                ide->num, ide->hdhfd.cyls, ide->hdhfd.secspertrack, ide->hdhfd.heads);
@@ -564,33 +594,33 @@ static void ide_initialize_drive_parameters (void)
 }
 static void ide_set_multiple_mode (void)
 {
-       write_log (_T("IDE%d drive multiple mode = %d\n"), ide->num, ide->regs->ide_nsector);
-       ide->multiple_mode = ide->regs->ide_nsector;
+       write_log (_T("IDE%d drive multiple mode = %d\n"), ide->num, ide->regs.ide_nsector);
+       ide->multiple_mode = ide->regs.ide_nsector;
        ide_interrupt ();
 }
 static void ide_set_features (void)
 {
-       int type = ide->regs->ide_nsector >> 3;
-       int mode = ide->regs->ide_nsector & 7;
+       int type = ide->regs.ide_nsector >> 3;
+       int mode = ide->regs.ide_nsector & 7;
 
-       write_log (_T("IDE%d set features %02X (%02X)\n"), ide->num, ide->regs->ide_feat, ide->regs->ide_nsector);
+       write_log (_T("IDE%d set features %02X (%02X)\n"), ide->num, ide->regs.ide_feat, ide->regs.ide_nsector);
        ide_fail ();
 }
 
 static void get_lbachs (struct ide_hdf *ide, uae_u64 *lbap, unsigned int *cyl, unsigned int *head, unsigned int *sec, int lba48)
 {
-       if (lba48 && (ide->regs->ide_select & 0x40)) {
+       if (lba48 && (ide->regs.ide_select & 0x40)) {
                uae_u64 lba;
-               lba = (ide->regs->ide_hcyl << 16) | (ide->regs->ide_lcyl << 8) | ide->regs->ide_sector;
-               lba |= ((ide->regs->ide_hcyl2 << 16) | (ide->regs->ide_lcyl2 << 8) | ide->regs->ide_sector2) << 24;
+               lba = (ide->regs.ide_hcyl << 16) | (ide->regs.ide_lcyl << 8) | ide->regs.ide_sector;
+               lba |= ((ide->regs.ide_hcyl2 << 16) | (ide->regs.ide_lcyl2 << 8) | ide->regs.ide_sector2) << 24;
                *lbap = lba;
        } else {
-               if (ide->regs->ide_select & 0x40) {
-                       *lbap = ((ide->regs->ide_select & 15) << 24) | (ide->regs->ide_hcyl << 16) | (ide->regs->ide_lcyl << 8) | ide->regs->ide_sector;
+               if (ide->regs.ide_select & 0x40) {
+                       *lbap = ((ide->regs.ide_select & 15) << 24) | (ide->regs.ide_hcyl << 16) | (ide->regs.ide_lcyl << 8) | ide->regs.ide_sector;
                } else {
-                       *cyl = (ide->regs->ide_hcyl << 8) | ide->regs->ide_lcyl;
-                       *head = ide->regs->ide_select & 15;
-                       *sec = ide->regs->ide_sector;
+                       *cyl = (ide->regs.ide_hcyl << 8) | ide->regs.ide_lcyl;
+                       *head = ide->regs.ide_select & 15;
+                       *sec = ide->regs.ide_sector;
                        *lbap = (((*cyl) * ide->hdhfd.heads + (*head)) * ide->hdhfd.secspertrack) + (*sec) - 1;
                }
        }
@@ -599,22 +629,22 @@ static void get_lbachs (struct ide_hdf *ide, uae_u64 *lbap, unsigned int *cyl, u
 static int get_nsec (int lba48)
 {
        if (lba48)
-               return (ide->regs->ide_nsector == 0 && ide->regs->ide_nsector2 == 0) ? 65536 : (ide->regs->ide_nsector2 * 256 + ide->regs->ide_nsector);
+               return (ide->regs.ide_nsector == 0 && ide->regs.ide_nsector2 == 0) ? 65536 : (ide->regs.ide_nsector2 * 256 + ide->regs.ide_nsector);
        else
-               return ide->regs->ide_nsector == 0 ? 256 : ide->regs->ide_nsector;
+               return ide->regs.ide_nsector == 0 ? 256 : ide->regs.ide_nsector;
 }
 static int dec_nsec (int lba48, int v)
 {
        if (lba48) {
                uae_u16 nsec;
-               nsec = ide->regs->ide_nsector2 * 256 + ide->regs->ide_nsector;
-               ide->regs->ide_nsector -= v;
-               ide->regs->ide_nsector2 = nsec >> 8;
-               ide->regs->ide_nsector = nsec & 0xff;
-               return (ide->regs->ide_nsector2 << 8) | ide->regs->ide_nsector;
+               nsec = ide->regs.ide_nsector2 * 256 + ide->regs.ide_nsector;
+               ide->regs.ide_nsector -= v;
+               ide->regs.ide_nsector2 = nsec >> 8;
+               ide->regs.ide_nsector = nsec & 0xff;
+               return (ide->regs.ide_nsector2 << 8) | ide->regs.ide_nsector;
        } else {
-               ide->regs->ide_nsector -= v;
-               return ide->regs->ide_nsector;
+               ide->regs.ide_nsector -= v;
+               return ide->regs.ide_nsector;
        }
 }
 
@@ -622,21 +652,21 @@ static void put_lbachs (struct ide_hdf *ide, uae_u64 lba, unsigned int cyl, unsi
 {
        if (lba48) {
                lba += inc;
-               ide->regs->ide_hcyl = (lba >> 16) & 0xff;
-               ide->regs->ide_lcyl = (lba >> 8) & 0xff;
-               ide->regs->ide_sector = lba & 0xff;
+               ide->regs.ide_hcyl = (lba >> 16) & 0xff;
+               ide->regs.ide_lcyl = (lba >> 8) & 0xff;
+               ide->regs.ide_sector = lba & 0xff;
                lba >>= 24;
-               ide->regs->ide_hcyl2 = (lba >> 16) & 0xff;
-               ide->regs->ide_lcyl2 = (lba >> 8) & 0xff;
-               ide->regs->ide_sector2 = lba & 0xff;
+               ide->regs.ide_hcyl2 = (lba >> 16) & 0xff;
+               ide->regs.ide_lcyl2 = (lba >> 8) & 0xff;
+               ide->regs.ide_sector2 = lba & 0xff;
        } else {
-               if (ide->regs->ide_select & 0x40) {
+               if (ide->regs.ide_select & 0x40) {
                        lba += inc;
-                       ide->regs->ide_select &= ~15;
-                       ide->regs->ide_select |= (lba >> 24) & 15;
-                       ide->regs->ide_hcyl = (lba >> 16) & 0xff;
-                       ide->regs->ide_lcyl = (lba >> 8) & 0xff;
-                       ide->regs->ide_sector = lba & 0xff;
+                       ide->regs.ide_select &= ~15;
+                       ide->regs.ide_select |= (lba >> 24) & 15;
+                       ide->regs.ide_hcyl = (lba >> 16) & 0xff;
+                       ide->regs.ide_lcyl = (lba >> 8) & 0xff;
+                       ide->regs.ide_sector = lba & 0xff;
                } else {
                        sec += inc;
                        while (sec >= ide->hdhfd.secspertrack) {
@@ -647,11 +677,11 @@ static void put_lbachs (struct ide_hdf *ide, uae_u64 lba, unsigned int cyl, unsi
                                        cyl++;
                                }
                        }
-                       ide->regs->ide_select &= ~15;
-                       ide->regs->ide_select |= head;
-                       ide->regs->ide_sector = sec;
-                       ide->regs->ide_hcyl = cyl >> 8;
-                       ide->regs->ide_lcyl = (uae_u8)cyl;
+                       ide->regs.ide_select &= ~15;
+                       ide->regs.ide_select |= head;
+                       ide->regs.ide_sector = sec;
+                       ide->regs.ide_hcyl = cyl >> 8;
+                       ide->regs.ide_lcyl = (uae_u8)cyl;
                }
        }
 }
@@ -660,7 +690,7 @@ static void check_maxtransfer (int state)
 {
        if (state == 1) {
                // transfer was started
-               if (ide->maxtransferstate < 2 && ide->regs->ide_nsector == 0) {
+               if (ide->maxtransferstate < 2 && ide->regs.ide_nsector == 0) {
                        ide->maxtransferstate = 1;
                } else if (ide->maxtransferstate == 2) {
                        // second transfer was started (part of split)
@@ -702,7 +732,7 @@ static void ide_read_sectors (int flags)
        }
        ide->data_multi = multi ? ide->multiple_mode : 1;
        ide->data_offset = 0;
-       ide->status |= IDE_STATUS_DRQ;
+       ide->regs.ide_status |= IDE_STATUS_DRQ;
        ide->data_size = nsec * ide->blocksize;
        ide_interrupt ();
 }
@@ -718,7 +748,7 @@ static void ide_write_sectors (int flags)
                ide_fail ();
                return;
        }
-       check_maxtransfer(1);
+       check_maxtransfer (1);
        gui_flicker_led (LED_HD, ide->num, 2);
        nsec = get_nsec (lba48);
        get_lbachs (ide, &lba, &cyl, &head, &sec, lba48);
@@ -738,18 +768,24 @@ static void ide_write_sectors (int flags)
        }
        ide->data_multi = multi ? ide->multiple_mode : 1;
        ide->data_offset = 0;
-       ide->status |= IDE_STATUS_DRQ;
+       ide->regs.ide_status |= IDE_STATUS_DRQ;
        ide->data_size = nsec * ide->blocksize;
 }
 
 static void atapi_packet (void)
 {
-       ide->regs->ide_error = 1; /* C/D = 1 */
-       ide->status = IDE_STATUS_DRQ;
-       ide->data_size = (ide->regs->ide_hcyl << 8) | ide->regs->ide_lcyl;
+       ide->data_size = (ide->regs.ide_hcyl << 8) | ide->regs.ide_lcyl;
        if (ide->data_size == 65535)
                ide->data_size = 65534;
-
+       ide->packet_data_size = (ide->data_size + 1) & ~1;
+       ide->data_size = 12;
+       write_log (_T("ATAPI packet command\n"));
+       ide->packet_cnt = 1;
+       ide->data_multi = 1;
+       ide->data_offset = 0;
+       ide->regs.ide_status = IDE_STATUS_DRQ;
+       ide->regs.ide_nsector = ATAPI_CD;
+       ide->regs.ide_error = 0;
 }
 
 static void ide_do_command (uae_u8 cmd)
@@ -758,63 +794,120 @@ static void ide_do_command (uae_u8 cmd)
 
        if (IDE_LOG > 1)
                write_log (_T("**** IDE%d command %02X\n"), ide->num, cmd);
-       ide->status &= ~ (IDE_STATUS_DRDY | IDE_STATUS_DRQ | IDE_STATUS_ERR);
-       ide->regs->ide_error = 0;
+       ide->regs.ide_status &= ~ (IDE_STATUS_DRDY | IDE_STATUS_DRQ | IDE_STATUS_ERR);
+       ide->regs.ide_error = 0;
 
        if (ide->atapi) {
+
                if (cmd == 0x08) { /* device reset */
-                       ide_execute_drive_diagnostics (false);
+                       ide_execute_drive_diagnostics (true);
                } else if (cmd == 0xa1) { /* identify packet device */
                        ide_identify_drive ();
                } else if (cmd == 0xa0) { /* packet */
                        atapi_packet ();
+               } else {
+                       ide_execute_drive_diagnostics (false);
+                       ide_fail ();
+                       write_log (_T("IDE%d: unknown ATAPI command 0x%02x\n"), ide->num, cmd);
                }
-       }
 
-       if (cmd == 0x10) { /* recalibrate */
-               ide_recalibrate ();
-       } else if (cmd == 0xec) { /* identify drive */
-               ide_identify_drive ();
-       } else if (cmd == 0x90) { /* execute drive diagnostics */
-               ide_execute_drive_diagnostics (true);
-       } else if (cmd == 0x91) { /* initialize drive parameters */
-               ide_initialize_drive_parameters ();
-       } else if (cmd == 0xc6) { /* set multiple mode */
-               if (ide->atapi)
-                       ide_fail ();
-               else
+       } else {
+
+               if (cmd == 0x10) { /* recalibrate */
+                       ide_recalibrate ();
+               } else if (cmd == 0xec) { /* identify drive */
+                       ide_identify_drive ();
+               } else if (cmd == 0x90) { /* execute drive diagnostics */
+                       ide_execute_drive_diagnostics (true);
+               } else if (cmd == 0x91) { /* initialize drive parameters */
+                       ide_initialize_drive_parameters ();
+               } else if (cmd == 0xc6) { /* set multiple mode */
                        ide_set_multiple_mode ();
-       } else if (cmd == 0x20 || cmd == 0x21) { /* read sectors */
-               ide_read_sectors (0);
-       } else if (cmd == 0x24 && lba48) { /* read sectors ext */
-               ide_read_sectors (2);
-       } else if (cmd == 0xc4) { /* read multiple */
-               ide_read_sectors (1);
-       } else if (cmd == 0x29 && lba48) { /* read multiple ext */
-               ide_read_sectors (1|2);
-       } else if (cmd == 0x30 || cmd == 0x31) { /* write sectors */
-               ide_write_sectors (0);
-       } else if (cmd == 0x34 && lba48) { /* write sectors ext */
-               ide_write_sectors (2);
-       } else if (cmd == 0xc5) { /* write multiple */
-               ide_write_sectors (1);
-       } else if (cmd == 0x39 && lba48) { /* write multiple ext */
-               ide_write_sectors (1|2);
-       } else if (cmd == 0x50) { /* format track (nop) */
-               ide_interrupt ();
-       } else if (cmd == 0xef) { /* set features  */
-               ide_set_features ();
-       } else if (cmd == 0x00) { /* nop */
-               ide_fail ();
-       } else if (cmd == 0xe0 || cmd == 0xe1 || cmd == 0xe7 || cmd == 0xea) { /* standby now/idle/flush cache/flush cache ext */
-               ide_interrupt ();
-       } else if (cmd == 0xe5) { /* check power mode */
-               ide->regs->ide_nsector = 0xff;
-               ide_interrupt ();
+               } else if (cmd == 0x20 || cmd == 0x21) { /* read sectors */
+                       ide_read_sectors (0);
+               } else if (cmd == 0x24 && lba48) { /* read sectors ext */
+                       ide_read_sectors (2);
+               } else if (cmd == 0xc4) { /* read multiple */
+                       ide_read_sectors (1);
+               } else if (cmd == 0x29 && lba48) { /* read multiple ext */
+                       ide_read_sectors (1|2);
+               } else if (cmd == 0x30 || cmd == 0x31) { /* write sectors */
+                       ide_write_sectors (0);
+               } else if (cmd == 0x34 && lba48) { /* write sectors ext */
+                       ide_write_sectors (2);
+               } else if (cmd == 0xc5) { /* write multiple */
+                       ide_write_sectors (1);
+               } else if (cmd == 0x39 && lba48) { /* write multiple ext */
+                       ide_write_sectors (1|2);
+               } else if (cmd == 0x50) { /* format track (nop) */
+                       ide_interrupt ();
+               } else if (cmd == 0xef) { /* set features  */
+                       ide_set_features ();
+               } else if (cmd == 0x00) { /* nop */
+                       ide_fail ();
+               } else if (cmd == 0xe0 || cmd == 0xe1 || cmd == 0xe7 || cmd == 0xea) { /* standby now/idle/flush cache/flush cache ext */
+                       ide_interrupt ();
+               } else if (cmd == 0xe5) { /* check power mode */
+                       ide->regs.ide_nsector = 0xff;
+                       ide_interrupt ();
+               } else {
+                       ide_fail ();
+                       write_log (_T("IDE%d: unknown ATA command 0x%02x\n"), ide->num, cmd);
+               }
+       }
+}
+
+static void atapi_data_done (void)
+{
+       ide->regs.ide_nsector = ATAPI_IO | ATAPI_CD;
+       ide->regs.ide_status = IDE_STATUS_DRDY;
+}
+
+static void do_packet_command (void)
+{
+       memcpy (ide->scsi.cmd, ide->secbuf, 12);
+       ide->scsi.cmd_len = 12;
+       if (IDE_LOG > 0) {
+               uae_u8 *c = ide->scsi.cmd;
+               write_log (_T("SCSI %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"),
+                       c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11], c[12]);
+       }
+       ide->packet_cnt = 0;
+       scsi_emulate_analyze (&ide->scsi);
+       if (ide->scsi.direction <= 0) {
+               // data in
+               scsi_emulate_cmd (&ide->scsi);
+               ide->data_size = ide->scsi.data_len;
+               if (ide->data_size > ide->packet_data_size)
+                       ide->data_size = ide->packet_data_size;
+               ide->data_offset = 0;
+               ide->regs.ide_status = 0;
+               if (ide->scsi.status) {
+                       // error
+                       ide->regs.ide_status = ATAPI_STATUS_CHK;
+                       ide->regs.ide_error = ide->scsi.status << 4;
+                       atapi_data_done ();
+               } else if (ide->scsi.data_len) {
+                       // data
+                       ide->regs.ide_status = IDE_STATUS_DRQ;
+                       memcpy (ide->secbuf, ide->scsi.buffer, ide->scsi.data_len);
+                       ide->packet_cnt = -1;
+                       ide->regs.ide_nsector = ATAPI_IO;
+               } else {
+                       // no data
+                       atapi_data_done ();
+               }
        } else {
-               ide_fail ();
-               write_log (_T("IDE%d: unknown command %x\n"), ide->num, cmd);
+               // data out
+               ide->regs.ide_status = IDE_STATUS_DRQ;
+               ide->packet_cnt = -1;
+               ide->regs.ide_nsector = 0;
+               ide->data_size = ide->scsi.data_len;
+               if (ide->data_size > ide->packet_data_size)
+                       ide->data_size = ide->packet_data_size;
        }
+       ide->regs.ide_lcyl = ide->data_size & 0xff;
+       ide->regs.ide_hcyl = ide->data_size >> 8;
 }
 
 static uae_u16 ide_get_data (void)
@@ -829,49 +922,65 @@ static uae_u16 ide_get_data (void)
                write_log (_T("IDE%d DATA read\n"), ide->num);
        if (ide->data_size == 0) {
                if (IDE_LOG > 0)
-                       write_log (_T("IDE%d DATA read without DRQ!?\n"), ide->num);
-               if (ide->hdhfd.size == 0)
+                       write_log (_T("IDE%d DATA read without DRQ!? PC=%08X\n"), ide->num, m68k_getpc ());
+               if (!isdrive (ide))
                        return 0xffff;
                return 0;
        }
-       nsec = 0;
-       if (ide->data_offset == 0 && ide->data_size >= 0) {
-               get_lbachs (ide, &lba, &cyl, &head, &sec, ide->lba48);
-               nsec = get_nsec (ide->lba48);
-               if (nsec * ide->blocksize > ide->hdhfd.size - lba * ide->blocksize)
-                       nsec = (ide->hdhfd.size - lba * ide->blocksize) / ide->blocksize;
-               if (nsec <= 0) {
-                       ide_data_ready ();
-                       ide_fail_err (IDE_ERR_IDNF);
-                       return 0;
+       if (ide->packet_cnt) {
+               v = ide->secbuf[ide->data_offset + 1] | (ide->secbuf[ide->data_offset + 0] << 8);
+               ide->data_offset += 2;
+               if (ide->data_size < 0)
+                       ide->data_size += 2;
+               else
+                       ide->data_size -= 2;
+               if (ide->data_size == 0) {
+                       ide->packet_cnt = 0;
+                       atapi_data_done ();
+                       if (IDE_LOG > 1)
+                               write_log (_T("IDE%d ATAPI read finished\n"), ide->num);
+                       irq = true;
                }
-               if (nsec > ide->data_multi)
-                       nsec = ide->data_multi;
-               hdf_read (&ide->hdhfd.hfd, ide->secbuf, lba * ide->blocksize, nsec * ide->blocksize);
-               if (!dec_nsec (ide->lba48, nsec))
-                       last = true;
-               if (IDE_LOG > 1)
-                       write_log (_T("IDE%d read, read %d bytes to buffer\n"), ide->num, nsec * ide->blocksize);
-       }
-
-       v = ide->secbuf[ide->data_offset + 1] | (ide->secbuf[ide->data_offset + 0] << 8);
-       ide->data_offset += 2;
-       if (ide->data_size < 0) {
-               ide->data_size += 2;
        } else {
-               ide->data_size -= 2;
-               if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) {
-                       irq = true;
-                       ide->data_offset = 0;
+               nsec = 0;
+               if (ide->data_offset == 0 && ide->data_size >= 0) {
+                       get_lbachs (ide, &lba, &cyl, &head, &sec, ide->lba48);
+                       nsec = get_nsec (ide->lba48);
+                       if (nsec * ide->blocksize > ide->hdhfd.size - lba * ide->blocksize)
+                               nsec = (ide->hdhfd.size - lba * ide->blocksize) / ide->blocksize;
+                       if (nsec <= 0) {
+                               ide_data_ready ();
+                               ide_fail_err (IDE_ERR_IDNF);
+                               return 0;
+                       }
+                       if (nsec > ide->data_multi)
+                               nsec = ide->data_multi;
+                       hdf_read (&ide->hdhfd.hfd, ide->secbuf, lba * ide->blocksize, nsec * ide->blocksize);
+                       if (!dec_nsec (ide->lba48, nsec))
+                               last = true;
+                       if (IDE_LOG > 1)
+                               write_log (_T("IDE%d read, read %d bytes to buffer\n"), ide->num, nsec * ide->blocksize);
+               }
+
+               v = ide->secbuf[ide->data_offset + 1] | (ide->secbuf[ide->data_offset + 0] << 8);
+               ide->data_offset += 2;
+               if (ide->data_size < 0) {
+                       ide->data_size += 2;
+               } else {
+                       ide->data_size -= 2;
+                       if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) {
+                               irq = true;
+                               ide->data_offset = 0;
+                       }
+               }
+               if (ide->data_size == 0) {
+                       ide->regs.ide_status &= ~IDE_STATUS_DRQ;
+                       if (IDE_LOG > 1)
+                               write_log (_T("IDE%d read finished\n"), ide->num);
+               }
+               if (nsec) {
+                       put_lbachs (ide, lba, cyl, head, sec, last ? nsec - 1 : nsec, ide->lba48);
                }
-       }
-       if (ide->data_size == 0) {
-               ide->status &= ~IDE_STATUS_DRQ;
-               if (IDE_LOG > 1)
-                       write_log (_T("IDE%d read finished\n"), ide->num);
-       }
-       if (nsec) {
-               put_lbachs (ide, lba, cyl, head, sec, last ? nsec - 1 : nsec, ide->lba48);
        }
        if (irq) {
                ide_interrupt ();
@@ -898,28 +1007,44 @@ static void ide_write_drive (bool last)
 
 static void ide_put_data (uae_u16 v)
 {
-       int irq = 0;
+       bool irq = false;
 
        if (IDE_LOG > 4)
                write_log (_T("IDE%d DATA write %04x %d/%d\n"), ide->num, v, ide->data_offset, ide->data_size);
        if (ide->data_size == 0) {
                if (IDE_LOG > 0)
-                       write_log (_T("IDE%d DATA write without DRQ!?\n"), ide->num);
+                       write_log (_T("IDE%d DATA write without DRQ!? PC=%08X\n"), ide->num, m68k_getpc ());
                return;
        }
        ide->secbuf[ide->data_offset + 1] = v & 0xff;
        ide->secbuf[ide->data_offset + 0] = v >> 8;
        ide->data_offset += 2;
        ide->data_size -= 2;
-       if (ide->data_size == 0) {
-               irq = 1;
-               ide_write_drive (true);
-               ide->status &= ~IDE_STATUS_DRQ;
-               if (IDE_LOG > 1)
-                       write_log (_T("IDE%d write finished\n"), ide->num);
-       } else if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) {
-               irq = 1;
-               ide_write_drive (false);
+       if (ide->packet_cnt) {
+               if (ide->data_size == 0) {
+                       if (ide->packet_cnt > 0) {
+                               do_packet_command ();
+                       } else if (ide->packet_cnt < 0) {
+                               ide->packet_cnt = 0;
+                               memcpy (&ide->scsi.buffer, ide->secbuf, ide->data_size);
+                               ide->scsi.data_len = ide->data_size;
+                               scsi_emulate_cmd (&ide->scsi);
+                               if (IDE_LOG > 1)
+                                       write_log (_T("IDE%d ATAPI write finished\n"), ide->num);
+                       }
+                       irq = true;
+               }
+       } else {
+               if (ide->data_size == 0) {
+                       irq = true;
+                       ide_write_drive (true);
+                       ide->regs.ide_status &= ~IDE_STATUS_DRQ;
+                       if (IDE_LOG > 1)
+                               write_log (_T("IDE%d write finished\n"), ide->num);
+               } else if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) {
+                       irq = 1;
+                       ide_write_drive (false);
+               }
        }
        if (irq)
                ide_interrupt ();
@@ -929,7 +1054,7 @@ static int get_gayle_ide_reg (uaecptr addr)
 {
        uaecptr a = addr;
        addr &= 0xffff;
-       if (addr >= 0x3020 && addr <= 0x3021 && currprefs.cs_ide == IDE_A4000)
+       if (addr >= GAYLE_IRQ_4000 && addr <= GAYLE_IRQ_4000 + 1 && currprefs.cs_ide == IDE_A4000)
                return -1;
        addr &= ~0x2020;
        addr >>= 2;
@@ -940,74 +1065,84 @@ static int get_gayle_ide_reg (uaecptr addr)
                        addr &= ~0x400;
                }
        }
-       ide = idedrive[ide2 + (ide->regs->ide_drv ? 1 : 0)];
+       ide = idedrive[ide2 + (ide->ide_drv ? 1 : 0)];
        return addr;
 }
 
 static uae_u32 ide_read_reg (int ide_reg)
 {
        uae_u8 v = 0;
-       bool isdrive = ide->hdhfd.size != 0;
+       bool isdrv = isdrive (ide);
+
+       if (ide->regs.ide_status & IDE_STATUS_BSY)
+               ide_reg = IDE_STATUS;
+       if (!isdrive (ide)) {
+               v = 0;
+               goto end;
+       }
 
        switch (ide_reg)
        {
        case IDE_DRVADDR:
-               v = ((ide->regs->ide_drv ? 2 : 1) | ((ide->regs->ide_select & 15) << 2)) ^ 0xff;
+               v = ((ide->ide_drv ? 2 : 1) | ((ide->regs.ide_select & 15) << 2)) ^ 0xff;
                break;
        case IDE_DATA:
                break;
        case IDE_ERROR:
-               v = ide->regs->ide_error;
+               v = ide->regs.ide_error;
                break;
        case IDE_NSECTOR:
-               if (isdrive) {
-                       if (ide->regs->ide_devcon & 0x80)
-                               v = ide->regs->ide_nsector2;
+               if (isdrv) {
+                       if (ide->regs.ide_devcon & 0x80)
+                               v = ide->regs.ide_nsector2;
                        else
-                               v = ide->regs->ide_nsector;
+                               v = ide->regs.ide_nsector;
                }
                break;
        case IDE_SECTOR:
-               if (isdrive) {
-                       if (ide->regs->ide_devcon & 0x80)
-                               v = ide->regs->ide_sector2;
+               if (isdrv) {
+                       if (ide->regs.ide_devcon & 0x80)
+                               v = ide->regs.ide_sector2;
                        else
-                               v = ide->regs->ide_sector;
+                               v = ide->regs.ide_sector;
                        check_maxtransfer (2);
                }
                break;
        case IDE_LCYL:
-               if (isdrive) {
-                       if (ide->regs->ide_devcon & 0x80)
-                               v = ide->regs->ide_lcyl2;
+               if (isdrv) {
+                       if (ide->regs.ide_devcon & 0x80)
+                               v = ide->regs.ide_lcyl2;
                        else
-                               v = ide->regs->ide_lcyl;
+                               v = ide->regs.ide_lcyl;
                }
                break;
        case IDE_HCYL:
-               if (isdrive) {
-                       if (ide->regs->ide_devcon & 0x80)
-                               v = ide->regs->ide_hcyl2;
+               if (isdrv) {
+                       if (ide->regs.ide_devcon & 0x80)
+                               v = ide->regs.ide_hcyl2;
                        else
-                               v = ide->regs->ide_hcyl;
+                               v = ide->regs.ide_hcyl;
                }
                break;
        case IDE_SELECT:
-               v = ide->regs->ide_select;
+               v = ide->regs.ide_select;
                break;
        case IDE_STATUS:
-               ide->irq = 0; /* fall through */
+               ide->irq = 0;
+               /* fall through */
        case IDE_DEVCON: /* ALTSTATUS when reading */
-               if (!isdrive) {
+               if (!isdrv) {
                        v = 0;
-                       if (ide->regs->ide_error)
+                       if (ide->regs.ide_error)
                                v |= IDE_STATUS_ERR;
                } else {
-                       v = ide->status;
-                       v |= IDE_STATUS_DRDY | IDE_STATUS_DSC;
+                       v = ide->regs.ide_status;
+                       if (!ide->atapi)
+                               v |= IDE_STATUS_DRDY | IDE_STATUS_DSC;
                }
                break;
        }
+end:
        if (IDE_LOG > 2 && ide_reg > 0 && (1 || ide->num > 0))
                write_log (_T("IDE%d GET register %d->%02X\n"), ide->num, ide_reg, (uae_u32)v & 0xff);
        return v;
@@ -1015,7 +1150,7 @@ static uae_u32 ide_read_reg (int ide_reg)
 
 static void ide_write_reg (int ide_reg, uae_u32 val)
 {
-       ide->regs->ide_devcon &= ~0x80; /* clear HOB */
+       ide->regs.ide_devcon &= ~0x80; /* clear HOB */
        if (IDE_LOG > 2 && ide_reg > 0 && (1 || ide->num > 0))
                write_log (_T("IDE%d PUT register %d=%02X\n"), ide->num, ide_reg, (uae_u32)val & 0xff);
        switch (ide_reg)
@@ -1023,39 +1158,45 @@ static void ide_write_reg (int ide_reg, uae_u32 val)
        case IDE_DRVADDR:
                break;
        case IDE_DEVCON:
-               if ((ide->regs->ide_devcon & 4) == 0 && (val & 4) != 0)
+               if ((ide->regs.ide_devcon & 4) == 0 && (val & 4) != 0)
                        ide_execute_drive_diagnostics (false);
-               ide->regs->ide_devcon = val;
+               ide->regs.ide_devcon = val;
                break;
        case IDE_DATA:
                break;
        case IDE_ERROR:
-               ide->regs->ide_feat2 = ide->regs->ide_feat;
-               ide->regs->ide_feat = val;
+               ide->regs.ide_feat2 = ide->regs.ide_feat;
+               ide->regs.ide_feat = val;
                break;
        case IDE_NSECTOR:
-               ide->regs->ide_nsector2 = ide->regs->ide_nsector;
-               ide->regs->ide_nsector = val;
+               ide->regs.ide_nsector2 = ide->regs.ide_nsector;
+               ide->regs.ide_nsector = val;
                break;
        case IDE_SECTOR:
-               ide->regs->ide_sector2 = ide->regs->ide_sector;
-               ide->regs->ide_sector = val;
+               ide->regs.ide_sector2 = ide->regs.ide_sector;
+               ide->regs.ide_sector = val;
                break;
        case IDE_LCYL:
-               ide->regs->ide_lcyl2 = ide->regs->ide_lcyl;
-               ide->regs->ide_lcyl = val;
+               ide->regs.ide_lcyl2 = ide->regs.ide_lcyl;
+               ide->regs.ide_lcyl = val;
                break;
        case IDE_HCYL:
-               ide->regs->ide_hcyl2 = ide->regs->ide_hcyl;
-               ide->regs->ide_hcyl = val;
+               ide->regs.ide_hcyl2 = ide->regs.ide_hcyl;
+               ide->regs.ide_hcyl = val;
                break;
        case IDE_SELECT:
-               ide->regs->ide_select = val;
-               ide->regs->ide_drv = (val & 0x10) ? 1 : 0;
+               ide->regs0->ide_select = val;
+               ide->regs1->ide_select = val;
+#if IDE_LOG > 2
+               if (ide->ide_drv != (val & 0x10) ? 1 : 0)
+                       write_log (_T("DRIVE=%d\n"), (val & 0x10) ? 1 : 0);
+#endif
+               ide->pair->ide_drv = ide->ide_drv = (val & 0x10) ? 1 : 0;
                break;
        case IDE_STATUS:
                ide->irq = 0;
-               ide_do_command (val);
+               if (isdrive (ide))
+                       ide_do_command (val);
                break;
        }
 }
@@ -1066,7 +1207,7 @@ static uae_u32 gayle_read2 (uaecptr addr)
        uae_u8 v = 0;
 
        addr &= 0xffff;
-       if ((IDE_LOG > 2 && (addr != 0x2000 && addr != 0x2001 && addr != 0x2020 && addr != 0x2021 && addr != GAYLE_IRQ_1200)) || IDE_LOG > 4)
+       if ((IDE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x3020 && addr != 0x3021 && addr != GAYLE_IRQ_1200)) || IDE_LOG > 5)
                write_log (_T("IDE_READ %08X PC=%X\n"), addr, M68K_GETPC);
        if (currprefs.cs_ide <= 0) {
                if (addr == 0x201c) // AR1200 IDE detection hack
@@ -1092,7 +1233,7 @@ static uae_u32 gayle_read2 (uaecptr addr)
        }
        ide_reg = get_gayle_ide_reg (addr);
        /* Emulated "ide killer". Prevents long KS boot delay if no drives installed */
-       if (idedrive[0]->hdhfd.size == 0 && idedrive[2]->hdhfd.size == 0) {
+       if (!isdrive (idedrive[0]) && !isdrive (idedrive[1]) && !isdrive (idedrive[2]) && !isdrive (idedrive[3])) {
                if (ide_reg == IDE_STATUS)
                        return 0x7f;
                return 0xff;
@@ -1104,7 +1245,7 @@ static void gayle_write2 (uaecptr addr, uae_u32 val)
 {
        int ide_reg;
 
-       if ((IDE_LOG > 2 && (addr != 0x2000 && addr != 0x2001 && addr != 0x2020 && addr != 0x2021 && addr != GAYLE_IRQ_1200)) || IDE_LOG > 4)
+       if ((IDE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x2020 && addr != 0x2021 && addr != GAYLE_IRQ_1200)) || IDE_LOG > 5)
                write_log (_T("IDE_WRITE %08X=%02X PC=%X\n"), addr, (uae_u32)val & 0xff, M68K_GETPC);
        if (currprefs.cs_ide <= 0)
                return;
@@ -1562,8 +1703,10 @@ static void alloc_ide_mem (struct ide_hdf **ide, int max)
        int i;
 
        for (i = 0; i < max; i++) {
-               if (!ide[i])
+               if (!ide[i]) {
                        ide[i] = xcalloc (struct ide_hdf, 1);
+                       ide[i]->cd_unit_num = -1;
+               }
        }
 }
 
@@ -1575,14 +1718,38 @@ static struct ide_hdf *add_ide_unit (int ch, struct uaedev_config_info *ci)
        ide = idedrive[ch];
        if (ci)
                memcpy (&ide->hdhfd.hfd.ci, ci, sizeof (struct uaedev_config_info));
-       if (!hdf_hd_open (&ide->hdhfd))
-               return NULL;
-       ide->blocksize = ide->hdhfd.hfd.ci.blocksize;
-       ide->lba48 = ide->hdhfd.size >= 128 * (uae_u64)0x40000000 ? 1 : 0;
-       ide->status = 0;
+       if (ci->cd_emu_unit >= 0) {
+               device_func_init (0);
+               ide->cd_unit_num = ci->cd_emu_unit;
+               if (!sys_command_open (ide->cd_unit_num)) {
+                       write_log (_T("IDE: CD EMU unit %d failed to open\n"), ide->cd_unit_num);
+                       return NULL;
+               }
+               ide->atapi = true;
+               ide->blocksize = 512;
+               gui_flicker_led (LED_CD, ch, -1);
+               ide->scsi.cd_emu_unit = ide->cd_unit_num;
+
+               write_log (_T("IDE%d CD %d\n"), ch, ide->cd_unit_num);
+
+       } else {
+               if (!hdf_hd_open (&ide->hdhfd))
+                       return NULL;
+               ide->blocksize = ide->hdhfd.hfd.ci.blocksize;
+               ide->lba48 = ide->hdhfd.size >= 128 * (uae_u64)0x40000000 ? 1 : 0;
+               gui_flicker_led (LED_HD, ch, -1);
+               ide->cd_unit_num = -1;
+
+               write_log (_T("IDE%d HD '%s', LCHS=%d/%d/%d. PCHS=%d/%d/%d %uM. LBA48=%d\n"),
+                       ch, ide->hdhfd.hfd.ci.rootdir,
+                       ide->hdhfd.cyls, ide->hdhfd.heads, ide->hdhfd.secspertrack,
+                       ide->hdhfd.hfd.ci.pcyls, ide->hdhfd.hfd.ci.pheads, ide->hdhfd.hfd.ci.psecs,
+                       (int)(ide->hdhfd.size / (1024 * 1024)), ide->lba48);
+
+       }
+       ide->regs.ide_status = 0;
        ide->data_offset = 0;
        ide->data_size = 0;
-       gui_flicker_led (LED_HD, ch, -1);
        return ide;
 }
 
@@ -1610,7 +1777,7 @@ static int get_pcmcmia_ide_reg (uaecptr addr, int width)
                addr |= 1;
        }
        ide = idedrive[PCMCIA_IDE_ID * 2];
-       if (ide->regs->ide_drv)
+       if (ide->ide_drv)
                ide = idedrive[PCMCIA_IDE_ID * 2 + 1];
        if (pcmcia_configured == 1) {
                // IO mapped linear
@@ -2260,8 +2427,13 @@ void gayle_free_units (void)
        for (i = 0; i < TOTAL_IDE * 2; i++) {
                struct ide_hdf *ide = idedrive[i];
                if (ide) {
-                       hdf_hd_close (&ide->hdhfd);
+                       if (ide->cd_unit_num >= 0) {
+                               sys_command_close (ide->cd_unit_num);
+                       } else {
+                               hdf_hd_close (&ide->hdhfd);
+                       }
                        memset (ide, 0, sizeof (struct ide_hdf));
+                       ide->cd_unit_num = -1;
                }
        }
        freepcmcia (1);
@@ -2296,11 +2468,6 @@ int gayle_add_ide_unit (int ch, struct uaedev_config_info *ci)
        ide = add_ide_unit (ch, ci);
        if (ide == NULL)
                return 0;
-       write_log (_T("GAYLE_IDE%d '%s', LCHS=%d/%d/%d. PCHS=%d/%d/%d %uM. LBA48=%d\n"),
-               ch, ide->hdhfd.hfd.ci.rootdir,
-               ide->hdhfd.cyls, ide->hdhfd.heads, ide->hdhfd.secspertrack,
-               ide->hdhfd.hfd.ci.pcyls, ide->hdhfd.hfd.ci.pheads, ide->hdhfd.hfd.ci.psecs,
-               (int)(ide->hdhfd.size / (1024 * 1024)), ide->lba48);
        ide->type = IDE_GAYLE;
        //dumphdf (&ide->hdhfd.hfd);
        return 1;
@@ -2340,19 +2507,20 @@ static void initide (void)
        if (isrestore ())
                return;
        for (i = 0; i < TOTAL_IDE; i++) {
-               ideregs[i].ide_error = 1;
-               ideregs[i].ide_sector = ideregs[i].ide_nsector = 1;
-               ideregs[i].ide_select = 0;
-               ideregs[i].ide_lcyl = ideregs[i].ide_hcyl = ideregs[i].ide_devcon = ideregs[i].ide_feat = 0;
-               idedrive[i * 2 + 0]->regs = &ideregs[i];
-               idedrive[i * 2 + 1]->regs = &ideregs[i];
                ide = idedrive[i * 2 + 0];
+               ide->regs0 = &ide->regs;
+               ide->regs1 = &idedrive[i * 2 + 1]->regs;
+               ide->pair = idedrive[i * 2 + 1];
                ide_execute_drive_diagnostics (false);
+
                ide = idedrive[i * 2 + 1];
+               ide->regs1 = &ide->regs;
+               ide->regs0 = &idedrive[i * 2 + 0]->regs;
+               ide->pair = idedrive[i * 2 + 0];
                ide_execute_drive_diagnostics (false);
        }
        ide_splitter = 0;
-       if (idedrive[2]->hdhfd.size) {
+       if (isdrive (idedrive[2]) || isdrive(idedrive[3])) {
                ide_splitter = 1;
                write_log (_T("IDE splitter enabled\n"));
        }
@@ -2440,19 +2608,19 @@ uae_u8 *save_ide (int num, int *len, uae_u8 *dstptr)
        save_u32 (ide->hdhfd.cyls);
        save_u32 (ide->hdhfd.heads);
        save_u32 (ide->hdhfd.secspertrack);
-       save_u8 (ide->regs->ide_select);
-       save_u8 (ide->regs->ide_nsector);
-       save_u8 (ide->regs->ide_nsector2);
-       save_u8 (ide->regs->ide_sector);
-       save_u8 (ide->regs->ide_sector2);
-       save_u8 (ide->regs->ide_lcyl);
-       save_u8 (ide->regs->ide_lcyl2);
-       save_u8 (ide->regs->ide_hcyl);
-       save_u8 (ide->regs->ide_hcyl2);
-       save_u8 (ide->regs->ide_feat);
-       save_u8 (ide->regs->ide_feat2);
-       save_u8 (ide->regs->ide_error);
-       save_u8 (ide->regs->ide_devcon);
+       save_u8 (ide->regs.ide_select);
+       save_u8 (ide->regs.ide_nsector);
+       save_u8 (ide->regs.ide_nsector2);
+       save_u8 (ide->regs.ide_sector);
+       save_u8 (ide->regs.ide_sector2);
+       save_u8 (ide->regs.ide_lcyl);
+       save_u8 (ide->regs.ide_lcyl2);
+       save_u8 (ide->regs.ide_hcyl);
+       save_u8 (ide->regs.ide_hcyl2);
+       save_u8 (ide->regs.ide_feat);
+       save_u8 (ide->regs.ide_feat2);
+       save_u8 (ide->regs.ide_error);
+       save_u8 (ide->regs.ide_devcon);
        save_u64 (ide->hdhfd.hfd.virtual_size);
        save_u32 (ide->hdhfd.hfd.ci.sectors);
        save_u32 (ide->hdhfd.hfd.ci.surfaces);
@@ -2481,19 +2649,19 @@ uae_u8 *restore_ide (uae_u8 *src)
        ide->hdhfd.cyls = restore_u32 ();
        ide->hdhfd.heads = restore_u32 ();
        ide->hdhfd.secspertrack = restore_u32 ();
-       ide->regs->ide_select = restore_u8 ();
-       ide->regs->ide_nsector = restore_u8 ();
-       ide->regs->ide_sector = restore_u8 ();
-       ide->regs->ide_lcyl = restore_u8 ();
-       ide->regs->ide_hcyl = restore_u8 ();
-       ide->regs->ide_feat = restore_u8 ();
-       ide->regs->ide_nsector2 = restore_u8 ();
-       ide->regs->ide_sector2 = restore_u8 ();
-       ide->regs->ide_lcyl2 = restore_u8 ();
-       ide->regs->ide_hcyl2 = restore_u8 ();
-       ide->regs->ide_feat2 = restore_u8 ();
-       ide->regs->ide_error = restore_u8 ();
-       ide->regs->ide_devcon = restore_u8 ();
+       ide->regs.ide_select = restore_u8 ();
+       ide->regs.ide_nsector = restore_u8 ();
+       ide->regs.ide_sector = restore_u8 ();
+       ide->regs.ide_lcyl = restore_u8 ();
+       ide->regs.ide_hcyl = restore_u8 ();
+       ide->regs.ide_feat = restore_u8 ();
+       ide->regs.ide_nsector2 = restore_u8 ();
+       ide->regs.ide_sector2 = restore_u8 ();
+       ide->regs.ide_lcyl2 = restore_u8 ();
+       ide->regs.ide_hcyl2 = restore_u8 ();
+       ide->regs.ide_feat2 = restore_u8 ();
+       ide->regs.ide_error = restore_u8 ();
+       ide->regs.ide_devcon = restore_u8 ();
        ide->hdhfd.hfd.virtual_size = restore_u64 ();
        ide->hdhfd.hfd.ci.sectors = restore_u32 ();
        ide->hdhfd.hfd.ci.surfaces = restore_u32 ();
index 2858dac1fd6a682d00b1a77050fae11a63f18525..d58a05a94661c2629340060916bc95c06b6a8c97 100644 (file)
@@ -52,6 +52,8 @@ static int optimized_flags;
 #define GF_FC 32
 #define GF_MOVE 64
 #define GF_IR2IRC 128
+#define GF_LRMW 256
+#define GF_NOFAULTPC 512
 
 /* For the current opcode, the next lower level that will have different code.
 * Initialized to -1 for each opcode. If it remains unchanged, indicates we
@@ -78,6 +80,8 @@ static int mmudisp020cnt;
 static char *srcl, *dstl;
 static char *srcw, *dstw;
 static char *srcb, *dstb;
+static char *srcbrmw, *srcwrmw, *srclrmw;
+static char *dstbrmw, *dstwrmw, *dstlrmw;
 static char *prefetch_long, *prefetch_word;
 static char *srcli, *srcwi, *srcbi, *nextl, *nextw, *nextb;
 static char *srcld, *dstld;
@@ -472,6 +476,26 @@ static void sync_m68k_pc (void)
        m68k_pc_offset = 0;
 }
 
+static void addmmufixup (char *reg)
+{
+       if (!using_mmu)
+               return;
+       if (using_mmu == 68040 && (mmufixupstate || mmufixupcnt > 0))
+               return;
+       printf ("\tmmufixup[%d].reg = %s;\n", mmufixupcnt, reg);
+       printf ("\tmmufixup[%d].value = m68k_areg (regs, %s);\n", mmufixupcnt, reg);
+       mmufixupstate |= 1 << mmufixupcnt;
+       mmufixupcnt++;
+}
+
+static void clearmmufixup (int cnt)
+{
+       if (mmufixupstate & (1 << cnt)) {
+               printf ("\tmmufixup[%d].reg = -1;\n", cnt);
+               mmufixupstate &= ~(1 << cnt);
+       }
+}
+
 static void gen_set_fault_pc (void)
 {
        if (using_mmu != 68040)
@@ -479,8 +503,20 @@ static void gen_set_fault_pc (void)
        sync_m68k_pc ();
        printf ("\tregs.instruction_pc = m68k_getpci ();\n");
        m68k_pc_offset = 0;
+       clearmmufixup (0);
 }
 
+static void add_mmu040_movem (int movem)
+{
+       if (movem != 3)
+               return;
+       printf ("\tif (mmu040_movem) {\n");
+       printf ("\t\tsrca = mmu040_movem_ea;\n");
+       printf ("\t} else\n");
+       start_brace ();
+}
+
+
 static void syncmovepc (int getv, int flags)
 {
 #if 0
@@ -494,26 +530,6 @@ static void syncmovepc (int getv, int flags)
 }
 
 
-static void addmmufixup (char *reg)
-{
-       if (!using_mmu)
-               return;
-       if (using_mmu == 68040 && (mmufixupstate || mmufixupcnt > 0))
-               return;
-       printf ("\tmmufixup[%d].reg = %s;\n", mmufixupcnt, reg);
-       printf ("\tmmufixup[%d].value = m68k_areg (regs, %s);\n", mmufixupcnt, reg);
-       mmufixupstate |= 1 << mmufixupcnt;
-       mmufixupcnt++;
-}
-
-static void clearmmufixup (int cnt)
-{
-       if (mmufixupstate & (1 << cnt)) {
-               printf ("\tmmufixup[%d].reg = -1;\n", cnt);
-               mmufixupstate &= ~(1 << cnt);
-       }
-}
-
 /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
 * the calling routine handles Apdi and Aipi modes.
 * gb-- movem == 2 means the same thing but for a MOVE16 instruction */
@@ -618,6 +634,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                        if (next_cpu_level < 1)
                                next_cpu_level = 1;
                        sync_m68k_pc ();
+                       add_mmu040_movem (movem);
                        start_brace ();
                        /* This would ordinarily be done in gen_nextiword, which we bypass.  */
                        insn_n_cycles += 4;
@@ -633,7 +650,9 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                }
                break;
        case PC16: // (d16,PC,Xn)
-               printf ("\tuaecptr %sa = m68k_getpc () + %d;\n", name, m68k_pc_offset);
+               printf ("\tuaecptr %sa;\n", name);
+               add_mmu040_movem (movem);
+               printf ("\t%sa = m68k_getpc () + %d;\n", name, m68k_pc_offset);
                printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags));
                break;
        case PC8r: // (d8,PC,Xn)
@@ -643,6 +662,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                        if (next_cpu_level < 1)
                                next_cpu_level = 1;
                        sync_m68k_pc ();
+                       add_mmu040_movem (movem);
                        start_brace ();
                        /* This would ordinarily be done in gen_nextiword, which we bypass.  */
                        insn_n_cycles += 4;
@@ -774,9 +794,9 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                                }
                        } else {
                                switch (size) {
-                               case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); break;
-                               case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcw, name); break;
-                               case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, srcl, name); break;
+                               case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, (flags & GF_LRMW) ? srcbrmw : srcb, name); break;
+                               case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, (flags & GF_LRMW) ? srcwrmw : srcw, name); break;
+                               case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, (flags & GF_LRMW) ? srclrmw : srcl, name); break;
                                default: abort ();
                                }
                        }
@@ -817,6 +837,10 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g
                default:
                        break;
        }
+
+       if (movem == 3) {
+               close_brace ();
+       }
 }
 
 
@@ -869,7 +893,8 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha
        case absl:
        case PC16:
        case PC8r:
-               gen_set_fault_pc ();
+               if (!(flags & GF_NOFAULTPC))
+                       gen_set_fault_pc ();
                if (using_ce020) {
                        switch (size) {
                        case sz_byte:
@@ -922,7 +947,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha
                                if (flags & GF_FC)
                                        printf ("\tdfc%s_put_byte (%sa, %s);\n", mmu_postfix, to, from);
                                else
-                                       printf ("\t%s (%sa, %s);\n", dstb, to, from);
+                                       printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstbrmw : dstb, to, from);
                                break;
                        case sz_word:
                                insn_n_cycles += 4;
@@ -931,7 +956,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha
                                if (flags & GF_FC)
                                        printf ("\tdfc%s_put_word (%sa, %s);\n", mmu_postfix, to, from);
                                else
-                                       printf ("\t%s (%sa, %s);\n", dstw, to, from);
+                                       printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstwrmw :dstw, to, from);
                                break;
                        case sz_long:
                                insn_n_cycles += 8;
@@ -940,7 +965,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha
                                if (flags & GF_FC)
                                        printf ("\tdfc%s_put_long (%sa, %s);\n", mmu_postfix, to, from);
                                else
-                                       printf ("\t%s (%sa, %s);\n", dstl, to, from);
+                                       printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstlrmw : dstl, to, from);
                                break;
                        default:
                                abort ();
@@ -987,6 +1012,14 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char
 {
        genastore_2 (from, mode, reg, size, to, 0, 0);
 }
+static void genastore_tas (char *from, amodes mode, char *reg, wordsizes size, char *to)
+{
+       genastore_2 (from, mode, reg, size, to, 0, GF_LRMW);
+}
+static void genastore_cas (char *from, amodes mode, char *reg, wordsizes size, char *to)
+{
+       genastore_2 (from, mode, reg, size, to, 0, GF_LRMW | GF_NOFAULTPC);
+}
 static void genastore_rev (char *from, amodes mode, char *reg, wordsizes size, char *to)
 {
        genastore_2 (from, mode, reg, size, to, 1, 0);
@@ -996,6 +1029,93 @@ static void genastore_fc (char *from, amodes mode, char *reg, wordsizes size, ch
        genastore_2 (from, mode, reg, size, to, 1, GF_FC);
 }
 
+static void movem_mmu060 (const char *code, int size, bool put, bool aipi, bool apdi)
+{
+       char *index;
+       int dphase, aphase;
+       if (apdi) {
+               dphase = 1; aphase = 0;
+               index = "movem_index2";
+       } else {
+               dphase = 0; aphase = 1;
+               index = "movem_index1";
+       }
+
+       for (int i = 0; i < 2; i++) {
+               char reg;
+               if (i == dphase)
+                       reg = 'd';
+               else
+                       reg = 'a';
+               printf ("\twhile (%cmask) {\n", reg);
+               if (apdi)
+                       printf ("\t\tsrca -= %d;\n", size);
+               if (put) {
+                       printf ("\t\t%s, m68k_%creg (regs, %s[%cmask]));\n", code, reg, index, reg);
+               } else {
+                       printf ("\t\tm68k_%creg (regs, %s[%cmask]) = %s;\n", reg, index, reg, code);
+               }
+               if (!apdi)
+                       printf ("\t\tsrca += %d;\n", size);
+               printf ("\t\t%cmask = movem_next[%cmask];\n", reg, reg);
+               printf ("\t}\n");
+       }
+       if (aipi || apdi)
+               printf ("\tm68k_areg (regs, dstreg) = srca;\n");
+}
+
+static bool mmu040_special_movem (uae_u16 opcode)
+{
+       if (using_mmu != 68040)
+               return false;
+       return (((((opcode >> 3) & 7) == 7) && ((opcode & 7) == 2 || (opcode & 7) == 3)) || ((opcode >> 3) & 7) == 6);
+}
+
+static void movem_mmu040 (const char *code, int size, bool put, bool aipi, bool apdi, uae_u16 opcode)
+{
+       char *index;
+       int dphase, aphase;
+       bool mvm = false;
+
+       if (apdi) {
+               dphase = 1; aphase = 0;
+               index = "movem_index2";
+       } else {
+               dphase = 0; aphase = 1;
+               index = "movem_index1";
+       }
+
+       if (mmu040_special_movem (opcode)) {
+               printf ("\tmmu040_movem = 1;\n");
+               printf ("\tmmu040_movem_ea = srca;\n");
+               mvm = true;
+       }
+
+       for (int i = 0; i < 2; i++) {
+               char reg;
+               if (i == dphase)
+                       reg = 'd';
+               else
+                       reg = 'a';
+               printf ("\twhile (%cmask) {\n", reg);
+               if (apdi)
+                       printf ("\t\tsrca -= %d;\n", size);
+               if (put) {
+                       printf ("\t\t%s, m68k_%creg (regs, %s[%cmask]));\n", code, reg, index, reg);
+               } else {
+                       printf ("\t\tm68k_%creg (regs, %s[%cmask]) = %s;\n", reg, index, reg, code);
+               }
+               if (!apdi)
+                       printf ("\t\tsrca += %d;\n", size);
+               printf ("\t\t%cmask = movem_next[%cmask];\n", reg, reg);
+               printf ("\t}\n");
+       }
+       if (aipi || apdi)
+               printf ("\tm68k_areg (regs, dstreg) = srca;\n");
+       if (mvm)
+               printf ("\tmmu040_movem = 0;\n");
+}
+
 /* 68030 MMU does not restore register state if it bus faults.
  * (also there wouldn't be enough space in stack frame to store all registers)
  */
@@ -1057,10 +1177,14 @@ static void genmovemel (uae_u16 opcode)
        count_read += table68k[opcode].size == sz_long ? 2 : 1;
        printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0));
        printf ("\tuae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
-       genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, 0);
+       genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, 0);
        start_brace ();
        if (using_mmu == 68030) {
                movem_mmu030 (getcode, size, false, table68k[opcode].dmode == Aipi, false);
+       } else if (using_mmu == 68060) {
+               movem_mmu060 (getcode, size, false, table68k[opcode].dmode == Aipi, false);
+       } else if (using_mmu == 68040) {
+               movem_mmu040 (getcode, size, false, table68k[opcode].dmode == Aipi, false, opcode);
        } else {
                printf ("\twhile (dmask) { m68k_dreg (regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n",
                        getcode, size);
@@ -1117,14 +1241,19 @@ static void genmovemle (uae_u16 opcode)
        count_write += table68k[opcode].size == sz_long ? 2 : 1;
 
        printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0));
-       genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, 0);
+       genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, 0);
        start_brace ();
-       if (using_mmu == 68030) {
+       if (using_mmu >= 68030) {
                if (table68k[opcode].dmode == Apdi)
                        printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
                else
                        printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
-               movem_mmu030 (putcode, size, true, false, table68k[opcode].dmode == Apdi);
+               if (using_mmu == 68030)
+                       movem_mmu030 (putcode, size, true, false, table68k[opcode].dmode == Apdi);
+               else if (using_mmu == 68060)
+                       movem_mmu060 (putcode, size, true, false, table68k[opcode].dmode == Apdi);
+               else if (using_mmu == 68040)
+                       movem_mmu040 (putcode, size, true, false, table68k[opcode].dmode == Apdi, opcode);
        } else {
                if (table68k[opcode].dmode == Apdi) {
                        printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
@@ -1132,9 +1261,12 @@ static void genmovemle (uae_u16 opcode)
                                printf ("\tint type = get_cpu_model () >= 68020;\n");
                        printf ("\twhile (amask) {\n");
                        printf ("\t\tsrca -= %d;\n", size);
-                       if (!using_mmu)
-                               printf ("\t\tif (type) m68k_areg (regs, dstreg) = srca;\n");
-                       printf ("\t\t%s, m68k_areg (regs, movem_index2[amask]));\n", putcode);
+
+                       printf ("\t\tif (!type || movem_index2[amask] != dstreg)\n");
+                       printf ("\t\t\t%s, m68k_areg (regs, movem_index2[amask]));\n", putcode);
+                       printf ("\t\telse\n");
+                       printf ("\t\t\t%s, m68k_areg (regs, movem_index2[amask]) - %d);\n", putcode, size);
+
                        printf ("\t\tamask = movem_next[amask];\n");
                        printf ("\t}\n");
                        printf ("\twhile (dmask) { srca -= %d; %s, m68k_dreg (regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n",
@@ -1523,6 +1655,12 @@ static void gen_opcode (unsigned long int opcode)
        do_cycles = "do_cycles";
        srcwd = srcld = NULL;
        dstwd = dstld = NULL;
+       srcbrmw = NULL;
+       srcwrmw = NULL;
+       srclrmw = NULL;
+       dstbrmw = NULL;
+       dstwrmw = NULL;
+       dstlrmw = NULL;
 
        if (using_indirect) {
                // tracer
@@ -1621,6 +1759,12 @@ static void gen_opcode (unsigned long int opcode)
                dstw = "put_word_mmu030_state";
                srcb = "get_byte_mmu030_state";
                dstb = "put_byte_mmu030_state";
+               srcbrmw = "get_rmw_byte_mmu030_state";
+               srcwrmw = "get_rmw_word_mmu030_state";
+               srclrmw = "get_rmw_long_mmu030_state";
+               dstbrmw = "put_rmw_byte_mmu030_state";
+               dstwrmw = "put_rmw_word_mmu030_state";
+               dstlrmw = "put_rmw_long_mmu030_state";
                srcld = "get_long_mmu030";
                srcwd = "get_word_mmu030";
                dstld = "put_long_mmu030";
@@ -1641,6 +1785,12 @@ static void gen_opcode (unsigned long int opcode)
                dstw = "put_word_mmu040";
                srcb = "get_byte_mmu040";
                dstb = "put_byte_mmu040";
+               srcbrmw = "get_rmw_byte_mmu040";
+               srcwrmw = "get_rmw_word_mmu040";
+               srclrmw = "get_rmw_long_mmu040";
+               dstbrmw = "put_rmw_byte_mmu040";
+               dstwrmw = "put_rmw_word_mmu040";
+               dstlrmw = "put_rmw_long_mmu040";
        } else if (using_mmu) {
                // 68060 MMU
                disp020 = "x_get_disp_ea_020";
@@ -1657,6 +1807,12 @@ static void gen_opcode (unsigned long int opcode)
                dstw = "put_word_mmu060";
                srcb = "get_byte_mmu060";
                dstb = "put_byte_mmu060";
+               srcbrmw = "get_rmw_byte_mmu060";
+               srcwrmw = "get_rmw_word_mmu060";
+               srclrmw = "get_rmw_long_mmu060";
+               dstbrmw = "put_rmw_byte_mmu060";
+               dstwrmw = "put_rmw_word_mmu060";
+               dstlrmw = "put_rmw_long_mmu060";
        } else if (using_ce) {
                // 68000 ce
                prefetch_word = "get_word_ce000_prefetch";
@@ -1702,6 +1858,14 @@ static void gen_opcode (unsigned long int opcode)
                srcld = srcl;
        if (!srcwd)
                srcwd = srcw;
+       if (!srcbrmw) {
+               srcbrmw = srcb;
+               srcwrmw = srcw;
+               srclrmw = srcl;
+               dstbrmw = dstb;
+               dstwrmw = dstw;
+               dstlrmw = dstl;
+       }
 
        insn_n_cycles020 = 0;
 
@@ -3258,10 +3422,14 @@ static void gen_opcode (unsigned long int opcode)
        case i_CAS:
                {
                        int old_brace_level;
-                       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
-                       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
+                       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_LRMW);
+                       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_LRMW);
                        if (cpu_level == 5 && curi->size > 0) {
-                               printf ("\tif ((dsta & %d) && currprefs.cpu_compatible && get_cpu_model () == 68060) {\n", curi->size == 1 ? 1 : 3);
+                               if (!using_mmu) {
+                                       printf ("\tif ((dsta & %d) && currprefs.cpu_compatible && get_cpu_model () == 68060) {\n", curi->size == 1 ? 1 : 3);
+                               } else {
+                                       printf ("\tif ((dsta & %d) && currprefs.cpu_compatible) {\n", curi->size == 1 ? 1 : 3);
+                               }
                                if (curi->dmode == Aipi || curi->dmode == Apdi)
                                        printf ("\t\tm68k_areg (regs, dstreg) %c= %d;\n", curi->dmode == Aipi ? '-' : '+', 1 << curi->size);
                                printf ("\t\top_unimpl ();\n");
@@ -3275,40 +3443,49 @@ static void gen_opcode (unsigned long int opcode)
                        printf ("\tint rc = src & 7;\n");
                        genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, rc)", "dst");
                        sync_m68k_pc ();
-                       printf ("\tif (GET_ZFLG ())");
+                       gen_set_fault_pc ();
+                       printf ("\tif (GET_ZFLG ()) ");
                        old_brace_level = n_braces;
                        start_brace ();
-                       genastore ("(m68k_dreg (regs, ru))", curi->dmode, "dstreg", curi->size, "dst");
+                       printf ("\n\t");
+                       genastore_cas ("(m68k_dreg (regs, ru))", curi->dmode, "dstreg", curi->size, "dst");
+                       printf ("\t");
                        pop_braces (old_brace_level);
                        printf ("else");
                        start_brace ();
+                       printf ("\n");
                        switch (curi->size) {
                                case sz_byte:
-                               printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xff) | (dst & 0xff);\n");
+                               printf ("\t\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xff) | (dst & 0xff);\n");
                                break;
                                case sz_word:
-                               printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xffff) | (dst & 0xffff);\n");
+                               printf ("\t\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xffff) | (dst & 0xffff);\n");
                                break;
                                default:
-                               printf ("\tm68k_dreg(regs, rc) = dst;\n");
+                               printf ("\t\tm68k_dreg(regs, rc) = dst;\n");
                                break;
                        }
+                       if (cpu_level >= 4) {
+                               // apparently 68040/060 needs to always write at the end of RMW cycle
+                               printf ("\t");
+                               genastore_cas ("dst", curi->dmode, "dstreg", curi->size, "dst");
+                       }
                        pop_braces (old_brace_level);
                }
                break;
        case i_CAS2:
-               genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
+               genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0, GF_LRMW);
                printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n");
                printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n");
                if (curi->size == sz_word) {
                        int old_brace_level = n_braces;
-                       printf ("\tuae_u16 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcw, srcw);
+                       printf ("\tuae_u16 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcwrmw, srcwrmw);
                        genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1");
                        printf ("\tif (GET_ZFLG ()) {\n");
                        genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2");
                        printf ("\tif (GET_ZFLG ()) {\n");
-                       printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstw);
-                       printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstw);
+                       printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstwrmw);
+                       printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstwrmw);
                        printf ("\t}}\n");
                        pop_braces (old_brace_level);
                        printf ("\tif (! GET_ZFLG ()) {\n");
@@ -3317,13 +3494,13 @@ static void gen_opcode (unsigned long int opcode)
                        printf ("\t}\n");
                } else {
                        int old_brace_level = n_braces;
-                       printf ("\tuae_u32 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcl, srcl);
+                       printf ("\tuae_u32 dst1 = %s (rn1), dst2 = %s (rn2);\n", srclrmw, srclrmw);
                        genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1");
                        printf ("\tif (GET_ZFLG ()) {\n");
                        genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2");
                        printf ("\tif (GET_ZFLG ()) {\n");
-                       printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstl);
-                       printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstl);
+                       printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstlrmw);
+                       printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstlrmw);
                        printf ("\t}}\n");
                        pop_braces (old_brace_level);
                        printf ("\tif (! GET_ZFLG ()) {\n");
@@ -3533,7 +3710,7 @@ static void gen_opcode (unsigned long int opcode)
                }
                break;
        case i_TAS:
-               genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+               genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_LRMW);
                genflags (flag_logical, curi->size, "src", "", "");
                if (!isreg (curi->smode))
                        addcycles000 (2);
@@ -3542,7 +3719,7 @@ static void gen_opcode (unsigned long int opcode)
                if (cpu_level >= 2 || curi->smode == Dreg || !using_ce) {
                        if (next_cpu_level < 2)
                                next_cpu_level = 2 - 1;
-                       genastore ("src", curi->smode, "srcreg", curi->size, "src");
+                       genastore_tas ("src", curi->smode, "srcreg", curi->size, "src");
                } else {
                        printf ("\tif (!is_cycle_ce ()) {\n");
                        genastore ("src", curi->smode, "srcreg", curi->size, "src");
@@ -3618,9 +3795,9 @@ static void gen_opcode (unsigned long int opcode)
                                printf ("\tuaecptr mems = m68k_areg (regs, srcreg) & ~15, memd;\n");
                                printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword (0));
                                printf ("\tmemd = m68k_areg (regs, dstreg) & ~15;\n");
-                               if (using_mmu == 68060) {
-                                       printf ("\tget_move16_mmu060 (mems, v);\n");
-                                       printf ("\tput_move16_mmu060 (memd, v);\n");
+                               if (using_mmu >= 68040) {
+                                       printf ("\tget_move16_mmu (mems, v);\n");
+                                       printf ("\tput_move16_mmu (memd, v);\n");
                                } else {
                                        printf ("\tv[0] = %s (mems);\n", srcl);
                                        printf ("\tv[1] = %s (mems + 4);\n", srcl);
@@ -3641,9 +3818,9 @@ static void gen_opcode (unsigned long int opcode)
                                genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2, 0);
                                printf ("\tmemsa &= ~15;\n");
                                printf ("\tmemda &= ~15;\n");
-                               if (using_mmu == 68060) {
-                                       printf ("\tget_move16_mmu060 (memsa, v);\n");
-                                       printf ("\tput_move16_mmu060 (memda, v);\n");
+                               if (using_mmu >= 68040) {
+                                       printf ("\tget_move16_mmu (memsa, v);\n");
+                                       printf ("\tput_move16_mmu (memda, v);\n");
                                } else {
                                        printf ("\tv[0] = %s (memsa);\n", srcl);
                                        printf ("\tv[1] = %s (memsa + 4);\n", srcl);
index 350dcfd52dd2a5ceb4ea02b2a80bed6cbe138c8c..ddbe7a71b6df2fbff4e53e6f9aa269ce0a6e726b 100644 (file)
@@ -1031,6 +1031,9 @@ int hdf_read (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len)
 {
        int v;
 
+       hf_log3 (_T("cmd_read: %p %04x-%08x (%d) %08x (%d)\n"),
+               buffer, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->ci.blocksize), (uae_u32)len, (uae_u32)(len / hfd->ci.blocksize));
+
        if (!hfd->adide) {
                v = hdf_cache_read (hfd, buffer, offset, len);
        } else {
@@ -1047,6 +1050,9 @@ int hdf_write (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len)
 {
        int v;
 
+       hf_log3 (_T("cmd_write: %p %04x-%08x (%d) %08x (%d)\n"),
+               buffer, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->ci.blocksize), (uae_u32)len, (uae_u32)(len / hfd->ci.blocksize));
+
        if (hfd->byteswap)
                hdf_byteswap (buffer, len);
        if (!hfd->adide) {
@@ -1065,8 +1071,6 @@ int hdf_write (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len)
 static uae_u64 cmd_readx (struct hardfiledata *hfd, uae_u8 *dataptr, uae_u64 offset, uae_u64 len)
 {
        gui_flicker_led (LED_HD, hfd->unitnum, 1);
-       hf_log3 (_T("cmd_read: %p %04x-%08x (%d) %08x (%d)\n"),
-               dataptr, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->ci.blocksize), (uae_u32)len, (uae_u32)(len / hfd->ci.blocksize));
        return hdf_read (hfd, dataptr, offset, len);
 }
 static uae_u64 cmd_read (struct hardfiledata *hfd, uaecptr dataptr, uae_u64 offset, uae_u64 len)
@@ -1079,8 +1083,6 @@ static uae_u64 cmd_read (struct hardfiledata *hfd, uaecptr dataptr, uae_u64 offs
 static uae_u64 cmd_writex (struct hardfiledata *hfd, uae_u8 *dataptr, uae_u64 offset, uae_u64 len)
 {
        gui_flicker_led (LED_HD, hfd->unitnum, 2);
-       hf_log3 (_T("cmd_write: %p %04x-%08x (%d) %08x (%d)\n"),
-               dataptr, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->ci.blocksize), (uae_u32)len, (uae_u32)(len / hfd->ci.blocksize));
        return hdf_write (hfd, dataptr, offset, len);
 }
 
@@ -1108,7 +1110,7 @@ static int nodisk (struct hardfiledata *hfd)
        return 0;
 }
 
-int scsi_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len,
+int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len,
        uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len)
 {
        uae_u64 len, offset;
@@ -1122,7 +1124,7 @@ int scsi_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u
        memset (r, 0, 256);
        memset (s, 0, 256);
        lun = cmdbuf[1] >> 5;
-       if (lun) {
+       if (cmdbuf[0] != 0x03 && cmdbuf[0] != 0x12 && lun) {
                status = 2; /* CHECK CONDITION */
                s[0] = 0x70;
                s[2] = 5; /* ILLEGAL REQUEST */
@@ -1173,9 +1175,14 @@ int scsi_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u
                        if ((cmdbuf[1] & 1) || cmdbuf[2] != 0)
                                goto err;
                        int alen = (cmdbuf[3] << 8) | cmdbuf[4];
-                       if (hfd->drive_empty) {
-                               r[1] |= 0x80; // removable..
-                               r[0] |= 0x20; // not present
+                       if (lun != 0) {
+                               r[0] = 0x7f;
+                       } else {
+                               r[0] = 0;
+                               if (hfd->drive_empty) {
+                                       r[1] |= 0x80; // removable..
+                                       r[0] |= 0x20; // not present
+                               }
                        }
                        r[2] = 2; /* supports SCSI-2 */
                        r[3] = 2; /* response data format */
@@ -1416,6 +1423,9 @@ int scsi_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u
                s[12] = 0x1c; /* DEFECT LIST NOT FOUND */
                ls = 12;
                break;
+       case 0x1b: /* START/STOP UNIT */
+               scsi_len = 0;
+               break;
 readprot:
                status = 2; /* CHECK CONDITION */
                s[0] = 0x70;
@@ -1433,7 +1443,7 @@ nodisk:
 
        default:
 err:
-               write_log (_T("UAEHF: unsupported scsi command 0x%02X\n"), cmdbuf[0]);
+               write_log (_T("UAEHF: unsupported scsi command 0x%02X LUN=%d\n"), cmdbuf[0], lun);
 errreq:
                lr = -1;
                status = 2; /* CHECK CONDITION */
@@ -1495,7 +1505,7 @@ static int handle_scsi (uaecptr request, struct hardfiledata *hfd)
        }
        scsi_log (_T("\n"));
 
-       status = scsi_emulate (hfd, NULL, cmdbuf, scsi_cmd_len, scsi_data_ptr, &scsi_len, reply, &reply_len, sense, &sense_len);
+       status = scsi_hd_emulate (hfd, NULL, cmdbuf, scsi_cmd_len, scsi_data_ptr, &scsi_len, reply, &reply_len, sense, &sense_len);
 
        put_word (acmd + 18, status != 0 ? 0 : scsi_cmd_len); /* fake scsi_CmdActual */
        put_byte (acmd + 21, status); /* scsi_Status */
index a2225999def032bd10c9e093c80d945c4a502427..d00edd491686728553276bed99eb707f55775a2e 100644 (file)
@@ -26,6 +26,7 @@ extern struct scsi_data *scsis[8];
 extern int a2091_add_scsi_unit (int ch, struct uaedev_config_info *ci);
 extern int a3000_add_scsi_unit (int ch, struct uaedev_config_info *ci);
 
-extern int addscsi (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int scsi_level);
+extern int add_scsi_hd (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int scsi_level);
+extern int add_scsi_cd (int ch, int unitnum);
 
 #endif
index 6638e56be84f026ea16f1eba775ee6b74978ec45..6162786d335eda7374b35d332226e77e098e7909 100644 (file)
@@ -52,10 +52,11 @@ extern uaecptr need_uae_boot_rom (void);
 
 struct mountedinfo
 {
-    uae_u64 size;
+    uae_s64 size;
     bool ismounted;
     bool ismedia;
     int nrcyls;
+       TCHAR rootdir[MAX_DPATH];
 };
 
 extern int add_filesys_unitconfig (struct uae_prefs *p, int index, TCHAR *error);
index 52f13e4efdb0a08736609074a7289bef1cd7c792..a3d72927780579456c5f0399a3f3c7030cece77c 100644 (file)
@@ -174,6 +174,7 @@ extern int sys_command_scsi_direct_native (int unitnum, struct amigascsi *as);
 extern int sys_command_scsi_direct (int unitnum, uaecptr request);
 extern int sys_command_ismedia (int unitnum, int quick);
 extern struct device_info *sys_command_info_session (int unitnum, struct device_info *di, int, int);
+extern bool blkdev_get_info (struct uae_prefs *p, int unitnum, struct device_info *di);
 
 extern void scsi_atapi_fixup_pre (uae_u8 *scsi_cmd, int *len, uae_u8 **data, int *datalen, int *parm);
 extern void scsi_atapi_fixup_post (uae_u8 *scsi_cmd, int len, uae_u8 *olddata, uae_u8 *data, int *datalen, int parm);
@@ -181,6 +182,9 @@ extern void scsi_atapi_fixup_post (uae_u8 *scsi_cmd, int len, uae_u8 *olddata, u
 extern void scsi_log_before (uae_u8 *cdb, int cdblen, uae_u8 *data, int datalen);
 extern void scsi_log_after (uae_u8 *data, int datalen, uae_u8 *sense, int senselen);
 
+extern int scsi_cd_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
+       uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len);
+
 extern void blkdev_vsync (void);
 
 extern int msf2lsn (int msf);
index c63bf69ef95e1f59616f6ce99e23be24647cef2a..63d2e206e939c53e96f88d8c3110a5d5fafbd1f8 100644 (file)
@@ -14,7 +14,7 @@ uae_u8 cdtv_battram_read (int addr);
 extern void cdtv_loadcardmem (uae_u8*, int);
 extern void cdtv_savecardmem (uae_u8*, int);
 
-extern int cdtv_add_scsi_unit (int ch, struct uaedev_config_info *ci);
+extern int cdtv_add_scsi_hd_unit (int ch, struct uaedev_config_info *ci);
 
 
 extern void cdtv_getdmadata (uae_u32*);
index 0e5d25b44f8d0caf80449bc1efd781c61d4ad2df..7c8fe43b55340d9f1de571b118e481c5aea68332 100644 (file)
 static __inline void flush_internals (void) { }
 
 extern int mmu060_state;
+extern uae_u16 mmu060_opcode;
+
+extern int mmu040_movem;
+extern uaecptr mmu040_movem_ea;
+
 extern bool mmu_pagesize_8k;
 
 //typedef uae_u8 flagtype;
@@ -342,6 +347,9 @@ extern void REGPARAM3 dfc_put_byte(uaecptr addr, uae_u8 val) REGPARAM;
 #define dfc060_put_word dfc_put_word
 #define dfc060_put_byte dfc_put_byte
 
+extern void uae_mmu_put_rmw (uaecptr addr, uae_u32 v, int size, int type);
+extern uae_u32 uae_mmu_get_rmw (uaecptr addr, int size, int type);
+
 extern void REGPARAM3 mmu_flush_atc(uaecptr addr, bool super, bool global) REGPARAM;
 extern void REGPARAM3 mmu_flush_atc_all(bool global) REGPARAM;
 extern void REGPARAM3 mmu_op_real(uae_u32 opcode, uae_u16 extra) REGPARAM;
@@ -355,7 +363,7 @@ static ALWAYS_INLINE uaecptr mmu_get_real_address(uaecptr addr, struct mmu_atc_l
     return cl->phys | (addr & mmu_pagemask);
 }
 
-static ALWAYS_INLINE void mmu060_get_move16(uaecptr addr, uae_u32 *v, bool data, int size)
+static ALWAYS_INLINE void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size)
 {
        struct mmu_atc_line *cl;
        for (int i = 0; i < 4; i++) {
@@ -421,7 +429,7 @@ static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int
                mmu_put_long_slow(addr, val, regs.s != 0, data, size, cl);
 }
 
-static ALWAYS_INLINE void mmu060_put_move16(uaecptr addr, uae_u32 *val, bool data, int size)
+static ALWAYS_INLINE void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size)
 {
        struct mmu_atc_line *cl;
        for (int i = 0; i < 4; i++) {
@@ -466,38 +474,38 @@ static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, bool data, int
                mmu_put_byte_slow(addr, val, regs.s != 0, data, size, cl);
 }
 
-static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool data, int size)
+static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool data, bool write, int size)
 {
        struct mmu_atc_line *cl;
 
        //                                       addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH))
                return phys_get_long(addr);
-       if (likely(mmu_user_lookup(addr, super, data, false, &cl)))
+       if (likely(mmu_user_lookup(addr, super, data, write, &cl)))
                return phys_get_long(mmu_get_real_address(addr, cl));
        return mmu_get_long_slow(addr, super, data, size, cl);
 }
 
-static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool data, int size)
+static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool data, bool write, int size)
 {
        struct mmu_atc_line *cl;
 
        //                                       addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH))
                return phys_get_word(addr);
-       if (likely(mmu_user_lookup(addr, super, data, false, &cl)))
+       if (likely(mmu_user_lookup(addr, super, data, write, &cl)))
                return phys_get_word(mmu_get_real_address(addr, cl));
        return mmu_get_word_slow(addr, super, data, size, cl);
 }
 
-static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool data, int size)
+static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool data, bool write, int size)
 {
        struct mmu_atc_line *cl;
 
        //                                       addr,super,data
        if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH))
                return phys_get_byte(addr);
-       if (likely(mmu_user_lookup(addr, super, data, false, &cl)))
+       if (likely(mmu_user_lookup(addr, super, data, write, &cl)))
                return phys_get_byte(mmu_get_real_address(addr, cl));
        return mmu_get_byte_slow(addr, super, data, size, cl);
 }
@@ -658,10 +666,10 @@ static ALWAYS_INLINE uae_u8 uae_mmu060_get_byte(uaecptr addr)
 {
        return mmu_get_byte(addr, true, sz_byte);
 }
-static ALWAYS_INLINE void uae_mmu060_get_move16(uaecptr addr, uae_u32 *val)
+static ALWAYS_INLINE void uae_mmu_get_move16(uaecptr addr, uae_u32 *val)
 {
        // move16 is always aligned
-       mmu060_get_move16(addr, val, true, 16);
+       mmu_get_move16(addr, val, true, 16);
 }
 
 static ALWAYS_INLINE void uae_mmu060_put_long(uaecptr addr, uae_u32 val)
@@ -682,10 +690,10 @@ static ALWAYS_INLINE void uae_mmu060_put_byte(uaecptr addr, uae_u8 val)
 {
        mmu_put_byte(addr, val, true, sz_byte);
 }
-static ALWAYS_INLINE void uae_mmu060_put_move16(uaecptr addr, uae_u32 *val)
+static ALWAYS_INLINE void uae_mmu_put_move16(uaecptr addr, uae_u32 *val)
 {
        // move16 is always aligned
-       mmu060_put_move16(addr, val, true, 16);
+       mmu_put_move16(addr, val, true, 16);
 }
 
 
@@ -739,13 +747,63 @@ STATIC_INLINE uae_u32 get_long_mmu060 (uaecptr addr)
     return uae_mmu060_get_long (addr);
 }
 
-STATIC_INLINE void get_move16_mmu060 (uaecptr addr, uae_u32 *v)
+STATIC_INLINE void get_move16_mmu (uaecptr addr, uae_u32 *v)
+{
+    return uae_mmu_get_move16 (addr, v);
+}
+STATIC_INLINE void put_move16_mmu (uaecptr addr, uae_u32 *v)
+{
+    return uae_mmu_put_move16 (addr, v);
+}
+
+STATIC_INLINE void put_rmw_byte_mmu060 (uaecptr addr, uae_u32 v)
+{
+    uae_mmu_put_rmw (addr, v, sz_byte, 1);
+}
+STATIC_INLINE void put_rmw_word_mmu060 (uaecptr addr, uae_u32 v)
+{
+    uae_mmu_put_rmw (addr, v, sz_word, 1);
+}
+STATIC_INLINE void put_rmw_long_mmu060 (uaecptr addr, uae_u32 v)
+{
+    uae_mmu_put_rmw (addr, v, sz_long, 1);
+}
+STATIC_INLINE uae_u32 get_rmw_byte_mmu060 (uaecptr addr)
+{
+    return uae_mmu_get_rmw (addr, sz_byte, 1);
+}
+STATIC_INLINE uae_u32 get_rmw_word_mmu060 (uaecptr addr)
+{
+    return uae_mmu_get_rmw (addr, sz_word, 1);
+}
+STATIC_INLINE uae_u32 get_rmw_long_mmu060 (uaecptr addr)
+{
+    return uae_mmu_get_rmw (addr, sz_long, 1);
+}
+
+STATIC_INLINE void put_rmw_byte_mmu040 (uaecptr addr, uae_u32 v)
+{
+    uae_mmu_put_rmw (addr, v, sz_byte, 0);
+}
+STATIC_INLINE void put_rmw_word_mmu040 (uaecptr addr, uae_u32 v)
+{
+    uae_mmu_put_rmw (addr, v, sz_word, 0);
+}
+STATIC_INLINE void put_rmw_long_mmu040 (uaecptr addr, uae_u32 v)
+{
+    uae_mmu_put_rmw (addr, v, sz_long, 0);
+}
+STATIC_INLINE uae_u32 get_rmw_byte_mmu040 (uaecptr addr)
+{
+    return uae_mmu_get_rmw (addr, sz_byte, 0);
+}
+STATIC_INLINE uae_u32 get_rmw_word_mmu040 (uaecptr addr)
 {
-    return uae_mmu060_get_move16 (addr, v);
+    return uae_mmu_get_rmw (addr, sz_word, 0);
 }
-STATIC_INLINE void put_move16_mmu060 (uaecptr addr, uae_u32 *v)
+STATIC_INLINE uae_u32 get_rmw_long_mmu040 (uaecptr addr)
 {
-    return uae_mmu060_put_move16 (addr, v);
+    return uae_mmu_get_rmw (addr, sz_long, 0);
 }
 
 STATIC_INLINE uae_u32 get_ibyte_mmu040 (int o)
index 565e37dad94cdcd359951752a4d2680efe847238..0ae8b857c95b9b58edb2fbc25aa4fcee94016603 100644 (file)
@@ -71,89 +71,95 @@ void mmu030_reset(int hardreset);
 uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write);
 
 int mmu030_match_ttr(uaecptr addr, uae_u32 fc, bool write);
+int mmu030_match_ttr_access(uaecptr addr, uae_u32 fc, bool write);
+int mmu030_match_rmw_ttr(uaecptr addr, uae_u32 fc);
 int mmu030_do_match_ttr(uae_u32 tt, TT_info masks, uaecptr addr, uae_u32 fc, bool write);
+int mmu030_do_match_rmw_ttr(uae_u32 tt, TT_info masks, uaecptr addr, uae_u32 fc);
 
-void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc, int size);
-void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc, int size);
-void mmu030_put_byte(uaecptr addr, uae_u8  val, uae_u32 fc, int size);
-uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc, int size);
-uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc, int size);
-uae_u8  mmu030_get_byte(uaecptr addr, uae_u32 fc, int size);
+void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc);
+void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc);
+void mmu030_put_byte(uaecptr addr, uae_u8  val, uae_u32 fc);
+uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc);
+uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc);
+uae_u8  mmu030_get_byte(uaecptr addr, uae_u32 fc);
 
-void mmu030_page_fault(uaecptr addr, bool read, int size);
+uae_u32 uae_mmu030_get_rmw(uaecptr addr, int size);
+void uae_mmu030_put_rmw(uaecptr addr, uae_u32 val, int size);
 
-extern uae_u16 REGPARAM3 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc) REGPARAM;
-extern uae_u32 REGPARAM3 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc) REGPARAM;
-extern void REGPARAM3 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc) REGPARAM;
-extern void REGPARAM3 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc) REGPARAM;
+extern uae_u16 REGPARAM3 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
+extern uae_u32 REGPARAM3 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
+extern uae_u16 REGPARAM3 mmu030_get_rmw_word_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
+extern uae_u32 REGPARAM3 mmu030_get_rmw_long_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM;
+extern void REGPARAM3 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc, int flags) REGPARAM;
+extern void REGPARAM3 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc, int flags) REGPARAM;
 
 static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong(uaecptr addr)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 2;
 
        if (unlikely(is_unaligned(addr, 4)))
-               return mmu030_get_long_unaligned(addr, fc);
-       return mmu030_get_long(addr, fc, sz_long);
+               return mmu030_get_long_unaligned(addr, fc, 0);
+       return mmu030_get_long(addr, fc);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu030_get_iword(uaecptr addr)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 2;
 
        if (unlikely(is_unaligned(addr, 2)))
-               return mmu030_get_word_unaligned(addr, fc);
-       return mmu030_get_word(addr, fc, sz_word);
+               return mmu030_get_word_unaligned(addr, fc, 0);
+       return mmu030_get_word(addr, fc);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu030_get_ibyte(uaecptr addr)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 2;
 
-       return mmu030_get_byte(addr, fc, sz_byte);
+       return mmu030_get_byte(addr, fc);
 }
 static ALWAYS_INLINE uae_u32 uae_mmu030_get_long(uaecptr addr)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
 
        if (unlikely(is_unaligned(addr, 4)))
-               return mmu030_get_long_unaligned(addr, fc);
-       return mmu030_get_long(addr, fc, sz_long);
+               return mmu030_get_long_unaligned(addr, fc, 0);
+       return mmu030_get_long(addr, fc);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu030_get_word(uaecptr addr)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
 
        if (unlikely(is_unaligned(addr, 2)))
-               return mmu030_get_word_unaligned(addr, fc);
-       return mmu030_get_word(addr, fc, sz_word);
+               return mmu030_get_word_unaligned(addr, fc, 0);
+       return mmu030_get_word(addr, fc);
 }
 static ALWAYS_INLINE uae_u8 uae_mmu030_get_byte(uaecptr addr)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
 
-       return mmu030_get_byte(addr, fc, sz_byte);
+       return mmu030_get_byte(addr, fc);
 }
 static ALWAYS_INLINE void uae_mmu030_put_long(uaecptr addr, uae_u32 val)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
     
        if (unlikely(is_unaligned(addr, 4)))
-               mmu030_put_long_unaligned(addr, val, fc);
+               mmu030_put_long_unaligned(addr, val, fc, 0);
        else
-               mmu030_put_long(addr, val, fc, sz_long);
+               mmu030_put_long(addr, val, fc);
 }
 static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u16 val)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
 
        if (unlikely(is_unaligned(addr, 2)))
-               mmu030_put_word_unaligned(addr, val, fc);
+               mmu030_put_word_unaligned(addr, val, fc, 0);
        else
-               mmu030_put_word(addr, val, fc, sz_word);
+               mmu030_put_word(addr, val, fc);
 }
 static ALWAYS_INLINE void uae_mmu030_put_byte(uaecptr addr, uae_u8 val)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
 
-       mmu030_put_byte(addr, val, fc, sz_byte);
+       mmu030_put_byte(addr, val, fc);
 }
 
 static ALWAYS_INLINE uae_u32 sfc030_get_long(uaecptr addr)
@@ -163,8 +169,8 @@ static ALWAYS_INLINE uae_u32 sfc030_get_long(uaecptr addr)
        write_log(_T("sfc030_get_long: FC = %i\n"),fc);
 #endif
        if (unlikely(is_unaligned(addr, 4)))
-               return mmu030_get_long_unaligned(addr, fc);
-       return mmu030_get_long(addr, fc, sz_long);
+               return mmu030_get_long_unaligned(addr, fc, 0);
+       return mmu030_get_long(addr, fc);
 }
 
 static ALWAYS_INLINE uae_u16 sfc030_get_word(uaecptr addr)
@@ -174,8 +180,8 @@ static ALWAYS_INLINE uae_u16 sfc030_get_word(uaecptr addr)
        write_log(_T("sfc030_get_word: FC = %i\n"),fc);
 #endif
     if (unlikely(is_unaligned(addr, 2)))
-               return mmu030_get_word_unaligned(addr, fc);
-       return mmu030_get_word(addr, fc, sz_word);
+               return mmu030_get_word_unaligned(addr, fc, 0);
+       return mmu030_get_word(addr, fc);
 }
 
 static ALWAYS_INLINE uae_u8 sfc030_get_byte(uaecptr addr)
@@ -184,7 +190,7 @@ static ALWAYS_INLINE uae_u8 sfc030_get_byte(uaecptr addr)
 #if MMUDEBUG > 1
        write_log(_T("sfc030_get_byte: FC = %i\n"),fc);
 #endif
-       return mmu030_get_byte(addr, fc, sz_byte);
+       return mmu030_get_byte(addr, fc);
 }
 
 static ALWAYS_INLINE void dfc030_put_long(uaecptr addr, uae_u32 val)
@@ -194,9 +200,9 @@ static ALWAYS_INLINE void dfc030_put_long(uaecptr addr, uae_u32 val)
        write_log(_T("dfc030_put_long: FC = %i\n"),fc);
 #endif
     if (unlikely(is_unaligned(addr, 4)))
-               mmu030_put_long_unaligned(addr, val, fc);
+               mmu030_put_long_unaligned(addr, val, fc, 0);
        else
-               mmu030_put_long(addr, val, fc, sz_long);
+               mmu030_put_long(addr, val, fc);
 }
 
 static ALWAYS_INLINE void dfc030_put_word(uaecptr addr, uae_u16 val)
@@ -206,9 +212,9 @@ static ALWAYS_INLINE void dfc030_put_word(uaecptr addr, uae_u16 val)
        write_log(_T("dfc030_put_word: FC = %i\n"),fc);
 #endif
        if (unlikely(is_unaligned(addr, 2)))
-               mmu030_put_word_unaligned(addr, val, fc);
+               mmu030_put_word_unaligned(addr, val, fc, 0);
        else
-               mmu030_put_word(addr, val, fc, sz_word);
+               mmu030_put_word(addr, val, fc);
 }
 
 static ALWAYS_INLINE void dfc030_put_byte(uaecptr addr, uae_u8 val)
@@ -217,7 +223,7 @@ static ALWAYS_INLINE void dfc030_put_byte(uaecptr addr, uae_u8 val)
 #if MMUDEBUG > 1
        write_log(_T("dfc030_put_byte: FC = %i\n"),fc);
 #endif
-       mmu030_put_byte(addr, val, fc, sz_byte);
+       mmu030_put_byte(addr, val, fc);
 }
 
 #define ACCESS_CHECK_PUT \
@@ -260,18 +266,37 @@ STATIC_INLINE void put_byte_mmu030_state (uaecptr addr, uae_u32 v)
     uae_mmu030_put_byte (addr, v);
        ACCESS_EXIT_PUT
 }
+STATIC_INLINE void put_rmw_byte_mmu030_state (uaecptr addr, uae_u32 v)
+{
+       ACCESS_CHECK_PUT
+    uae_mmu030_put_rmw (addr, v, sz_byte);
+       ACCESS_EXIT_PUT
+}
 STATIC_INLINE void put_word_mmu030_state (uaecptr addr, uae_u32 v)
 {
        ACCESS_CHECK_PUT
     uae_mmu030_put_word (addr, v);
        ACCESS_EXIT_PUT
 }
+STATIC_INLINE void put_rmw_word_mmu030_state (uaecptr addr, uae_u32 v)
+{
+       ACCESS_CHECK_PUT
+    uae_mmu030_put_rmw (addr, v, sz_word);
+       ACCESS_EXIT_PUT
+}
 STATIC_INLINE void put_long_mmu030_state (uaecptr addr, uae_u32 v)
 {
        ACCESS_CHECK_PUT
     uae_mmu030_put_long (addr, v);
        ACCESS_EXIT_PUT
 }
+STATIC_INLINE void put_rmw_long_mmu030_state (uaecptr addr, uae_u32 v)
+{
+       ACCESS_CHECK_PUT
+    uae_mmu030_put_rmw (addr, v, sz_long);
+       ACCESS_EXIT_PUT
+}
+
 STATIC_INLINE uae_u32 get_byte_mmu030_state (uaecptr addr)
 {
        uae_u32 v;
@@ -280,6 +305,15 @@ STATIC_INLINE uae_u32 get_byte_mmu030_state (uaecptr addr)
        ACCESS_EXIT_GET
        return v;
 }
+STATIC_INLINE uae_u32 get_rmw_byte_mmu030_state (uaecptr addr)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET
+    v = uae_mmu030_get_rmw (addr, sz_byte);
+       ACCESS_EXIT_GET
+       return v;
+}
+
 STATIC_INLINE uae_u32 get_word_mmu030_state (uaecptr addr)
 {
        uae_u32 v;
@@ -288,6 +322,14 @@ STATIC_INLINE uae_u32 get_word_mmu030_state (uaecptr addr)
        ACCESS_EXIT_GET
        return v;
 }
+STATIC_INLINE uae_u32 get_rmw_word_mmu030_state (uaecptr addr)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET
+    v = uae_mmu030_get_rmw (addr, sz_word);
+       ACCESS_EXIT_GET
+       return v;
+}
 STATIC_INLINE uae_u32 get_long_mmu030_state (uaecptr addr)
 {
        uae_u32 v;
@@ -296,6 +338,15 @@ STATIC_INLINE uae_u32 get_long_mmu030_state (uaecptr addr)
        ACCESS_EXIT_GET
        return v;
 }
+STATIC_INLINE uae_u32 get_rmw_long_mmu030_state (uaecptr addr)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET
+    v = uae_mmu030_get_rmw (addr, sz_long);
+       ACCESS_EXIT_GET
+       return v;
+}
+
 STATIC_INLINE uae_u32 get_ibyte_mmu030_state (int o)
 {
        uae_u32 v;
index be46aa4659c22bc5cae4545c1bff68bbef66af8c..fe7a03428c9344fd7c93703c263a049687733037 100644 (file)
@@ -79,6 +79,7 @@ typedef enum {
     NUMSG_MODRIP_NOTFOUND, NUMSG_MODRIP_FINISHED, NUMSG_MODRIP_SAVE,
     NUMSG_KS68EC020, NUMSG_KS68020, NUMSG_KS68030,
     NUMSG_ROMNEED, NUMSG_EXPROMNEED, NUMSG_NOZLIB, NUMSG_STATEHD,
-    NUMSG_NOCAPS, NUMSG_OLDCAPS, NUMSG_KICKREP, NUMSG_KICKREPNO
+    NUMSG_NOCAPS, NUMSG_OLDCAPS, NUMSG_KICKREP, NUMSG_KICKREPNO,
+       NUMSG_KS68030PLUS
 } notify_user_msg;
 
index 2738f460abb299b1ac32d2e015fefd53001ad128..a681a1315d55680a463271e84f0a3649738ee7b5 100644 (file)
@@ -49,12 +49,14 @@ typedef  int m68k_exception;
 #define MMU_FSLW_LK            0x02000000
 #define MMU_FSLW_R             0x01000000
 #define MMU_FSLW_W             0x00800000
-#define MMU_FSLW_SIZE_B        0x00000000
+#define MMU_FSLW_SIZE_L        0x00000000 /* Note: wrong in mc68060 manual! */
+#define MMU_FSLW_SIZE_B        0x00200000
 #define MMU_FSLW_SIZE_W        0x00400000
-#define MMU_FSLW_SIZE_L        0x00200000
 #define MMU_FSLW_SIZE_D        0x00600000
 #define MMU_FSLW_TT            0x00180000
-#define MMU_FSLW_TM            0x00070000
+#define MMU_FSLW_TT_N  0x00000000 /* Normal access */
+#define MMU_FSLW_TT_16  0x00080000 /* MOVE16 */
+#define MMU_FSLW_TM            0x00070000 /* = function code */
 #define MMU_FSLW_IO            0x00008000
 #define MMU_FSLW_PBE   0x00004000
 #define MMU_FSLW_SBE   0x00002000
@@ -73,6 +75,8 @@ typedef  int m68k_exception;
 /* 68040 */
 #define MMU_SSW_TM             0x0007
 #define MMU_SSW_TT             0x0018
+#define MMU_SSW_TT1            0x0010
+#define MMU_SSW_TT0            0x0008
 #define MMU_SSW_SIZE   0x0060
 #define MMU_SSW_SIZE_B 0x0020
 #define MMU_SSW_SIZE_W 0x0040
index c69892c0206b2a17b979aaee4231580ccbc68c3b..0680b784a4e3faaf61176291c75f044b7a06b9ec 100644 (file)
@@ -108,7 +108,11 @@ struct wh {
 };
 
 #define MOUNT_CONFIG_SIZE 30
+#define UAEDEV_DIR 0
+#define UAEDEV_HDF 1
+#define UAEDEV_CD 2
 struct uaedev_config_info {
+       int type;
        TCHAR devname[MAX_DPATH];
        TCHAR volname[MAX_DPATH];
        TCHAR rootdir[MAX_DPATH];
@@ -138,6 +142,8 @@ struct uaedev_config_info {
        int unit;
        int interleave;
        int sectorsperblock;
+       int forceload;
+       int cd_emu_unit;
 
 };
 
@@ -145,7 +151,6 @@ struct uaedev_config_data
 {
        struct uaedev_config_info ci;
        int configoffset;
-       bool ishdf;
 };
 
 enum { CP_GENERIC = 1, CP_CDTV, CP_CD32, CP_A500, CP_A500P, CP_A600, CP_A1000,
@@ -571,7 +576,7 @@ extern void cfgfile_target_write_str (struct zfile *f, const TCHAR *option, cons
 extern void cfgfile_target_dwrite_str (struct zfile *f, const TCHAR *option, const TCHAR *value);
 
 extern void cfgfile_backup (const TCHAR *path);
-extern struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, struct uaedev_config_info*, bool hdf);
+extern struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, struct uaedev_config_info*);
 extern bool get_hd_geometry (struct uaedev_config_info *);
 extern void uci_set_defaults (struct uaedev_config_info *uci, bool rdb);
 
index 9e80cf020541e8b95d99d5a1541d20421fc34f8e..b6152c040c045d4c0428a021526c9869a706d92a 100644 (file)
@@ -18,10 +18,12 @@ struct scsi_data
     uae_u8 buffer[SCSI_DATA_BUFFER_SIZE];
     struct hd_hardfiledata *hfd;
     int nativescsiunit;
+       int cd_emu_unit;
 };
 
-extern struct scsi_data *scsi_alloc(int,struct hd_hardfiledata*);
-extern struct scsi_data *scsi_alloc_native(int,int);
+extern struct scsi_data *scsi_alloc_hd(int, struct hd_hardfiledata*);
+extern struct scsi_data *scsi_alloc_cd(int, int);
+extern struct scsi_data *scsi_alloc_native(int, int);
 extern void scsi_free(struct scsi_data*);
 extern void scsi_reset(void);
 
@@ -30,6 +32,6 @@ extern int scsi_send_data(struct scsi_data*, uae_u8);
 extern int scsi_receive_data(struct scsi_data*, uae_u8*);
 extern void scsi_emulate_cmd(struct scsi_data *sd);
 
-extern int scsi_emulate(struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len,
+extern int scsi_hd_emulate(struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len,
                uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len);
 extern void scsi_emulate_analyze (struct scsi_data*);
\ No newline at end of file
index 6afcd6df53d29be042fa2fef5c85761a52ab5c7a..8c2d6e6db835eff4040804b354a3f2967e5bb32a 100644 (file)
@@ -2490,7 +2490,10 @@ void memory_reset (void)
                        struct romdata *rd = getromdatabydata (kickmemory, kickmem_size);
                        if (rd) {
                                write_log (_T("Known ROM '%s' loaded\n"), rd->name);
-                               if ((rd->cpu & 3) == 3 && changed_prefs.cpu_model != 68030) {
+                               if ((rd->cpu & 8) && changed_prefs.cpu_model < 68030) {
+                                       notify_user (NUMSG_KS68030PLUS);
+                                       uae_restart (-1, NULL);
+                               } else if ((rd->cpu & 3) == 3 && changed_prefs.cpu_model != 68030) {
                                        notify_user (NUMSG_KS68030);
                                        uae_restart (-1, NULL);
                                } else if ((rd->cpu & 3) == 1 && changed_prefs.cpu_model < 68020) {
index aadbdc17566fd492065093dd3a47e5a8abaf0618..376ba9239154db07977ab106b83e6e07a489f360 100644 (file)
@@ -4267,7 +4267,7 @@ retry:
                for (;;) {
                        pc = regs.instruction_pc = m68k_getpc ();
                        mmu060_state = 0;
-                       opcode = x_prefetch (0);
+                       mmu060_opcode = opcode = x_prefetch (0);
                        mmu060_state = 1;
                        count_instr (opcode);
                        do_cycles (cpu_cycles);
@@ -4317,6 +4317,14 @@ retry:
        TRY (prb) {
                for (;;) {
                        pc = regs.instruction_pc = m68k_getpc ();
+
+#if 0
+                       if (pc == 0x000fa01c) {
+                               write_log (_T("*"));
+                               //activate_debugger ();
+                       }
+#endif
+
                        opcode = x_prefetch (0);
                        count_instr (opcode);
                        do_cycles (cpu_cycles);
@@ -4375,8 +4383,8 @@ insretry:
                        pc = regs.instruction_pc = m68k_getpc ();
 
                        mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0;
-#if 1
-                       if (pc == 0x1000) {
+#if 0
+                       if (pc == 0x00109FFC) {
                                write_log (_T("*"));
                                //activate_debugger ();
                        }
@@ -5052,13 +5060,16 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                        }
                        pc += 2;
                } else if (lookup->mnemo == i_MVMEL) {
+                       uae_u16 mask = get_word_debug (pc);
+                       pc += 2;
                        pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                        _tcscat (instrname, _T(","));
-                       movemout (instrname, get_word_debug (pc), dp->dmode);
+                       movemout (instrname, mask, dp->dmode);
                        pc += 2;
                } else if (lookup->mnemo == i_MVMLE) {
-                       movemout (instrname, get_word_debug (pc), dp->dmode);
+                       uae_u16 mask = get_word_debug (pc);
                        pc += 2;
+                       movemout (instrname, mask, dp->dmode);
                        _tcscat (instrname, _T(","));
                        pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                } else {
@@ -5085,12 +5096,13 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                        buf = buf_out (buf, &bufsize, _T(" ]"));
 
                if (ccpt != 0) {
+                       uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
                        if (deaddr)
                                *deaddr = pc;
                        if (cctrue (dp->cc))
-                               buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), seaddr2);
+                               buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2);
                        else
-                               buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), seaddr2);
+                               buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2);
                } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
                        if (deaddr)
                                *deaddr = pc;
index 263c93e7e83bb8c6f250ee78d5e07581032ba2e4..b55431e0532c68ee9f5ff143a67a7cb96d1007c3 100644 (file)
@@ -45,7 +45,7 @@
     <ConfigurationType>Application</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
     <UseOfAtl>false</UseOfAtl>
-    <CharacterSet>Unicode</CharacterSet>
+    <CharacterSet>MultiByte</CharacterSet>
     <PlatformToolset>v110</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
index 7c63a1c1d5dd5717292a4ffb632576c28824146a..526c9acd924055dcacacecabe85a25db9a6ddefe 100644 (file)
@@ -180,8 +180,8 @@ bool preinit_shm (void)
        }
 
        natmem_size = (max_allowed_mman + 1) * 1024 * 1024;
-       if (natmem_size < 256 * 1024 * 1024)
-               natmem_size = 256 * 1024 * 1024;
+       if (natmem_size < 17 * 1024 * 1024)
+               natmem_size = 17 * 1024 * 1024;
 
        write_log (_T("Total physical RAM %lluM, all RAM %lluM. Attempting to reserve: %uM.\n"), totalphys64 >> 20, total64 >> 20, natmem_size >> 20);
        natmem_offset = 0;
@@ -203,12 +203,21 @@ bool preinit_shm (void)
                                break;
                        natmem_size -= 128 * 1024 * 1024;
                        if (!natmem_size) {
-                               write_log (_T("Can't allocate 256M of virtual address space!?\n"));
-                               return false;
+                               write_log (_T("Can't allocate 257M of virtual address space!?\n"));
+                               natmem_size = 17 * 1024 * 1024;
+                               natmem_offset = (uae_u8*)VirtualAlloc (NULL, natmem_size, MEM_RESERVE | (VAMODE == 1 ? MEM_WRITE_WATCH : 0), PAGE_READWRITE);
+                               if (!natmem_size) {
+                                       write_log (_T("Can't allocate 17M of virtual address space!? Something is seriously wrong\n"));
+                                       return false;
+                               }
+                               break;
                        }
                }
        }
-       max_z3fastmem = natmem_size;
+       if (natmem_size <= 257 * 1024 * 1024)
+               max_z3fastmem = 0;
+       else
+               max_z3fastmem = natmem_size;
        write_log (_T("Reserved: 0x%p-0x%p (%08x %dM)\n"),
                natmem_offset, (uae_u8*)natmem_offset + natmem_size,
                natmem_size, natmem_size >> 20);
@@ -737,6 +746,8 @@ void *shmat (int shmid, void *shmaddr, int shmflg)
                                size += BARRIER;
                } else if(!_tcscmp (shmids[shmid].name, _T("ramsey_low"))) {
                        shmaddr=natmem_offset + a3000lmem_start;
+                       if (!a3000hmem_start)
+                               size += BARRIER;
                        got = TRUE;
                } else if(!_tcscmp (shmids[shmid].name, _T("ramsey_high"))) {
                        shmaddr=natmem_offset + a3000hmem_start;
diff --git a/od-win32/resources/RCa02620 b/od-win32/resources/RCa02620
new file mode 100644 (file)
index 0000000..9bdff41
Binary files /dev/null and b/od-win32/resources/RCa02620 differ
diff --git a/od-win32/resources/RCa06412 b/od-win32/resources/RCa06412
new file mode 100644 (file)
index 0000000..c953cbc
Binary files /dev/null and b/od-win32/resources/RCa06412 differ
diff --git a/od-win32/resources/RCb02620 b/od-win32/resources/RCb02620
new file mode 100644 (file)
index 0000000..9bdff41
Binary files /dev/null and b/od-win32/resources/RCb02620 differ
diff --git a/od-win32/resources/RCb06412 b/od-win32/resources/RCb06412
new file mode 100644 (file)
index 0000000..c953cbc
Binary files /dev/null and b/od-win32/resources/RCb06412 differ
index e7416216b955742445346d09efec4ac7530bdf98..93f4ed6fd4bcdfcf3804eb713cc011657a2f745f 100644 (file)
@@ -27,6 +27,7 @@
 #define IDS_CHIPSET2                    20
 #define IDS_GAMEPORTS                   21
 #define IDS_EXPANSION                   22
+#define IDS_STRING23                    23
 #define IDS_EXTTEXT                     100
 #define IDS_EXTACTUAL                   101
 #define IDS_SOUND                       102
 #define IDD_LIST                        386
 #define IDS_MISCLISTITEMS1              386
 #define IDS_MISCLISTITEMS2              387
+#define IDD_CDDRIVE                     387
 #define IDS_MISCLISTITEMS3              388
 #define IDS_WHEELMOUSE                  389
 #define IDS_JOYMODE_WHEELMOUSE          389
+#define IDS_NUMSG_KS68030PLUS           390
 #define IDS_QS_MODELS                   1000
 #define IDS_QS_MODEL_A500               1001
 #define IDS_QS_MODEL_A500P              1002
 #define IDC_PORT0                       1342
 #define IDC_NEW_FSARCH                  1342
 #define IDC_PORT1                       1343
+#define IDC_NEW_CD                      1344
 #define IDC_PATH_NAME                   1362
 #define IDC_SELECTOR                    1363
 #define IDC_VOLUME_NAME                 1364
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NO_MFC                     1
 #define _APS_3D_CONTROLS                     1
-#define _APS_NEXT_RESOURCE_VALUE        387
+#define _APS_NEXT_RESOURCE_VALUE        388
 #define _APS_NEXT_COMMAND_VALUE         40050
 #define _APS_NEXT_CONTROL_VALUE         1815
 #define _APS_NEXT_SYMED_VALUE           101
index 5c6e0ba51679cf8f6afd708ca5f264be7ed5e1a2..056a6f7e04c7d1d28dd02ffc20427495d0ca4375 100644 (file)
@@ -321,6 +321,7 @@ BEGIN
     COMBOBOX        IDC_CD_TYPE,282,279,71,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
     PUSHBUTTON      "Eject",IDC_CD_EJECT,360,278,30,15
     COMBOBOX        IDC_CD_TEXT,5,297,386,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+    PUSHBUTTON      "Add SCSI/IDE CD Drive",IDC_NEW_CD,135,176,126,15
 END
 
 IDD_SOUND DIALOGEX 0, 0, 396, 288
@@ -1107,6 +1108,17 @@ BEGIN
     CONTROL         "",IDC_LISTDIALOG_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,7,302,171
 END
 
+IDD_CDDRIVE DIALOGEX 0, 0, 396, 109
+STYLE DS_LOCALEDIT | DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | DS_CENTERMOUSE | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "CD Settings"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
+BEGIN
+    RTEXT           "HD Controller:",IDC_STATIC,12,90,65,10,SS_CENTERIMAGE
+    COMBOBOX        IDC_HDF_CONTROLLER,91,89,61,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
+    DEFPUSHBUTTON   "Add CD Drive",IDOK,236,87,73,14
+    PUSHBUTTON      "Cancel",IDCANCEL,316,87,73,14
+END
+
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -1262,12 +1274,10 @@ GUIDELINES DESIGNINFO
 BEGIN
     IDD_KICKSTART, DIALOG
     BEGIN
-        BOTTOMMARGIN, 214
     END
 
     IDD_DISPLAY, DIALOG
     BEGIN
-        BOTTOMMARGIN, 270
     END
 
     IDD_MEMORY, DIALOG
@@ -1296,7 +1306,6 @@ BEGIN
 
     IDD_IOPORTS, DIALOG
     BEGIN
-        BOTTOMMARGIN, 293
     END
 
     IDD_GAMEPORTS, DIALOG
@@ -1345,12 +1354,10 @@ BEGIN
 
     IDD_FILTER, DIALOG
     BEGIN
-        BOTTOMMARGIN, 286
     END
 
     IDD_HARDDRIVE, DIALOG
     BEGIN
-        BOTTOMMARGIN, 108
     END
 
     IDD_MISC2, DIALOG
@@ -1399,7 +1406,6 @@ BEGIN
 
     IDD_INPUTMAP, DIALOG
     BEGIN
-        TOPMARGIN, 1
     END
 
     IDD_INFOBOX, DIALOG
@@ -1408,10 +1414,10 @@ BEGIN
 
     IDD_LIST, DIALOG
     BEGIN
-        LEFTMARGIN, 7
-        RIGHTMARGIN, 309
-        TOPMARGIN, 7
-        BOTTOMMARGIN, 199
+    END
+
+    IDD_CDDRIVE, DIALOG
+    BEGIN
     END
 END
 #endif    // APSTUDIO_INVOKED
@@ -1803,6 +1809,7 @@ BEGIN
     IDS_MISCLISTITEMS2      "Always on top\nDisable screensaver\nSynchronize clock\nFaster RTG\nClipboard sharing\nAllow native code\n"
     IDS_MISCLISTITEMS3      "Native on-screen display\nRTG on-screen display\nCreate winuaelog.txt log\nLog illegal memory accesses\nBlank unused displays\nStart mouse uncaptured\nStart minimized\nMinimize when focus is lost\n"
     IDS_JOYMODE_WHEELMOUSE  "Wheel Mouse"
+    IDS_NUMSG_KS68030PLUS   "The selected system ROM requires a 68030 or higher CPU."
 END
 
 #endif    // English resources
index 734fab4bcf6722bbba1a7ef2ab5b1af8b5bbf812..b962759d2a492477a2c958499bc8670328b1f8ca 100644 (file)
 #define LANG_DLL 1
 
 #if WINUAEPUBLICBETA
-#define WINUAEBETA _T("1")
+#define WINUAEBETA _T("2")
 #else
 #define WINUAEBETA _T("")
 #endif
-#define WINUAEDATE MAKEBD(2013, 1, 12)
+#define WINUAEDATE MAKEBD(2013, 1, 20)
 #define WINUAEEXTRA _T("")
 //#define WINUAEEXTRA _T("AmiKit Preview")
 #define WINUAEREV _T("")
index 30ea5373c444a96a3d22f668346d692ac76ef0eb..f654266bfa35ba2e2acc290e394e2fc4ed8ceba3 100644 (file)
@@ -1968,6 +1968,8 @@ static UINT_PTR CALLBACK ofnhook (HWND hDlg, UINT message, WPARAM wParam, LPARAM
 static void eject_cd (void)
 {
        workprefs.cdslots[0].name[0] = 0;
+       if (full_property_sheet)
+               workprefs.cdslots[0].type = SCSI_UNIT_DEFAULT;
        quickstart_cddrive[0] = 0;
        workprefs.cdslots[0].inuse = false;
        if (full_property_sheet) {
@@ -3878,19 +3880,23 @@ void InitializeListView (HWND hDlg)
 
        } else if (lv_type == LV_HARDDISK) {
 #ifdef FILESYS
+               listview_column_width[1] = 60;
                for(i = 0; i < workprefs.mountitems; i++)
                {
                        struct uaedev_config_data *uci = &workprefs.mountconfig[i];
                        struct uaedev_config_info *ci = &uci->ci;
                        int nosize = 0, type;
                        struct mountedinfo mi;
-                       TCHAR *rootdir = ci->rootdir;
+                       TCHAR *rootdir;
 
                        type = get_filesys_unitconfig (&workprefs, i, &mi);
                        if (type < 0) {
-                               type = uci->ishdf ? FILESYS_HARDFILE : FILESYS_VIRTUAL;
+                               type = ci->type == UAEDEV_HDF || ci->type == UAEDEV_CD ? FILESYS_HARDFILE : FILESYS_VIRTUAL;
                                nosize = 1;
                        }
+                       if (mi.size < 0)
+                               nosize = 1;
+                       rootdir = mi.rootdir;
 
                        if (nosize)
                                _tcscpy (size_str, _T("n/a"));
@@ -3949,7 +3955,7 @@ void InitializeListView (HWND hDlg)
                        WIN32GUI_LoadUIString (ci->readonly ? IDS_NO : IDS_YES, readwrite_str, sizeof (readwrite_str) / sizeof (TCHAR));
 
                        lvstruct.mask     = LVIF_TEXT | LVIF_PARAM;
-                       lvstruct.pszText  = mi.ismedia == false ? _T("E") : (nosize ? _T("X") : (mi.ismounted ? _T("*") : _T(" ")));
+                       lvstruct.pszText  = mi.ismedia == false ? _T("E") : (nosize && mi.size >= 0 ? _T("X") : (mi.ismounted ? _T("*") : _T(" ")));
                        if (ci->controller && mi.ismedia)
                                lvstruct.pszText = _T(" ");
                        lvstruct.lParam   = 0;
@@ -3958,7 +3964,7 @@ void InitializeListView (HWND hDlg)
                        result = ListView_InsertItem (list, &lvstruct);
                        if (result != -1) {
 
-                               listview_column_width[0] = 15;
+                               listview_column_width[0] = 20;
 
                                ListView_SetItemText(list, result, 1, devname_str);
                                width = ListView_GetStringWidth(list, devname_str) + 10;
@@ -4009,8 +4015,10 @@ void InitializeListView (HWND hDlg)
                        }
                }
                // Adjust our column widths so that we can see the contents...
-               for(i = 0; i < listview_num_columns; i++)
-                       ListView_SetColumnWidth (list, i, listview_column_width[i]);
+               for(i = 0; i < listview_num_columns; i++) {
+                       if (ListView_GetColumnWidth (list, i) < listview_column_width[i])
+                               ListView_SetColumnWidth (list, i, listview_column_width[i]);
+               }
                // Redraw the items in the list...
                items = ListView_GetItemCount (list);
                ListView_RedrawItems (list, 0, items);
@@ -5422,6 +5430,8 @@ static INT_PTR CALLBACK QuickstartDlgProc (HWND hDlg, UINT msg, WPARAM wParam, L
                                val = SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, CB_GETCURSEL, 0, 0);
                                if (val != CB_ERR) {
                                        quickstart_cdtype = val;
+                                       if (full_property_sheet)
+                                               workprefs.cdslots[0].type = SCSI_UNIT_DEFAULT;
                                        if (quickstart_cdtype >= 2) {
                                                int len = sizeof quickstart_cddrive / sizeof (TCHAR);
                                                quickstart_cdtype = 2;
@@ -9141,6 +9151,10 @@ static INT_PTR CALLBACK SoundDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM
 
 #ifdef FILESYS
 
+struct cddlg_vals
+{
+       struct uaedev_config_info ci;
+};
 struct fsvdlg_vals
 {
        struct uaedev_config_info ci;
@@ -9156,6 +9170,7 @@ struct hfdlg_vals
        bool rdb;
 };
 
+static struct cddlg_vals current_cddlg;
 static struct fsvdlg_vals current_fsvdlg;
 static struct hfdlg_vals current_hfdlg;
 static int archivehd;
@@ -9164,15 +9179,16 @@ static void default_fsvdlg (struct fsvdlg_vals *f)
 {
        memset (f, 0, sizeof (struct fsvdlg_vals));
        f->ci.autoboot = true;
+       f->ci.type = UAEDEV_DIR;
 }
 static void default_hfdlg (struct hfdlg_vals *f, bool rdb)
 {
        memset (f, 0, sizeof (struct hfdlg_vals));
        uci_set_defaults (&f->ci, rdb);
        f->original = true;
+       f->ci.type = UAEDEV_HDF;
 }
 
-
 static void volumeselectfile (HWND hDlg)
 {
        TCHAR directory_path[MAX_DPATH];
@@ -9549,6 +9565,45 @@ static void hardfilecreatehdf (HWND hDlg, TCHAR *newpath)
        sethardfile (hDlg);
 }
 
+static INT_PTR CALLBACK CDDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+       static int recursive = 0;
+       int posn;
+
+       switch (msg) {
+
+       case WM_INITDIALOG:
+               recursive++;
+               inithdcontroller (hDlg);
+               SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_SETCURSEL, current_cddlg.ci.controller, 0);
+               recursive--;
+               customDlgType = IDD_CDDRIVE;
+               customDlg = hDlg;
+               return TRUE;
+       case WM_COMMAND:
+               if (recursive)
+                       break;
+               recursive++;
+               switch (LOWORD (wParam))
+               {
+               case IDOK:
+                       EndDialog (hDlg, 1);
+                       break;
+               case IDCANCEL:
+                       EndDialog (hDlg, 0);
+                       break;
+               case IDC_HDF_CONTROLLER:
+                       posn = SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_GETCURSEL, 0, 0);
+                       if (posn != CB_ERR)
+                               current_cddlg.ci.controller = posn;
+                       break;
+               }
+               recursive--;
+               break;
+       }
+       return FALSE;
+}
+
 static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 {
        static int recursive = 0;
@@ -9887,7 +9942,7 @@ static void new_filesys (HWND hDlg, int entry)
        int bp = tweakbootpri (current_fsvdlg.ci.bootpri, current_fsvdlg.ci.autoboot, current_fsvdlg.ci.donotmount);
        memcpy (&ci, &current_fsvdlg.ci, sizeof (struct uaedev_config_info));
        ci.bootpri = bp;
-       uci = add_filesys_config (&workprefs, entry, &ci, false);
+       uci = add_filesys_config (&workprefs, entry, &ci);
        if (uci) {
                if (uci->ci.rootdir[0])
                        filesys_media_change (uci->ci.rootdir, 1, uci);
@@ -9896,6 +9951,17 @@ static void new_filesys (HWND hDlg, int entry)
        }
 }
 
+static void new_cddrive (HWND hDlg, int entry)
+{
+       struct uaedev_config_info ci = { 0 };
+       ci.cd_emu_unit = 0;
+       ci.controller = current_cddlg.ci.controller;
+       ci.type = UAEDEV_CD;
+       ci.readonly = true;
+       ci.blocksize = 2048;
+       add_filesys_config (&workprefs, entry, &ci);
+}
+
 static void new_hardfile (HWND hDlg, int entry)
 {
        struct uaedev_config_data *uci;
@@ -9903,7 +9969,7 @@ static void new_hardfile (HWND hDlg, int entry)
        int bp = tweakbootpri (current_hfdlg.ci.bootpri, current_hfdlg.ci.autoboot, current_hfdlg.ci.donotmount);
        memcpy (&ci, &current_hfdlg.ci, sizeof (struct uaedev_config_info));
        ci.bootpri = bp;
-       uci = add_filesys_config (&workprefs, entry, &ci, true);
+       uci = add_filesys_config (&workprefs, entry, &ci);
        if (uci) {
                struct hardfiledata *hfd = get_hardfile_data (uci->configoffset);
                hardfile_media_change (hfd, &ci, true, false);
@@ -9914,7 +9980,7 @@ static void new_harddrive (HWND hDlg, int entry)
 {
        struct uaedev_config_data *uci;
 
-       uci = add_filesys_config (&workprefs, entry, &current_hfdlg.ci, true);
+       uci = add_filesys_config (&workprefs, entry, &current_hfdlg.ci);
        if (uci) {
                struct hardfiledata *hfd = get_hardfile_data (uci->configoffset);
                hardfile_media_change (hfd, &current_hfdlg.ci, true, false);
@@ -9950,9 +10016,15 @@ static void harddisk_edit (HWND hDlg)
 
        type = get_filesys_unitconfig (&workprefs, entry, &mi);
        if (type < 0)
-               type = uci->ishdf ? FILESYS_HARDFILE : FILESYS_VIRTUAL;
+               type = uci->ci.type == UAEDEV_HDF ? FILESYS_HARDFILE : FILESYS_VIRTUAL;
 
-       if(type == FILESYS_HARDFILE || type == FILESYS_HARDFILE_RDB)
+       if (uci->ci.type == UAEDEV_CD) {
+               memcpy (&current_cddlg.ci, uci, sizeof (struct uaedev_config_info));
+               if (CustomDialogBox (IDD_CDDRIVE, hDlg, CDDriveSettingsProc)) {
+                       new_cddrive (hDlg, entry);
+               }
+       }
+       else if(type == FILESYS_HARDFILE || type == FILESYS_HARDFILE_RDB)
        {
                current_hfdlg.forcedcylinders = uci->ci.highcyl;
                memcpy (&current_hfdlg.ci, uci, sizeof (struct uaedev_config_info));
@@ -10018,6 +10090,11 @@ static int harddiskdlg_button (HWND hDlg, WPARAM wParam)
                        new_hardfile (hDlg, -1);
                return 1;
 
+       case IDC_NEW_CD:
+               if (CustomDialogBox (IDD_CDDRIVE, hDlg, CDDriveSettingsProc))
+                       new_cddrive (hDlg, -1);
+               return 1;
+
        case IDC_NEW_HD:
                memset (&current_hfdlg, 0, sizeof (current_hfdlg));
                if (hdf_init_target () == 0) {
@@ -10180,13 +10257,19 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA
                        getfloppyname (hDlg, 0, 1, IDC_CD_TEXT);
                        quickstart_cdtype = 1;
                        workprefs.cdslots[0].inuse = true;
+                       if (full_property_sheet)
+                               workprefs.cdslots[0].type = SCSI_UNIT_DEFAULT;
                        addcdtype (hDlg, IDC_CD_TYPE);
                        addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD);
+                       InitializeListView (hDlg);
+                       hilitehd (hDlg);
                        break;
                        case IDC_CD_TYPE:
                        int val = SendDlgItemMessage (hDlg, IDC_CD_TYPE, CB_GETCURSEL, 0, 0);
                        if (val != CB_ERR) {
                                quickstart_cdtype = val;
+                               if (full_property_sheet)
+                                       workprefs.cdslots[0].type = SCSI_UNIT_DEFAULT;
                                if (quickstart_cdtype >= 2) {
                                        int len = sizeof quickstart_cddrive / sizeof (TCHAR);
                                        quickstart_cdtype = 2;
@@ -10208,6 +10291,8 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA
                                }
                                addcdtype (hDlg, IDC_CD_TYPE);
                                addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD);
+                               InitializeListView (hDlg);
+                               hilitehd (hDlg);
                        }
                        break;
                        }
@@ -14999,7 +15084,6 @@ static void centerWindow (HWND hDlg)
                        y = mdc->rect.top;
                }
        }
-       SetForegroundWindow (hDlg);
        pt1.x = x + 100;
        pt1.y = y + (GetSystemMetrics (SM_CYMENU) + GetSystemMetrics (SM_CYBORDER)) / 2;
        pt2.x = x + gui_width - 100;
@@ -15200,7 +15284,7 @@ int dragdrop (HWND hDlg, HDROP hd, struct uae_prefs *prefs, int currentpage)
                        } else if (currentpage == HARDDISK_ID) {
                                default_fsvdlg (&current_fsvdlg);
                                _tcscpy (current_fsvdlg.ci.rootdir, file);
-                               add_filesys_config (&workprefs, -1, &current_fsvdlg.ci, false);
+                               add_filesys_config (&workprefs, -1, &current_fsvdlg.ci);
                        } else {
                                drv = floppyslot_addfile (prefs, file, drv, firstdrv, i);
                                if (drv < 0)
@@ -15226,18 +15310,18 @@ int dragdrop (HWND hDlg, HDROP hd, struct uae_prefs *prefs, int       currentpage)
                                } else {
                                        default_fsvdlg (&current_fsvdlg);
                                        _tcscpy (current_fsvdlg.ci.rootdir, file);
-                                       add_filesys_config (&workprefs, -1, &current_fsvdlg.ci, false);
+                                       add_filesys_config (&workprefs, -1, &current_fsvdlg.ci);
                                }
                        } else {
                                uci_set_defaults (&current_hfdlg.ci, false);
                                current_hfdlg.forcedcylinders = 0;
                                updatehdfinfo (NULL, true, true);
-                               add_filesys_config (&workprefs, -1, &current_hfdlg.ci, true);
+                               add_filesys_config (&workprefs, -1, &current_hfdlg.ci);
                        }
                        break;
                case ZFILE_HDFRDB:
                        default_hfdlg (&current_hfdlg, true);
-                       add_filesys_config (&workprefs, -1, &current_hfdlg.ci, true);
+                       add_filesys_config (&workprefs, -1, &current_hfdlg.ci);
                        break;
                case ZFILE_NVR:
                        _tcscpy (prefs->flashfile, file);
@@ -15269,7 +15353,7 @@ int dragdrop (HWND hDlg, HDROP hd, struct uae_prefs *prefs, int currentpage)
                                default_fsvdlg (&current_fsvdlg);
                                _tcscpy (current_fsvdlg.ci.rootdir, file);
                                _tcscpy (current_fsvdlg.ci.volname, filepart);
-                               add_filesys_config (&workprefs, -1, &current_fsvdlg.ci, false);
+                               add_filesys_config (&workprefs, -1, &current_fsvdlg.ci);
                                if (!full_property_sheet)
                                        do_filesys_insert (file);
                        } else {
@@ -16331,6 +16415,7 @@ static int transla[] = {
        NUMSG_NOCAPS, IDS_NUMSG_NOCAPS,
        NUMSG_KICKREP, IDS_NUMSG_KICKREP,
        NUMSG_KICKREPNO, IDS_NUMSG_KICKREPNO,
+       NUMSG_KS68030PLUS, IDS_NUMSG_KS68030PLUS,
        -1
 };
 
index 5061634628ee2749bde84d2a9e55e7523cfcb8ed..46e17d2fa068628b0e777d6887594af5d9de24ab 100644 (file)
@@ -1,6 +1,31 @@
 
 - restore only single input target to default.
 
+Beta 2:
+
+- 030/040/060 MMU TAS and CAS/CAS2 Read-Modify-Write cycle special handling emulated, RMW read access
+  part is internally considered a write access and it will cause access fault if address is write protected.
+- 040 MMU MOVEM special handling (SSR CM-bit) emulated.
+- Some 040/060 MMU emulation bug fixes. (It still isn't fully compatible)
+- A3000 2.04 ROM requires 68030 or higher, it is not 68030-only. (Only 1.4b is 68030-only)
+- Bogus filesystem.resource entry was added if RDB HDF had more than one partition with custom filesystem (b1)
+- Fixed stuck IDE emulation interrupt that hangs the emulated system, happened randomly during A4000 IDE detection. (Old bug)
+- Geometry file FORCELOAD parameter added, forceload=1: do not re-use already loaded filesystem(s).
+- A590/A2091/A3000 SCSI CDROM emulation added, uses SCSI emulation originally made for uaescsi.device.
+- Gayle/A4000 ATAPI CDROM emulation added (uses uaescsi.device SCSI emulation, ATAPI = IDE CROM SCSI command support)
+- CD image mounter SCSI emulation inquiry command's vendor/product/revision data was blank.
+- Ultra-minimal "Add CD Drive" GUI added. Only IDE or SCSI and only one CD entry can be added. Use hardddrives panel bottom
+  CD drive/image selection select menu to select mounted CD. uaescsi.device still works as previously but note that
+  same CD drive/image slot (internally there is more but they are not available in GUI yet) is shared = it may not be good
+  idea to enable both uaescsi.device and hardware IDE/SCSI CD emulation at the same time.
+- Added more emulated SCSI CD commands, READ TRACK INFORMATION, READ DISC INFORMATION and PREVENT/ALLOW MEDIUM REMOVAL
+  (which does nothing). READ TOC allocation length check fixed.
+
+Note: Curently SCSI and IDE CD is single threaded = whole emulation pauses while waiting for CD command to finish = better
+not to use real CD drives. Only uaescsi.device runs in background.
+
+Beta 1:
+
 Big MMU emulation update:
 
 - Previous (Next emulator) 68030 MMU added (+missing bus error exception stuff implemented by me),
index 242345de96a179c86b5aa723ff7b9d57c146d2a8..c14cb38293c01fb4cbd1aa1f5563004cc72379ba 100644 (file)
@@ -139,7 +139,7 @@ static struct romdata roms[] = {
        0x64466c2a, 0xF72D8914,0x8DAC39C6,0x96E30B10,0x859EBC85,0x9226637B },
        { _T("KS ROM v2.05 (A600HD)"), 2, 5, 37, 350, _T("A600HD\0A600\0"), 524288, 10, 0, 0, ROMTYPE_KICK, 0, 0, _T("391304-02"),
        0x43b0df7b, 0x02843C42,0x53BBD29A,0xBA535B0A,0xA3BD9A85,0x034ECDE4 },
-       { _T("KS ROM v2.04 (A3000)"), 2, 4, 37, 175, _T("A3000\0"), 524288, 71, 3, 0, ROMTYPE_KICK, 0, 0, NULL,
+       { _T("KS ROM v2.04 (A3000)"), 2, 4, 37, 175, _T("A3000\0"), 524288, 71, 8, 0, ROMTYPE_KICK, 0, 0, NULL,
        0x234a7233, 0xd82ebb59,0xafc53540,0xddf2d718,0x7ecf239b,0x7ea91590 },
        ALTROMPN(71, 1, 1, 262144, ROMTYPE_EVEN, _T("390629-03"), 0xa245dbdf,0x83bab8e9,0x5d378b55,0xb0c6ae65,0x61385a96,0xf638598f)
        ALTROMPN(71, 1, 2, 262144, ROMTYPE_ODD , _T("390630-03"), 0x7db1332b,0x48f14b31,0x279da675,0x7848df6f,0xeb531881,0x8f8f576c)
index cf512ddd35fac6faa7a8b45a46647318bedc940b..0237e27ad99fe6a8c698712d9ace90354d14973f 100644 (file)
--- a/scsi.cpp
+++ b/scsi.cpp
@@ -16,8 +16,8 @@
 #include "blkdev.h"
 
 static int outcmd[] = { 0x0a, 0x2a, 0x2f, 0xaa, -1 };
-static int incmd[] = { 0x03, 0x08, 0x12, 0x1a, 0x25, 0x28, 0x37, 0x42, 0x43, 0xa8, -1 };
-static int nonecmd[] = { 0x00, 0x35, -1 };
+static int incmd[] = { 0x03, 0x08, 0x12, 0x1a, 0x25, 0x28, 0x37, 0x42, 0x43, 0xa8, 0x51, 0x52, -1 };
+static int nonecmd[] = { 0x00, 0x1b, 0x1e, 0x35, -1 };
 
 static int scsi_data_dir(struct scsi_data *sd)
 {
@@ -40,8 +40,8 @@ static int scsi_data_dir(struct scsi_data *sd)
                        return 0;
                }
        }
-       write_log (_T("SCSI command %02X, no direction specified (IN?)!\n"), sd->cmd[0]);
-       return -2;
+       write_log (_T("SCSI command %02X, no direction specified!\n"), sd->cmd[0]);
+       return 0;
 }
 
 void scsi_emulate_analyze (struct scsi_data *sd)
@@ -67,6 +67,9 @@ void scsi_emulate_analyze (struct scsi_data *sd)
        case 0x25:
        case 0x28:
        case 0x35:
+       case 0x51:
+       case 0x52:
+       case 0x43:
                cmd_len = 10;
                break;
        case 0xa8:
@@ -85,19 +88,35 @@ void scsi_emulate_cmd(struct scsi_data *sd)
 {
        sd->status = 0;
        //write_log (_T("CMD=%02x\n"), sd->cmd[0]);
-       if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
-               int len = sd->cmd[4];
-               memset (sd->buffer, 0, len);
-               memcpy (sd->buffer, sd->sense, sd->sense_len > len ? len : sd->sense_len);
-               sd->data_len = len;
-               sd->status = 0;
+       if (sd->cd_emu_unit >= 0) {
+               if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
+                       int len = sd->cmd[4];
+                       memset (sd->buffer, 0, len);
+                       memcpy (sd->buffer, sd->sense, sd->sense_len > len ? len : sd->sense_len);
+                       sd->data_len = len;
+               } else {
+                       sd->status = scsi_cd_emulate(sd->cd_emu_unit, sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len);
+                       if (sd->status == 0) {
+                               if (sd->reply_len > 0) {
+                                       memset(sd->buffer, 0, 256);
+                                       memcpy(sd->buffer, sd->reply, sd->reply_len);
+                               }
+                       }
+               }
        } else if (sd->nativescsiunit < 0) {
-               sd->status = scsi_emulate(&sd->hfd->hfd, sd->hfd,
-                       sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len);
-               if (sd->status == 0) {
-                       if (sd->reply_len > 0) {
-                               memset(sd->buffer, 0, 256);
-                               memcpy(sd->buffer, sd->reply, sd->reply_len);
+               if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
+                       int len = sd->cmd[4];
+                       memset (sd->buffer, 0, len);
+                       memcpy (sd->buffer, sd->sense, sd->sense_len > len ? len : sd->sense_len);
+                       sd->data_len = len;
+               } else {
+                       sd->status = scsi_hd_emulate(&sd->hfd->hfd, sd->hfd,
+                               sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len);
+                       if (sd->status == 0) {
+                               if (sd->reply_len > 0) {
+                                       memset(sd->buffer, 0, 256);
+                                       memcpy(sd->buffer, sd->reply, sd->reply_len);
+                               }
                        }
                }
        } else {
@@ -125,12 +144,27 @@ void scsi_emulate_cmd(struct scsi_data *sd)
        sd->offset = 0;
 }
 
-struct scsi_data *scsi_alloc(int id, struct hd_hardfiledata *hfd)
+struct scsi_data *scsi_alloc_hd(int id, struct hd_hardfiledata *hfd)
 {
        struct scsi_data *sd = xcalloc (struct scsi_data, 1);
        sd->hfd = hfd;
        sd->id = id;
        sd->nativescsiunit = -1;
+       sd->cd_emu_unit = -1;
+       return sd;
+}
+
+struct scsi_data *scsi_alloc_cd(int id, int unitnum)
+{
+       struct scsi_data *sd;
+       if (!sys_command_open (unitnum)) {
+               write_log (_T("SCSI: CD EMU scsi unit %d failed to open\n"), unitnum);
+               return NULL;
+       }
+       sd = xcalloc (struct scsi_data, 1);
+       sd->id = id;
+       sd->cd_emu_unit = unitnum;
+       sd->nativescsiunit = -1;
        return sd;
 }
 
@@ -144,6 +178,7 @@ struct scsi_data *scsi_alloc_native(int id, int nativeunit)
        sd = xcalloc (struct scsi_data, 1);
        sd->id = id;
        sd->nativescsiunit = nativeunit;
+       sd->cd_emu_unit = -1;
        return sd;
 }
 
@@ -158,6 +193,11 @@ void scsi_free(struct scsi_data *sd)
                return;
        if (sd->nativescsiunit >= 0) {
                sys_command_close (sd->nativescsiunit);
+               sd->nativescsiunit = -1;
+       }
+       if (sd->cd_emu_unit >= 0) {
+               sys_command_close (sd->cd_emu_unit);
+               sd->cd_emu_unit = -1;
        }
        xfree(sd);
 }