Allow mounting VFS directories. Used to provide flash0 from within APK on Android.

This commit is contained in:
Henrik Rydgard 2013-02-27 00:59:30 +01:00
parent ba0362d817
commit aa06c1452e
8 changed files with 223 additions and 12 deletions

1
.gitignore vendored
View File

@ -46,5 +46,6 @@ __testfailure.bmp
GameLogNotes.txt
android/ui_atlas.zim
android/assets/flash0
ppge_atlas.zim.png
local.properties

View File

@ -18,7 +18,7 @@
#include "ChunkFile.h"
#include "FileUtil.h"
#include "DirectoryFileSystem.h"
#include "file/zip_read.h"
#ifdef _WIN32
#include <windows.h>
@ -595,3 +595,153 @@ void DirectoryFileSystem::DoState(PointerWrap &p) {
ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly.");
}
}
VFSFileSystem::VFSFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) {
INFO_LOG(HLE, "Creating VFS file system");
hAlloc = _hAlloc;
}
VFSFileSystem::~VFSFileSystem() {
for (auto iter = entries.begin(); iter != entries.end(); ++iter) {
delete [] iter->second.fileData;
}
entries.clear();
}
std::string VFSFileSystem::GetLocalPath(std::string localPath) {
return basePath + localPath;
}
bool VFSFileSystem::MkDir(const std::string &dirname) {
// NOT SUPPORTED - READ ONLY
return false;
}
bool VFSFileSystem::RmDir(const std::string &dirname) {
// NOT SUPPORTED - READ ONLY
return false;
}
bool VFSFileSystem::RenameFile(const std::string &from, const std::string &to) {
// NOT SUPPORTED - READ ONLY
return false;
}
bool VFSFileSystem::RemoveFile(const std::string &filename) {
// NOT SUPPORTED - READ ONLY
return false;
}
u32 VFSFileSystem::OpenFile(std::string filename, FileAccess access) {
if (access != FILEACCESS_READ) {
ERROR_LOG(HLE, "VFSFileSystem only supports plain reading");
return 0;
}
std::string fullName = GetLocalPath(filename);
const char *fullNameC = fullName.c_str();
INFO_LOG(HLE,"VFSFileSystem actually opening %s (%s)", fullNameC, filename.c_str());
size_t size;
u8 *data = VFSReadFile(fullNameC, &size);
if (!data) {
ERROR_LOG(HLE, "VFSFileSystem failed to open %s", filename.c_str());
return 0;
}
OpenFileEntry entry;
entry.fileData = data;
entry.size = size;
entry.seekPos = 0;
u32 newHandle = hAlloc->GetNewHandle();
entries[newHandle] = entry;
return newHandle;
}
PSPFileInfo VFSFileSystem::GetFileInfo(std::string filename) {
PSPFileInfo x;
x.name = filename;
std::string fullName = GetLocalPath(filename);
INFO_LOG(HLE,"Getting VFS file info %s (%s)", fullName.c_str(), filename.c_str());
FileInfo fo;
VFSGetFileInfo(fullName.c_str(), &fo);
x.exists = fo.exists;
if (x.exists) {
x.size = fo.size;
x.type = fo.isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL;
}
INFO_LOG(HLE,"Got VFS file info: size = %i", (int)x.size);
return x;
}
void VFSFileSystem::CloseFile(u32 handle) {
EntryMap::iterator iter = entries.find(handle);
if (iter != entries.end()) {
delete [] iter->second.fileData;
entries.erase(iter);
} else {
//This shouldn't happen...
ERROR_LOG(HLE,"Cannot close file that hasn't been opened: %08x", handle);
}
}
bool VFSFileSystem::OwnsHandle(u32 handle) {
EntryMap::iterator iter = entries.find(handle);
return (iter != entries.end());
}
size_t VFSFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) {
INFO_LOG(HLE,"VFSFileSystem::ReadFile %08x %p %i", handle, pointer, (u32)size);
EntryMap::iterator iter = entries.find(handle);
if (iter != entries.end())
{
size_t bytesRead = size;
memcpy(pointer, iter->second.fileData + iter->second.seekPos, size);
iter->second.seekPos += size;
return bytesRead;
} else {
ERROR_LOG(HLE,"Cannot read file that hasn't been opened: %08x", handle);
return 0;
}
}
size_t VFSFileSystem::WriteFile(u32 handle, const u8 *pointer, s64 size) {
// NOT SUPPORTED - READ ONLY
return 0;
}
size_t VFSFileSystem::SeekFile(u32 handle, s32 position, FileMove type) {
EntryMap::iterator iter = entries.find(handle);
if (iter != entries.end()) {
switch (type) {
case FILEMOVE_BEGIN: iter->second.seekPos = position; break;
case FILEMOVE_CURRENT: iter->second.seekPos += position; break;
case FILEMOVE_END: iter->second.seekPos = iter->second.size + position; break;
}
return iter->second.seekPos;
} else {
//This shouldn't happen...
ERROR_LOG(HLE,"Cannot seek in file that hasn't been opened: %08x", handle);
return 0;
}
}
bool VFSFileSystem::GetHostPath(const std::string &inpath, std::string &outpath) {
// NOT SUPPORTED
return false;
}
std::vector<PSPFileInfo> VFSFileSystem::GetDirListing(std::string path) {
std::vector<PSPFileInfo> myVector;
// TODO
return myVector;
}
void VFSFileSystem::DoState(PointerWrap &p) {
if (!entries.empty()) {
ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly.");
}
}

