Maelstrom: Updated to latest SDL API updates, upgraded filesystem code to run on Android

https://github.com/libsdl-org/Maelstrom/commit/1ebf3ff95bf3a0e381f4de322d9d0a3d4bfc7b15

From 1ebf3ff95bf3a0e381f4de322d9d0a3d4bfc7b15 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 5 Nov 2012 00:10:29 -0800
Subject: [PATCH] Updated to latest SDL API updates, upgraded filesystem code
 to run on Android

---
 Xcode-iOS/Maelstrom.xcodeproj/project.pbxproj |  79 +++++++++-
 Xcode/Maelstrom.xcodeproj/project.pbxproj     |   6 +
 game/init.cpp                                 |  18 ++-
 game/load.cpp                                 |   4 +-
 game/load.h                                   |   3 -
 game/main.cpp                                 |  12 ++
 game/replay.cpp                               | 140 +++++++-----------
 maclib/Mac_FontServ.cpp                       |  31 +---
 maclib/Mac_Sound.cpp                          |   4 +-
 screenlib/SDL_FrameBuf.cpp                    |  20 +--
 screenlib/UIManager.cpp                       |  10 +-
 screenlib/UITemplates.cpp                     |  26 +---
 utils/Makefile.am                             |   2 +
 utils/Makefile.in                             |   7 +-
 utils/array.h                                 |   2 +-
 utils/files.c                                 |  63 ++++++++
 utils/files.h                                 |  41 +++++
 utils/loadxml.cpp                             |  39 +----
 utils/loadxml.h                               |   1 +
 utils/physfsrwops.c                           |  37 +++--
 utils/prefs.cpp                               |  38 ++---
 21 files changed, 328 insertions(+), 255 deletions(-)
 create mode 100644 utils/files.c
 create mode 100644 utils/files.h

diff --git a/Xcode-iOS/Maelstrom.xcodeproj/project.pbxproj b/Xcode-iOS/Maelstrom.xcodeproj/project.pbxproj
index 2f4f609d..14746fe2 100644
--- a/Xcode-iOS/Maelstrom.xcodeproj/project.pbxproj
+++ b/Xcode-iOS/Maelstrom.xcodeproj/project.pbxproj
@@ -24,6 +24,7 @@
 /* Begin PBXBuildFile section */
 		93D8E49B15911A6700BD8D0E /* libSDL2_net.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 938A44A2157D55870081A436 /* libSDL2_net.a */; };
 		93D8E49C15911A6C00BD8D0E /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 938A44AE157D55AE0081A436 /* libSDL2.a */; };
+		93E9C29D16442B1900B39D38 /* libFreetype.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 93E9C29A16442ADC00B39D38 /* libFreetype.a */; };
 		AA0777CE145EB56C00DB8DB3 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA0777CD145EB56C00DB8DB3 /* OpenGLES.framework */; };
 		AA0777D2145EB60A00DB8DB3 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA0777D1145EB60A00DB8DB3 /* AudioToolbox.framework */; };
 		AA0777D4145EB68300DB8DB3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA0777D3145EB68300DB8DB3 /* QuartzCore.framework */; };
@@ -53,7 +54,6 @@
 		AA7557A61594EE8F00BBD41B /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA7557A51594EE8F00BBD41B /* GameKit.framework */; };
 		AA7557AB1595062C00BBD41B /* Maelstrom_GameKit.mm in Sources */ = {isa = PBXBuildFile; fileRef = AA7557AA1595062C00BBD41B /* Maelstrom_GameKit.mm */; };
 		AA9352DA1643958300B7B41B /* libSDL2_ttf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AAD53E7E164392D700203E03 /* libSDL2_ttf.a */; };
-		AA9352E21643960B00B7B41B /* libFreetype.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA9352E11643960B00B7B41B /* libFreetype.a */; };
 		AA97808315769F3400472542 /* mainstub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA97808215769F3400472542 /* mainstub.cpp */; };
 		AA9781571576A00100472542 /* Mac_FontServ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA97811D1576A00100472542 /* Mac_FontServ.cpp */; };
 		AA9781581576A00100472542 /* Mac_Sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA97811F1576A00100472542 /* Mac_Sound.cpp */; };
@@ -101,6 +101,7 @@
 		AAC0415B160E811F00E22BC5 /* libSDL2_image.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AAC0415A160E809F00E22BC5 /* libSDL2_image.a */; };
 		AAC04173160E837E00E22BC5 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AAC04172160E837E00E22BC5 /* ImageIO.framework */; };
 		AAC04179160E84D000E22BC5 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AAC04178160E84D000E22BC5 /* MobileCoreServices.framework */; };
