diff --git a/src/physfs/archivers/zip.c b/src/physfs/archivers/zip.c
index 00f3176d4bf25650f8ae81242001c1aa4665572c..ba10f277068d9575aad8bb03fe5738cc46f849a6 100644
--- a/src/physfs/archivers/zip.c
+++ b/src/physfs/archivers/zip.c
@@ -375,13 +375,13 @@ static int ZIP_fileClose(fvoid *opaque)
 static PHYSFS_sint64 zip_find_end_of_central_dir(void *in, PHYSFS_sint64 *len)
 {
     PHYSFS_uint8 buf[256];
+    PHYSFS_uint8 extra[4] = { 0, 0, 0, 0 };
     PHYSFS_sint32 i = 0;
     PHYSFS_sint64 filelen;
     PHYSFS_sint64 filepos;
     PHYSFS_sint32 maxread;
     PHYSFS_sint32 totalread = 0;
     int found = 0;
-    PHYSFS_uint32 extra = 0;
 
     filelen = __PHYSFS_platformFileLength(in);
     BAIL_IF_MACRO(filelen == -1, NULL, 0);  /* !!! FIXME: unlocalized string */
@@ -419,7 +419,7 @@ static PHYSFS_sint64 zip_find_end_of_central_dir(void *in, PHYSFS_sint64 *len)
         {
             if (__PHYSFS_platformRead(in, buf, maxread - 4, 1) != 1)
                 return(-1);
-            *((PHYSFS_uint32 *) (&buf[maxread - 4])) = extra;
+            memcpy(&buf[maxread - 4], &extra, sizeof (extra));
             totalread += maxread - 4;
         } /* if */
         else
@@ -429,7 +429,7 @@ static PHYSFS_sint64 zip_find_end_of_central_dir(void *in, PHYSFS_sint64 *len)
             totalread += maxread;
         } /* else */
 
-        extra = *((PHYSFS_uint32 *) (&buf[0]));
+        memcpy(&extra, buf, sizeof (extra));
 
         for (i = maxread - 4; i > 0; i--)
         {
@@ -544,8 +544,11 @@ static ZIPentry *zip_find_entry(ZIPinfo *info, const char *path, int *isDir)
 
             if (thispath[pathlen] == '\0') /* found entry? */
                 return(&a[middle]);
+            /* adjust search params, try again. */
+            else if (thispath[pathlen] > '/')
+                hi = middle - 1;
             else
-                hi = middle - 1;  /* adjust search params, try again. */
+                lo = middle + 1;
         } /* if */
     } /* while */
 