View File

@ -95,3 +95,41 @@ private:
bool FixPathCase(std::string &path, FixPathCaseBehavior behavior);
#endif
};
// VFSFileSystem: Ability to map in Android APK paths as well! Does not support all features, only meant for fonts.
// Very inefficient - always load the whole file on open.
class VFSFileSystem : public IFileSystem {
public:
VFSFileSystem(IHandleAllocator *_hAlloc, std::string _basePath);
~VFSFileSystem();
void DoState(PointerWrap &p);
std::vector<PSPFileInfo> GetDirListing(std::string path);
u32 OpenFile(std::string filename, FileAccess access);
void CloseFile(u32 handle);
size_t ReadFile(u32 handle, u8 *pointer, s64 size);
size_t WriteFile(u32 handle, const u8 *pointer, s64 size);
size_t SeekFile(u32 handle, s32 position, FileMove type);
PSPFileInfo GetFileInfo(std::string filename);
bool OwnsHandle(u32 handle);
bool MkDir(const std::string &dirname);
bool RmDir(const std::string &dirname);
bool RenameFile(const std::string &from, const std::string &to);
bool RemoveFile(const std::string &filename);
bool GetHostPath(const std::string &inpath, std::string &outpath);
private:
struct OpenFileEntry {
u8 *fileData;
size_t size;
size_t seekPos;
};
typedef std::map<u32, OpenFileEntry> EntryMap;
EntryMap entries;
std::string basePath;
IHandleAllocator *hAlloc;
std::string GetLocalPath(std::string localpath);
};

View File

