]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
imported winuaesrc1610b1.zip
authorToni Wilen <twilen@winuae.net>
Sat, 30 May 2009 17:20:27 +0000 (20:20 +0300)
committerToni Wilen <twilen@winuae.net>
Mon, 22 Feb 2010 19:46:33 +0000 (21:46 +0200)
22 files changed:
disk.c
diskutil.c
include/diskutil.h
include/options.h
include/zarchive.h
include/zfile.h
od-win32/blkdev_win32_aspi.c
od-win32/dxwrap.c
od-win32/fsdb_mywin32.c
od-win32/fsdb_win32.c
od-win32/hardfile_win32.c
od-win32/resources/winuae.rc
od-win32/uaeunp/uaeunp.vcproj
od-win32/uaeunp/uaeunp.vcxproj
od-win32/win32.c
od-win32/win32.h
od-win32/win32gfx.c
od-win32/win32gui.c
od-win32/winuaechangelog.txt
uaeunp.c
zfile.c
zfile_archive.c

diff --git a/disk.c b/disk.c
index 1d5b2863a44350eaa22b18ff270fbe5f5c406a2d..dec1869a7944a8b7cf3dc6634113a4c4b02fb5a5 100644 (file)
--- a/disk.c
+++ b/disk.c
@@ -997,10 +997,10 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR
            drv->ddhd = 1;
        } else if (size == 18 * 80 * 2 * 512 || size == 18 * 81 * 2 * 512 || size == 18 * 82 * 2 * 512) {
            drv->num_secs = 18;
-           drv->ddhd = 1;
+           drv->ddhd = 2;
        } else if (size == 10 * 80 * 2 * 512 || size == 10 * 81 * 2 * 512 || size == 10 * 82 * 2 * 512) {
            drv->num_secs = 10;
-           drv->ddhd = 2;
+           drv->ddhd = 1;
        } else if (size == 20 * 80 * 2 * 512 || size == 20 * 81 * 2 * 512 || size == 20 * 82 * 2 * 512) {
            drv->num_secs = 20;
            drv->ddhd = 2;
@@ -1281,7 +1281,7 @@ static uae_u16 *mfmcoder (uae_u8 *src, uae_u16 *dest, int len)
 
 static void decode_pcdos (drive *drv)
 {
-    int i;
+    int i, len;
     int tr = drv->cyl * 2 + side;
     uae_u16 *dstmfmbuf, *mfm2;
     uae_u8 secbuf[1000];
@@ -1326,7 +1326,9 @@ static void decode_pcdos (drive *drv)
        crc16 = get_crc16 (secbuf + 56, 3 + 1 + 512);
        secbuf[60 + 512] = crc16 >> 8;
        secbuf[61 + 512] = crc16 & 0xff;
-       memset(secbuf + 512 + 62, 0x4e, (tracklen / 2 - 96) / drv->num_secs - 574 / drv->ddhd);
+       len = (tracklen / 2 - 96) / drv->num_secs - 574 / drv->ddhd;
+       if (len > 0)
+           memset(secbuf + 512 + 62, 0x4e, len);
        dstmfmbuf = mfmcoder (secbuf, mfm2, 60 + 512 + 2 + 76 / drv->ddhd);
        mfm2[12] = 0x4489;
        mfm2[13] = 0x4489;
@@ -1815,15 +1817,15 @@ static int drive_write_pcdos (drive *drv)
            uae_u8 tmp[8];
            uae_u8 cyl, head, size;
 
-           cyl = mfmdecode(&mbuf, shift);
-           head = mfmdecode(&mbuf, shift);
-           sector = mfmdecode(&mbuf, shift);
-           size = mfmdecode(&mbuf, shift);
-           crc = (mfmdecode(&mbuf, shift) << 8) | mfmdecode(&mbuf, shift);
+           cyl = mfmdecode (&mbuf, shift);
+           head = mfmdecode (&mbuf, shift);
+           sector = mfmdecode (&mbuf, shift);
+           size = mfmdecode (&mbuf, shift);
+           crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
 
            tmp[0] = 0xa1; tmp[1] = 0xa1; tmp[2] = 0xa1; tmp[3] = mark;
            tmp[4] = cyl; tmp[5] = head; tmp[6] = sector; tmp[7] = size;
-           if (get_crc16(tmp, 8) != crc || cyl != drv->cyl || head != side || size != 2 || sector < 1 || sector > drv->num_secs) {
+           if (get_crc16 (tmp, 8) != crc || cyl != drv->cyl || head != side || size != 2 || sector < 1 || sector > drv->num_secs) {
                write_log (L"PCDOS: track %d, corrupted sector header\n", drv->cyl * 2 + side);
                return 1;
            }
@@ -1837,9 +1839,9 @@ static int drive_write_pcdos (drive *drv)
        if (sector < 0)
            continue;
        for (i = 0; i < 512; i++)
-           secbuf[i + 4] = mfmdecode(&mbuf, shift);
-       crc = (mfmdecode(&mbuf, shift) << 8) | mfmdecode(&mbuf, shift);
-       if (get_crc16(secbuf, 3 + 1 + 512) != crc) {
+           secbuf[i + 4] = mfmdecode (&mbuf, shift);
+       crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
+       if (get_crc16 (secbuf, 3 + 1 + 512) != crc) {
            write_log (L"PCDOS: track %d, sector %d data checksum error\n",
                drv->cyl * 2 + side, sector + 1);
            continue;
@@ -2473,8 +2475,8 @@ void dumpdisk (void)
        drive *drv = &floppy[i];
        if (!(disabled & (1 << i))) {
            console_out_f (L"Drive %d: motor %s cylinder %2d sel %s %s mfmpos %d/%d\n",
-               i, drv->motoroff ? "off" : " on", drv->cyl, (selected & (1 << i)) ? "no" : "yes",
-               drive_writeprotected(drv) ? "ro" : "rw", drv->mfmpos, drv->tracklen);
+               i, drv->motoroff ? L"off" : L" on", drv->cyl, (selected & (1 << i)) ? L"no" : L"yes",
+               drive_writeprotected(drv) ? L"ro" : L"rw", drv->mfmpos, drv->tracklen);
            w = word;
            for (j = 0; j < 15; j++) {
                console_out_f (L"%04X ", w);
index be0b238b7072fa592dbfe4a55438452bdc0873e9..543d124b474e4ba76e4fcd6a7b75ebf75e833eb2 100644 (file)
@@ -1,6 +1,8 @@
 #include "sysconfig.h"
 #include "sysdeps.h"
 
+#include "crc32.h"
+
 #define MFMMASK 0x55555555
 static uae_u32 getmfmlong (uae_u16 * mbuf)
 {
@@ -9,7 +11,7 @@ static uae_u32 getmfmlong (uae_u16 * mbuf)
 
 #define FLOPPY_WRITE_LEN 6250
 
-static int drive_write_adf_amigados (uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track)
+static int drive_write_adf_amigados (uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsize)
 {
        int i;
        uae_u32 odd, even, chksum, id, dlong;
@@ -17,6 +19,7 @@ static int drive_write_adf_amigados (uae_u16 *mbuf, uae_u16 *mend, uae_u8 *write
        uae_u8 secbuf[544];
 
        mend -= (4 + 16 + 8 + 512);
+       *outsize = 11 * 512;
        for (;;) {
                int trackoffs;
 
@@ -99,13 +102,14 @@ next:
 }
 
 /* search and align to 0x4489 WORDSYNC markers */
-int isamigatrack(uae_u16 *amigamfmbuffer, uae_u8 *mfmdata, int len, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track)
+int isamigatrack(uae_u16 *amigamfmbuffer, uae_u8 *mfmdata, int len, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsize)
 {
        uae_u16 *dst = amigamfmbuffer;
        int shift, syncshift, sync;
        uae_u32 l;
        uae_u16 w;
 
+       *outsize = 11 * 512;
        len *= 8;
        sync = syncshift = shift = 0;
        while (len--) {
@@ -127,6 +131,127 @@ int isamigatrack(uae_u16 *amigamfmbuffer, uae_u8 *mfmdata, int len, uae_u8 *writ
                }
        }
        if (sync)
-               return drive_write_adf_amigados (amigamfmbuffer, dst, writebuffer, writebuffer_ok, track);
+               return drive_write_adf_amigados (amigamfmbuffer, dst, writebuffer, writebuffer_ok, track, outsize);
        return -1;
-}
\ No newline at end of file
+}
+
+static uae_u16 getmfmword (uae_u16 *mbuf, int shift)
+{
+    return (mbuf[0] << shift) | (mbuf[1] >> (16 - shift));
+}
+static uae_u8 mfmdecode (uae_u16 **mfmp, int shift)
+{
+    uae_u16 mfm = getmfmword (*mfmp, shift);
+    uae_u8 out = 0;
+    int i;
+
+    (*mfmp)++;
+    mfm &= 0x5555;
+    for (i = 0; i < 8; i++) {
+       out >>= 1;
+       if (mfm & 1)
+           out |= 0x80;
+       mfm >>= 2;
+    }
+    return out;
+}
+
+static int drive_write_adf_pc (uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsize)
+{
+    int sectors, shift, sector, i;
+    uae_u8 mark;
+    uae_u8 secbuf[3 + 1 + 512];
+    uae_u16 crc;
+    int mfmcount;
+
+    secbuf[0] = secbuf[1] = secbuf[2] = 0xa1;
+    secbuf[3] = 0xfb;
+
+    sectors = 0;
+    sector = -1;
+    shift = 0;
+    mend -= (4 + 16 + 8 + 512);
+    mfmcount = 0;
+    for (;;) {
+
+       *outsize = sectors * 512;
+       while (getmfmword (mbuf, shift) != 0x4489) {
+           if (mbuf >= mend) {
+               if (sectors >= 7) {
+                   *outsize = sectors * 512;
+                   return 0;
+               }
+               write_log (L"* track %d, unexpected end of data\n", track);
+               return 1;
+           }
+           shift++;
+           if (shift == 16) {
+               shift = 0;
+               mbuf++;
+           }
+       }
+       mfmcount++;
+       while (getmfmword (mbuf, shift) == 0x4489) {
+           mfmcount++;
+           if (mbuf >= mend) {
+               if (sectors >= 7) {
+                   *outsize = sectors * 512;
+                   return 0;
+               }
+               return 1;
+           }
+           mbuf++;
+       }
+       mfmcount = 0;
+       mark = mfmdecode (&mbuf, shift);
+       if (mark == 0xfe) {
+           uae_u8 tmp[8];
+           uae_u8 cyl, head, size;
+
+           cyl = mfmdecode (&mbuf, shift);
+           head = mfmdecode (&mbuf, shift);
+           sector = mfmdecode (&mbuf, shift);
+           size = mfmdecode (&mbuf, shift);
+           crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
+
+           tmp[0] = 0xa1; tmp[1] = 0xa1; tmp[2] = 0xa1; tmp[3] = mark;
+           tmp[4] = cyl; tmp[5] = head; tmp[6] = sector; tmp[7] = size;
+           if (get_crc16 (tmp, 8) != crc || cyl != track / 2 || head != (track & 1) || size != 2 || sector < 1 || sector > 20) {
+               write_log (L"PCDOS: track %d, corrupted sector header\n", track);
+               continue;
+           }
+           sector--;
+           continue;
+       }
+       if (mark != 0xfb) {
+           write_log (L"PCDOS: track %d: unknown address mark %02X\n", track, mark);
+           continue;
+       }
+       if (sector < 0)
+           continue;
+       for (i = 0; i < 512; i++)
+           secbuf[i + 4] = mfmdecode (&mbuf, shift);
+       sectors++;
+       memcpy (writebuffer + sector * 512, secbuf + 4, 512);
+       sector = 0;
+       crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
+       if (get_crc16 (secbuf, 3 + 1 + 512) != crc) {
+           write_log (L"PCDOS: track %d, sector %d data checksum error\n",
+               track, sector + 1);
+           continue;
+       }
+
+    }
+
+}
+
+int ispctrack(uae_u16 *amigamfmbuffer, uae_u8 *mfmdata, int len, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsize)
+{
+    int i;
+    for (i = 0; i < len / 2; i++)
+       amigamfmbuffer[i] = mfmdata[i * 2 + 1] | (mfmdata[i * 2 + 0] << 8);
+    i = drive_write_adf_pc (amigamfmbuffer, amigamfmbuffer + len / 2, writebuffer, writebuffer_ok, track, outsize);
+    if (*outsize < 9 * 512)
+       *outsize = 9 * 512;
+    return i;
+}
index 48daf0e53222700b000f60070d827197c11c211b..b390818ab8ebeec677b1d1d11a334f4cb6ddff07 100644 (file)
@@ -1,2 +1,3 @@
 
-int isamigatrack (uae_u16 *amigamfmbuffer, uae_u8 *mfmdata, int len, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track);
+int isamigatrack (uae_u16 *amigamfmbuffer, uae_u8 *mfmdata, int len, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsize);
+int ispctrack (uae_u16 *amigamfmbuffer, uae_u8 *mfmdata, int len, uae_u8 *writebuffer, uae_u8 *writebuffer_ok, int track, int *outsize);
index a109f632d727c4e2b9f0936b44667ba3cb979df1..6364dc2cf07a633078270349c9b186a0410d3340 100644 (file)
@@ -9,7 +9,7 @@
 
 #define UAEMAJOR 1
 #define UAEMINOR 6
-#define UAESUBREV 0
+#define UAESUBREV 1
 
 typedef enum { KBD_LANG_US, KBD_LANG_DK, KBD_LANG_DE, KBD_LANG_SE, KBD_LANG_FR, KBD_LANG_IT, KBD_LANG_ES } KbdLang;
 
index b7c2f224341307debb7d6ebf0435d8e40e8d5b6d..c7d59712662adad113d8ed4e5fb88ce03d494ee5 100644 (file)
@@ -5,12 +5,15 @@ struct zfile {
     TCHAR *mode;
     FILE *f;
     uae_u8 *data;
-    uae_u64 size;
-    uae_u64 seek;
+    uae_s64 size;
+    uae_s64 seek;
     int deleteafterclose;
     int textmode;
     struct zfile *next;
     int zfdmask;
+    struct zfile *parent;
+    uae_u64 offset;
+    int opencnt;
 };
 
 #define ZNODE_FILE 0
@@ -28,7 +31,7 @@ struct znode {
     struct znode *vfile; // points to real file when this node is virtual directory
     TCHAR *name;
     TCHAR *fullname;
-    uae_u64 size;
+    uae_s64 size;
     struct zfile *f;
     TCHAR *comment;
     int flags;
@@ -49,10 +52,10 @@ struct zvolume
     struct znode *last;
     struct znode *parentz;
     struct zvolume *parent;
-    uae_u64 size;
+    uae_s64 size;
     unsigned int blocks;
     unsigned int id;
-    uae_u64 archivesize;
+    uae_s64 archivesize;
     unsigned int method;
     TCHAR *volumename;
     int zfdmask;
@@ -61,7 +64,7 @@ struct zvolume
 struct zarchive_info
 {
     const TCHAR *name;
-    uae_u64 size;
+    uae_s64 size;
     int flags;
     TCHAR *comment;
     time_t t;
@@ -76,6 +79,8 @@ struct zarchive_info
 #define ArchiveFormatAA 'aa  ' // method only
 #define ArchiveFormatADF 'DOS '
 #define ArchiveFormatRDB 'RDSK'
+#define ArchiveFormatMBR 'MBR '
+#define ArchiveFormatFAT 'FAT '
 
 extern int zfile_is_ignore_ext(const TCHAR *name);
 
@@ -104,9 +109,12 @@ extern struct zvolume *archive_directory_adf (struct znode *zn, struct zfile *z)
 extern struct zfile *archive_access_adf (struct znode *zn);
 extern struct zvolume *archive_directory_rdb (struct zfile *z);
 extern struct zfile *archive_access_rdb (struct znode *zn);
+extern struct zvolume *archive_directory_fat (struct zfile *z);
+extern struct zfile *archive_access_fat (struct znode *zn);
 
 extern struct zfile *archive_access_select (struct znode *parent, struct zfile *zf, unsigned int id, int doselect);
 extern struct zfile *archive_access_arcacc_select (struct zfile *zf, unsigned int id);
+extern int isfat (uae_u8*);
 
 extern void archive_access_scan (struct zfile *zf, zfile_callback zc, void *user, unsigned int id);
 
index 8c630222cdaf548ba92f0ccfa655fea98e982cb5..3c6e21bae86c33a445f3c54e52d01336e45e321d 100644 (file)
@@ -14,6 +14,8 @@ typedef int (*zfile_callback)(struct zfile*, void*);
 extern struct zfile *zfile_fopen (const TCHAR *, const TCHAR *, int mask);
 extern struct zfile *zfile_fopen_empty (struct zfile*, const TCHAR *name, uae_u64 size);
 extern struct zfile *zfile_fopen_data (const TCHAR *name, uae_u64 size, uae_u8 *data);
+extern struct zfile *zfile_fopen_parent (struct zfile*, const TCHAR*, uae_u64 offset, uae_u64 size);
+
 extern int zfile_exists (const TCHAR *name);
 extern void zfile_fclose (struct zfile *);
 extern uae_s64 zfile_fseek (struct zfile *z, uae_s64 offset, int mode);
@@ -53,7 +55,10 @@ extern TCHAR *zfile_geterror (void);
 #define ZFD_UNPACK 8 //gzip,dms
 #define ZFD_RAWDISK 16  //fdi->adf,ipf->adf etc..
 #define ZFD_NORMAL (ZFD_ARCHIVE|ZFD_UNPACK)
-#define ZFD_ALL -1
+#define ZFD_ALL 0x0000ffff
+
+#define ZFD_RAWDISK_AMIGA 0x10000
+#define ZFD_RAWDISK_PC 0x200000
 
 #define ZFILE_UNKNOWN 0
 #define ZFILE_CONFIGURATION 1
index e74773a873407eb980e0d5f79f76e78d52250737..6b0398d30d1dad9c3dc71d1d1392934799f64432 100644 (file)
@@ -26,11 +26,11 @@ int aspi_allow_misc = 1;
 int aspi_allow_all = 0;
 
 static int busses, AspiLoaded;
-static DWORD (*pfnGetASPI32SupportInfo)(void);
-static DWORD (*pfnSendASPI32Command)(LPSRB);
-static BOOL (*pfnGetASPI32Buffer)(PASPI32BUFF);
-static BOOL (*pfnFreeASPI32Buffer)(PASPI32BUFF);
-static BOOL (*pfnTranslateASPI32Address)(PDWORD, PDWORD);
+static DWORD (_cdecl *pfnGetASPI32SupportInfo)(void);
+static DWORD (_cdecl *pfnSendASPI32Command)(LPSRB);
+static BOOL (_cdecl *pfnGetASPI32Buffer)(PASPI32BUFF);
+static BOOL (_cdecl *pfnFreeASPI32Buffer)(PASPI32BUFF);
+static BOOL (_cdecl *pfnTranslateASPI32Address)(PDWORD, PDWORD);
 static HANDLE hAspiLib;
 static int scanphase;
 
@@ -220,17 +220,17 @@ static int open_driver (SCSI *scgp)
      * Get a pointer to GetASPI32SupportInfo function
      * and a pointer to SendASPI32Command function
      */
-    pfnGetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress(hAspiLib, "GetASPI32SupportInfo");
-    pfnSendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress(hAspiLib, "SendASPI32Command");
+    pfnGetASPI32SupportInfo = (DWORD(_cdecl *)(void))GetProcAddress (hAspiLib, "GetASPI32SupportInfo");
+    pfnSendASPI32Command = (DWORD(_cdecl *)(LPSRB))GetProcAddress (hAspiLib, "SendASPI32Command");
 
     if (pfnGetASPI32SupportInfo == NULL || pfnSendASPI32Command == NULL) {
        write_log (L"ASPI: obsolete wnaspi32.dll found\n");
        return FALSE;
     }
 
-    pfnGetASPI32Buffer = (BOOL(*)(PASPI32BUFF))GetProcAddress(hAspiLib, "GetASPI32Buffer");
-    pfnFreeASPI32Buffer = (BOOL(*)(PASPI32BUFF))GetProcAddress(hAspiLib, "FreeASPI32Buffer");
-    pfnTranslateASPI32Address = (BOOL(*)(PDWORD, PDWORD))GetProcAddress(hAspiLib, "TranslateASPI32Address");
+    pfnGetASPI32Buffer = (BOOL(_cdecl *)(PASPI32BUFF))GetProcAddress (hAspiLib, "GetASPI32Buffer");
+    pfnFreeASPI32Buffer = (BOOL(_cdecl *)(PASPI32BUFF))GetProcAddress (hAspiLib, "FreeASPI32Buffer");
+    pfnTranslateASPI32Address = (BOOL(_cdecl *)(PDWORD, PDWORD))GetProcAddress (hAspiLib, "TranslateASPI32Address");
 
     /*
      * Set AspiLoaded variable
index 25efd1ec6d8077aebadf601409c7059716111cb8..4cef88936e7e52848b70a8bb7098dc081fb1d350 100644 (file)
@@ -921,13 +921,15 @@ void DirectDraw_FillPrimary (void)
     DirectDraw_FillSurface (dxdata.primary, NULL, 0);
 }
 
-extern int vblank_skip;
+extern int vblank_skip, turbo_emulation;
 static void flip (void)
 {
     int result = 0;
     HRESULT ddrval = DD_OK;
     DWORD flags = DDFLIP_WAIT;
 
+    if (turbo_emulation)
+       flags |= DDFLIP_NOVSYNC;
     if (dxdata.backbuffers == 2) {
         DirectDraw_Blit (dxdata.flipping[1], dxdata.flipping[0]);
        if (currprefs.gfx_avsync) {
@@ -943,7 +945,7 @@ static void flip (void)
                }
            }
        } else {
-           ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags);
+           ddrval = IDirectDrawSurface7_Flip (dxdata.primary, NULL, flags| DDFLIP_NOVSYNC);
        }
     } else if(dxdata.backbuffers == 1) {
        if (currprefs.gfx_avsync) { 
@@ -961,7 +963,7 @@ static void flip (void)
            flip ();
            recurse--;
        }
-    } else if(FAILED (ddrval)) {
+    } else if (FAILED (ddrval)) {
        write_log (L"IDirectDrawSurface7_Flip: %s\n", DXError (ddrval));
     }
 }
index 88fa816a949f5b2dfaaa3a1a00690ff3ccb10da3..e000fc58a9d760a4834ba2cc87fbfba76667c865 100644 (file)
@@ -315,6 +315,8 @@ int dos_errno (void)
      case ERROR_INVALID_DRIVE:
      case ERROR_INVALID_NAME:
      case ERROR_PATH_NOT_FOUND:
+     case ERROR_NOT_READY:
+     case ERROR_BAD_UNIT:
        return ERROR_OBJECT_NOT_AROUND;
 
      case ERROR_HANDLE_DISK_FULL:
index 9299e10c7299859d867a8134c69a7d3f7bbb45d7..e4ae2f4b1b9e2b971b78c7aabe267b9b09bdcfb6 100644 (file)
@@ -205,7 +205,7 @@ static void create_uaefsdb (a_inode *aino, uae_u8 *buf, int winmode)
     char *s;
     buf[0] = 1;
     do_put_mem_long ((uae_u32 *)(buf + 1), aino->amigaos_mode);
-    s = uacp (aino->nname, currprefs.win32_fscodepage);
+    s = uacp (aino->aname, currprefs.win32_fscodepage);
     strncpy (buf + 5, s, 256);
     buf[5 + 256] = '\0';
     xfree (s);
@@ -219,7 +219,7 @@ static void create_uaefsdb (a_inode *aino, uae_u8 *buf, int winmode)
     buf[5 + 2 * 257 + 80] = '\0';
     xfree (s);
     do_put_mem_long ((uae_u32 *)(buf + 5 + 2 * 257 + 81), winmode);
-    _tcsncpy ((TCHAR*)(buf + 604), aino->nname, 256);
+    _tcsncpy ((TCHAR*)(buf + 604), aino->aname, 256);
     _tcsncpy ((TCHAR*)(buf + 1118), nn, 256);
     aino->has_dbentry = 0;
 }
@@ -525,16 +525,15 @@ static a_inode *custom_fsdb_lookup_aino (a_inode *base, const TCHAR *aname, int
     HANDLE h;
     WIN32_FIND_DATA fd;
     static a_inode dummy;
-    TCHAR *s;
 
     tmp1 = build_nname (base->nname, UAEFSDB_BEGINSX);
     if (!tmp1)
        return NULL;
-    s = au (fsdb + offset);
     h = FindFirstFile (tmp1, &fd);
     if (h != INVALID_HANDLE_VALUE) {
        do {
            if (read_uaefsdb (base->nname, fd.cFileName, fsdb)) {
+               TCHAR *s = au (fsdb + offset);
                if (same_aname (s, aname)) {
                    int winmode;
                    FindClose (h);
@@ -544,11 +543,11 @@ static a_inode *custom_fsdb_lookup_aino (a_inode *base, const TCHAR *aname, int
                        return &dummy;
                    return aino_from_buf (base, fsdb, &winmode);
                }
+               xfree (s);
            }
        } while (FindNextFile (h, &fd));
        FindClose (h);
     }
-    xfree (s);
     xfree (tmp1);
     return NULL;
 }
index 57a5953e2a98cf0fb8c833076c85f46827e34c06..07ab2597ac7d7ad6dca347391af0b17e1f4f911c 100644 (file)
@@ -115,7 +115,7 @@ static int safetycheck (HANDLE *h, uae_u64 offset, uae_u8 *buf, int blocksize)
        memset (buf, 0xaa, blocksize);
        ReadFile (h, buf, blocksize, &outlen, NULL);
        if (outlen != blocksize) {
-           write_log (L"hd ignored, read error %d!\n", GetLastError());
+           write_log (L"hd ignored, read error %d!\n", GetLastError ());
            return 2;
        }
        if (j == 0 && buf[0] == 0x39 && buf[1] == 0x10 && buf[2] == 0xd3 && buf[3] == 0x12) {
@@ -188,7 +188,7 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
     hfd->virtual_size = 0;
     hfd->virtual_rdb = NULL;
     if (!hfd->cache) {
-       write_log (L"VirtualAlloc(%d) failed, error %d\n", CACHE_SIZE, GetLastError());
+       write_log (L"VirtualAlloc(%d) failed, error %d\n", CACHE_SIZE, GetLastError ());
        goto end;
     }
     hfd_log (L"hfd open: '%s'\n", name);
@@ -212,7 +212,7 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
            if (h == INVALID_HANDLE_VALUE)
                goto end;
            if (!DeviceIoControl(h, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &r, NULL))
-               write_log (L"WARNING: '%s' FSCTL_ALLOW_EXTENDED_DASD_IO returned %d\n", name, GetLastError());
+               write_log (L"WARNING: '%s' FSCTL_ALLOW_EXTENDED_DASD_IO returned %d\n", name, GetLastError ());
            _tcsncpy (hfd->vendor_id, udi->vendor_id, 8);
            _tcsncpy (hfd->product_id, udi->product_id, 16);
            _tcsncpy (hfd->product_rev, udi->product_rev, 4);
@@ -272,10 +272,10 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
            DWORD ret, low, high;
            high = 0;
            ret = SetFilePointer (h, 0, &high, FILE_END);
-           if (ret == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
+           if (ret == INVALID_FILE_SIZE && GetLastError () != NO_ERROR)
                goto end;
            low = GetFileSize (h, &high);
-           if (low == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
+           if (low == INVALID_FILE_SIZE && GetLastError () != NO_ERROR)
                goto end;
            low &= ~(hfd->blocksize - 1);
            hfd->physsize = hfd->virtsize = ((uae_u64)high << 32) | low;
index 1278564db2e380e2778e46c7f716108332b886df..485348ad504d56d6d4e1bfdbee944ea480df9f0f 100644 (file)
@@ -972,8 +972,8 @@ IDI_PATHS               ICON                    "paths.ico"
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 1,6,0,0\r
- PRODUCTVERSION 1,6,0,0\r
+ FILEVERSION 1,6,1,0\r
+ PRODUCTVERSION 1,6,1,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -989,12 +989,12 @@ BEGIN
         BLOCK "040904b0"\r
         BEGIN\r
             VALUE "FileDescription", "WinUAE"\r
-            VALUE "FileVersion", "1.6.0"\r
+            VALUE "FileVersion", "1.6.1"\r
             VALUE "InternalName", "WinUAE"\r
             VALUE "LegalCopyright", "© 1996-2009 under the GNU Public License (GPL)"\r
             VALUE "OriginalFilename", "WinUAE.exe"\r
             VALUE "ProductName", "WinUAE"\r
-            VALUE "ProductVersion", "1.6.0"\r
+            VALUE "ProductVersion", "1.6.1"\r
         END\r
     END\r
     BLOCK "VarFileInfo"\r
index e2f2f0753e519199d8204e9ad9626316ba5a9b69..dc094be8449cb5364671ee493a07b2b8066c79c6 100644 (file)
@@ -65,6 +65,7 @@
                                LinkIncremental="2"
                                GenerateDebugInformation="true"
                                SubSystem="1"
+                               RandomizedBaseAddress="1"
                                TargetMachine="1"
                        />
                        <Tool
index d42faf12d27e6d22f8ddf8b2a778413eb22ee1bd..1275f44b94142f7d219c2a64b2a0e7e9a0c3aba3 100644 (file)
@@ -40,6 +40,7 @@
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
     <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
     <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IncludePath)</IncludePath>
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
index 97a132fd2bf25a4e2ac59c22feeb61c2c933431a..e685f40a525aa610e151a261c41ca82a2b12b52e 100644 (file)
@@ -525,10 +525,15 @@ void setmouseactive (int active)
        if (c != normalcursor)
            return;
     }
+    if (active) {
+       if (IsWindowVisible (hAmigaWnd) == FALSE)
+           return;
+    }
 
     if (active < 0)
        active = 1;
 
+
     mouseactive = active;
 
     mouseposx = mouseposy = 0;
@@ -2084,7 +2089,7 @@ void target_default_options (struct uae_prefs *p, int type)
        p->win32_rtgallowscaling = 0;
        p->win32_rtgscaleaspectratio = -1;
        p->win32_rtgvblankrate = 0;
-       p->win32_fscodepage = 1252;
+       p->win32_fscodepage = 0;
     }
     if (type == 1 || type == 0) {
        p->win32_uaescsimode = get_aspi (p->win32_uaescsimode);
index 3ecc7f7a069135db94fc867ccb206e336509b7e4..41ceb121543e7ded309423b6a2b5195fb4fa9725 100644 (file)
 #define GETBDM(x) (((x) - ((x / 10000) * 10000)) / 100)
 #define GETBDD(x) ((x) % 100)
 
-#define WINUAEPUBLICBETA 0
+#define WINUAEPUBLICBETA 1
 
-#define WINUAEBETA L""
-#define WINUAEDATE MAKEBD(2009, 5, 21)
+#define WINUAEBETA L"Beta 1"
+#define WINUAEDATE MAKEBD(2009, 5, 30)
 #define WINUAEEXTRA L""
 #define WINUAEREV L""
 
index bbbef30adf73e93888f8853018f49a432d30c44f..03ebaaf60bc25600881d96b1bf9689fdd0e28d26 100644 (file)
@@ -2009,6 +2009,7 @@ static int getbestmode (int nextbest)
 
 static int create_windows_2 (void)
 {
+    static int firstwindow = 1;
     int dxfs = currentmode->flags & (DM_DX_FULLSCREEN);
     int d3dfs = currentmode->flags & (DM_D3D_FULLSCREEN);
     int fsw = currentmode->flags & (DM_W_FULLSCREEN);
@@ -2228,11 +2229,12 @@ static int create_windows_2 (void)
        SetCursorPos (x + w / 2, y + h / 2);
     addnotifications (hAmigaWnd, FALSE);
     if (hMainWnd != hAmigaWnd) {
-       ShowWindow (hMainWnd, SW_SHOWNORMAL);
+       ShowWindow (hMainWnd, firstwindow ? SW_SHOWDEFAULT : SW_SHOWNORMAL);
        UpdateWindow (hMainWnd);
     }
-    ShowWindow (hAmigaWnd, SW_SHOWNORMAL);
+    ShowWindow (hAmigaWnd, firstwindow ? SW_SHOWDEFAULT : SW_SHOWNORMAL);
     UpdateWindow (hAmigaWnd);
+    firstwindow = 0;
 
     return 1;
 }
index 98b43ef69184f50c617a9ed4c000c60803acf712..554a54a2e33e210ceb0e919cd813a1472e77886e 100644 (file)
@@ -11708,7 +11708,7 @@ int dragdrop (HWND hDlg, HDROP hd, struct uae_prefs *prefs, int currentpage)
 
        if (drvdrag) {
            type = ZFILE_DISKIMAGE;
-       } else if (zip) {
+       } else if (zip || harddrive) {
            do_filesys_insert (file);
            continue;
        }
index b42b5cec70b22fb1fb9b129fa961ca20bd443bde..982d719f60e0682b6c83cf7caa17b6740b50dfd1 100644 (file)
@@ -1,4 +1,23 @@
 
+Beta 1
+
+- development PC updated to Intel Core i7 based. (Asus P6T DeluxeV2,
+  i7 920 2.66GHz CPU @ 3.7GHz, 3x2G 1866MHz RAM)
+- ASPI crash fixed (calling convention mismatch.. I didn't test and
+  only assumed previous fix would be the only problem left..)
+- filesys default codepage changed to default ansi page (1252 breaks
+  many non-european characters)
+- added more directory harddrive error codes to Windows->Amiga code
+  translation table (unit not ready, bad unit)
+- directory harddrive Windows illegal character handling was broken
+- do not capture mouse at startup if window is hidden/minimized
+- archive dragging to HD-led really mounts it as a harddrive, even
+  if it contains only disk images
+- 1760k HD and 10 sector DD PC formatted had switched internal
+  DD/HD flag (=above image types didn't work)
+- FAT12 formatted images supported as a harddrive (uaeunp feature)
+- turbo/warp mode in fullscreen mode wasn't as fast as possible
+
 Final 1.6.0
 
 - filter mode PAL aspect ratio corrected (~5% difference) if keep
index 0970666c2441b9e6e3d83ba1e29be8ba77b44d6e..53c0f182468c1dc045484b2ef38479f9cbbc166b 100644 (file)
--- a/uaeunp.c
+++ b/uaeunp.c
@@ -692,7 +692,7 @@ int wmain (int argc, wchar_t *argv[], wchar_t *envp[])
        ok = 1;
     }
     if (!ok) {
-       _tprintf (L"UAE unpacker uaeunp 0.5c by Toni Wilen (c)2009\n");
+       _tprintf (L"UAE unpacker uaeunp 0.6 by Toni Wilen (c)2009\n");
        _tprintf (L"\n");
        _tprintf (L"List: \"uaeunp (-l) <path>\"\n");
        _tprintf (L"List all recursively: \"uaeunp -l <path> **\"\n");
@@ -703,7 +703,9 @@ int wmain (int argc, wchar_t *argv[], wchar_t *envp[])
        _tprintf (L"Output to console: \"uaeunp (-x) -o <path> <filename>\"\n");
        _tprintf (L"\n");
        _tprintf (L"Supported disk image formats:\n");
-       _tprintf (L" ADF and HDF (OFS/FFS/SFS/SFS2), DMS, encrypted DMS, IPF, FDI, DSQ, WRP\n");
+       _tprintf (L" ADF, HDF, DMS, encrypted DMS, IPF, FDI, DSQ, WRP\n");
+       _tprintf (L"Supported filesystems:\n");
+       _tprintf (L" OFS, FFS, SFS, SFS2 and FAT12\n");
        _tprintf (L"Supported archive formats:\n");
        _tprintf (L" 7ZIP, LHA, LZX, RAR (unrar.dll), ZIP, ArchiveAccess.DLL\n");
        _tprintf (L"Miscellaneous formats:\n");
@@ -715,6 +717,11 @@ int wmain (int argc, wchar_t *argv[], wchar_t *envp[])
 }
 
 /*
+    0.6:
+
+    - rdb handling optimization (no more huge memory usage)
+    - fat16 supported
+
     0.5:
 
     - adf protection flags fixed
diff --git a/zfile.c b/zfile.c
index 23bbb8e36a71b9197a05d7b4bbc4c03b2ccf45b2..e23e5d7cff6a503c810ce0e7f5f4b0dcf073f83c 100644 (file)
--- a/zfile.c
+++ b/zfile.c
@@ -33,7 +33,7 @@ static struct zfile *zlist = 0;
 
 const TCHAR *uae_archive_extensions[] = { L"zip", L"rar", L"7z", L"lha", L"lzh", L"lzx", NULL };
 
-static struct zfile *zfile_create (void)
+static struct zfile *zfile_create (struct zfile *prev)
 {
     struct zfile *z;
 
@@ -43,6 +43,10 @@ static struct zfile *zfile_create (void)
     memset (z, 0, sizeof *z);
     z->next = zlist;
     zlist = z;
+    z->opencnt = 1;
+    if (prev) {
+       z->zfdmask = prev->zfdmask;
+    }
     return z;
 }
 
@@ -77,9 +81,22 @@ void zfile_fclose (struct zfile *f)
 
     if (!f)
        return;
+    if (f->opencnt < 0) {
+       write_log (L"zfile: tried to free already closed filehandle!\n");
+       return;
+    }
+    f->opencnt--;
+    if (f->opencnt > 0)
+       return;
+    f->opencnt = -100;
+    if (f->parent) {
+       f->parent->opencnt--;
+       if (f->parent->opencnt <= 0)
+           zfile_fclose (f->parent);
+    }
     while (l != f) {
        if (l == 0) {
-           write_log (L"zfile: tried to free already freed filehandle!\n");
+           write_log (L"zfile: tried to free already freed or nonexisting filehandle!\n");
            return;
        }
        pl = l;
@@ -227,30 +244,43 @@ struct zfile *zfile_gunzip (struct zfile *z)
     return z2;
 }
 
-static struct zfile *extadf (struct zfile *z)
+static struct zfile *extadf (struct zfile *z, int pctype)
 {
     int i, r;
     struct zfile *zo;
     uae_u16 *mfm;
     uae_u16 *amigamfmbuffer;
-    uae_u8 writebuffer_ok[11];
-    int tracks, size, len, offs, pos;
+    uae_u8 writebuffer_ok[32], *outbuf;
+    int tracks, len, offs, pos;
     uae_u8 buffer[2 + 2 + 4 + 4];
+    int outsize;
+    TCHAR newname[MAX_DPATH];
+    TCHAR *ext;
+
+    //pctype = 1;
 
     mfm = xcalloc (32000, 1);
     amigamfmbuffer = xcalloc (32000, 1);
+    outbuf = xcalloc (16384, 1);
 
     zfile_fread (buffer, 1, 8, z);
     zfile_fread (buffer, 1, 4, z);
     tracks = buffer[2] * 256 + buffer[3];
     offs = 8 + 2 + 2 + tracks * (2 + 2 + 4 + 4);
 
-    size = tracks * 512 * 11;
-    zo = zfile_fopen_empty (z, zfile_getname (z), size);
+    _tcscpy (newname, zfile_getname (z));
+    ext = _tcsrchr (newname, '.');
+    if (ext) {
+       _tcscpy (newname + _tcslen (newname) - _tcslen (ext), L".ext.adf");
+    } else {
+       _tcscat (newname, L".adf");
+    }
+    zo = zfile_fopen_empty (z, newname, 0);
     if (!zo)
        goto end;
 
     pos = 12;
+    outsize = 0;
     for (i = 0; i < tracks; i++) {
        int type, bitlen;
        
@@ -265,14 +295,25 @@ static struct zfile *extadf (struct zfile *z)
        if (type == 1) {
            zfile_fread (mfm, len, 1, z);
            memset (writebuffer_ok, 0, sizeof writebuffer_ok);
-           r = isamigatrack (amigamfmbuffer, (uae_u8*)mfm, len, zo->data + i * 512 * 11, writebuffer_ok, i);
-           if (r < 0 && i == 0) {
-               zfile_seterror (L"'%s' is not AmigaDOS formatted", zo->name);
-               goto end;
+           memset (outbuf, 0, 16384);
+           if (pctype <= 0) {
+               r = isamigatrack (amigamfmbuffer, (uae_u8*)mfm, len, outbuf, writebuffer_ok, i, &outsize);
+               if (r < 0 && i == 0) {
+                   zfile_seterror (L"'%s' is not AmigaDOS formatted", zo->name);
+                   goto end;
+               }
+           } else {
+               r = ispctrack (amigamfmbuffer, (uae_u8*)mfm, len, outbuf, writebuffer_ok, i, &outsize);
+               if (r < 0 && i == 0) {
+                   zfile_seterror (L"'%s' is not PC formatted", zo->name);
+                   goto end;
+               }
            }
        } else {
-           zfile_fread (zo->data + i * 512 * 11, 11 * 512, 1, z);
+           outsize = 512 * 11;
+           zfile_fread (outbuf, outsize, 1, z);
        }
+       zfile_fwrite (outbuf, outsize, 1, zo);
 
        offs += len;
 
@@ -290,7 +331,7 @@ end:
 
 
 #include "fdi2raw.h"
-static struct zfile *fdi (struct zfile *z)
+static struct zfile *fdi (struct zfile *z, int type)
 {
     int i, j, r;
     struct zfile *zo;
@@ -299,8 +340,8 @@ static struct zfile *fdi (struct zfile *z)
     TCHAR newname[MAX_DPATH];
     uae_u16 *mfm;
     uae_u16 *amigamfmbuffer;
-    uae_u8 writebuffer_ok[11];
-    int tracks, size, len;
+    uae_u8 writebuffer_ok[32], *outbuf;
+    int tracks, len, outsize;
     FDI *fdi;
 
     fdi = fdi2raw_header (z);
@@ -308,17 +349,18 @@ static struct zfile *fdi (struct zfile *z)
        return z;
     mfm = xcalloc (32000, 1);
     amigamfmbuffer = xcalloc (32000, 1);
+    outbuf = xcalloc (16384, 1);
     tracks = fdi2raw_get_last_track (fdi);
-    size = tracks * 512 * 11;
     if (ext) {
        _tcscpy (newname, orgname);
        _tcscpy (newname + _tcslen (newname) - _tcslen (ext), L".adf");
     } else {
        _tcscat (newname, L".adf");
     }
-    zo = zfile_fopen_empty (z, newname, size);
+    zo = zfile_fopen_empty (z, newname, 0);
     if (!zo)
        goto end;
+    outsize = 0;
     for (i = 0; i < tracks; i++) {
        uae_u8 *p = (uae_u8*)mfm;
        fdi2raw_loadtrack (fdi, mfm, NULL, i, &len, NULL, NULL, 1);
@@ -329,16 +371,27 @@ static struct zfile *fdi (struct zfile *z)
            *p++ = v;
        }
        memset (writebuffer_ok, 0, sizeof writebuffer_ok);
-       r = isamigatrack (amigamfmbuffer, (uae_u8*)mfm, len, zo->data + i * 512 * 11, writebuffer_ok, i);
-       if (r < 0 && i == 0) {
-           zfile_seterror (L"'%s' is not AmigaDOS formatted", orgname);
-           goto end;
+       memset (outbuf, 0, 16384);
+       if (type <= 0) {
+           r = isamigatrack (amigamfmbuffer, (uae_u8*)mfm, len, outbuf, writebuffer_ok, i, &outsize);
+           if (r < 0 && i == 0) {
+               zfile_seterror (L"'%s' is not AmigaDOS formatted", orgname);
+               goto end;
+           }
+       } else if (type == 1) {
+           r = ispctrack (amigamfmbuffer, (uae_u8*)mfm, len, outbuf, writebuffer_ok, i, &outsize);
+           if (r < 0 && i == 0) {
+               zfile_seterror (L"'%s' is not PC formatted", orgname);
+               goto end;
+           }
        }
+       zfile_fwrite (outbuf, outsize, 1, zo);
     }
     zfile_fclose (z);
     fdi2raw_header_free (fdi);
     xfree (mfm);
     xfree (amigamfmbuffer);
+    xfree (outbuf);
     return zo;
 end:
     if (zo)
@@ -346,13 +399,13 @@ end:
     fdi2raw_header_free (fdi);
     xfree (mfm);
     xfree (amigamfmbuffer);
+    xfree (outbuf);
     return z;
 }
 
-
 #ifdef CAPS
 #include "caps/caps_win32.h"
-static struct zfile *ipf (struct zfile *z)
+static struct zfile *ipf (struct zfile *z, int type)
 {
     int i, j, r;
     struct zfile *zo;
@@ -361,24 +414,26 @@ static struct zfile *ipf (struct zfile *z)
     TCHAR newname[MAX_DPATH];
     uae_u16 *mfm;
     uae_u16 *amigamfmbuffer;
-    uae_u8 writebuffer_ok[11];
-    int tracks, size, len;
-
+    uae_u8 writebuffer_ok[32];
+    int tracks, len;
+    int outsize;
+    uae_u8 *outbuf;
 
     if (!caps_loadimage (z, 0, &tracks))
        return z;
     mfm = xcalloc (32000, 1);
+    outbuf = xcalloc (16384, 1);
     amigamfmbuffer = xcalloc (32000, 1);
-    size = tracks * 512 * 11;
     if (ext) {
        _tcscpy (newname, orgname);
        _tcscpy (newname + _tcslen (newname) - _tcslen (ext), L".adf");
     } else {
        _tcscat (newname, L".adf");
     }
-    zo = zfile_fopen_empty (z, newname, size);
+    zo = zfile_fopen_empty (z, newname, 0);
     if (!zo)
        goto end;
+    outsize = 0;
     for (i = 0; i < tracks; i++) {
        uae_u8 *p = (uae_u8*)mfm;
        caps_loadrevolution (mfm, 0, i, &len);
@@ -389,16 +444,19 @@ static struct zfile *ipf (struct zfile *z)
            *p++ = v;
        }
        memset (writebuffer_ok, 0, sizeof writebuffer_ok);
-       r = isamigatrack (amigamfmbuffer, (uae_u8*)mfm, len, zo->data + i * 512 * 11, writebuffer_ok, i);
+       memset (outbuf, 0, 16384);
+       r = isamigatrack (amigamfmbuffer, (uae_u8*)mfm, len, outbuf, writebuffer_ok, i, &outsize);
        if (r < 0 && i == 0) {
            zfile_seterror (L"'%s' is not AmigaDOS formatted", orgname);
            goto end;
        }
+       zfile_fwrite (outbuf, 1, outsize, zo);
     }
     caps_unloadimage (0);
     zfile_fclose (z);
     xfree (mfm);
     xfree (amigamfmbuffer);
+    xfree (outbuf);
     return zo;
 end:
     if (zo)
@@ -406,6 +464,7 @@ end:
     caps_unloadimage (0);
     xfree (mfm);
     xfree (amigamfmbuffer);
+    xfree (outbuf);
     return z;
 }
 #endif
@@ -541,7 +600,7 @@ int iszip (struct zfile *z)
 {
     TCHAR *name = z->name;
     TCHAR *ext = _tcsrchr (name, '.');
-    uae_u8 header[7];
+    uae_u8 header[32];
     int i;
     int mask = z->zfdmask;
 
@@ -587,6 +646,8 @@ int iszip (struct zfile *z)
        if (!strcasecmp (ext, L".adf")) {
            if (header[0] == 'D' && header[1] == 'O' && header[2] == 'S' && (header[3] >= 0 && header[3] <= 7))
                return ArchiveFormatADF;
+           if (isfat (header))
+               return ArchiveFormatFAT;
            return 0;
        }
     }
@@ -598,6 +659,8 @@ int iszip (struct zfile *z)
                return ArchiveFormatADF;
            if (header[0] == 'R' && header[1] == 'D' && header[2] == 'S' && header[3] == 'K')
                return ArchiveFormatRDB;
+           if (isfat (header))
+               return ArchiveFormatFAT;
            return 0;
        }
     }
@@ -615,11 +678,11 @@ struct zfile *zuncompress (struct znode *parent, struct zfile *z, int dodefault,
 {
     TCHAR *name = z->name;
     TCHAR *ext = NULL;
-    uae_u8 header[8];
+    uae_u8 header[32];
     int i;
 
     if (!mask)
-       return z;
+       return NULL;
     if (name) {
        ext = _tcsrchr (name, '.');
        if (ext)
@@ -655,11 +718,25 @@ struct zfile *zuncompress (struct znode *parent, struct zfile *z, int dodefault,
        }
        if (mask & ZFD_RAWDISK) {
 #ifdef CAPS
-           if (strcasecmp (ext, L"ipf") == 0)
-                return ipf (z);
+           if (strcasecmp (ext, L"ipf") == 0) {
+               if (mask & ZFD_RAWDISK_PC)
+                   return ipf (z, 1);
+               else if (mask & ZFD_RAWDISK_AMIGA)
+                   return ipf (z, 0);
+               else
+                   return ipf (z, -1);
+           }
 #endif
-           if (strcasecmp (ext, L"fdi") == 0)
-                return fdi (z);
+           if (strcasecmp (ext, L"fdi") == 0) {
+               if (mask & ZFD_RAWDISK_PC)
+                   return fdi (z, 1);
+               else if (mask & ZFD_RAWDISK_AMIGA)
+                   return fdi (z, 0);
+               else
+                   return fdi (z, -1);
+           }
+           if (mask & (ZFD_RAWDISK_PC | ZFD_RAWDISK_AMIGA))
+               return NULL;
        }
 #if defined(ARCHIVEACCESS)
        for (i = 0; plugins_7z_x[i]; i++) {
@@ -682,13 +759,31 @@ struct zfile *zuncompress (struct znode *parent, struct zfile *z, int dodefault,
     }
     if (mask & ZFD_RAWDISK) {
 #ifdef CAPS
-       if (header[0] == 'C' && header[1] == 'A' && header[2] == 'P' && header[3] == 'S')
-            return ipf (z);
+       if (header[0] == 'C' && header[1] == 'A' && header[2] == 'P' && header[3] == 'S') {
+           if (mask & ZFD_RAWDISK_PC)
+               return ipf (z, 1);
+           else if (mask & ZFD_RAWDISK_AMIGA)
+               return ipf (z, 0);
+           else
+               return ipf (z, -1);
+       }
 #endif
-       if (!memcmp (header, "Formatte", 8))
-           return fdi (z);
-       if (!memcmp (header, "UAE-1ADF", 8))
-           return extadf (z);
+       if (!memcmp (header, "Formatte", 8)) {
+           if (mask & ZFD_RAWDISK_PC)
+               return fdi (z, 1);
+           else if (mask & ZFD_RAWDISK_AMIGA)
+               return fdi (z, 0);
+           else
+               return fdi (z, -1);
+       }
+       if (!memcmp (header, "UAE-1ADF", 8)) {
+           if (mask & ZFD_RAWDISK_PC)
+               return extadf (z, 1);
+           else if (mask & ZFD_RAWDISK_AMIGA)
+               return extadf (z, 0);
+           else
+               return extadf (z, -1);
+       }
     }
     if (mask & ZFD_ARCHIVE) {
         if (header[0] == 'P' && header[1] == 'K')
@@ -705,6 +800,8 @@ struct zfile *zuncompress (struct znode *parent, struct zfile *z, int dodefault,
            return archive_access_select (parent, z, ArchiveFormatADF, dodefault);
        if (header[0] == 'S' && header[1] == 'F' && header[2] == 'S')
            return archive_access_select (parent, z, ArchiveFormatADF, dodefault);
+       if (isfat (header))
+           return archive_access_select (parent, z, ArchiveFormatFAT, dodefault);
     }
 
     if (ext) {
@@ -717,7 +814,7 @@ struct zfile *zuncompress (struct znode *parent, struct zfile *z, int dodefault,
                return archive_access_select (parent, z, ArchiveFormatADF, dodefault);
        }
     }
-    return z;
+    return NULL;
 }
 
 
@@ -766,7 +863,7 @@ static struct zfile *zfile_fopen_nozip (const TCHAR *name, const TCHAR *mode)
 
     if(*name == '\0')
        return NULL;
-    l = zfile_create ();
+    l = zfile_create (NULL);
     l->name = my_strdup (name);
     l->mode = my_strdup (mode);
     f = _tfopen (name, mode);
@@ -829,7 +926,7 @@ static struct zfile *zfile_fopen_2 (const TCHAR *name, const TCHAR *mode, int ma
        }
        l->zfdmask = mask;
     } else {
-       l = zfile_create ();
+       l = zfile_create (NULL);
        l->mode = my_strdup (mode);
        l->name = my_strdup (name);
        l->zfdmask = mask;
@@ -906,13 +1003,12 @@ struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode, int mask)
        return l;
     l2 = NULL;
     while (cnt-- > 0) {
-       l = zuncompress (NULL, l, 0, mask);
-       if (!l)
-           break;
        zfile_fseek (l, 0, SEEK_SET);
-       if (l == l2)
+       l2 = zuncompress (NULL, l, 0, mask);
+       zfile_fseek (l, 0, SEEK_SET);
+       if (!l2)
            break;
-       l2 = l;
+       l = l2;
     }
     return l;
 }
@@ -923,7 +1019,7 @@ struct zfile *zfile_dup (struct zfile *zf)
     if (!zf)
        return NULL;
     if (zf->data) {
-       nzf = zfile_create ();
+       nzf = zfile_create (zf);
        nzf->data = xmalloc (zf->size);
        memcpy (nzf->data, zf->data, zf->size);
        nzf->size = zf->size;
@@ -931,7 +1027,7 @@ struct zfile *zfile_dup (struct zfile *zf)
        nzf = openzip (zf->name);
        return nzf;
     } else {
-       nzf = zfile_create ();
+       nzf = zfile_create (zf);
         nzf->f = _tfopen (zf->name, zf->mode);
     }
     zfile_fseek (nzf, zf->seek, SEEK_SET);
@@ -975,7 +1071,7 @@ int zfile_iscompressed (struct zfile *z)
 struct zfile *zfile_fopen_empty (struct zfile *prev, const TCHAR *name, uae_u64 size)
 {
     struct zfile *l;
-    l = zfile_create ();
+    l = zfile_create (prev);
     l->name = name ? my_strdup (name) : L"";
     if (size) {
        l->data = xcalloc (size, 1);
@@ -988,16 +1084,36 @@ struct zfile *zfile_fopen_empty (struct zfile *prev, const TCHAR *name, uae_u64
        l->data = xcalloc (1, 1);
        l->size = 0;
     }
-    if (prev) {
-       l->zfdmask = prev->zfdmask;
+    return l;
+}
+
+struct zfile *zfile_fopen_parent (struct zfile *z, const TCHAR *name, uae_u64 offset, uae_u64 size)
+{
+    struct zfile *l;
+
+    l = zfile_create (z);
+    if (name)
+       l->name = my_strdup (name);
+    else if (z->name)
+       l->name = my_strdup (z->name);
+    l->size = size;
+    l->offset = offset;
+    for (;;) {
+       l->parent = z;
+       if (!z->parent)
+           break;
+        l->offset += z->offset;
+       z = z->parent;
     }
+    z->opencnt++;
     return l;
 }
 
 struct zfile *zfile_fopen_data (const TCHAR *name, uae_u64 size, uae_u8 *data)
 {
     struct zfile *l;
-    l = zfile_create ();
+
+    l = zfile_create (NULL);
     l->name = name ? my_strdup (name) : L"";
     l->data = xmalloc (size);
     l->size = size;
@@ -1007,9 +1123,16 @@ struct zfile *zfile_fopen_data (const TCHAR *name, uae_u64 size, uae_u8 *data)
 
 uae_s64 zfile_ftell (struct zfile *z)
 {
+    uae_s64 v;
     if (z->data)
        return z->seek;
-    return _ftelli64 (z->f);
+    if (z->parent) {
+       v = _ftelli64 (z->parent->f);
+       v -= z->offset;
+    } else {
+       v = _ftelli64 (z->f);
+    }
+    return v;
 }
 
 uae_s64 zfile_fseek (struct zfile *z, uae_s64 offset, int mode)
@@ -1037,8 +1160,46 @@ uae_s64 zfile_fseek (struct zfile *z, uae_s64 offset, int mode)
            ret = 1;
        }
        return ret;
+    } else {
+       if (z->parent) {
+           switch (mode)
+           {
+               case SEEK_SET:
+               if (offset >= z->size) {
+                   _fseeki64 (z->parent->f, z->offset + z->size, SEEK_SET);
+                   return 1;
+               } else if (offset < 0) {
+                   return 1;
+               }
+               return _fseeki64 (z->parent->f, offset + z->offset, SEEK_SET);
+
+               case SEEK_END:
+               if (offset > 0)
+                   return 1;
+               if (offset < -z->size) {
+                   _fseeki64 (z->parent->f, z->offset, SEEK_SET);
+                   return 1;
+               }
+               return _fseeki64 (z->parent->f, offset + z->size + z->offset, SEEK_SET);
+
+               case SEEK_CUR:
+               {
+                   uae_s64 v = zfile_ftell (z->parent);
+                   if (v + offset > z->size) {
+                       _fseeki64 (z->parent->f, z->offset + z->size, SEEK_SET);
+                       return 1;
+                   } else if (v + offset < 0) {
+                       _fseeki64 (z->parent->f, z->offset, SEEK_SET);
+                       return 1;
+                   }
+                   return _fseeki64 (z->parent->f, v + offset + z->offset, SEEK_SET);
+               }
+           }
+       } else {
+           return _fseeki64 (z->f, offset, mode);
+       }
     }
-    return _fseeki64 (z->f, offset, mode);
+    return 1;
 }
 
 size_t zfile_fread  (void *b, size_t l1, size_t l2,struct zfile *z)
@@ -1052,23 +1213,36 @@ size_t zfile_fread  (void *b, size_t l1, size_t l2,struct zfile *z)
            if (l2 < 0)
                l2 = 0;
        }
-       memcpy (b, z->data + z->seek, l1 * l2);
+       memcpy (b, z->data + z->offset + z->seek, l1 * l2);
        z->seek += l1 * l2;
        return l2;
     }
+    if (z->parent) {
+       uae_s64 v;
+       uae_s64 size = z->size;
+       z = z->parent;
+       v = zfile_ftell (z);
+       if (v + l1 * l2 > size) {
+           if (l1)
+               l2 = (size - v) / l1;
+           else
+               l2 = 0;
+           if (l2 < 0)
+               l2 = 0;
+       }
+    }
     return fread (b, l1, l2, z->f);
 }
 
 size_t zfile_fwrite (void *b, size_t l1, size_t l2, struct zfile *z)
 {
+    if (z->parent)
+       return 0;
     if (z->data) {
-       if (z->seek + l1 * l2 > z->size) {
-           if (l1)
-               l2 = (z->size - z->seek) / l1;
-           else
-               l2 = 0;
-           if (l2 < 0)
-               l2 = 0;
+       int off = z->seek + l1 * l2;
+       if (off > z->size) {
+           z->data = realloc (z->data, off);
+           z->size = off;
        }
        memcpy (z->data + z->seek, b, l1 * l2);
        z->seek += l1 * l2;
@@ -1158,8 +1332,9 @@ int zfile_getc (struct zfile *z)
 {
     int out = -1;
     if (z->data) {
-       if (z->seek < z->size)
+       if (z->seek < z->size) {
            out = z->data[z->seek++];
+       }
     } else {
        out = fgetc (z->f);
     }
@@ -1514,7 +1689,7 @@ static struct zvolume *zfile_fopen_archive_ext (struct znode *parent, struct zfi
 static struct zvolume *zfile_fopen_archive_data (struct znode *parent, struct zfile *zf)
 {
     struct zvolume *zv = NULL;
-    uae_u8 header[7];
+    uae_u8 header[32];
 
     memset (header, 0, sizeof (header));
     zfile_fread (header, sizeof (header), 1, zf);
@@ -1531,6 +1706,8 @@ static struct zvolume *zfile_fopen_archive_data (struct znode *parent, struct zf
         zv = archive_directory_adf (parent, zf);
     if (header[0] == 'R' && header[1] == 'D' && header[2] == 'S' && header[3] == 'K')
         zv = archive_directory_rdb (zf);
+    if (isfat (header))
+       zv = archive_directory_fat (zf);
     return zv;
 }
 
@@ -1601,10 +1778,11 @@ static struct zvolume *prepare_recursive_volume (struct zvolume *zv, const TCHAR
        goto end;
     zvnew = zfile_fopen_archive_ext (zv->parentz, zf);
     if (!zvnew) {
-       struct zfile *zf2 = zf;
-       zf = zuncompress (&zv->root, zf2, 0, ZFD_ALL);
-       if (zf != zf2)
+       struct zfile *zf2 = zuncompress (&zv->root, zf, 0, ZFD_ALL);
+       if (zf2) {
+           zf = zf2;
            zvnew = archive_directory_plain (zf);
+       }
     }
     if (!zvnew)
        goto end;
@@ -1800,6 +1978,7 @@ struct zvolume *zfile_fopen_archive (const TCHAR *filename)
        zvolume_addtolist (zv);
     else
        zfile_fclose (zf);
+
     return zv;
 }
 
@@ -1868,6 +2047,7 @@ void zfile_fclose_archive (struct zvolume *zv)
        xfree (zn->fullname);
        xfree (zn->name);
        zfile_fclose (zn->f);
+       memset (zn, 0, sizeof (struct znode));
        if (zn != &zv->root)
            xfree (zn);
        zn = zn2;
index ffbae8dfbac25eeaafe4b496fc4eed1515ccf08b..c441ac75f4131c9a6511fe7e6a8da03505d9db5a 100644 (file)
@@ -74,6 +74,9 @@ static struct zvolume *getzvolume (struct znode *parent, struct zfile *zf, unsig
        case ArchiveFormatRDB:
        zv = archive_directory_rdb (zf);
        break;
+       case ArchiveFormatFAT:
+       zv = archive_directory_fat (zf);
+       break;
     }
     if (!zv)
        zv = archive_directory_arcacc (zf, id);
@@ -110,6 +113,9 @@ struct zfile *archive_getzfile (struct znode *zn, unsigned int id)
        case ArchiveFormatRDB:
        zf = archive_access_rdb (zn);
        break;
+       case ArchiveFormatFAT:
+       zf = archive_access_fat (zn);
+       break;
     }
     return zf;
 }
@@ -844,8 +850,9 @@ static struct znode *addfile (struct zvolume *zv, struct zfile *zf, const TCHAR
 {
     struct zarchive_info zai;
     struct znode *zn;
-    struct zfile *z = zfile_fopen_empty (zf, path, size);
-
+    struct zfile *z;
+    
+    z = zfile_fopen_empty (zf, path, size);
     zfile_fwrite (data, size, 1, z);
     memset(&zai, 0, sizeof zai);
     zai.name = path;
@@ -887,18 +894,19 @@ struct zvolume *archive_directory_plain (struct zfile *z)
     }
     zf = zfile_dup (z);
     zf2 = zuncompress (NULL, zf, 0, ZFD_ALL);
-    if (zf2 != zf) {
-       zf = zf2;
-       zai.name = zfile_getfilename (zf);
+    if (zf2) {
+       zf = NULL;
+       zai.name = zfile_getfilename (zf2);
        zai.flags = -1;
-       zfile_fseek(zf, 0, SEEK_END);
+       zfile_fseek (zf2, 0, SEEK_END);
        zai.size = zfile_ftell (zf2);
-       zfile_fseek(zf, 0, SEEK_SET);
+       zfile_fseek (zf2, 0, SEEK_SET);
        zn = zvolume_addfile_abs (zv, &zai);
        if (zn)
            zn->offset = 1;
+       zfile_fclose (zf2);
     }
-    zfile_fclose (zf2);
+    zfile_fclose (zf);
     return zv;
 }
 struct zfile *archive_access_plain (struct znode *zn)
@@ -909,8 +917,10 @@ struct zfile *archive_access_plain (struct znode *zn)
        struct zfile *zf;
        z = zfile_fopen_empty (zn->volume->archive, zn->fullname, zn->size);
        zf = zfile_fopen (zfile_getname (zn->volume->archive), L"rb", zn->volume->archive->zfdmask & ~ZFD_ADF);
-       zfile_fread (z->data, zn->size, 1, zf);
-       zfile_fclose (zf);
+       if (zf) {
+           zfile_fread (z->data, zn->size, 1, zf);
+           zfile_fclose (zf);
+       }
     } else {
        z = zfile_fopen_empty (zn->volume->archive, zn->fullname, zn->size);
        if (z) {
@@ -1207,11 +1217,12 @@ struct zvolume *archive_directory_adf (struct znode *parent, struct zfile *z)
            bs = adf->blocksize = 512;
            if (adf->size < 2000000 && adf->rootblock != 880) {
                adf->rootblock = 880;
+               if (!adf_read_block (adf, adf->rootblock))
+                   goto fail;
                if (gl (adf, 0) != 2 || gl (adf, bs - 1 * 4) != 1)
                    goto fail;
                if (dos_checksum (adf->block, bs) != 0)
                    goto fail;
-               goto fail;
            }
        }
 
@@ -1593,12 +1604,283 @@ struct zfile *archive_access_rdb (struct znode *zn)
        size = zn->size;
     }
 
-    zf = zfile_fopen_empty (z, zn->fullname, size);
-    zfile_fseek (z, block * blocksize, SEEK_SET);
-    zfile_fread (zf->data, size, 1, z);
+    zf = zfile_fopen_parent (z, zn->fullname, block * blocksize, size);
     return zf;
 }
 
+int isfat (uae_u8 *p)
+{
+    int i, b;
+
+    if ((p[0x15] & 0xf0) != 0xf0)
+       return 0;
+    if (p[0x0b] != 0x00 || p[0x0c] != 0x02)
+       return 0;
+    b = 0;
+    for (i = 0; i < 8; i++) {
+       if (p[0x0d] & (1 << i))
+           b++;
+    }
+    if (b != 1)
+       return 0;
+    if (p[0x0f] != 0)
+       return 0;
+    if (p[0x0e] > 8 || p[0x0e] == 0)
+       return 0;
+    if (p[0x10] == 0 || p[0x10] > 8)
+       return 0;
+    b = (p[0x12] << 8) | p[0x11];
+    if (b > 8192 || b <= 0)
+       return 0;
+    b = p[0x16] | (p[0x17] << 8);
+    if (b == 0 || b > 8192)
+       return 0;
+    return 1;
+}
+
+/*
+ * The epoch of FAT timestamp is 1980.
+ *     :  bits :     value
+ * date:  0 -  4: day   (1 -  31)
+ * date:  5 -  8: month (1 -  12)
+ * date:  9 - 15: year  (0 - 127) from 1980
+ * time:  0 -  4: sec   (0 -  29) 2sec counts
+ * time:  5 - 10: min   (0 -  59)
+ * time: 11 - 15: hour  (0 -  23)
+ */
+#define SECS_PER_MIN    60
+#define SECS_PER_HOUR   (60 * 60)
+#define SECS_PER_DAY    (SECS_PER_HOUR * 24)
+#define UNIX_SECS_1980  315532800L   
+#if BITS_PER_LONG == 64
+#define UNIX_SECS_2108  4354819200L
+#endif
+/* days between 1.1.70 and 1.1.80 (2 leap days) */
+#define DAYS_DELTA      (365 * 10 + 2)         
+/* 120 (2100 - 1980) isn't leap year */
+#define YEAR_2100       120 
+#define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != YEAR_2100)
+
+/* Linear day numbers of the respective 1sts in non-leap years. */
+static time_t days_in_year[] = {
+        /* Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec */
+        0,   0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
+};
+
+/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
+static time_t fat_time_fat2unix (uae_u16 time, uae_u16 date, int fat12)
+{
+    time_t second, day, leap_day, month, year;
+
+    if (0 && fat12) {
+       year = date & 0x7f;
+       month = (date >> 7) & 0x0f;
+       day = (date >> 11);
+    } else {
+       year  = date >> 9;  
+       month = max(1, (date >> 5) & 0xf);
+       day   = max(1, date & 0x1f) - 1;
+    }
+
+    leap_day = (year + 3) / 4;
+    if (year > YEAR_2100)           /* 2100 isn't leap year */
+       leap_day--;
+    if (IS_LEAP_YEAR(year) && month > 2)
+       leap_day++;
+
+    second =  (time & 0x1f) << 1;
+    second += ((time >> 5) & 0x3f) * SECS_PER_MIN;
+    second += (time >> 11) * SECS_PER_HOUR;
+    second += (year * 365 + leap_day
+       + days_in_year[month] + day
+       + DAYS_DELTA) * SECS_PER_DAY;
+    return second;
+}
+
+static int getcluster (struct zfile *z, int cluster, int fatstart, int fatbits)
+{
+    uae_u32 fat = 0;
+    uae_u8 p[4];
+    int offset = cluster * fatbits;
+    zfile_fseek (z, fatstart * 512 + offset / 8, SEEK_SET);
+    if (fatbits == 12) {
+       zfile_fread (p, 2, 1, z);
+       if ((offset & 4))
+           fat = ((p[0] & 0xf0) >> 4) | (p[1] << 4);
+       else
+           fat = (p[0]) | ((p[1] & 0x0f) << 8);
+       if (fat >= 0xff0)
+           return -1;
+    } else if (fatbits == 16) {
+       zfile_fread (p, 2, 1, z);
+       fat = p[0] | (p[1] << 8);
+       if (fat >= 0xfff0)
+           return -1;
+    } else if (fatbits == 32) {
+       zfile_fread (p, 4, 1, z);
+       fat = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+       fat &= ~0x0fffffff;
+       if (fat >= 0x0ffffff0)
+           return -1;
+    }
+    return fat;
+}
+
+static void fatdirectory (struct zfile *z, struct zvolume *zv, TCHAR *name, int startblock, int entries, int sectorspercluster, int fatstart, int dataregion, int fatbits)
+{
+    struct zarchive_info zai;
+    struct znode *znnew;
+    int i, j;
+
+    for (i = 0; i < entries; i++) {
+       TCHAR name2[MAX_DPATH], *fname;
+       uae_s64 size;
+       uae_u8 fatname[16];
+       uae_u8 buf[32];
+       int attr, cnt, ext;
+       int startcluster;
+
+       memset (buf, 0, sizeof buf);
+       memset (&zai, 0, sizeof zai);
+       zfile_fseek (z, startblock * 512 + i * 32, SEEK_SET);
+       zfile_fread (buf, 32, 1, z);
+       if (buf[0] == 0)
+           break;
+       if (buf[0] == 0xe5)
+           continue;
+       if (buf[0] == 0x05)
+           buf[0] = 0xe5;
+       size = buf[0x1c] | (buf[0x1d] << 8) | (buf[0x1e] << 16) | (buf[0x1f] << 24);
+       attr = buf[0x0b];
+       startcluster = buf[0x1a] | (buf[0x1b] << 8);
+       if ((attr & (0x4 | 0x2)) == 0x06) // system+hidden
+           continue;
+       if (attr & 8) // disk name
+           continue;
+       if (attr & 1) // read-only
+           zai.flags |= 1 << 3;
+       if (!(attr & 32)) // archive
+           zai.flags |= 1 << 4;
+       
+       cnt = 0;
+       ext = 0;
+       for (j = 0; j < 8 && buf[j] != 0x20 && buf[j] != 0; j++)
+           fatname[cnt++] = buf[j];
+       for (j = 0; j < 3 && buf[8 + j] != 0x20 && buf[8 + j] != 0; j++) {
+           if (ext == 0)
+               fatname[cnt++] = '.';
+           ext = 1;
+           fatname[cnt++] = buf[8 + j];
+       }
+       fatname[cnt] = 0;
+
+       fname = au (fatname);
+       name2[0] = 0;
+       if (name[0]) {
+           TCHAR sep[] = { FSDB_DIR_SEPARATOR, 0 };
+           _tcscpy (name2, name);
+           _tcscat (name2, sep);
+       }
+       _tcscat (name2, fname);
+
+       zai.name = name2;
+       zai.t = fat_time_fat2unix (buf[0x16] | (buf[0x17] << 8), buf[0x18] | (buf[0x19] << 8), 1);
+       if (attr & (16 | 8)) {
+           int nextblock, cluster;
+           nextblock = dataregion + (startcluster - 2) * sectorspercluster;
+           cluster = getcluster (z, startcluster, fatstart, fatbits);
+           if ((cluster < 0 || cluster >= 3) && nextblock != startblock) {
+               znnew = zvolume_adddir_abs (zv, &zai);
+               fatdirectory (z, zv, name2, nextblock, sectorspercluster * 512 / 32, sectorspercluster, fatstart, dataregion, fatbits);
+               while (cluster >= 3) {
+                   nextblock = dataregion + (cluster - 2) * sectorspercluster;
+                   fatdirectory (z, zv, name2, nextblock, sectorspercluster * 512 / 32, sectorspercluster, fatstart, dataregion, fatbits);
+                   cluster = getcluster (z, cluster, fatstart, fatbits);
+               }
+           }
+       } else {
+           zai.size = size;
+           znnew = zvolume_addfile_abs (zv, &zai);
+           znnew->offset = startcluster;
+       }
+
+       xfree (fname);
+    }
+}
+
+struct zvolume *archive_directory_fat (struct zfile *z)
+{
+    uae_u8 buf[512] = { 0 };
+    int fatbits = 12;
+    struct zvolume *zv;
+    int rootdir, reserved, sectorspercluster;
+    int numfats, sectorsperfat, rootentries;
+    int dataregion;
+
+    zfile_fseek (z, 0, SEEK_SET);
+    zfile_fread (buf, 1, 512, z);
+
+    if (!isfat (buf))
+       return NULL;
+    reserved = buf[0x0e] | (buf[0x0f] << 8);
+    numfats = buf[0x10];
+    sectorsperfat = buf[0x16] | (buf[0x17] << 8);
+    rootentries = buf[0x11] | (buf[0x12] << 8);
+    sectorspercluster = buf[0x0d];
+    rootdir = reserved + numfats * sectorsperfat;
+    dataregion = rootdir + rootentries * 32 / 512;
+
+    zv = zvolume_alloc (z, ArchiveFormatFAT, NULL, NULL);
+    fatdirectory (z, zv, L"", rootdir, rootentries, sectorspercluster, reserved, dataregion, fatbits);
+    zv->method = ArchiveFormatFAT;
+    return zv;
+}
+
+struct zfile *archive_access_fat (struct znode *zn)
+{
+    uae_u8 buf[512] = { 0 };
+    int fatbits = 12;
+    int size = zn->size;
+    struct zfile *sz, *dz;
+    int rootdir, reserved, sectorspercluster;
+    int numfats, sectorsperfat, rootentries;
+    int dataregion;
+    int offset, cluster;
+
+    sz = zn->volume->archive;
+
+    zfile_fseek (sz, 0, SEEK_SET);
+    zfile_fread (buf, 1, 512, sz);
+
+    if (!isfat (buf))
+       return NULL;
+    reserved = buf[0x0e] | (buf[0x0f] << 8);
+    numfats = buf[0x10];
+    sectorsperfat = buf[0x16] | (buf[0x17] << 8);
+    rootentries = buf[0x11] | (buf[0x12] << 8);
+    sectorspercluster = buf[0x0d];
+    rootdir = reserved + numfats * sectorsperfat;
+    dataregion = rootdir + rootentries * 32 / 512;
+
+    dz = zfile_fopen_empty (sz, zn->fullname, size);
+    if (!dz)
+       return NULL;
+
+    offset = 0;
+    cluster = zn->offset;
+    while (size && cluster >= 2) {
+       int left = size > sectorspercluster * 512 ? sectorspercluster * 512 : size;
+       int sector = dataregion + (cluster - 2) * sectorspercluster;
+       zfile_fseek (sz, sector * 512, SEEK_SET);
+       zfile_fread (dz->data + offset, 1, left, sz);
+       size -= left;
+       offset += left;
+       cluster = getcluster (sz, cluster, reserved, fatbits);
+    }
+
+    return dz;
+}
+
 void archive_access_close (void *handle, unsigned int id)
 {
     switch (id)