diff --git a/src/physfs/physfs.c b/src/physfs/physfs.c
index 1b62eacfa5661654c7318b69484dc833ffa85d60..49281e89e1cd3ab4623390c42c179ac82ec115d4 100644
--- a/src/physfs/physfs.c
+++ b/src/physfs/physfs.c
@@ -605,18 +605,21 @@ static int freeDirHandle(DirHandle *dh, FileHandle *openList)
 
 static char *calculateUserDir(void)
 {
-    char *retval = NULL;
-    const char *str = NULL;
+    char *retval = __PHYSFS_platformGetUserDir();
+    if (retval != NULL)
+    {
+        /* make sure it really exists and is normalized. */
+        char *ptr = __PHYSFS_platformRealPath(retval);
+        allocator.Free(retval);
+        retval = ptr;
+    } /* if */
 
-    str = __PHYSFS_platformGetUserDir();
-    if (str != NULL)
-        retval = (char *) str;
-    else
+    if (retval == NULL)
     {
         const char *dirsep = PHYSFS_getDirSeparator();
         const char *uname = __PHYSFS_platformGetUserName();
+        const char *str = (uname != NULL) ? uname : "default";
 
-        str = (uname != NULL) ? uname : "default";
         retval = (char *) allocator.Malloc(strlen(baseDir) + strlen(str) +
                                            strlen(dirsep) + 6);
 
@@ -754,13 +757,6 @@ int PHYSFS_init(const char *argv0)
     BAIL_IF_MACRO(!appendDirSep(&baseDir), NULL, 0);
 
     userDir = calculateUserDir();
-    if (userDir != NULL)
-    {
-        ptr = __PHYSFS_platformRealPath(userDir);
-        allocator.Free(userDir);
-        userDir = ptr;
-    } /* if */
-
     if ((userDir == NULL) || (!appendDirSep(&userDir)))
     {
         allocator.Free(baseDir);
diff --git a/src/physfs/physfs.h b/src/physfs/physfs.h
index 7a242649249db43a146d96ceeb681be1e4bdbb72..f0d78d72173a058f2754d870506558ce86d33f0c 100644
--- a/src/physfs/physfs.h
+++ b/src/physfs/physfs.h
@@ -1,4 +1,8 @@
-/** \file physfs.h */
+/**
+ * \file physfs.h
+ *
+ * Main header file for PhysicsFS.
+ */
 
 #define PHYSFS_NO_CDROM_SUPPORT
 
@@ -403,7 +407,7 @@ typedef struct PHYSFS_Version
 #ifndef DOXYGEN_SHOULD_IGNORE_THIS
 #define PHYSFS_VER_MAJOR 2
 #define PHYSFS_VER_MINOR 0
-#define PHYSFS_VER_PATCH 0
+#define PHYSFS_VER_PATCH 2
 #endif  /* DOXYGEN_SHOULD_IGNORE_THIS */
 
 
@@ -1000,7 +1004,7 @@ __EXPORT__ const char *PHYSFS_getRealDir(const char *filename);
  * PHYSFS_freeList(rc);
  * \endcode
  *
- *  ...will print:
+ *  \...will print:
  *
  * \verbatim
  * We've got [x.sav].
@@ -1225,9 +1229,9 @@ __EXPORT__ PHYSFS_sint64 PHYSFS_read(PHYSFS_File *handle,
  * The file must be opened for writing.
  *
  *   \param handle retval from PHYSFS_openWrite() or PHYSFS_openAppend().
- *   \param buffer buffer to store read data into.
- *   \param objSize size in bytes of objects being read from (handle).
- *   \param objCount number of (objSize) objects to read from (handle).
+ *   \param buffer buffer of bytes to write to (handle).
+ *   \param objSize size in bytes of objects being written to (handle).
+ *   \param objCount number of (objSize) objects to write to (handle).
  *  \return number of objects written. PHYSFS_getLastError() can shed light on
  *           the reason this might be < (objCount). -1 if complete failure.
  */
@@ -2282,7 +2286,7 @@ __EXPORT__ void PHYSFS_enumerateFilesCallback(const char *dir,
  *
  * Strings that don't fit in the destination buffer will be truncated, but
  *  will always be null-terminated and never have an incomplete UTF-8
- *  sequence at the end.
+ *  sequence at the end. If the buffer length is 0, this function does nothing.
  *
  *   \param src Null-terminated source string in UCS-4 format.
  *   \param dst Buffer to store converted UTF-8 string.
@@ -2304,7 +2308,7 @@ __EXPORT__ void PHYSFS_utf8FromUcs4(const PHYSFS_uint32 *src, char *dst,
  *
  * Strings that don't fit in the destination buffer will be truncated, but
  *  will always be null-terminated and never have an incomplete UCS-4
- *  sequence at the end.
+ *  sequence at the end. If the buffer length is 0, this function does nothing.
  *
  *   \param src Null-terminated source string in UTF-8 format.
  *   \param dst Buffer to store converted UCS-4 string.
@@ -2327,7 +2331,7 @@ __EXPORT__ void PHYSFS_utf8ToUcs4(const char *src, PHYSFS_uint32 *dst,
  *
  * Strings that don't fit in the destination buffer will be truncated, but
  *  will always be null-terminated and never have an incomplete UTF-8
- *  sequence at the end.
+ *  sequence at the end. If the buffer length is 0, this function does nothing.
  *
  * Please note that UCS-2 is not UTF-16; we do not support the "surrogate"
  *  values at this time.
@@ -2353,7 +2357,7 @@ __EXPORT__ void PHYSFS_utf8FromUcs2(const PHYSFS_uint16 *src, char *dst,
  *
  * Strings that don't fit in the destination buffer will be truncated, but
  *  will always be null-terminated and never have an incomplete UCS-2
- *  sequence at the end.
+ *  sequence at the end. If the buffer length is 0, this function does nothing.
  *
  * Please note that UCS-2 is not UTF-16; we do not support the "surrogate"
  *  values at this time.
@@ -2379,7 +2383,7 @@ __EXPORT__ void PHYSFS_utf8ToUcs2(const char *src, PHYSFS_uint16 *dst,
  *
  * Strings that don't fit in the destination buffer will be truncated, but
  *  will always be null-terminated and never have an incomplete UTF-8
- *  sequence at the end.
+ *  sequence at the end. If the buffer length is 0, this function does nothing.
  *
  * Please note that we do not supply a UTF-8 to Latin1 converter, since Latin1
  *  can't express most Unicode codepoints. It's a legacy encoding; you should
diff --git a/src/physfs/physfs_internal.h b/src/physfs/physfs_internal.h
index 187b50dc2aff985ed27f31f0fd5a4a0e712d6c85..89114954bc6a15c9fd47dabe95310d2b23869fe5 100644
--- a/src/physfs/physfs_internal.h
+++ b/src/physfs/physfs_internal.h
@@ -29,6 +29,10 @@
 #include <malloc.h>
 #endif
 
+#if defined(__sun) || defined(sun)
+#include <alloca.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -969,7 +973,7 @@ char *__PHYSFS_convertToDependent(const char *prepend,
 #define PHYSFS_LIL_ENDIAN  1234
 #define PHYSFS_BIG_ENDIAN  4321
 
-#if  defined(__i386__) || defined(__ia64__) || defined(WIN32) || \
+#if  defined(__i386__) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || \
     (defined(__alpha__) || defined(__alpha)) || \
      defined(__arm__) || defined(ARM) || \
     (defined(__mips__) && defined(__MIPSEL__)) || \
diff --git a/src/physfs/physfs_unicode.c b/src/physfs/physfs_unicode.c
index 030bcc869f7ea33621b32022ee90f3c455c0b55d..d9cc73ffc79dbba36e2ff49ec6b99cdd8c8a9f00 100644
--- a/src/physfs/physfs_unicode.c
+++ b/src/physfs/physfs_unicode.c
@@ -305,10 +305,11 @@ static void utf8fromcodepoint(PHYSFS_uint32 cp, char **_dst, PHYSFS_uint64 *_len
 } /* utf8fromcodepoint */
 
 #define UTF8FROMTYPE(typ, src, dst, len) \
+    if (len == 0) return; \
     len--;  \
     while (len) \
     { \
-        const PHYSFS_uint32 cp = (PHYSFS_uint32) *(src++); \
+        const PHYSFS_uint32 cp = (PHYSFS_uint32) ((typ) (*(src++))); \
         if (cp == 0) break; \
         utf8fromcodepoint(cp, &dst, &len); \
     } \
diff --git a/src/physfs/platform/posix.c b/src/physfs/platform/posix.c
index 22b8408854acc28c0456ff8dec59af2673111ec6..a736b52d0018027ddd755d8ee95fc2a72c751f8a 100644
--- a/src/physfs/platform/posix.c
+++ b/src/physfs/platform/posix.c
@@ -97,8 +97,21 @@ char *__PHYSFS_platformGetUserName(void)
 char *__PHYSFS_platformGetUserDir(void)
 {
     char *retval = __PHYSFS_platformCopyEnvironmentVariable("HOME");
+
+    /* if the environment variable was set, make sure it's really a dir. */
+    if (retval != NULL)
+    {
+        struct stat statbuf;
+        if ((stat(retval, &statbuf) == -1) || (S_ISDIR(statbuf.st_mode) == 0))
+        {
+            allocator.Free(retval);
+            retval = NULL;
+        } /* if */
+    } /* if */
+
     if (retval == NULL)
         retval = getUserDirByUID();
+
     return(retval);
 } /* __PHYSFS_platformGetUserDir */
 
diff --git a/src/physfs/platform/unix.c b/src/physfs/platform/unix.c
index 2b47cc99029f7f4e009f3dfac0d02f0a880e3084..4e714b40bb4e5f9d266dba776031c863249f4571 100644
--- a/src/physfs/platform/unix.c
+++ b/src/physfs/platform/unix.c
@@ -23,9 +23,8 @@
 #include <dirent.h>
 #include <time.h>
 #include <errno.h>
-#include <sys/mount.h>
 
-#if (!defined PHYSFS_NO_PTHREADS_SUPPORT)
+#if (!defined PHYSFS_NO_THREAD_SUPPORT)
 #include <pthread.h>
 #endif
 
@@ -34,6 +33,7 @@
 #    undef PHYSFS_HAVE_MNTENT_H /* don't do both... */
 #  endif
 #  include <sys/ucred.h>
+#  include <sys/mount.h>
 #endif
 
 #ifdef PHYSFS_HAVE_MNTENT_H
@@ -42,6 +42,9 @@
 
 #include "physfs_internal.h"
 
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
 
 int __PHYSFS_platformInit(void)
 {
@@ -101,6 +104,14 @@ void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
         int add_it = 0;
         if (strcmp(ent->mnt_type, "iso9660") == 0)
             add_it = 1;
+        else if (strcmp(ent->mnt_type, "udf") == 0)
+            add_it = 1;
+
+        /* !!! FIXME: these might pick up floppy drives, right? */
+        else if (strcmp(ent->mnt_type, "auto") == 0)
+            add_it = 1;
+        else if (strcmp(ent->mnt_type, "supermount") == 0)
+            add_it = 1;
 
         /* add other mount types here */
 
@@ -182,12 +193,42 @@ static char *findBinaryInPath(const char *bin, char *envr)
 } /* findBinaryInPath */
 
 
+static char *readSymLink(const char *path)
+{
+    ssize_t len = 64;
+    ssize_t rc = -1;
+    char *retval = NULL;
+
+    while (1)
+    {
+         char *ptr = (char *) allocator.Realloc(retval, (size_t) len);
+         if (ptr == NULL)
+             break;   /* out of memory. */
+         retval = ptr;
+
+         rc = readlink(path, retval, len);
+         if (rc == -1)
+             break;  /* not a symlink, i/o error, etc. */
+
+         else if (rc < len)
+         {
+             retval[rc] = '\0';  /* readlink doesn't null-terminate. */
+             return retval;  /* we're good to go. */
+         } /* else if */
+
+         len *= 2;  /* grow buffer, try again. */
+    } /* while */
+
+    if (retval != NULL)
+        allocator.Free(retval);
+    return NULL;
+} /* readSymLink */
+
+
 char *__PHYSFS_platformCalcBaseDir(const char *argv0)
 {
-    const char *PROC_SELF_EXE = "/proc/self/exe";
     char *retval = NULL;
     char *envr = NULL;
-    struct stat stbuf;
 
     /* fast path: default behaviour can handle this. */
     if ( (argv0 != NULL) && (strchr(argv0, '/') != NULL) )
@@ -198,20 +239,22 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
      *  /proc filesystem, you can get the full path to the current process from
      *  the /proc/self/exe symlink.
      */
-    if ((lstat(PROC_SELF_EXE, &stbuf) != -1) && (S_ISLNK(stbuf.st_mode)))
+    retval = readSymLink("/proc/self/exe");
+    if (retval == NULL)
     {
-        const size_t len = stbuf.st_size;
-        char *buf = (char *) allocator.Malloc(len+1);
-        if (buf != NULL)  /* if NULL, maybe you'll get lucky later. */
-        {
-            if (readlink(PROC_SELF_EXE, buf, len) != len)
-                allocator.Free(buf);
-            else
-            {
-                buf[len] = '\0';  /* readlink doesn't null-terminate. */
-                retval = buf;  /* we're good to go. */
-            } /* else */
-        } /* if */
+        /* older kernels don't have /proc/self ... try PID version... */
+        const unsigned long long pid = (unsigned long long) getpid();
+        char path[64];
+        const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid);
+        if ( (rc > 0) && (rc < sizeof(path)) )
+            retval = readSymLink(path);
+    } /* if */
+
+    if (retval != NULL)  /* chop off filename. */
+    {
+        char *ptr = strrchr(retval, '/');
+        if (ptr != NULL)
+            *ptr = '\0';
     } /* if */
 
     if ((retval == NULL) && (argv0 != NULL))
@@ -223,6 +266,14 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
         allocator.Free(envr);
     } /* if */
 
+    if (retval != NULL)
+    {
+        /* try to shrink buffer... */
+        char *ptr = (char *) allocator.Realloc(retval, strlen(retval) + 1);
+        if (ptr != NULL)
+            retval = ptr;  /* oh well if it failed. */
+    } /* if */
+
     return(retval);
 } /* __PHYSFS_platformCalcBaseDir */
 
@@ -289,7 +340,7 @@ int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
 } /* __PHYSFS_platformSetDefaultAllocator */
 
 
-#if (defined PHYSFS_NO_PTHREADS_SUPPORT)
+#if (defined PHYSFS_NO_THREAD_SUPPORT)
 
 PHYSFS_uint64 __PHYSFS_platformGetThreadID(void) { return(0x0001); }
 void *__PHYSFS_platformCreateMutex(void) { return((void *) 0x0001); }
@@ -387,7 +438,7 @@ void __PHYSFS_platformReleaseMutex(void *mutex)
     } /* if */
 } /* __PHYSFS_platformReleaseMutex */
 
-#endif /* !PHYSFS_NO_PTHREADS_SUPPORT */
+#endif /* !PHYSFS_NO_THREAD_SUPPORT */
 
 #endif /* PHYSFS_PLATFORM_UNIX */
 
diff --git a/src/physfs/platform/windows.c b/src/physfs/platform/windows.c
index 02c595bad36efe29da6ad90bf9466dc9e8a4617e..c5b05c7ea2cdce0d254a77b11bb45276a3ab3033 100644
--- a/src/physfs/platform/windows.c
+++ b/src/physfs/platform/windows.c
@@ -1027,8 +1027,8 @@ static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly)
 
     UTF8_TO_UNICODE_STACK_MACRO(wfname, fname);
     BAIL_IF_MACRO(wfname == NULL, ERR_OUT_OF_MEMORY, NULL);
-    fileHandle = pCreateFileW(wfname, mode, FILE_SHARE_READ, NULL,
-                              creation, FILE_ATTRIBUTE_NORMAL, NULL);
+    fileHandle = pCreateFileW(wfname, mode, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                              NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
     __PHYSFS_smallFree(wfname);
 
     BAIL_IF_MACRO