+		AAC257641647A9B000F5FB43 /* files.c in Sources */ = {isa = PBXBuildFile; fileRef = AAC257621647A9B000F5FB43 /* files.c */; };
 		AACF51001598BC2C00585701 /* gameover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AACF50FE1598BC2C00585701 /* gameover.cpp */; };
 		AAD13B82145E8A8F0040B19C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AAD13B81145E8A8F0040B19C /* UIKit.framework */; };
 		AAD13B84145E8A8F0040B19C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AAD13B83145E8A8F0040B19C /* Foundation.framework */; };
@@ -152,6 +153,34 @@
 			remoteGlobalIDString = FD6526620DE8FCCB002AD96B;
 			remoteInfo = libSDL;
 		};
+		93E9C28C16442AD100B39D38 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = AAD53E5E1643923500203E03 /* SDL_ttf.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = BE48FD6807AFA17000BB41DA;
+			remoteInfo = "Static Library";
+		};
+		93E9C28E16442AD100B39D38 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = AAC04155160E809E00E22BC5 /* SDL_image.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = BE1FA72F07AF4C45004B6283;
+			remoteInfo = libSDL_image;
+		};
+		93E9C29916442ADC00B39D38 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 93E9C29516442ADC00B39D38 /* Freetype.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = D2AAC07E0554694100DB518D;
+			remoteInfo = libFreetype;
+		};
+		93E9C29B16442AE300B39D38 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 93E9C29516442ADC00B39D38 /* Freetype.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = D2AAC07D0554694100DB518D;
+			remoteInfo = libFreetype;
+		};
 		AAC04159160E809F00E22BC5 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = AAC04155160E809E00E22BC5 /* SDL_image.xcodeproj */;
@@ -173,6 +202,7 @@
 		938A4498157D555C0081A436 /* SDL_net.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL_net.xcodeproj; path = "Xcode-iOS/SDL_net.xcodeproj"; sourceTree = "<group>"; };
 		938A44A3157D55AE0081A436 /* SDL.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL.xcodeproj; path = "Xcode-iOS/SDL/SDL.xcodeproj"; sourceTree = "<group>"; };
 		93D8E4A315911CDC00BD8D0E /* Maelstrom-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Maelstrom-Info.plist"; path = "Xcode-iOS/Maelstrom-Info.plist"; sourceTree = "<group>"; };
+		93E9C29516442ADC00B39D38 /* Freetype.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Freetype.xcodeproj; path = "../../../../../3rdparty/iphone/libfreetype/Xcode-iPhoneOS/Freetype.xcodeproj"; sourceTree = SOURCE_ROOT; };
 		AA07778A145EB40800DB8DB3 /* begin_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = begin_code.h; sourceTree = "<group>"; };
 		AA07778B145EB40800DB8DB3 /* close_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = close_code.h; sourceTree = "<group>"; };
 		AA07778C145EB40800DB8DB3 /* SDL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL.h; sourceTree = "<group>"; };
@@ -268,7 +298,6 @@
 		AA7557A51594EE8F00BBD41B /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; };
 		AA7557A71595019400BBD41B /* Maelstrom_GameKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Maelstrom_GameKit.h; path = "Xcode-iOS/Maelstrom_GameKit.h"; sourceTree = "<group>"; };
 		AA7557AA1595062C00BBD41B /* Maelstrom_GameKit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Maelstrom_GameKit.mm; path = "Xcode-iOS/Maelstrom_GameKit.mm"; sourceTree = "<group>"; };
-		AA9352E11643960B00B7B41B /* libFreetype.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libFreetype.a; path = "../../../../../3rdparty/iphone/libfreetype/Xcode-iPhoneOS/build/Release-iphoneos/libFreetype.a"; sourceTree = "<group>"; };
 		AA97808215769F3400472542 /* mainstub.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mainstub.cpp; sourceTree = "<group>"; };
 		AA97811A1576A00100472542 /* bitesex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitesex.h; sourceTree = "<group>"; };
 		AA97811C1576A00100472542 /* Mac_Compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Mac_Compat.h; sourceTree = "<group>"; };
@@ -374,6 +403,8 @@
 		AAC04155160E809E00E22BC5 /* SDL_image.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL_image.xcodeproj; path = "Xcode-iOS/SDL_image.xcodeproj"; sourceTree = "<group>"; };
 		AAC04172160E837E00E22BC5 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; };
 		AAC04178160E84D000E22BC5 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+		AAC257621647A9B000F5FB43 /* files.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = files.c; sourceTree = "<group>"; };
+		AAC257631647A9B000F5FB43 /* files.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = files.h; sourceTree = "<group>"; };
 		AACF50FE1598BC2C00585701 /* gameover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gameover.cpp; sourceTree = "<group>"; };
 		AACF50FF1598BC2C00585701 /* gameover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gameover.h; sourceTree = "<group>"; };
 		AAD13B7D145E8A8F0040B19C /* Maelstrom.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Maelstrom.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -390,12 +421,12 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				93E9C29D16442B1900B39D38 /* libFreetype.a in Frameworks */,
 				AA0777DB145EC12900DB8DB3 /* libz.dylib in Frameworks */,
 				93D8E49C15911A6C00BD8D0E /* libSDL2.a in Frameworks */,
 				AAC0415B160E811F00E22BC5 /* libSDL2_image.a in Frameworks */,
 				AA9352DA1643958300B7B41B /* libSDL2_ttf.a in Frameworks */,
 				93D8E49B15911A6700BD8D0E /* libSDL2_net.a in Frameworks */,