@ -178,6 +178,13 @@ private:
class FontLib;
// These should not need to be state saved.
static std::vector<Font *> internalFonts;
// However, these we must save - but we could take a shortcut
// for LoadedFonts that point to internal fonts.
static std::map<u32, LoadedFont *> fontMap;
static std::map<u32, FontLib *> fontLibMap;
class PostAllocCallback : public Action {
public:
PostAllocCallback() {}
@ -222,8 +229,17 @@ public:
}
void Done() {
for (size_t i = 0; i < fonts_.size(); i++) {
if (Memory::Read_U32(fonts_[i]) == FONT_IS_OPEN) {
fontMap[fonts_[i]]->Close();
delete fontMap[fonts_[i]];
fontMap.erase(fonts_[i]);
}
}
u32 args[1] = { handle_ };
__KernelDirectMipsCall(params_.freeFuncAddr, 0, args, 1, false);
handle_ = 0;
fonts_.clear();
}
void AllocDone(u32 allocatedAddr) {
@ -274,6 +290,7 @@ public:
for (size_t i = 0; i < fonts_.size(); i++) {
if (fonts_[i] == font->Handle()) {
Memory::Write_U32(FONT_IS_CLOSED, font->Handle());
}
}
font->Close();
@ -296,7 +313,7 @@ public:
u32 GetAltCharCode() const { return altCharCode_; }
private:
std::vector<int> fonts_;
std::vector<u32> fonts_;
FontNewLibParams params_;
float fontHRes_;
@ -308,18 +325,13 @@ private:
};
// These should not need to be state saved.
static std::vector<Font *> internalFonts;
// However, these we must save - but we could take a shortcut
// for LoadedFonts that point to internal fonts.
static std::map<u32, LoadedFont *> fontMap;
static std::map<u32, FontLib *> fontLibMap;
void PostAllocCallback::run(MipsCall &call) {
INFO_LOG(HLE, "Entering PostAllocCallback::run");
u32 v0 = currentMIPS->r[0];
fontLib_->AllocDone(call.savedV0);
fontLibMap[fontLib_->handle()] = fontLib_;
call.setReturnValue(fontLib_->handle());
INFO_LOG(HLE, "Leaving PostAllocCallback::run");
}
void PostOpenCallback::run(MipsCall &call) {
@ -357,8 +369,14 @@ void __LoadInternalFonts() {
std::string fontFilename = fontPath + entry.fileName;
PSPFileInfo info = pspFileSystem.GetFileInfo(fontFilename);
if (info.exists) {
INFO_LOG(HLE, "Loading font %s (%i bytes)", fontFilename.c_str(), (int)info.size);
u8 *buffer = new u8[(size_t)info.size];
u32 handle = pspFileSystem.OpenFile(fontFilename, FILEACCESS_READ);
if (!handle) {
ERROR_LOG(HLE, "Failed opening font");
delete [] buffer;
continue;
}
pspFileSystem.ReadFile(handle, buffer, info.size);
pspFileSystem.CloseFile(handle);

View File

@ -220,13 +220,15 @@ void __IoInit() {
DirectoryFileSystem *memstick = new DirectoryFileSystem(&pspFileSystem, memstickpath);
#ifdef ANDROID
VFSFileSystem *flash0 = new VFSFileSystem(&pspFileSystem, "flash0");
#else
DirectoryFileSystem *flash0 = new DirectoryFileSystem(&pspFileSystem, flash0path);
DirectoryFileSystem *flash1 = new DirectoryFileSystem(&pspFileSystem, flash0path);
#endif
pspFileSystem.Mount("ms0:", memstick);
pspFileSystem.Mount("fatms0:", memstick);
pspFileSystem.Mount("fatms:", memstick);
pspFileSystem.Mount("flash0:", flash0);
pspFileSystem.Mount("flash1:", flash1);
__KernelListenThreadEnd(&TellFsThreadEnded);
}

View File

@ -1,3 +1,4 @@
xcopy ..\flash0 assets\flash0 /s /y
SET NDK=C:\AndroidNDK
SET NDK_MODULE_PATH=..;..\native\ext
REM Need to force target-platform to android-9 to get access to OpenSL headers.

View File

@ -1 +1,2 @@
cp -r ../flash0 assets
NDK_MODULE_PATH=..:../native/ext $NDK/ndk-build -j3 TARGET_PLATFORM=android-9 $*

2
native

@ -1 +1 @@
Subproject commit 17c8eb1ae7ca285a4228bac56059ca441b53ba6f
Subproject commit 3f6353af5afe1542a50c33eb0bb554ea25653258