From: Toni Wilen Date: Sun, 24 Feb 2013 15:58:20 +0000 (+0200) Subject: 2600b9 X-Git-Tag: 2600~12 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=19540313a0e3ced39496c252cb96cb80f28a10e7;p=francis%2Fwinuae.git 2600b9 --- diff --git a/filesys.cpp b/filesys.cpp index e307e267..2680a8df 100644 --- a/filesys.cpp +++ b/filesys.cpp @@ -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 bec59ff3..185fd100 100644 --- 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) { diff --git a/gencpu.cpp b/gencpu.cpp index c2f89437..b59b1947 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -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; diff --git a/include/fsdb.h b/include/fsdb.h index 4160ff40..0e75ea09 100644 --- a/include/fsdb.h +++ b/include/fsdb.h @@ -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); diff --git a/newcpu.cpp b/newcpu.cpp index 0982b810..e11f52eb 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -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; diff --git a/od-win32/fsdb_mywin32.cpp b/od-win32/fsdb_mywin32.cpp index 2d300021..d99b58dc 100644 --- a/od-win32/fsdb_mywin32.cpp +++ b/od-win32/fsdb_mywin32.cpp @@ -11,6 +11,7 @@ #include #include #include +#include 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 diff --git a/od-win32/fsdb_win32.cpp b/od-win32/fsdb_win32.cpp index 4f4128ae..635fe4c6 100644 --- a/od-win32/fsdb_win32.cpp +++ b/od-win32/fsdb_win32.cpp @@ -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; } diff --git a/od-win32/win32.h b/od-win32/win32.h index 4ffe5408..ef3f1342 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -19,11 +19,11 @@ #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("") diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index db529d7d..f5760367 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -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, '\\'); diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 90257d8b..f196405b 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -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