mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Allow mounting VFS directories. Used to provide flash0 from within APK on Android.
This commit is contained in:
parent
ba0362d817
commit
aa06c1452e
1
.gitignore
vendored
1
.gitignore
vendored
@ -46,5 +46,6 @@ __testfailure.bmp
|
||||
GameLogNotes.txt
|
||||
|
||||
android/ui_atlas.zim
|
||||
android/assets/flash0
|
||||
ppge_atlas.zim.png
|
||||
local.properties
|
||||
|
@ -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.");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -1 +1,2 @@
|
||||
cp -r ../flash0 assets
|
||||
NDK_MODULE_PATH=..:../native/ext $NDK/ndk-build -j3 TARGET_PLATFORM=android-9 $*
|
||||
|
2
native
2
native
@ -1 +1 @@
|
||||
Subproject commit 17c8eb1ae7ca285a4228bac56059ca441b53ba6f
|
||||
Subproject commit 3f6353af5afe1542a50c33eb0bb554ea25653258
|
Loading…
Reference in New Issue
Block a user