-				AA9352E21643960B00B7B41B /* libFreetype.a in Frameworks */,
 				AAD13B82145E8A8F0040B19C /* UIKit.framework in Frameworks */,
 				AAD13B84145E8A8F0040B19C /* Foundation.framework in Frameworks */,
 				AAC04179160E84D000E22BC5 /* MobileCoreServices.framework in Frameworks */,
@@ -436,6 +467,14 @@
 			name = Products;
 			sourceTree = "<group>";
 		};
+		93E9C29616442ADC00B39D38 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				93E9C29A16442ADC00B39D38 /* libFreetype.a */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
 		AA077788145EB3F500DB8DB3 /* SDL */ = {
 			isa = PBXGroup;
 			children = (
@@ -620,6 +659,8 @@
 			children = (
 				AA97814A1576A00100472542 /* array.h */,
 				AA97814B1576A00100472542 /* ErrorBase.h */,
+				AAC257621647A9B000F5FB43 /* files.c */,
+				AAC257631647A9B000F5FB43 /* files.h */,
 				AA97814C1576A00100472542 /* hashtable.c */,
 				AA97814D1576A00100472542 /* hashtable.h */,
 				AABDBE2415C8A6F300C3E936 /* loadxml.cpp */,
@@ -722,7 +763,6 @@
 		AAD13B72145E8A8F0040B19C = {
 			isa = PBXGroup;
 			children = (
-				AA9352E11643960B00B7B41B /* libFreetype.a */,
 				02659AAF163AE3EA00A8047B /* scripts */,
 				AA0777C8145EB43900DB8DB3 /* physfs */,
 				AA077788145EB3F500DB8DB3 /* SDL */,
@@ -801,6 +841,7 @@
 		AAD53E43164391BD00203E03 /* SDL_ttf */ = {
 			isa = PBXGroup;
 			children = (
+				93E9C29516442ADC00B39D38 /* Freetype.xcodeproj */,
 				AAD53E5E1643923500203E03 /* SDL_ttf.xcodeproj */,
 				AAD53E5C1643921100203E03 /* include */,
 			);
@@ -839,6 +880,9 @@
 			buildRules = (
 			);
 			dependencies = (
+				93E9C29C16442AE300B39D38 /* PBXTargetDependency */,
+				93E9C28D16442AD100B39D38 /* PBXTargetDependency */,
+				93E9C28F16442AD100B39D38 /* PBXTargetDependency */,
 				93D8E495159117BC00BD8D0E /* PBXTargetDependency */,
 				93D8E497159117BC00BD8D0E /* PBXTargetDependency */,
 			);
@@ -866,6 +910,10 @@
 			productRefGroup = AAD13B7E145E8A8F0040B19C /* Products */;
 			projectDirPath = "";
 			projectReferences = (
+				{
+					ProductGroup = 93E9C29616442ADC00B39D38 /* Products */;
+					ProjectRef = 93E9C29516442ADC00B39D38 /* Freetype.xcodeproj */;
+				},
 				{
 					ProductGroup = 938A44A4157D55AE0081A436 /* Products */;
 					ProjectRef = 938A44A3157D55AE0081A436 /* SDL.xcodeproj */;
@@ -913,6 +961,13 @@
 			remoteRef = 938A44AF157D55AE0081A436 /* PBXContainerItemProxy */;
 			sourceTree = BUILT_PRODUCTS_DIR;
 		};
+		93E9C29A16442ADC00B39D38 /* libFreetype.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libFreetype.a;
+			remoteRef = 93E9C29916442ADC00B39D38 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
 		AAC0415A160E809F00E22BC5 /* libSDL2_image.a */ = {
 			isa = PBXReferenceProxy;
 			fileType = archive.ar;
@@ -1048,6 +1103,7 @@
 				AA439073161EBE1800FE5F41 /* platform_windows.c in Sources */,
 				AA43907B161ED5CB00FE5F41 /* MaelstromFeatures.cpp in Sources */,
 				AA43907F1620E35800FE5F41 /* UIElementThumbstick.cpp in Sources */,
+				AAC257641647A9B000F5FB43 /* files.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1069,6 +1125,21 @@
 			name = libSDL;
 			targetProxy = 93D8E496159117BC00BD8D0E /* PBXContainerItemProxy */;
 		};
+		93E9C28D16442AD100B39D38 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "Static Library";
+			targetProxy = 93E9C28C16442AD100B39D38 /* PBXContainerItemProxy */;
+		};
+		93E9C28F16442AD100B39D38 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = libSDL_image;
+			targetProxy = 93E9C28E16442AD100B39D38 /* PBXContainerItemProxy */;
+		};
+		93E9C29C16442AE300B39D38 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = libFreetype;
+			targetProxy = 93E9C29B16442AE300B39D38 /* PBXContainerItemProxy */;
+		};
 /* End PBXTargetDependency section */
 
 /* Begin PBXVariantGroup section */
diff --git a/Xcode/Maelstrom.xcodeproj/project.pbxproj b/Xcode/Maelstrom.xcodeproj/project.pbxproj
index 5a91de89..273b54fe 100644
--- a/Xcode/Maelstrom.xcodeproj/project.pbxproj
+++ b/Xcode/Maelstrom.xcodeproj/project.pbxproj
@@ -74,6 +74,7 @@
 		AA8B1905161C1188005318A4 /* loadxml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA8B1903161C1188005318A4 /* loadxml.cpp */; };
 		AA93530E164399C400B7B41B /* SDL2_ttf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA93530D164399C400B7B41B /* SDL2_ttf.framework */; };
 		AAAA999F162FE466008140E1 /* Maelstrom_Data.zip in Resources */ = {isa = PBXBuildFile; fileRef = AAAA999E162FE466008140E1 /* Maelstrom_Data.zip */; };
+		AAC2576C1647AA6700F5FB43 /* files.c in Sources */ = {isa = PBXBuildFile; fileRef = AAC2576A1647AA6700F5FB43 /* files.c */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -236,6 +237,8 @@
 		AA8B191A161C343E005318A4 /* Package */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Package; sourceTree = BUILT_PRODUCTS_DIR; };
 		AA93530D164399C400B7B41B /* SDL2_ttf.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2_ttf.framework; path = /Library/Frameworks/SDL2_ttf.framework; sourceTree = "<absolute>"; };
 		AAAA999E162FE466008140E1 /* Maelstrom_Data.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; name = Maelstrom_Data.zip; path = ../Maelstrom_Data.zip; sourceTree = SOURCE_ROOT; };
+		AAC2576A1647AA6700F5FB43 /* files.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = files.c; sourceTree = "<group>"; };
+		AAC2576B1647AA6700F5FB43 /* files.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = files.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -441,6 +444,8 @@
 			children = (
 				AA40881F14D493A800EB2196 /* array.h */,
 				AA40882014D493A800EB2196 /* ErrorBase.h */,
+				AAC2576A1647AA6700F5FB43 /* files.c */,
+				AAC2576B1647AA6700F5FB43 /* files.h */,
 				AA40882114D493A800EB2196 /* hashtable.c */,
 				AA40882214D493A800EB2196 /* hashtable.h */,
 				AA8B1903161C1188005318A4 /* loadxml.cpp */,
@@ -650,6 +655,7 @@
 				AA439053161EBDCA00FE5F41 /* platform_windows.c in Sources */,
 				AA439078161ED5AC00FE5F41 /* MaelstromFeatures.cpp in Sources */,
 				AA4390821620E38800FE5F41 /* UIElementThumbstick.cpp in Sources */,
+				AAC2576C1647AA6700F5FB43 /* files.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/game/init.cpp b/game/init.cpp
index 6533d520..e5126507 100644
--- a/game/init.cpp
+++ b/game/init.cpp
@@ -37,7 +37,9 @@
 #include "MaelstromUI.h"
 #include "../screenlib/UIElement.h"
 
+#include "../physfs/physfs.h"
 #include "../utils/loadxml.h"
+#include "../utils/files.h"
 
 
 #define GAME_PREFS_FILE	"Maelstrom_Prefs.txt"
@@ -123,7 +125,7 @@ static bool InitResolutions(int &w, int &h)
 		attr = node->first_attribute("w", 0, false);
 		if (!attr) {
 			error("Resolution missing 'w' attribute in resolutions.xml\n");
-			delete[] buffer;
+			SDL_free(buffer);
 			return false;;
 		}
 		resolution.w = SDL_atoi(attr->value());
@@ -131,7 +133,7 @@ static bool InitResolutions(int &w, int &h)
 		attr = node->first_attribute("h", 0, false);
 		if (!attr) {
 			error("Resolution missing 'h' attribute in resolutions.xml\n");
-			delete[] buffer;
+			SDL_free(buffer);
 			return false;;
 		}
 		resolution.h = SDL_atoi(attr->value());
@@ -139,7 +141,7 @@ static bool InitResolutions(int &w, int &h)
 		attr = node->first_attribute("path_suffix", 0, false);
 		if (!attr) {
 			error("Resolution missing 'path_suffix' attribute in resolutions.xml\n");
-			delete[] buffer;
+			SDL_free(buffer);
 			return false;;
 		}
 		SDL_strlcpy(resolution.path_suffix, attr->value(), sizeof(resolution.path_suffix));
@@ -147,7 +149,7 @@ static bool InitResolutions(int &w, int &h)
 		attr = node->first_attribute("file_suffix", 0, false);
 		if (!attr) {
 			error("Resolution missing 'file_suffix' attribute in resolutions.xml\n");
-			delete[] buffer;
+			SDL_free(buffer);
 			return false;;
 		}
 		SDL_strlcpy(resolution.file_suffix, attr->value(), sizeof(resolution.file_suffix));
@@ -155,7 +157,7 @@ static bool InitResolutions(int &w, int &h)
 		attr = node->first_attribute("scale", 0, false);
 		if (!attr) {
 			error("Resolution missing 'scale' attribute in resolutions.xml\n");
-			delete[] buffer;
+			SDL_free(buffer);
 			return false;;
 		}
 		int numerator, denominator;
@@ -164,7 +166,7 @@ static bool InitResolutions(int &w, int &h)
 
 		gResolutions.add(resolution);
 	}
-	delete[] buffer;
+	SDL_free(buffer);
 
 	if (prefs->GetBool(PREFERENCES_CLASSIC)) {
 		gClassic = true;
@@ -835,7 +837,7 @@ int DoInitializations(Uint32 window_flags, Uint32 render_flags)
 	}
 
 	/* Load the Maelstrom icon */
-	icon = SDL_LoadBMP_RW(PHYSFSRWOPS_openRead("icon.bmp"), 1);
+	icon = SDL_LoadBMP_RW(OpenRead("icon.bmp"), 1);
 	if ( icon == NULL ) {
 		error("Fatal: Couldn't load icon: %s\n", SDL_GetError());
 		return(-1);
@@ -1223,7 +1225,7 @@ static int LoadSprite(bool large, BlitPtr *theBlit, int baseID, int numFrames)
 	/* -- Load in the image data */
 	for (index = 0; index < numFrames; index++) {
 		SDL_snprintf(file, sizeof(file), "Sprites_Classic/Maelstrom_%s#%d.bmp", large ? "icl" : "ics", baseID+index);
-		surface = SDL_LoadBMP_RW(PHYSFSRWOPS_openRead(file), 1);
+		surface = SDL_LoadBMP_RW(OpenRead(file), 1);
 
 		if ( surface == NULL ) {
 			error("LoadSprite(): Couldn't load image %s\n", file);
diff --git a/game/load.cpp b/game/load.cpp
index e6d0e032..08b55979 100644
--- a/game/load.cpp
+++ b/game/load.cpp
@@ -25,7 +25,7 @@
 #include "Maelstrom_Globals.h"
 #include "load.h"
 
-#include "../utils/physfsrwops.h"
+#include "../utils/files.h"
 
 
 UITexture *Load_Texture(FrameBuf *screen, const char *folder, const char *name)
@@ -41,7 +41,7 @@ UITexture *Load_Texture(FrameBuf *screen, const char *folder, const char *name)
 		for (int j = 0; j < SDL_arraysize(extensions); ++j) {
 			SDL_snprintf(file, sizeof(file), "%s%s/%s%s.%s",
 					folder, gResolutions[i].path_suffix, name, gResolutions[i].file_suffix, extensions[j]);
-			SDL_Surface *surface = IMG_Load_RW(PHYSFSRWOPS_openRead(file), 1);
+			SDL_Surface *surface = IMG_Load_RW(OpenRead(file), 1);
 			if (surface) {
 				SDL_Texture *texture = screen->LoadImage(surface);
 				SDL_FreeSurface(surface);
diff --git a/game/load.h b/game/load.h
index 906469df..e15b0807 100644
--- a/game/load.h
+++ b/game/load.h
@@ -23,9 +23,6 @@
 #ifndef _load_h
 #define _load_h
 
-#include "../physfs/physfs.h"
-#include "../utils/physfsrwops.h"
-
 #include "../screenlib/SDL_FrameBuf.h"
 
 /* Functions exported from load.cpp */
diff --git a/game/main.cpp b/game/main.cpp
index 189224e4..00620840 100644
--- a/game/main.cpp
+++ b/game/main.cpp
@@ -42,6 +42,8 @@
 #include "netplay.h"
 #include "main.h"
 
+#include "../physfs/physfs.h"
+
 #include "../screenlib/UIDialog.h"
 #include "../screenlib/UIElement.h"
 #include "../screenlib/UIElementCheckbox.h"
@@ -162,7 +164,11 @@ InitFilesystem(const char *argv0)
 	}
 
 	// Set up the write directory for this platform
+#ifdef __ANDROID__
+	prefspath = SDL_AndroidGetInternalStoragePath();
+#else
 	prefspath = PHYSFS_getPrefDir(MAELSTROM_ORGANIZATION, MAELSTROM_NAME);
+#endif
 	if (!prefspath) {
 		error("Couldn't get preferences path for this platform\n");
 		return false;
@@ -175,6 +181,11 @@ InitFilesystem(const char *argv0)
 	/* Put the write directory first in the search path */
 	PHYSFS_mount(prefspath, NULL, 0);
 
+#ifdef __ANDROID__
+	// We'll use SDL's asset manager code path for Android
+	return true;
+
+#else
 	/* Then add the base directory to the search path */
 	PHYSFS_mount(PHYSFS_getBaseDir(), NULL, 0);
 
@@ -197,6 +208,7 @@ InitFilesystem(const char *argv0)
 
 	error("Couldn't find %s", MAELSTROM_DATA);
 	return false;
+#endif // __ANDROID__
 }
 
 /* ----------------------------------------------------------------- */
diff --git a/game/replay.cpp b/game/replay.cpp
index cd839d8d..31b7a71a 100644
--- a/game/replay.cpp
+++ b/game/replay.cpp
@@ -22,6 +22,7 @@
 
 #include <zlib.h>
 #include "../physfs/physfs.h"
+#include "../utils/files.h"
 
 #include "Maelstrom_Globals.h"
 #include "netplay.h"
@@ -65,9 +66,8 @@ Replay::SetMode(REPLAY_MODE mode)
 	Uint8 compressed_data[]
 */
 
-// This is a temporary hack
-static PHYSFS_File *
-CopyTempReplay(const char *file)
+static SDL_RWops *
+CopyReplayIntoSandbox(const char *file)
 {
 	FILE *rfp;
 	PHYSFS_File *wfp;
@@ -101,17 +101,17 @@ CopyTempReplay(const char *file)
 
 	while ((size = fread(data, 1, sizeof(data), rfp)) > 0) {
 		if (!PHYSFS_writeBytes(wfp, data, size)) {
-			goto physfs_write_error;
+			goto write_error;
 		}
 	}
 	if (!PHYSFS_close(wfp)) {
-		goto physfs_write_error;
+		goto write_error;
 	}
 	fclose(rfp);
 
-	return PHYSFS_openRead(path);
+	return OpenRead(path);
 
-physfs_write_error:
+write_error:
 	fprintf(stderr, "Error writing to %s: %s\n", path, PHYSFS_getLastError());
 	fclose(rfp);
 	PHYSFS_close(wfp);
@@ -123,7 +123,7 @@ bool
 Replay::Load(const char *file, bool headerOnly)
 {
 	char path[1024];
-	PHYSFS_File *fp;
+	SDL_RWops *fp;
 	DynamicPacket data;
 	uLongf destLen;
 	Uint32 size;
@@ -134,52 +134,38 @@ Replay::Load(const char *file, bool headerOnly)
 		SDL_snprintf(path, sizeof(path), "%s/%s", REPLAY_DIRECTORY, file);
 		file = path;
 	}
-	fp = PHYSFS_openRead(file);
+	fp = OpenRead(file);
 	if (!fp) {
 		// If the file is outside our sandbox, try to copy it in
-		fp = CopyTempReplay(file);
+		fp = CopyReplayIntoSandbox(file);
 	}
 	if (!fp) {
-		fprintf(stderr, "Couldn't read %s: %s\n", file, PHYSFS_getLastError());
+		fprintf(stderr, "Couldn't read %s: %s\n", file, SDL_GetError());
 		return false;
 	}
 
 	Uint8 version;
-	if (!PHYSFS_readBytes(fp, &version, 1)) {
-		goto physfs_read_error;
+	if (!SDL_RWread(fp, &version, 1, 1)) {
+		goto read_error;
 	}
 	if (version != REPLAY_VERSION) {
 		fprintf(stderr, "Unsupported version %d, expected %d\n", version, REPLAY_VERSION);
 		goto error_return;
 	}
-	if (!PHYSFS_readULE32(fp, &m_frameCount)) {
-		goto physfs_read_error;
-	}
-	if (!PHYSFS_readBytes(fp, &m_finalPlayer, 1)) {
-		goto physfs_read_error;
-	}
-	if (!PHYSFS_readBytes(fp, &m_finalWave, 1)) {
-		goto physfs_read_error;
-	}
-	if (!PHYSFS_readBytes(fp, &m_finalContinues, 1)) {
-		goto physfs_read_error;
-	}
+	m_frameCount = SDL_ReadLE32(fp);
+	m_finalPlayer = SDL_ReadU8(fp);
+	m_finalWave = SDL_ReadU8(fp);
+	m_finalContinues = SDL_ReadU8(fp);
 	for (int i = 0; i < MAX_PLAYERS; ++i) {
-		if (!PHYSFS_readULE32(fp, &m_finalScore[i].Score)) {
-			goto physfs_read_error;
-		}
-		if (!PHYSFS_readBytes(fp, &m_finalScore[i].Frags, 1)) {
-			goto physfs_read_error;
-		}
+		m_finalScore[i].Score = SDL_ReadLE32(fp);
+		m_finalScore[i].Frags = SDL_ReadU8(fp);
 	}
 
-	if (!PHYSFS_readULE32(fp, &size)) {
-		goto physfs_read_error;
-	}
+	size = SDL_ReadLE32(fp);
 	data.Reset();
 	data.Grow(size);
-	if (!PHYSFS_readBytes(fp, data.data, size)) {
-		goto physfs_read_error;
+	if (!SDL_RWread(fp, data.data, size, 1)) {
+		goto read_error;
 	}
 	data.len = size;
 	if (!m_game.ReadFromPacket(data)) {
@@ -188,20 +174,16 @@ Replay::Load(const char *file, bool headerOnly)
 	}
 
 	if (!headerOnly) {
-		if (!PHYSFS_readULE32(fp, &size)) {
-			goto physfs_read_error;
-		}
+		size = SDL_ReadLE32(fp);
 		m_data.Reset();
 		m_data.Grow(size);
 
-		if (!PHYSFS_readULE32(fp, &compressedSize)) {
-			goto physfs_read_error;
-		}
+		compressedSize = SDL_ReadLE32(fp);
 		data.Reset();
 		data.Grow(compressedSize);
 
-		if (!PHYSFS_readBytes(fp, data.data, compressedSize)) {
-			goto physfs_read_error;
+		if (!SDL_RWread(fp, data.data, compressedSize, 1)) {
+			goto read_error;
 		}
 		destLen = size;
 		if (uncompress(m_data.Data(), &destLen, data.Data(), compressedSize) != Z_OK) {
@@ -212,13 +194,13 @@ Replay::Load(const char *file, bool headerOnly)
 	}
 
 	// We're done!
-	PHYSFS_close(fp);
+	SDL_RWclose(fp);
 	return true;
 
-physfs_read_error:
-	fprintf(stderr, "Error reading from %s: %s\n", file, PHYSFS_getLastError());
+read_error:
+	fprintf(stderr, "Error reading from %s: %s\n", file, SDL_GetError());
 error_return:
-	PHYSFS_close(fp);
+	SDL_RWclose(fp);
 	return false;
 }
 
@@ -226,7 +208,7 @@ bool
 Replay::Save(const char *file)
 {
 	char path[1024];
-	PHYSFS_File *fp;
+	SDL_RWops *fp;
 	DynamicPacket data;
 	uLongf destLen;
 
@@ -241,44 +223,28 @@ Replay::Save(const char *file)
 		SDL_snprintf(path, sizeof(path), "%s/%s", REPLAY_DIRECTORY, file);
 		file = path;
 	}
-	fp = PHYSFS_openWrite(file);
+	fp = OpenWrite(file);
 	if (!fp) {
 		fprintf(stderr, "Couldn't write to %s: %s\n", file, PHYSFS_getLastError());
 		return false;
 	}
 
 	Uint8 version = REPLAY_VERSION;
-	if (!PHYSFS_writeBytes(fp, &version, 1)) {
-		goto physfs_write_error;
-	}
-	if (!PHYSFS_writeULE32(fp, m_frameCount)) {
-		goto physfs_write_error;
-	}
-	if (!PHYSFS_writeBytes(fp, &m_finalPlayer, 1)) {
-		goto physfs_write_error;
-	}
-	if (!PHYSFS_writeBytes(fp, &m_finalWave, 1)) {
-		goto physfs_write_error;
-	}
-	if (!PHYSFS_writeBytes(fp, &m_finalContinues, 1)) {
-		goto physfs_write_error;
-	}
+	SDL_WriteU8(fp, version);
+	SDL_WriteLE32(fp, m_frameCount);
+	SDL_WriteU8(fp, m_finalPlayer);
+	SDL_WriteU8(fp, m_finalWave);
+	SDL_WriteU8(fp, m_finalContinues);
 	for (int i = 0; i < MAX_PLAYERS; ++i) {
-		if (!PHYSFS_writeULE32(fp, m_finalScore[i].Score)) {
-			goto physfs_write_error;
-		}
-		if (!PHYSFS_writeBytes(fp, &m_finalScore[i].Frags, 1)) {
-			goto physfs_write_error;
-		}
+		SDL_WriteLE32(fp, m_finalScore[i].Score);
+		SDL_WriteU8(fp, m_finalScore[i].Frags);
 	}
 
 	data.Reset();
 	m_game.WriteToPacket(data);
-	if (!PHYSFS_writeULE32(fp, data.Size())) {
-		goto physfs_write_error;
-	}
-	if (!PHYSFS_writeBytes(fp, data.Data(), data.Size())) {
-		goto physfs_write_error;
+	SDL_WriteLE32(fp, data.Size());
+	if (!SDL_RWwrite(fp, data.Data(), data.Size(), 1)) {
+		goto write_error;
 	}
 
 	destLen = compressBound(m_data.Size());
@@ -289,26 +255,22 @@ Replay::Save(const char *file)
 		goto error_return;
 	}
 	data.len = destLen;
-	if (!PHYSFS_writeULE32(fp, m_data.Size())) {
-		goto physfs_write_error;
-	}
-	if (!PHYSFS_writeULE32(fp, data.Size())) {
-		goto physfs_write_error;
-	}
-	if (!PHYSFS_writeBytes(fp, data.Data(), data.Size())) {
-		goto physfs_write_error;
+	SDL_WriteLE32(fp, m_data.Size());
+	SDL_WriteLE32(fp, data.Size());
+	if (!SDL_RWwrite(fp, data.Data(), data.Size(), 1)) {
+		goto write_error;
 	}
 
 	// We're done!
-	if (!PHYSFS_close(fp)) {
-		goto physfs_write_error;
+	if (SDL_RWclose(fp) < 0) {
+		goto write_error;
 	}
 	return true;
 
-physfs_write_error:
-	fprintf(stderr, "Error writing to %s: %s\n", file, PHYSFS_getLastError());
+write_error:
+	fprintf(stderr, "Error writing to %s: %s\n", file, SDL_GetError());
 error_return:
-	PHYSFS_close(fp);
+	SDL_RWclose(fp);
 	PHYSFS_delete(path);
 	return false;
 }
diff --git a/maclib/Mac_FontServ.cpp b/maclib/Mac_FontServ.cpp
index a9c2d908..a155fe81 100644
--- a/maclib/Mac_FontServ.cpp
+++ b/maclib/Mac_FontServ.cpp
@@ -26,10 +26,9 @@
 #include <ctype.h>
 #include <string.h>
 
-#include "../physfs/physfs.h"
-#include "../utils/physfsrwops.h"
 #include "SDL_types.h"
 #include "bitesex.h"
+#include "../utils/files.h"
 #include "Mac_FontServ.h"
 
 #define copy_short(S, D)	memcpy(&S, D, 2); D += 2;
@@ -77,7 +76,7 @@ static TTF_Font *GetTrueTypeFont(const char *name, int ptsize)
 	SDL_RWops *src;
 
 	SDL_snprintf(file, sizeof(file), "Fonts/%s.ttf", name);
-	src = PHYSFSRWOPS_openRead(file);
+	src = OpenRead(file);
 	if (src) {
 		return TTF_OpenFontRW(src, 1, ptsize);
 	}
@@ -87,28 +86,8 @@ static TTF_Font *GetTrueTypeFont(const char *name, int ptsize)
 static Uint8 *GetFontData(const char *type, int ID)
 {
 	char file[128];
-	PHYSFS_File *fp;
-	PHYSFS_sint64 size;
-	Uint8 *data;
-
 	SDL_snprintf(file, sizeof(file), "Fonts/Maelstrom_%s#%d", type, ID);
-	fp = PHYSFS_openRead(file);
-	if (!fp) {
-		fprintf(stderr, "Couldn't open %s: %s\n", file, PHYSFS_getLastError());
-		return NULL;
-	}
-
-	size = PHYSFS_fileLength(fp);
-	data = new Uint8[size];
-	if (PHYSFS_readBytes(fp, data, size) != size) {
-		fprintf(stderr, "Couldn't read data from %s: %s\n", file, PHYSFS_getLastError());
-		PHYSFS_close(fp);
-		delete[] data;
-		return NULL;
-	}
-
-	PHYSFS_close(fp);
-	

(Patch may be truncated, please check the link at the top of this post.)