]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
2600b9
authorToni Wilen <twilen@winuae.net>
Sun, 24 Feb 2013 15:58:20 +0000 (17:58 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 24 Feb 2013 15:58:20 +0000 (17:58 +0200)
filesys.cpp
fpp.cpp
gencpu.cpp
include/fsdb.h
newcpu.cpp
od-win32/fsdb_mywin32.cpp
od-win32/fsdb_win32.cpp
od-win32/win32.h
od-win32/win32gui.cpp
od-win32/winuaechangelog.txt

index e307e267b2166a93476d08acbf422221428e7620..2680a8df3626b4a322aea43b70ae9d1fad592c01 100644 (file)
@@ -529,7 +529,6 @@ static int set_filesys_unit_1 (int nr, struct uaedev_config_info *ci)
        bool emptydrive = false;
        bool iscd;
        struct uaedev_config_info c;
-       TCHAR newrootdir[MAX_DPATH];
 
        memcpy (&c, ci, sizeof (struct uaedev_config_info));
 
@@ -546,7 +545,7 @@ static int set_filesys_unit_1 (int nr, struct uaedev_config_info *ci)
                }
        }
 
-       my_resolveshortcut (c.rootdir, MAX_DPATH);
+       my_resolvesoftlink (c.rootdir, MAX_DPATH);
        iscd = nr >= cd_unit_offset && nr < cd_unit_offset + cd_unit_number;
 
        for (i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
@@ -850,6 +849,15 @@ struct hardfiledata *get_hardfile_data (int nr)
 #define DOS_TRUE ((uae_u32)-1L)
 #define DOS_FALSE (0L)
 
+/* DirEntryTypes */
+#define ST_PIPEFILE -5
+#define ST_LINKFILE -4
+#define ST_FILE -3
+#define ST_ROOT 1
+#define ST_USERDIR 2
+#define ST_SOFTLINK 3
+#define ST_LINKDIR 4
+
 #define MAXFILESIZE32 (0x7fffffff)
 
 /* Passed as type to Lock() */
@@ -1110,6 +1118,19 @@ static TCHAR *bstr (Unit *unit, uaecptr addr)
        au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
        return unit->tmpbuf3;
 }
+static TCHAR *cstr (Unit *unit, uaecptr addr)
+{
+       int i;
+       uae_char buf[257];
+
+       for (i = 0;;i++,addr++) {
+               buf[i] = get_byte (addr);
+               if (!buf[i])
+                       break;
+       }
+       au_fs_copy (unit->tmpbuf3, sizeof (unit->tmpbuf3) / sizeof (TCHAR), buf);
+       return unit->tmpbuf3;
+}
 
 static TCHAR *bstr_cut (Unit *unit, uaecptr addr)
 {
@@ -2417,7 +2438,7 @@ static a_inode *get_aino (Unit *unit, a_inode *base, const TCHAR *rel, int *err)
 {
        TCHAR *tmp;
        TCHAR *p;
-       a_inode *curr;
+       a_inode *curr, *prev;
        int i;
 
        aino_test (base);
@@ -2434,6 +2455,7 @@ static a_inode *get_aino (Unit *unit, a_inode *base, const TCHAR *rel, int *err)
        tmp = my_strdup (rel);
        p = tmp;
        curr = base;
+       prev = NULL;
 
        while (*p) {
                /* start with a slash? go up a level. */
@@ -2444,6 +2466,13 @@ static a_inode *get_aino (Unit *unit, a_inode *base, const TCHAR *rel, int *err)
                } else {
                        a_inode *next;
 
+
+                       if (prev && prev->softlink) {
+                               *err = ERROR_IS_SOFT_LINK;
+                               curr = NULL;
+                               break;
+                       }
+
                        TCHAR *component_end;
                        component_end = _tcschr (p, '/');
                        if (component_end != 0)
@@ -2452,16 +2481,16 @@ static a_inode *get_aino (Unit *unit, a_inode *base, const TCHAR *rel, int *err)
                        if (next == 0) {
                                /* if only last component not found, return parent dir. */
                                if (*err != ERROR_OBJECT_NOT_AROUND || component_end != 0)
-                                       curr = 0;
+                                       curr = NULL;
                                /* ? what error is appropriate? */
                                break;
                        }
+                       prev = next;
                        curr = next;
                        if (component_end)
                                p = component_end+1;
                        else
                                break;
-
                }
        }
        xfree (tmp);
@@ -3164,6 +3193,8 @@ static void
        DUMPLOCK(unit, lock);
 
        a = find_aino (unit, lock, bstr (unit, name), &err);
+       if (err == 0 && a->softlink)
+               err = ERROR_IS_SOFT_LINK;
        if (err == 0 && (a->elock || (mode != SHARED_LOCK && a->shlock > 0))) {
                err = ERROR_OBJECT_IN_USE;
        }
@@ -3180,6 +3211,135 @@ static void
        de_recycle_aino (unit, a);
        PUT_PCK_RES1 (packet, make_lock (unit, a->uniq, mode) >> 2);
 }
+static void action_read_link_add_parent (Unit *u, a_inode *a, TCHAR *path)
+{
+       if (a == NULL)
+               return;
+       action_read_link_add_parent(u, a->parent, path);
+       if (a == &u->rootnode) {
+               _tcscat (path, a->aname);
+               _tcscat (path, _T(":"));
+       } else {
+               if (path[0] && path[_tcslen (path) - 1] != ':')
+                       _tcscat (path, _T("/"));
+               _tcscat (path, a->aname);
+       }
+}
+
+#if 0
+#define LINK_HARD 0
+#define LINK_SOFT 1
+
+static void action_make_link (Unit *unit, dpacket packet)
+{
+       uaecptr lock = GET_PCK_ARG1 (packet) << 2;
+       uaecptr name = GET_PCK_ARG2 (packet) << 2;
+       uaecptr linkname = GET_PCK_ARG3 (packet);
+       int type = GET_PCK_ARG4 (packet);
+       a_inode *a1, *a2;
+       int err;
+
+       if (type == LINK_HARD) {
+               PUT_PCK_RES1 (packet, DOS_FALSE);
+               PUT_PCK_RES2 (packet, ERROR_NOT_IMPLEMENTED);
+               return;
+       }
+       a1 = find_aino (unit, lock, bstr (unit, name), &err);
+       if (err != 0) {
+               PUT_PCK_RES1 (packet, DOS_FALSE);
+               PUT_PCK_RES2 (packet, err);
+               return;
+       }
+       a2 = find_aino (unit, lock, cstr (unit, linkname), &err);
+       if (err != 0) {
+               PUT_PCK_RES1 (packet, DOS_FALSE);
+               PUT_PCK_RES2 (packet, err);
+               return;
+       }
+       if (!my_createsoftlink (a1->nname, a2->nname)) {
+               PUT_PCK_RES1 (packet, DOS_FALSE);
+               PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
+               return;
+       }
+}
+#endif
+
+static void action_read_link (Unit *unit, dpacket packet)
+{
+       uaecptr lock = GET_PCK_ARG1 (packet) << 2;
+       uaecptr name = GET_PCK_ARG2 (packet);
+       uaecptr newname = GET_PCK_ARG3 (packet);
+       int size = GET_PCK_ARG4 (packet);
+       a_inode *a;
+       Unit *u = NULL;
+       int err, i;
+       TCHAR tmp[MAX_DPATH];
+       TCHAR *namep, *extrapath;
+
+       extrapath = NULL;
+       namep = cstr (unit, name);
+       for (;;) {
+               a = find_aino (unit, lock, namep, &err);
+               if (err != ERROR_IS_SOFT_LINK)
+                       break;
+               for (i = _tcslen (namep) - 1; i > 0; i--) {
+                       if (namep[i] == '/') {
+                               namep[i] = 0;
+                               xfree (extrapath);
+                               extrapath = my_strdup (namep + i + 1);
+                               break;
+                       }
+               }
+       }
+       if (err != 0) {
+               PUT_PCK_RES1 (packet, DOS_FALSE);
+               PUT_PCK_RES2 (packet, err);
+               return;
+       }
+       _tcscpy (tmp, a->nname);
+       if (!my_resolvesoftlink (tmp, sizeof tmp / sizeof (TCHAR))) {
+               PUT_PCK_RES1 (packet, DOS_FALSE);
+               //  not sure what to return
+               PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
+               return;
+       }
+       // TODO:
+       // now we have full absolute path, need to check if it can
+       // mapped to any Amiga side filesystem
+       // not that trivial..
+       a = NULL;
+       err = 0;
+       for (u = units; u; u = u->next) {
+               if (!(u->volflags & (MYVOLUMEINFO_ARCHIVE | MYVOLUMEINFO_CDFS))) {
+                       TCHAR path[MAX_DPATH];
+                       if (my_issamevolume (u->rootnode.nname, tmp, path)) {
+                               a = find_aino (u, 0, path, &err);
+                               if (a && !err)
+                                       break;
+                       }
+               }
+       }
+       if (!a || err) {
+               PUT_PCK_RES1 (packet, DOS_FALSE);
+               PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
+               return;
+       }
+       tmp[0] = 0;
+       action_read_link_add_parent (u, a, tmp);
+       if (extrapath) {
+               _tcscat (tmp, _T("/"));
+               _tcscat (tmp, extrapath);
+       }
+       xfree (extrapath);
+       char *s = ua_fs (tmp, -1);
+       for (i = 0; s[i]; i++) {
+               if (i >= size - 1)
+                       break;
+               put_byte (newname + i, s[i]);
+       }
+       xfree (s);
+       put_byte (newname + i, 0);
+}
 
 static void action_free_lock (Unit *unit, dpacket packet)
 {
@@ -3375,10 +3535,10 @@ static void
                /* Guru book says ST_ROOT = 1 (root directory, not currently used)
                * but some programs really expect 2 from root dir..
                */
-               entrytype = 2;
+               entrytype = ST_USERDIR;
                xs = unit->ui.volname;
        } else {
-               entrytype = aino->dir ? 2 : -3;
+               entrytype = aino->softlink ? ST_SOFTLINK : (aino->dir ? ST_USERDIR : ST_FILE);
                xs = aino->aname;
        }
        put_long (info + 4, entrytype);
@@ -3680,10 +3840,10 @@ static int exalldo (uaecptr exalldata, uae_u32 exalldatasize, uae_u32 type, uaec
                my_stat (aino->nname, &statbuf);
 
        if (aino->parent == 0) {
-               entrytype = 2;
+               entrytype = ST_USERDIR;
                xs = unit->ui.volname;
        } else {
-               entrytype = aino->dir ? 2 : -3;
+               entrytype = aino->softlink ? ST_SOFTLINK : (aino->dir ? ST_USERDIR : ST_FILE);
                xs = aino->aname;
        }
        x = ua_fs (xs, -1);
@@ -3972,7 +4132,7 @@ fail:
        return 1;
 }
 
-static uae_u32 exall_helpder(TrapContext *context)
+static uae_u32 exall_helpder (TrapContext *context)
 {
        int i;
        Unit *u;
@@ -4188,6 +4348,11 @@ static void do_find (Unit *unit, dpacket packet, int mode, int create, int fallb
                PUT_PCK_RES2 (packet, err);
                return;
        }
+       if (aino->softlink) {
+               PUT_PCK_RES1 (packet, DOS_FALSE);
+               PUT_PCK_RES2 (packet, ERROR_IS_SOFT_LINK);
+               return;
+       }
        if (err == 0) {
                /* Object exists. */
                if (aino->dir) {
@@ -4314,6 +4479,12 @@ static void
        aino = lookup_aino (unit, get_long (lock + 4));
        if (aino == 0)
                aino = &unit->rootnode;
+       if (aino->softlink) {
+               PUT_PCK_RES1 (packet, DOS_FALSE);
+               PUT_PCK_RES2 (packet, ERROR_IS_SOFT_LINK);
+               return;
+       }
+
        mode = aino->amigaos_mode; /* Use same mode for opened filehandle as existing Lock() */
 
        prepare_for_open (aino->nname);
@@ -5686,7 +5857,10 @@ static int handle_packet (Unit *unit, dpacket pck, uae_u32 msg)
        case ACTION_EXAMINE_ALL_END: return action_examine_all_end (unit, pck);
        case ACTION_LOCK_RECORD: return action_lock_record (unit, pck, msg); break;
        case ACTION_FREE_RECORD: action_free_record (unit, pck); break;
-
+       case ACTION_READ_LINK: action_read_link (unit, pck); break;
+#if 0
+       case ACTION_MAKE_LINK: action_make_link (unit, pck); break;
+#endif
                /* OS4+ packet types */
        case ACTION_CHANGE_FILE_POSITION64: action_change_file_position64 (unit, pck); break;
        case ACTION_GET_FILE_POSITION64: action_get_file_position64 (unit, pck); break;
@@ -5694,9 +5868,9 @@ static int handle_packet (Unit *unit, dpacket pck, uae_u32 msg)
        case ACTION_GET_FILE_SIZE64: action_get_file_size64 (unit, pck); break;
 
                /* unsupported packets */
-       case ACTION_MAKE_LINK:
-       case ACTION_READ_LINK:
        case ACTION_FORMAT:
+       case ACTION_MAKE_LINK:
+               write_log (_T("FILESYS: UNSUPPORTED PACKET %x\n"), type);
                return 0;
        default:
                write_log (_T("FILESYS: UNKNOWN PACKET %x\n"), type);
@@ -6879,9 +7053,11 @@ static uae_u32 REGPARAM2 filesys_dev_storeinfo (TrapContext *context)
                        put_long (parmpacket + 56, 1); /* hiCyl */
                } else {
                        uae_u8 buf[512] = { 0 };
-                       buf[36] = _tcslen (uip[unit_no].devname);
+                       char *s = ua_fs (uip[unit_no].devname, -1);
+                       buf[36] = strlen (s);                   
                        for (int i = 0; i < buf[36]; i++)
-                               buf[37 + i] = uip[unit_no].devname[i];
+                               buf[37 + i] = s[i];
+                       xfree (s);
                        put_long (parmpacket + 4, ROM_hardfile_resname);
                        put_long (parmpacket + 20, ci->blocksize >> 2); /* longwords per block */
                        put_long (parmpacket + 28, ci->surfaces); /* heads */
diff --git a/fpp.cpp b/fpp.cpp
index bec59ff3b65b0127a0edc30e305463c62306628f..185fd100be08c10c5d1dee523a46db51d86dfd67 100644 (file)
--- a/fpp.cpp
+++ b/fpp.cpp
@@ -237,18 +237,20 @@ static void fpu_op_illg (uae_u16 opcode, uaecptr oldpc)
        fpu_op_illg2 (opcode, 0, oldpc);
 }
 
-static bool fault_if_no_fpu (uae_u16 opcode, uaecptr ea, uaecptr oldpc)
+static bool fault_if_no_fpu (uae_u16 opcode, uae_u32 extra, uaecptr ea, uaecptr oldpc)
 {
        if ((regs.pcr & 2) || currprefs.fpu_model <= 0) {
+//             write_log (_T("no FPU: %04x %08x PC=%08x\n"), opcode, extra, oldpc);
                fpu_op_illg2 (opcode, ea, oldpc);
                return true;
        }
        return false;
 }
 
-static bool fault_if_no_6888x (uae_u16 opcode, uaecptr oldpc)
+static bool fault_if_no_6888x (uae_u16 opcode, uae_u32 extra, uaecptr oldpc)
 {
        if (currprefs.cpu_model < 68040 && currprefs.fpu_model <= 0) {
+//             write_log (_T("6888x no FPU: %04x %08x PC=%08x\n"), opcode, extra, oldpc);
                m68k_setpc (oldpc);
                op_illg (opcode);
                return true;
@@ -258,7 +260,7 @@ static bool fault_if_no_6888x (uae_u16 opcode, uaecptr oldpc)
 
 static         void fpu_noinst (uae_u16 opcode, uaecptr pc)
 {
-       write_log (_T("Unknown FPU instruction %04X %08X\n"), opcode, pc);
+//     write_log (_T("Unknown FPU instruction %04X %08X\n"), opcode, pc);
        m68k_setpc (pc);
        op_illg (opcode);
 }
@@ -484,7 +486,7 @@ STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra, fptype *src, uaec
        static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
 
        if (!(extra & 0x4000)) {
-               if (fault_if_no_fpu (opcode, 0, oldpc))
+               if (fault_if_no_fpu (opcode, extra, 0, oldpc))
                        return -1;
                *src = regs.fp[(extra >> 10) & 7];
                return 1;
@@ -559,7 +561,7 @@ STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra, fptype *src, uaec
                        }
        }
 
-       if (fault_if_no_fpu (opcode, ad, oldpc))
+       if (fault_if_no_fpu (opcode, extra, ad, oldpc))
                return -1;
 
        switch (size)
@@ -625,7 +627,7 @@ STATIC_INLINE int put_fp_value (fptype value, uae_u32 opcode, uae_u16 extra, uae
                write_log (_T("PUTFP: %f %04X %04X\n"), value, opcode, extra);
 #endif
        if (!(extra & 0x4000)) {
-               if (fault_if_no_fpu (opcode, 0, oldpc))
+               if (fault_if_no_fpu (opcode, extra, 0, oldpc))
                        return 1;
                regs.fp[(extra >> 10) & 7] = value;
                return 1;
@@ -701,7 +703,7 @@ STATIC_INLINE int put_fp_value (fptype value, uae_u32 opcode, uae_u16 extra, uae
                        }
        }
 
-       if (fault_if_no_fpu (opcode, ad, oldpc))
+       if (fault_if_no_fpu (opcode, extra, ad, oldpc))
                return 1;
 
        switch (size)
@@ -898,13 +900,13 @@ void fpuop_dbcc (uae_u32 opcode, uae_u16 extra)
        if (!isinrom ())
                write_log (_T("fdbcc_opp at %08lx\n"), m68k_getpc ());
 #endif
-       if (fault_if_no_6888x (opcode, pc - 4))
+       if (fault_if_no_6888x (opcode, extra, pc - 4))
                return;
 
        disp = (uae_s32) (uae_s16) x_next_iword ();
-       if (fault_if_no_fpu (opcode, pc + disp, pc))
+       if (fault_if_no_fpu (opcode, extra, pc + disp, pc - 4))
                return;
-       regs.fpiar = m68k_getpc () - 4;
+       regs.fpiar = pc - 4;
        cc = fpp_cond (extra & 0x3f);
        if (cc == -1) {
                fpu_op_illg (opcode, regs.fpiar);
@@ -922,20 +924,21 @@ void fpuop_scc (uae_u32 opcode, uae_u16 extra)
 {
        uae_u32 ad;
        int cc;
+       uaecptr pc = m68k_getpc () - 4;
 
 #if DEBUG_FPP
        if (!isinrom ())
                write_log (_T("fscc_opp at %08lx\n"), m68k_getpc ());
 #endif
-       if (fault_if_no_fpu (opcode, 0, 4))
+       if (fault_if_no_fpu (opcode, extra, 0, pc))
                return;
 
-       regs.fpiar = m68k_getpc () - 4;
+       regs.fpiar = pc;
        cc = fpp_cond (extra & 0x3f);
        if (cc == -1) {
                fpu_op_illg (opcode, regs.fpiar);
        } else if ((opcode & 0x38) == 0) {
-               if (fault_if_no_fpu (opcode, 0, 4))
+               if (fault_if_no_fpu (opcode, extra, 0, pc))
                        return;
                m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | (cc ? 0xff : 0x00);
        } else {
@@ -950,13 +953,12 @@ void fpuop_scc (uae_u32 opcode, uae_u16 extra)
 void fpuop_trapcc (uae_u32 opcode, uaecptr oldpc, uae_u16 extra)
 {
        int cc;
-       uaecptr pc = m68k_getpc ();
 
 #if DEBUG_FPP
        if (!isinrom ())
                write_log (_T("ftrapcc_opp at %08lx\n"), m68k_getpc ());
 #endif
-       if (fault_if_no_fpu (opcode, 0, pc))
+       if (fault_if_no_fpu (opcode, extra, 0, oldpc))
                return;
 
        regs.fpiar = oldpc;
@@ -971,19 +973,18 @@ void fpuop_trapcc (uae_u32 opcode, uaecptr oldpc, uae_u16 extra)
 void fpuop_bcc (uae_u32 opcode, uaecptr oldpc, uae_u32 extra)
 {
        int cc;
-       uaecptr pc = m68k_getpc ();
 
 #if DEBUG_FPP
        if (!isinrom ())
                write_log (_T("fbcc_opp at %08lx\n"), m68k_getpc ());
 #endif
-       if (fault_if_no_fpu (opcode, 0, pc))
+       if (fault_if_no_fpu (opcode, extra, 0, oldpc - 2))
                return;
 
-       regs.fpiar = oldpc;
+       regs.fpiar = oldpc - 2;
        cc = fpp_cond (opcode & 0x3f);
        if (cc == -1) {
-               fpu_op_illg (opcode, oldpc);
+               fpu_op_illg (opcode, oldpc - 2);
        } else if (cc) {
                if ((opcode & 0x40) == 0)
                        extra = (uae_s32) (uae_s16) extra;
@@ -1004,7 +1005,7 @@ void fpuop_save (uae_u32 opcode)
                write_log (_T("fsave_opp at %08lx\n"), m68k_getpc ());
 #endif
 
-       if (fault_if_no_6888x (opcode, pc))
+       if (fault_if_no_6888x (opcode, 0, pc))
                return;
 
        if (get_fp_ad (opcode, &ad) == 0) {
@@ -1012,7 +1013,7 @@ void fpuop_save (uae_u32 opcode)
                return;
        }
 
-       if (fault_if_no_fpu (opcode, ad, pc))
+       if (fault_if_no_fpu (opcode, 0, ad, pc))
                return;
        regs.fpiar = pc;
 
@@ -1114,7 +1115,7 @@ void fpuop_restore (uae_u32 opcode)
                write_log (_T("frestore_opp at %08lx\n"), m68k_getpc ());
 #endif
 
-       if (fault_if_no_6888x (opcode, pc))
+       if (fault_if_no_6888x (opcode, 0, pc))
                return;
 
        if (get_fp_ad (opcode, &ad) == 0) {
@@ -1122,7 +1123,7 @@ void fpuop_restore (uae_u32 opcode)
                return;
        }
 
-       if (fault_if_no_fpu (opcode, ad, pc))
+       if (fault_if_no_fpu (opcode, 0, ad, pc))
                return;
        regs.fpiar = pc;
 
@@ -1355,7 +1356,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
        if (!isinrom ())
                write_log (_T("FPP %04lx %04x at %08lx\n"), opcode & 0xffff, extra, pc);
 #endif
-       if (fault_if_no_6888x (opcode, pc))
+       if (fault_if_no_6888x (opcode, extra, pc))
                return;
 
        switch ((extra >> 13) & 0x7)
@@ -1368,7 +1369,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                case 4:
                case 5:
                        if ((opcode & 0x38) == 0) {
-                               if (fault_if_no_fpu (opcode, 0, pc))
+                               if (fault_if_no_fpu (opcode, extra, 0, pc))
                                        return;
                                if (extra & 0x2000) {
                                        if (extra & 0x1000)
@@ -1388,7 +1389,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                                                regs.fpiar = m68k_dreg (regs, opcode & 7);
                                }
                        } else if ((opcode & 0x38) == 0x08) {
-                               if (fault_if_no_fpu (opcode, 0, pc))
+                               if (fault_if_no_fpu (opcode, extra, 0, pc))
                                        return;
                                if (extra & 0x2000) {
                                        if (extra & 0x1000)
@@ -1408,7 +1409,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                                                regs.fpiar = m68k_areg (regs, opcode & 7);
                                }
                        } else if ((opcode & 0x3f) == 0x3c) {
-                               if (fault_if_no_fpu (opcode, 0, pc))
+                               if (fault_if_no_fpu (opcode, extra, 0, pc))
                                        return;
                                if ((extra & 0x2000) == 0) {
                                        if (extra & 0x1000) {
@@ -1429,7 +1430,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                                        fpu_noinst (opcode, pc);
                                        return;
                                }
-                               if (fault_if_no_fpu (opcode, ad, pc))
+                               if (fault_if_no_fpu (opcode, extra, ad, pc))
                                        return;
 
                                if ((opcode & 0x38) == 0x20) {
@@ -1467,7 +1468,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                                        fpu_noinst (opcode, pc);
                                        return;
                                }
-                               if (fault_if_no_fpu (opcode, ad, pc))
+                               if (fault_if_no_fpu (opcode, extra, ad, pc))
                                        return;
 
                                if((opcode & 0x38) == 0x20) {
@@ -1510,7 +1511,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                                                fpu_noinst (opcode, pc);
                                                return;
                                        }
-                                       if (fault_if_no_fpu (opcode, ad, pc))
+                                       if (fault_if_no_fpu (opcode, extra, ad, pc))
                                                return;
 
                                        switch ((extra >> 11) & 3)
@@ -1543,7 +1544,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                                                fpu_noinst (opcode, pc);
                                                return;
                                        }
-                                       if (fault_if_no_fpu (opcode, ad, pc))
+                                       if (fault_if_no_fpu (opcode, extra, ad, pc))
                                                return;
                                        switch ((extra >> 11) & 3)
                                        {
@@ -1578,7 +1579,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
                        regs.fpiar =  pc;
                        reg = (extra >> 7) & 7;
                        if ((extra & 0xfc00) == 0x5c00) {
-                               if (fault_if_no_fpu (opcode, 0, pc))
+                               if (fault_if_no_fpu (opcode, extra, 0, pc))
                                        return;
                                switch (extra & 0x7f)
                                {
index c2f89437f1131810cab8b72056951659550311dd..b59b1947bece36a187f370aefab3da1046ddd95d 100644 (file)
@@ -2241,9 +2241,9 @@ static void gen_opcode (unsigned long int opcode)
                printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG () ? 1 : 0);\n");
                printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n");
                printf ("\tuae_u16 newv;\n");
-               printf ("\tint cflg;\n");
+               printf ("\tint cflg, tmp_newv;\n");
                printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n");
-               printf ("\tnewv = newv_hi + newv_lo;");
+               printf ("\ttmp_newv = newv = newv_hi + newv_lo;\n");
                printf ("\tcflg = (newv & 0x1F0) > 0x90;\n");
                printf ("\tif (cflg) newv -= 0x60;\n");
                printf ("\tSET_CFLG (cflg);\n");
@@ -2256,6 +2256,7 @@ static void gen_opcode (unsigned long int opcode)
                }
                else {
                        genflags (flag_zn, curi->size, "newv", "", "");
+                       printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
                }
                genastore ("newv", curi->smode, "srcreg", curi->size, "src");
                break;
index 4160ff4045f7cf023a774bb71102f87a3edb417f..0e75ea0977ce3b973ed6111842dd4d6a4baed7e7 100644 (file)
@@ -37,6 +37,7 @@
 #define ERROR_NOT_A_DOS_DISK           225
 #define ERROR_NO_DISK                          226
 #define ERROR_NO_MORE_ENTRIES          232
+#define ERROR_IS_SOFT_LINK                     233
 #define ERROR_NOT_IMPLEMENTED          236
 #define ERROR_RECORD_NOT_LOCKED                240
 #define ERROR_LOCK_COLLISION           241
@@ -81,6 +82,7 @@ typedef struct a_inode_struct {
     int shlock;
     long db_offset;
     unsigned int dir:1;
+    unsigned int softlink:1;
     unsigned int elock:1;
     /* Nonzero if this came from an entry in our database.  */
     unsigned int has_dbentry:1;
@@ -157,6 +159,10 @@ extern bool my_stat (const TCHAR *name, struct mystat *ms);
 extern bool my_utime (const TCHAR *name, struct mytimeval *tv);
 extern bool my_chmod (const TCHAR *name, uae_u32 mode);
 extern bool my_resolveshortcut(TCHAR *linkfile, int size);
+extern bool my_resolvessymboliclink(TCHAR *linkfile, int size);
+extern bool my_resolvesoftlink(TCHAR *linkfile, int size);
+extern bool my_issamevolume(const TCHAR *path1, const TCHAR *path2, TCHAR *path);
+extern bool my_createsoftlink(const TCHAR *path, const TCHAR *target);
 
 extern char *custom_fsdb_search_dir (const char *dirname, TCHAR *rel);
 extern a_inode *custom_fsdb_lookup_aino_aname (a_inode *base, const TCHAR *aname);
index 0982b810497d5abeab95d0c92c05b72bde692fd4..e11f52eb9476465012856d368130355466d8ab09 100644 (file)
@@ -9,7 +9,7 @@
 #define MOVEC_DEBUG 0
 #define MMUOP_DEBUG 2
 #define DEBUG_CD32CDTVIO 0
-#define EXCEPTION3_DEBUG 0
+#define EXCEPTION3_DEBUG 1
 #define CPUTRACE_DEBUG 0
 
 #include "sysconfig.h"
@@ -3886,10 +3886,8 @@ STATIC_INLINE int do_specialties (int cycles)
                set_special (SPCFLAG_INT);
        }
 
-       if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
-               unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
+       if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
                return 1;
-       }
        return 0;
 }
 
@@ -4296,7 +4294,7 @@ void cpu_halt (int id)
                gui_led (LED_CPU, 0);
        }
        while (regs.halted) {
-               do_cycles (8 * CYCLE_UNIT);
+               x_do_cycles (8 * CYCLE_UNIT);
                cpu_cycles = adjust_cycles (cpu_cycles);
                if (regs.spcflags) {
                        if (do_specialties (cpu_cycles))
@@ -4927,6 +4925,7 @@ void m68k_go (int may_quit)
                }
 #endif
                run_func ();
+               unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
        }
        protect_roms (false);
        in_m68k_go--;
@@ -5127,7 +5126,6 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                        pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
                        _tcscat (instrname, _T(","));
                        movemout (instrname, mask, dp->dmode);
-                       pc += 2;
                } else if (lookup->mnemo == i_MVMLE) {
                        uae_u16 mask = get_word_debug (pc);
                        pc += 2;
index 2d30002112ec334a425e35343072651163224ee4..d99b58dc58606f49b7456dc95b2b380380c4d13c 100644 (file)
@@ -11,6 +11,7 @@
 #include <sys/timeb.h>
 #include <Shobjidl.h>
 #include <ShlGuid.h>
+#include <Shlwapi.h>
 
 bool my_isfilehidden (const TCHAR *path)
 {
@@ -761,6 +762,116 @@ bool my_utime (const TCHAR *name, struct mytimeval *tv)
        return false;
 }
 
+bool my_createsoftlink(const TCHAR *path, const TCHAR *target)
+{
+       return CreateSymbolicLink(path, target, my_existsdir(target) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) != 0;
+}
+
+bool my_issamevolume(const TCHAR *path1, const TCHAR *path2, TCHAR *path)
+{
+       TCHAR p1[MAX_DPATH];
+       TCHAR p2[MAX_DPATH];
+       TCHAR p1b[MAX_DPATH];
+       TCHAR p2b[MAX_DPATH];
+       int len;
+
+       if (!GetFullPathName(path1, sizeof p1 / sizeof (TCHAR), p1, NULL))
+               return false;
+       if (!GetFullPathName(path2, sizeof p2 / sizeof (TCHAR), p2, NULL))
+               return false;
+       PathCanonicalize(p1b, p1);
+       PathCanonicalize(p2b, p2);
+       len = _tcslen (p1b);
+       if (len > _tcslen (p2b))
+               len = _tcslen (p2b);
+       if (_tcsnicmp (p1b, p2b, len))
+               return false;
+       _tcscpy (path, p2b + len);
+       for (int i = 0; i < _tcslen (path); i++) {
+               if (path[i] == '\\')
+                       path[i] = '/';
+       }
+       return true;
+}
+
+bool my_resolvesoftlink(TCHAR *linkfile, int size)
+{
+       if (my_resolvessymboliclink(linkfile, size))
+               return true;
+       if (my_resolveshortcut(linkfile,size))
+               return true;
+       return false;
+}
+
+typedef struct _REPARSE_DATA_BUFFER {
+  ULONG  ReparseTag;
+  USHORT ReparseDataLength;
+  USHORT Reserved;
+  union {
+    struct {
+      USHORT SubstituteNameOffset;
+      USHORT SubstituteNameLength;
+      USHORT PrintNameOffset;
+      USHORT PrintNameLength;
+      ULONG  Flags;
+      WCHAR  PathBuffer[1];
+    } SymbolicLinkReparseBuffer;
+    struct {
+      USHORT SubstituteNameOffset;
+      USHORT SubstituteNameLength;
+      USHORT PrintNameOffset;
+      USHORT PrintNameLength;
+      WCHAR  PathBuffer[1];
+    } MountPointReparseBuffer;
+    struct {
+      UCHAR DataBuffer[1];
+    } GenericReparseBuffer;
+  };
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
+bool my_resolvessymboliclink(TCHAR *linkfile, int size)
+{
+       WIN32_FIND_DATA fd;
+       HANDLE h;
+       bool ret = false;
+       DWORD returnedDataSize;
+       uae_u8 tmp[MAX_DPATH * 2];
+
+       h = FindFirstFile (linkfile, &fd);
+       if (h == INVALID_HANDLE_VALUE)
+               return false;
+       FindClose(h);
+       if (fd.dwReserved0 != IO_REPARSE_TAG_SYMLINK || !(fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
+               return false;
+       h = CreateFile (linkfile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
+               OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_REPARSE_POINT | FILE_FLAG_OPEN_REPARSE_POINT , NULL);
+       if (h == INVALID_HANDLE_VALUE)
+               return false;
+       if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, tmp, sizeof tmp, &returnedDataSize, NULL)) {
+               REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)tmp;
+               if (rdb->SymbolicLinkReparseBuffer.Flags & 1) { // SYMLINK_FLAG_RELATIVE
+                       PathRemoveFileSpec (linkfile);
+                       _tcscat (linkfile, _T("\\"));
+                       TCHAR *p = linkfile + _tcslen (linkfile);
+                       memcpy (p,
+                               (uae_u8*)rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset,
+                               rdb->SymbolicLinkReparseBuffer.SubstituteNameLength);
+                       p[rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / 2] = 0;
+               } else {
+                       memcpy (linkfile,
+                               (uae_u8*)rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset,
+                               rdb->SymbolicLinkReparseBuffer.SubstituteNameLength);
+                       linkfile[rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / 2] = 0;
+               }
+               ret = true;
+               if (!_tcsnicmp (linkfile, _T("\\??\\"), 4)) {
+                       memmove (linkfile, linkfile + 4, (_tcslen (linkfile + 4) + 1) * sizeof (TCHAR));
+               }
+       }
+       CloseHandle(h);
+       return ret;
+}
+
 // http://msdn.microsoft.com/en-us/library/aa969393.aspx
 bool my_resolveshortcut(TCHAR *linkfile, int size) 
 { 
@@ -772,7 +883,7 @@ bool my_resolveshortcut(TCHAR *linkfile, int size)
     WIN32_FIND_DATA wfd; 
  
        const TCHAR *ext = _tcsrchr (linkfile, '.');
-       if (!ext || _tcsicmp (ext, _T("lnk")) == 0)
+       if (!ext || _tcsicmp (ext, _T(".lnk")) != 0)
                return false;
 
     // Get a pointer to the IShellLink interface. It is assumed that CoInitialize
index 4f4128aeb9c4a2538c79deddec3cdee705c9e149..635fe4c6aa19f121a19f906ee98f24aaa908ba98 100644 (file)
@@ -387,6 +387,18 @@ int fsdb_fill_file_attrs (a_inode *base, a_inode *aino)
                return 0;
        }
        aino->dir = (mode & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
+
+       if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
+               WIN32_FIND_DATA fd;
+               HANDLE h = FindFirstFile (aino->nname, &fd);
+               if (h != INVALID_HANDLE_VALUE) {
+                       FindClose(h);
+                       if (fd.dwReserved0 == IO_REPARSE_TAG_SYMLINK && (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
+                               aino->softlink = true;
+                       }
+               }
+       }
+       
        mode &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
 
        if ((base->volflags & MYVOLUMEINFO_STREAMS) && read_uaefsdb (aino->nname, NULL, fsdb)) {
@@ -419,6 +431,18 @@ int fsdb_fill_file_attrs (a_inode *base, a_inode *aino)
                create_uaefsdb (aino, fsdb, mode);
                write_uaefsdb (aino->nname, fsdb);
        }
+
+       if (!aino->softlink && !aino->dir) {
+               const TCHAR *ext = _tcsrchr (aino->nname, '.');
+               if (ext && !_tcsicmp (ext, _T(".lnk"))) {
+                       TCHAR tmp[MAX_DPATH];
+                       _tcscpy (tmp, aino->nname);
+                       if (my_resolvesoftlink (tmp, sizeof tmp / sizeof (TCHAR))) {
+                               aino->softlink = true;
+                       }
+               }
+       }
+
        return 1;
 }
 
index 4ffe540849ccbc076248d377f8f9cc7724c31b11..ef3f13421a83b3f12898cfec9d1f4a4c1ee8824e 100644 (file)
 #define LANG_DLL 1
 
 #if WINUAEPUBLICBETA
-#define WINUAEBETA _T("8")
+#define WINUAEBETA _T("9")
 #else
 #define WINUAEBETA _T("")
 #endif
-#define WINUAEDATE MAKEBD(2013, 2, 23)
+#define WINUAEDATE MAKEBD(2013, 2, 24)
 #define WINUAEEXTRA _T("")
 //#define WINUAEEXTRA _T("AmiKit Preview")
 #define WINUAEREV _T("")
index db529d7d93ec7311830200f387ac3a99f6a6e11b..f57603675760f2210d9adfc547aa3270c63aca0f 100644 (file)
@@ -15287,7 +15287,7 @@ int dragdrop (HWND hDlg, HDROP hd, struct uae_prefs *prefs, int currentpage)
                int mask;
 
                DragQueryFile (hd, i, file, sizeof (file) / sizeof (TCHAR));
-               my_resolveshortcut (file, sizeof file / sizeof (TCHAR));
+               my_resolvesoftlink (file, sizeof file / sizeof (TCHAR));
                filepart = _tcsrchr (file, '/');
                if (!filepart)
                        filepart = _tcsrchr (file, '\\');
index 90257d8b121a6336c68ad06171455be75ac6e2fb..f196405b35c5ad7e6a4a8401a10df927dee43a2c 100644 (file)
@@ -1,6 +1,16 @@
 
 - restore only single input target to default.
 
+Beta 9:
+
+- 68000 NBCD didn't emulate undocumented V-flag behavior. (Probably forgotten long time ago because SBCD had correct
+  implementation)
+- It was impossible to get out of halted CPU state in some situations.
+- FDBcc and FScc 6888x FPU instructions without installed FPU returned wrong f-line exception PC field.
+- Directory filesystem: emulate Windows shortcut (.lnk) files and symbolic links as Amiga side soft links.
+  Implements ACTION_READ_LINK. Works also across drives if shortcut/link target exists in any mounted directory harddrive.
+  Not guaranteed to be 100% correct implementation, Amiga softlinks are a bit strange.
+
 Beta 8:
 
 - CD SCSI emulation: implemented mode sense CD/DVD page code 0x2A. Used to detect drive capabilities, for example