Moving mmap to poly, cleaning up devices.
This commit is contained in:
parent
24fe169f36
commit
854bcdb60a
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef POLY_MAPPED_MEMORY_H_
|
||||
#define POLY_MAPPED_MEMORY_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace poly {
|
||||
|
||||
class MappedMemory {
|
||||
public:
|
||||
enum class Mode {
|
||||
READ,
|
||||
READ_WRITE,
|
||||
};
|
||||
|
||||
virtual ~MappedMemory() = default;
|
||||
|
||||
static std::unique_ptr<MappedMemory> Open(const std::wstring& path, Mode mode,
|
||||
size_t offset = 0,
|
||||
size_t length = 0);
|
||||
|
||||
uint8_t* data() const { return reinterpret_cast<uint8_t*>(data_); }
|
||||
size_t size() const { return size_; }
|
||||
|
||||
protected:
|
||||
MappedMemory(const std::wstring& path, Mode mode)
|
||||
: path_(path), mode_(mode), data_(nullptr), size_(0) {}
|
||||
|
||||
std::wstring path_;
|
||||
Mode mode_;
|
||||
void* data_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
} // namespace poly
|
||||
|
||||
#endif // POLY_MAPPED_MEMORY_H_
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <poly/mapped_memory.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include <poly/string.h>
|
||||
|
||||
namespace poly {
|
||||
|
||||
class PosixMappedMemory : public MappedMemory {
|
||||
public:
|
||||
PosixMappedMemory(const std::wstring& path, Mode mode)
|
||||
: MappedMemory(path, mode), file_handle(nullptr) {}
|
||||
|
||||
~PosixMappedMemory() override {
|
||||
if (data_) {
|
||||
munmap(data_, size_);
|
||||
}
|
||||
if (file_handle) {
|
||||
fclose(file_handle);
|
||||
}
|
||||
}
|
||||
|
||||
FILE* file_handle;
|
||||
};
|
||||
|
||||
std::unique_ptr<MappedMemory> MappedMemory::Open(const std::wstring& path,
|
||||
Mode mode, size_t offset,
|
||||
size_t length) {
|
||||
const char* mode;
|
||||
int prot;
|
||||
switch (mode) {
|
||||
case Mode::READ:
|
||||
mode = "rb";
|
||||
prot = PROT_READ;
|
||||
break;
|
||||
case Mode::READ_WRITE:
|
||||
mode = "r+b";
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
auto mm = std::make_unique<PosixMappedMemory>(path, mode);
|
||||
|
||||
mm->file_handle = fopen(poly::to_string(path).c_str(), mode);
|
||||
if (!mm->file_handle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t map_length;
|
||||
map_length = length;
|
||||
if (!length) {
|
||||
fseeko(mm->file_handle, 0, SEEK_END);
|
||||
map_length = ftello(mm->file_handle);
|
||||
fseeko(mm->file_handle, 0, SEEK_SET);
|
||||
}
|
||||
mm->size_ = map_length;
|
||||
|
||||
mm->data_ =
|
||||
mmap(0, map_length, prot, MAP_SHARED, fileno(mm->file_handle), offset);
|
||||
if (!mm->data_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::move(mm);
|
||||
}
|
||||
|
||||
} // namespace poly
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <poly/mapped_memory.h>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace poly {
|
||||
|
||||
class Win32MappedMemory : public MappedMemory {
|
||||
public:
|
||||
Win32MappedMemory(const std::wstring& path, Mode mode)
|
||||
: MappedMemory(path, mode),
|
||||
file_handle(nullptr),
|
||||
mapping_handle(nullptr) {}
|
||||
|
||||
~Win32MappedMemory() override {
|
||||
if (data_) {
|
||||
UnmapViewOfFile(data_);
|
||||
}
|
||||
if (mapping_handle) {
|
||||
CloseHandle(mapping_handle);
|
||||
}
|
||||
if (file_handle) {
|
||||
CloseHandle(file_handle);
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE file_handle;
|
||||
HANDLE mapping_handle;
|
||||
};
|
||||
|
||||
std::unique_ptr<MappedMemory> MappedMemory::Open(const std::wstring& path,
|
||||
Mode mode, size_t offset,
|
||||
size_t length) {
|
||||
DWORD file_access = 0;
|
||||
DWORD file_share = 0;
|
||||
DWORD create_mode = 0;
|
||||
DWORD mapping_protect = 0;
|
||||
DWORD view_access = 0;
|
||||
switch (mode) {
|
||||
case Mode::READ:
|
||||
file_access |= GENERIC_READ;
|
||||
file_share |= FILE_SHARE_READ;
|
||||
create_mode |= OPEN_EXISTING;
|
||||
mapping_protect |= PAGE_READONLY;
|
||||
view_access |= FILE_MAP_READ;
|
||||
break;
|
||||
case Mode::READ_WRITE:
|
||||
file_access |= GENERIC_READ | GENERIC_WRITE;
|
||||
file_share |= 0;
|
||||
create_mode |= OPEN_EXISTING;
|
||||
mapping_protect |= PAGE_READWRITE;
|
||||
view_access |= FILE_MAP_READ | FILE_MAP_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetSystemInfo(&systemInfo);
|
||||
|
||||
const size_t aligned_offset =
|
||||
offset & (~(systemInfo.dwAllocationGranularity - 1));
|
||||
const size_t aligned_length = length + (offset - aligned_offset);
|
||||
|
||||
auto mm = std::make_unique<Win32MappedMemory>(path, mode);
|
||||
|
||||
mm->file_handle = CreateFile(path.c_str(), file_access, file_share, nullptr,
|
||||
create_mode, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (!mm->file_handle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mm->mapping_handle = CreateFileMapping(mm->file_handle, nullptr,
|
||||
mapping_protect, 0, 0, nullptr);
|
||||
//(DWORD)(aligned_length >> 32), (DWORD)(aligned_length & 0xFFFFFFFF), NULL);
|
||||
if (!mm->mapping_handle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mm->data_ = reinterpret_cast<uint8_t*>(MapViewOfFile(
|
||||
mm->mapping_handle, view_access, static_cast<DWORD>(aligned_offset >> 32),
|
||||
static_cast<DWORD>(aligned_offset & 0xFFFFFFFF), aligned_length));
|
||||
if (!mm->data_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (length) {
|
||||
mm->size_ = aligned_length;
|
||||
} else {
|
||||
DWORD length_high;
|
||||
size_t map_length = GetFileSize(mm->file_handle, &length_high);
|
||||
map_length |= static_cast<uint64_t>(length_high) << 32;
|
||||
mm->size_ = map_length - aligned_offset;
|
||||
}
|
||||
|
||||
return std::move(mm);
|
||||
}
|
||||
|
||||
} // namespace poly
|
|
@ -16,6 +16,7 @@
|
|||
#include <poly/config.h>
|
||||
#include <poly/cxx_compat.h>
|
||||
#include <poly/debugging.h>
|
||||
#include <poly/mapped_memory.h>
|
||||
#include <poly/math.h>
|
||||
#include <poly/memory.h>
|
||||
#include <poly/platform.h>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
'config.h',
|
||||
'cxx_compat.h',
|
||||
'main.h',
|
||||
'mapped_memory.h',
|
||||
'math.cc',
|
||||
'math.h',
|
||||
'memory.cc',
|
||||
|
@ -23,6 +24,7 @@
|
|||
['OS == "mac" or OS == "linux"', {
|
||||
'sources': [
|
||||
'main_posix.cc',
|
||||
'mapped_memory_posix.cc',
|
||||
],
|
||||
}],
|
||||
['OS == "linux"', {
|
||||
|
@ -40,6 +42,7 @@
|
|||
'sources': [
|
||||
'debugging_win.cc',
|
||||
'main_win.cc',
|
||||
'mapped_memory_win.cc',
|
||||
'threading_win.cc',
|
||||
],
|
||||
}],
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace xe {
|
|||
using Memory = alloy::Memory;
|
||||
} // namespace xe
|
||||
|
||||
#include <xenia/core/mmap.h>
|
||||
#include <xenia/core/ref.h>
|
||||
#include <xenia/core/run_loop.h>
|
||||
#include <xenia/core/socket.h>
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_CORE_MMAP_H_
|
||||
#define XENIA_CORE_MMAP_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core/ref.h>
|
||||
|
||||
|
||||
struct xe_mmap;
|
||||
typedef struct xe_mmap* xe_mmap_ref;
|
||||
|
||||
typedef enum {
|
||||
kXEFileModeRead = (1 << 0),
|
||||
kXEFileModeWrite = (1 << 1),
|
||||
} xe_file_mode;
|
||||
|
||||
xe_mmap_ref xe_mmap_open(const xe_file_mode mode, const wchar_t *path,
|
||||
const size_t offset, const size_t length);
|
||||
xe_mmap_ref xe_mmap_retain(xe_mmap_ref mmap);
|
||||
void xe_mmap_release(xe_mmap_ref mmap);
|
||||
uint8_t* xe_mmap_get_addr(xe_mmap_ref mmap);
|
||||
size_t xe_mmap_get_length(xe_mmap_ref mmap);
|
||||
|
||||
|
||||
#endif // XENIA_CORE_MMAP_H_
|
|
@ -1,100 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <xenia/core/mmap.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
typedef struct xe_mmap {
|
||||
xe_ref_t ref;
|
||||
|
||||
void* file_handle;
|
||||
void* mmap_handle;
|
||||
|
||||
void* addr;
|
||||
size_t length;
|
||||
} xe_mmap_t;
|
||||
|
||||
|
||||
xe_mmap_ref xe_mmap_open(const xe_file_mode mode, const xechar_t *path,
|
||||
const size_t offset, const size_t length) {
|
||||
xe_mmap_ref mmap = (xe_mmap_ref)xe_calloc(sizeof(xe_mmap_t));
|
||||
xe_ref_init((xe_ref)mmap);
|
||||
|
||||
xechar_t mode_string[10];
|
||||
mode_string[0] = 0;
|
||||
if (mode & kXEFileModeRead) {
|
||||
XEIGNORE(xestrcat(mode_string, XECOUNT(mode_string), XT("r")));
|
||||
}
|
||||
if (mode & kXEFileModeWrite) {
|
||||
XEIGNORE(xestrcat(mode_string, XECOUNT(mode_string), XT("w")));
|
||||
}
|
||||
XEIGNORE(xestrcat(mode_string, XECOUNT(mode_string), XT("b")));
|
||||
|
||||
int prot = 0;
|
||||
if (mode & kXEFileModeRead) {
|
||||
prot |= PROT_READ;
|
||||
}
|
||||
if (mode & kXEFileModeWrite) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
|
||||
FILE* file_handle = fopen(path, mode_string);
|
||||
mmap->file_handle = file_handle;
|
||||
XEEXPECTNOTNULL(mmap->file_handle);
|
||||
|
||||
size_t map_length;
|
||||
map_length = length;
|
||||
if (!length) {
|
||||
fseeko(file_handle, 0, SEEK_END);
|
||||
map_length = ftello(file_handle);
|
||||
}
|
||||
mmap->length = map_length;
|
||||
|
||||
mmap->addr = ::mmap(0, map_length, prot, MAP_SHARED, fileno(file_handle),
|
||||
offset);
|
||||
XEEXPECTNOTNULL(mmap->addr);
|
||||
|
||||
return mmap;
|
||||
|
||||
XECLEANUP:
|
||||
xe_mmap_release(mmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void xe_mmap_dealloc(xe_mmap_ref mmap) {
|
||||
if (mmap->addr) {
|
||||
munmap(mmap->addr, mmap->length);
|
||||
mmap->addr = NULL;
|
||||
}
|
||||
|
||||
FILE* file_handle = (FILE*)mmap->file_handle;
|
||||
if (file_handle) {
|
||||
fclose(file_handle);
|
||||
mmap->file_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
xe_mmap_ref xe_mmap_retain(xe_mmap_ref mmap) {
|
||||
xe_ref_retain((xe_ref)mmap);
|
||||
return mmap;
|
||||
}
|
||||
|
||||
void xe_mmap_release(xe_mmap_ref mmap) {
|
||||
xe_ref_release((xe_ref)mmap, (xe_ref_dealloc_t)xe_mmap_dealloc);
|
||||
}
|
||||
|
||||
uint8_t* xe_mmap_get_addr(xe_mmap_ref mmap) {
|
||||
return (uint8_t*)mmap->addr;
|
||||
}
|
||||
|
||||
size_t xe_mmap_get_length(xe_mmap_ref mmap) {
|
||||
return mmap->length;
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <xenia/core/mmap.h>
|
||||
|
||||
|
||||
typedef struct xe_mmap {
|
||||
xe_ref_t ref;
|
||||
|
||||
HANDLE file_handle;
|
||||
HANDLE mmap_handle;
|
||||
|
||||
void* addr;
|
||||
size_t length;
|
||||
} xe_mmap_t;
|
||||
|
||||
|
||||
xe_mmap_ref xe_mmap_open(const xe_file_mode mode, const wchar_t *path,
|
||||
const size_t offset, const size_t length) {
|
||||
xe_mmap_ref mmap = (xe_mmap_ref)xe_calloc(sizeof(xe_mmap_t));
|
||||
xe_ref_init((xe_ref)mmap);
|
||||
|
||||
DWORD fileAccess = 0;
|
||||
DWORD fileShare = 0;
|
||||
DWORD createMode = 0;
|
||||
DWORD mappingProtect = 0;
|
||||
DWORD viewAccess = 0;
|
||||
switch (mode) {
|
||||
case kXEFileModeRead:
|
||||
fileAccess |= GENERIC_READ;
|
||||
fileShare |= FILE_SHARE_READ;
|
||||
createMode |= OPEN_EXISTING;
|
||||
mappingProtect |= PAGE_READONLY;
|
||||
viewAccess |= FILE_MAP_READ;
|
||||
break;
|
||||
case kXEFileModeWrite:
|
||||
fileAccess |= GENERIC_WRITE;
|
||||
fileShare |= 0;
|
||||
createMode |= OPEN_ALWAYS;
|
||||
mappingProtect |= PAGE_READWRITE;
|
||||
viewAccess |= FILE_MAP_WRITE;
|
||||
break;
|
||||
case kXEFileModeRead | kXEFileModeWrite:
|
||||
fileAccess |= GENERIC_READ | GENERIC_WRITE;
|
||||
fileShare |= 0;
|
||||
createMode |= OPEN_EXISTING;
|
||||
mappingProtect |= PAGE_READWRITE;
|
||||
viewAccess |= FILE_MAP_READ | FILE_MAP_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetSystemInfo(&systemInfo);
|
||||
|
||||
const size_t aligned_offset =
|
||||
offset & (~(systemInfo.dwAllocationGranularity - 1));
|
||||
const size_t aligned_length =
|
||||
length + (offset - aligned_offset);
|
||||
|
||||
HANDLE file_handle = CreateFile(
|
||||
path, fileAccess, fileShare, NULL, createMode, FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
XEEXPECTNOTNULL(file_handle);
|
||||
|
||||
HANDLE handle = CreateFileMapping(
|
||||
file_handle, NULL, mappingProtect, 0, 0, NULL);
|
||||
//(DWORD)(aligned_length >> 32), (DWORD)(aligned_length & 0xFFFFFFFF), NULL);
|
||||
XEEXPECTNOTNULL(handle);
|
||||
|
||||
void* address = MapViewOfFile(handle, viewAccess,
|
||||
(DWORD)(aligned_offset >> 32),
|
||||
(DWORD)(aligned_offset & 0xFFFFFFFF),
|
||||
aligned_length);
|
||||
XEEXPECTNOTNULL(address);
|
||||
|
||||
mmap->file_handle = file_handle;
|
||||
mmap->mmap_handle = handle;
|
||||
mmap->addr = address;
|
||||
if (length) {
|
||||
mmap->length = length;
|
||||
} else {
|
||||
DWORD length_high;
|
||||
size_t map_length = GetFileSize(file_handle, &length_high);
|
||||
map_length |= ((uint64_t)length_high) << 32;
|
||||
mmap->length = map_length;
|
||||
}
|
||||
|
||||
return mmap;
|
||||
|
||||
XECLEANUP:
|
||||
xe_mmap_release(mmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void xe_mmap_dealloc(xe_mmap_ref mmap) {
|
||||
if (mmap->addr) {
|
||||
UnmapViewOfFile(mmap->addr);
|
||||
mmap->addr = NULL;
|
||||
}
|
||||
|
||||
if (mmap->mmap_handle) {
|
||||
CloseHandle(mmap->mmap_handle);
|
||||
mmap->mmap_handle = NULL;
|
||||
}
|
||||
|
||||
if (mmap->file_handle) {
|
||||
CloseHandle(mmap->file_handle);
|
||||
mmap->file_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
xe_mmap_ref xe_mmap_retain(xe_mmap_ref mmap) {
|
||||
xe_ref_retain((xe_ref)mmap);
|
||||
return mmap;
|
||||
}
|
||||
|
||||
void xe_mmap_release(xe_mmap_ref mmap) {
|
||||
xe_ref_release((xe_ref)mmap, (xe_ref_dealloc_t)xe_mmap_dealloc);
|
||||
}
|
||||
|
||||
uint8_t* xe_mmap_get_addr(xe_mmap_ref mmap) {
|
||||
return reinterpret_cast<uint8_t*>(mmap->addr);
|
||||
}
|
||||
|
||||
size_t xe_mmap_get_length(xe_mmap_ref mmap) {
|
||||
return mmap->length;
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
'sources': [
|
||||
'hash.cc',
|
||||
'hash.h',
|
||||
'mmap.h',
|
||||
'ref.cc',
|
||||
'ref.h',
|
||||
'run_loop.h',
|
||||
|
@ -13,7 +12,6 @@
|
|||
'conditions': [
|
||||
['OS == "mac" or OS == "linux"', {
|
||||
'sources': [
|
||||
'mmap_posix.cc',
|
||||
'socket_posix.cc',
|
||||
],
|
||||
}],
|
||||
|
@ -27,7 +25,6 @@
|
|||
}],
|
||||
['OS == "win"', {
|
||||
'sources': [
|
||||
'mmap_win.cc',
|
||||
'run_loop_win.cc',
|
||||
'socket_win.cc',
|
||||
],
|
||||
|
|
|
@ -13,35 +13,31 @@
|
|||
#include <xenia/kernel/fs/gdfx.h>
|
||||
#include <xenia/kernel/fs/devices/disc_image_entry.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::fs;
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
DiscImageDevice::DiscImageDevice(const std::string& path,
|
||||
const std::wstring& local_path)
|
||||
: Device(path), local_path_(local_path), mmap_(nullptr), gdfx_(nullptr) {}
|
||||
: Device(path), local_path_(local_path), gdfx_(nullptr) {}
|
||||
|
||||
DiscImageDevice::~DiscImageDevice() {
|
||||
delete gdfx_;
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
DiscImageDevice::~DiscImageDevice() { delete gdfx_; }
|
||||
|
||||
int DiscImageDevice::Init() {
|
||||
mmap_ = xe_mmap_open(kXEFileModeRead, local_path_.c_str(), 0, 0);
|
||||
mmap_ = poly::MappedMemory::Open(local_path_, poly::MappedMemory::Mode::READ);
|
||||
if (!mmap_) {
|
||||
XELOGE("Disc image could not be mapped");
|
||||
return 1;
|
||||
}
|
||||
|
||||
gdfx_ = new GDFX(mmap_);
|
||||
gdfx_ = new GDFX(mmap_.get());
|
||||
GDFX::Error error = gdfx_->Load();
|
||||
if (error != GDFX::kSuccess) {
|
||||
XELOGE("GDFX init failed: %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//gdfx_->Dump();
|
||||
// gdfx_->Dump();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -65,10 +61,10 @@ Entry* DiscImageDevice::ResolvePath(const char* path) {
|
|||
}
|
||||
}
|
||||
|
||||
Entry::Type type = gdfx_entry->attributes & X_FILE_ATTRIBUTE_DIRECTORY ?
|
||||
Entry::kTypeDirectory : Entry::kTypeFile;
|
||||
return new DiscImageEntry(
|
||||
type, this, path, mmap_, gdfx_entry);
|
||||
Entry::Type type = gdfx_entry->attributes & X_FILE_ATTRIBUTE_DIRECTORY
|
||||
? Entry::Type::DIRECTORY
|
||||
: Entry::Type::FILE;
|
||||
return new DiscImageEntry(type, this, path, mmap_.get(), gdfx_entry);
|
||||
}
|
||||
|
||||
X_STATUS DiscImageDevice::QueryVolume(XVolumeInfo* out_info, size_t length) {
|
||||
|
@ -76,7 +72,12 @@ X_STATUS DiscImageDevice::QueryVolume(XVolumeInfo* out_info, size_t length) {
|
|||
return X_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
X_STATUS DiscImageDevice::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
X_STATUS DiscImageDevice::QueryFileSystemAttributes(
|
||||
XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
assert_always();
|
||||
return X_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
#ifndef XENIA_KERNEL_FS_DEVICES_DISC_IMAGE_DEVICE_H_
|
||||
#define XENIA_KERNEL_FS_DEVICES_DISC_IMAGE_DEVICE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <poly/mapped_memory.h>
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/fs/device.h>
|
||||
|
||||
namespace xe {
|
||||
|
@ -38,7 +39,7 @@ class DiscImageDevice : public Device {
|
|||
|
||||
private:
|
||||
std::wstring local_path_;
|
||||
xe_mmap_ref mmap_;
|
||||
std::unique_ptr<poly::MappedMemory> mmap_;
|
||||
GDFX* gdfx_;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,60 +14,45 @@
|
|||
#include <xenia/kernel/fs/gdfx.h>
|
||||
#include <xenia/kernel/fs/devices/disc_image_file.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::fs;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
class DiscImageMemoryMapping : public MemoryMapping {
|
||||
public:
|
||||
DiscImageMemoryMapping(uint8_t* address, size_t length, xe_mmap_ref mmap) :
|
||||
MemoryMapping(address, length) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
}
|
||||
public:
|
||||
DiscImageMemoryMapping(uint8_t* address, size_t length,
|
||||
poly::MappedMemory* mmap)
|
||||
: MemoryMapping(address, length), mmap_(mmap) {}
|
||||
|
||||
virtual ~DiscImageMemoryMapping() {
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
virtual ~DiscImageMemoryMapping() {}
|
||||
|
||||
private:
|
||||
xe_mmap_ref mmap_;
|
||||
private:
|
||||
poly::MappedMemory* mmap_;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
DiscImageEntry::DiscImageEntry(Type type, Device* device, const char* path,
|
||||
xe_mmap_ref mmap, GDFXEntry* gdfx_entry) :
|
||||
gdfx_entry_(gdfx_entry),
|
||||
gdfx_entry_iterator_(gdfx_entry->children.end()),
|
||||
Entry(type, device, path) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
}
|
||||
poly::MappedMemory* mmap, GDFXEntry* gdfx_entry)
|
||||
: gdfx_entry_(gdfx_entry),
|
||||
gdfx_entry_iterator_(gdfx_entry->children.end()),
|
||||
mmap_(mmap),
|
||||
Entry(type, device, path) {}
|
||||
|
||||
DiscImageEntry::~DiscImageEntry() {
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
DiscImageEntry::~DiscImageEntry() {}
|
||||
|
||||
X_STATUS DiscImageEntry::QueryInfo(XFileInfo* out_info) {
|
||||
assert_not_null(out_info);
|
||||
out_info->creation_time = 0;
|
||||
out_info->last_access_time = 0;
|
||||
out_info->last_write_time = 0;
|
||||
out_info->change_time = 0;
|
||||
out_info->allocation_size = 2048;
|
||||
out_info->file_length = gdfx_entry_->size;
|
||||
out_info->attributes = gdfx_entry_->attributes;
|
||||
out_info->creation_time = 0;
|
||||
out_info->last_access_time = 0;
|
||||
out_info->last_write_time = 0;
|
||||
out_info->change_time = 0;
|
||||
out_info->allocation_size = 2048;
|
||||
out_info->file_length = gdfx_entry_->size;
|
||||
out_info->attributes = gdfx_entry_->attributes;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS DiscImageEntry::QueryDirectory(
|
||||
XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart) {
|
||||
X_STATUS DiscImageEntry::QueryDirectory(XDirectoryInfo* out_info, size_t length,
|
||||
const char* file_name, bool restart) {
|
||||
assert_not_null(out_info);
|
||||
|
||||
if (restart == true && gdfx_entry_iterator_ != gdfx_entry_->children.end()) {
|
||||
|
@ -97,40 +82,41 @@ X_STATUS DiscImageEntry::QueryDirectory(
|
|||
}
|
||||
|
||||
out_info->next_entry_offset = 0;
|
||||
out_info->file_index = 0xCDCDCDCD;
|
||||
out_info->creation_time = 0;
|
||||
out_info->last_access_time = 0;
|
||||
out_info->last_write_time = 0;
|
||||
out_info->change_time = 0;
|
||||
out_info->end_of_file = entry->size;
|
||||
out_info->allocation_size = 2048;
|
||||
out_info->attributes = (X_FILE_ATTRIBUTES)entry->attributes;
|
||||
out_info->file_name_length = static_cast<uint32_t>(entry_name.size());
|
||||
out_info->file_index = 0xCDCDCDCD;
|
||||
out_info->creation_time = 0;
|
||||
out_info->last_access_time = 0;
|
||||
out_info->last_write_time = 0;
|
||||
out_info->change_time = 0;
|
||||
out_info->end_of_file = entry->size;
|
||||
out_info->allocation_size = 2048;
|
||||
out_info->attributes = (X_FILE_ATTRIBUTES)entry->attributes;
|
||||
out_info->file_name_length = static_cast<uint32_t>(entry_name.size());
|
||||
memcpy(out_info->file_name, entry_name.c_str(), entry_name.size());
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
MemoryMapping* DiscImageEntry::CreateMemoryMapping(
|
||||
xe_file_mode file_mode, const size_t offset, const size_t length) {
|
||||
if (file_mode & kXEFileModeWrite) {
|
||||
MemoryMapping* DiscImageEntry::CreateMemoryMapping(Mode map_mode,
|
||||
const size_t offset,
|
||||
const size_t length) {
|
||||
if (map_mode != Mode::READ) {
|
||||
// Only allow reads.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t real_offset = gdfx_entry_->offset + offset;
|
||||
size_t real_length = length ?
|
||||
std::min(length, gdfx_entry_->size) : gdfx_entry_->size;
|
||||
return new DiscImageMemoryMapping(
|
||||
xe_mmap_get_addr(mmap_) + real_offset,
|
||||
real_length,
|
||||
mmap_);
|
||||
size_t real_length =
|
||||
length ? std::min(length, gdfx_entry_->size) : gdfx_entry_->size;
|
||||
return new DiscImageMemoryMapping(mmap_->data() + real_offset, real_length,
|
||||
mmap_);
|
||||
}
|
||||
|
||||
X_STATUS DiscImageEntry::Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file) {
|
||||
*out_file = new DiscImageFile(kernel_state, desired_access, this);
|
||||
X_STATUS DiscImageEntry::Open(KernelState* kernel_state, Mode mode,
|
||||
bool async, XFile** out_file) {
|
||||
*out_file = new DiscImageFile(kernel_state, mode, this);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -12,51 +12,45 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <poly/mapped_memory.h>
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/fs/entry.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
class GDFXEntry;
|
||||
|
||||
|
||||
class DiscImageEntry : public Entry {
|
||||
public:
|
||||
public:
|
||||
DiscImageEntry(Type type, Device* device, const char* path,
|
||||
xe_mmap_ref mmap, GDFXEntry* gdfx_entry);
|
||||
poly::MappedMemory* mmap, GDFXEntry* gdfx_entry);
|
||||
virtual ~DiscImageEntry();
|
||||
|
||||
xe_mmap_ref mmap() const { return mmap_; }
|
||||
poly::MappedMemory* mmap() const { return mmap_; }
|
||||
GDFXEntry* gdfx_entry() const { return gdfx_entry_; }
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info);
|
||||
virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info,
|
||||
size_t length, const char* file_name, bool restart);
|
||||
virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length,
|
||||
const char* file_name, bool restart);
|
||||
|
||||
virtual bool can_map() { return true; }
|
||||
virtual MemoryMapping* CreateMemoryMapping(
|
||||
xe_file_mode file_mode, const size_t offset, const size_t length);
|
||||
virtual MemoryMapping* CreateMemoryMapping(Mode map_mode, const size_t offset,
|
||||
const size_t length);
|
||||
|
||||
virtual X_STATUS Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file);
|
||||
virtual X_STATUS Open(KernelState* kernel_state, Mode mode,
|
||||
bool async, XFile** out_file);
|
||||
|
||||
private:
|
||||
xe_mmap_ref mmap_;
|
||||
GDFXEntry* gdfx_entry_;
|
||||
private:
|
||||
poly::MappedMemory* mmap_;
|
||||
GDFXEntry* gdfx_entry_;
|
||||
std::vector<GDFXEntry*>::iterator gdfx_entry_iterator_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_FS_DEVICES_DISC_IMAGE_ENTRY_H_
|
||||
|
|
|
@ -15,39 +15,30 @@
|
|||
#include <xenia/kernel/fs/devices/disc_image_entry.h>
|
||||
#include <xenia/kernel/fs/gdfx.h>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::fs;
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
DiscImageFile::DiscImageFile(KernelState* kernel_state, Mode mode,
|
||||
DiscImageEntry* entry)
|
||||
: entry_(entry), XFile(kernel_state, mode) {}
|
||||
|
||||
DiscImageFile::DiscImageFile(
|
||||
KernelState* kernel_state, uint32_t desired_access,
|
||||
DiscImageEntry* entry) :
|
||||
entry_(entry),
|
||||
XFile(kernel_state, desired_access) {
|
||||
}
|
||||
DiscImageFile::~DiscImageFile() {}
|
||||
|
||||
DiscImageFile::~DiscImageFile() {
|
||||
}
|
||||
|
||||
const std::string& DiscImageFile::path() const {
|
||||
return entry_->path();
|
||||
}
|
||||
const std::string& DiscImageFile::path() const { return entry_->path(); }
|
||||
|
||||
const std::string& DiscImageFile::absolute_path() const {
|
||||
return entry_->absolute_path();
|
||||
}
|
||||
|
||||
const std::string& DiscImageFile::name() const {
|
||||
return entry_->name();
|
||||
}
|
||||
const std::string& DiscImageFile::name() const { return entry_->name(); }
|
||||
|
||||
X_STATUS DiscImageFile::QueryInfo(XFileInfo* out_info) {
|
||||
return entry_->QueryInfo(out_info);
|
||||
}
|
||||
|
||||
X_STATUS DiscImageFile::QueryDirectory(XDirectoryInfo* out_info,
|
||||
size_t length, const char* file_name, bool restart) {
|
||||
X_STATUS DiscImageFile::QueryDirectory(XDirectoryInfo* out_info, size_t length,
|
||||
const char* file_name, bool restart) {
|
||||
return entry_->QueryDirectory(out_info, length, file_name, restart);
|
||||
}
|
||||
|
||||
|
@ -55,23 +46,25 @@ X_STATUS DiscImageFile::QueryVolume(XVolumeInfo* out_info, size_t length) {
|
|||
return entry_->device()->QueryVolume(out_info, length);
|
||||
}
|
||||
|
||||
X_STATUS DiscImageFile::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
X_STATUS DiscImageFile::QueryFileSystemAttributes(
|
||||
XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
return entry_->device()->QueryFileSystemAttributes(out_info, length);
|
||||
}
|
||||
|
||||
X_STATUS DiscImageFile::ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
X_STATUS DiscImageFile::ReadSync(void* buffer, size_t buffer_length,
|
||||
size_t byte_offset, size_t* out_bytes_read) {
|
||||
GDFXEntry* gdfx_entry = entry_->gdfx_entry();
|
||||
xe_mmap_ref mmap = entry_->mmap();
|
||||
if (byte_offset >= gdfx_entry->size) {
|
||||
return X_STATUS_END_OF_FILE;
|
||||
}
|
||||
size_t real_offset = gdfx_entry->offset + byte_offset;
|
||||
size_t real_length = std::min(buffer_length, gdfx_entry->size - byte_offset);
|
||||
xe_copy_memory(
|
||||
buffer, buffer_length,
|
||||
xe_mmap_get_addr(mmap) + real_offset, real_length);
|
||||
xe_copy_memory(buffer, buffer_length, entry_->mmap()->data() + real_offset,
|
||||
real_length);
|
||||
*out_bytes_read = real_length;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/objects/xfile.h>
|
||||
|
||||
namespace xe {
|
||||
|
@ -23,7 +22,7 @@ class DiscImageEntry;
|
|||
|
||||
class DiscImageFile : public XFile {
|
||||
public:
|
||||
DiscImageFile(KernelState* kernel_state, uint32_t desired_access,
|
||||
DiscImageFile(KernelState* kernel_state, Mode desired_access,
|
||||
DiscImageEntry* entry);
|
||||
~DiscImageFile() override;
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
#include <xenia/kernel/fs/devices/host_path_entry.h>
|
||||
#include <xenia/kernel/objects/xfile.h>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::fs;
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
HostPathDevice::HostPathDevice(const std::string& path,
|
||||
const std::wstring& local_path)
|
||||
|
@ -37,7 +37,7 @@ Entry* HostPathDevice::ResolvePath(const char* path) {
|
|||
// TODO(benvanik): fail if does not exit
|
||||
// TODO(benvanik): switch based on type
|
||||
|
||||
Entry::Type type = Entry::kTypeFile;
|
||||
auto type = Entry::Type::FILE;
|
||||
HostPathEntry* entry = new HostPathEntry(type, this, path, full_path);
|
||||
return entry;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ Entry* HostPathDevice::ResolvePath(const char* path) {
|
|||
// TODO(gibbed): call into HostPathDevice?
|
||||
X_STATUS HostPathDevice::QueryVolume(XVolumeInfo* out_info, size_t length) {
|
||||
assert_not_null(out_info);
|
||||
const char* name = "test"; // TODO(gibbed): actual value
|
||||
const char* name = "test"; // TODO(gibbed): actual value
|
||||
|
||||
auto end = (uint8_t*)out_info + length;
|
||||
size_t name_length = strlen(name);
|
||||
|
@ -62,9 +62,10 @@ X_STATUS HostPathDevice::QueryVolume(XVolumeInfo* out_info, size_t length) {
|
|||
}
|
||||
|
||||
// TODO(gibbed): call into HostPathDevice?
|
||||
X_STATUS HostPathDevice::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
X_STATUS HostPathDevice::QueryFileSystemAttributes(
|
||||
XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
assert_not_null(out_info);
|
||||
const char* name = "test"; // TODO(gibbed): actual value
|
||||
const char* name = "test"; // TODO(gibbed): actual value
|
||||
|
||||
auto end = (uint8_t*)out_info + length;
|
||||
size_t name_length = strlen(name);
|
||||
|
@ -73,8 +74,12 @@ X_STATUS HostPathDevice::QueryFileSystemAttributes(XFileSystemAttributeInfo* out
|
|||
}
|
||||
|
||||
out_info->attributes = 0;
|
||||
out_info->maximum_component_name_length = 255; // TODO(gibbed): actual value
|
||||
out_info->maximum_component_name_length = 255; // TODO(gibbed): actual value
|
||||
out_info->fs_name_length = (uint32_t)name_length;
|
||||
memcpy(out_info->fs_name, name, name_length);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/fs/device.h>
|
||||
|
||||
namespace xe {
|
||||
|
|
|
@ -9,33 +9,22 @@
|
|||
|
||||
#include <xenia/kernel/fs/devices/host_path_entry.h>
|
||||
|
||||
#include <poly/mapped_memory.h>
|
||||
#include <xenia/kernel/fs/devices/host_path_file.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::fs;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
class HostPathMemoryMapping : public MemoryMapping {
|
||||
public:
|
||||
HostPathMemoryMapping(uint8_t* address, size_t length, xe_mmap_ref mmap) :
|
||||
MemoryMapping(address, length) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
}
|
||||
virtual ~HostPathMemoryMapping() {
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
private:
|
||||
xe_mmap_ref mmap_;
|
||||
public:
|
||||
HostPathMemoryMapping(std::unique_ptr<poly::MappedMemory> mmap)
|
||||
: MemoryMapping(mmap->data(), mmap->size()), mmap_(std::move(mmap)) {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<poly::MappedMemory> mmap_;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
HostPathEntry::HostPathEntry(Type type, Device* device, const char* path,
|
||||
const std::wstring& local_path)
|
||||
: Entry(type, device, path),
|
||||
|
@ -54,24 +43,23 @@ X_STATUS HostPathEntry::QueryInfo(XFileInfo* out_info) {
|
|||
assert_not_null(out_info);
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||
if (!GetFileAttributesEx(
|
||||
local_path_.c_str(), GetFileExInfoStandard, &data)) {
|
||||
if (!GetFileAttributesEx(local_path_.c_str(), GetFileExInfoStandard, &data)) {
|
||||
return X_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
out_info->creation_time = COMBINE_TIME(data.ftCreationTime);
|
||||
out_info->last_access_time = COMBINE_TIME(data.ftLastAccessTime);
|
||||
out_info->last_write_time = COMBINE_TIME(data.ftLastWriteTime);
|
||||
out_info->change_time = COMBINE_TIME(data.ftLastWriteTime);
|
||||
out_info->allocation_size = 4096;
|
||||
out_info->file_length =
|
||||
out_info->creation_time = COMBINE_TIME(data.ftCreationTime);
|
||||
out_info->last_access_time = COMBINE_TIME(data.ftLastAccessTime);
|
||||
out_info->last_write_time = COMBINE_TIME(data.ftLastWriteTime);
|
||||
out_info->change_time = COMBINE_TIME(data.ftLastWriteTime);
|
||||
out_info->allocation_size = 4096;
|
||||
out_info->file_length =
|
||||
((uint64_t)data.nFileSizeHigh << 32) | data.nFileSizeLow;
|
||||
out_info->attributes = (X_FILE_ATTRIBUTES)data.dwFileAttributes;
|
||||
out_info->attributes = (X_FILE_ATTRIBUTES)data.dwFileAttributes;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS HostPathEntry::QueryDirectory(
|
||||
XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart) {
|
||||
X_STATUS HostPathEntry::QueryDirectory(XDirectoryInfo* out_info, size_t length,
|
||||
const char* file_name, bool restart) {
|
||||
assert_not_null(out_info);
|
||||
|
||||
WIN32_FIND_DATA ffd;
|
||||
|
@ -97,8 +85,7 @@ X_STATUS HostPathEntry::QueryDirectory(
|
|||
}
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (FindNextFile(handle, &ffd) == FALSE) {
|
||||
FindClose(handle);
|
||||
find_file_ = INVALID_HANDLE_VALUE;
|
||||
|
@ -115,62 +102,62 @@ X_STATUS HostPathEntry::QueryDirectory(
|
|||
}
|
||||
|
||||
out_info->next_entry_offset = 0;
|
||||
out_info->file_index = 0xCDCDCDCD;
|
||||
out_info->creation_time = COMBINE_TIME(ffd.ftCreationTime);
|
||||
out_info->last_access_time = COMBINE_TIME(ffd.ftLastAccessTime);
|
||||
out_info->last_write_time = COMBINE_TIME(ffd.ftLastWriteTime);
|
||||
out_info->change_time = COMBINE_TIME(ffd.ftLastWriteTime);
|
||||
out_info->end_of_file =
|
||||
out_info->file_index = 0xCDCDCDCD;
|
||||
out_info->creation_time = COMBINE_TIME(ffd.ftCreationTime);
|
||||
out_info->last_access_time = COMBINE_TIME(ffd.ftLastAccessTime);
|
||||
out_info->last_write_time = COMBINE_TIME(ffd.ftLastWriteTime);
|
||||
out_info->change_time = COMBINE_TIME(ffd.ftLastWriteTime);
|
||||
out_info->end_of_file =
|
||||
((uint64_t)ffd.nFileSizeHigh << 32) | ffd.nFileSizeLow;
|
||||
out_info->allocation_size = 4096;
|
||||
out_info->attributes = (X_FILE_ATTRIBUTES)ffd.dwFileAttributes;
|
||||
out_info->allocation_size = 4096;
|
||||
out_info->attributes = (X_FILE_ATTRIBUTES)ffd.dwFileAttributes;
|
||||
|
||||
out_info->file_name_length = (uint32_t)entry_name_length;
|
||||
out_info->file_name_length = (uint32_t)entry_name_length;
|
||||
for (size_t i = 0; i < entry_name_length; ++i) {
|
||||
out_info->file_name[i] =
|
||||
ffd.cFileName[i] < 256 ? (char)ffd.cFileName[i] : '?';
|
||||
out_info->file_name[i] =
|
||||
ffd.cFileName[i] < 256 ? (char)ffd.cFileName[i] : '?';
|
||||
}
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
MemoryMapping* HostPathEntry::CreateMemoryMapping(xe_file_mode file_mode,
|
||||
MemoryMapping* HostPathEntry::CreateMemoryMapping(Mode map_mode,
|
||||
const size_t offset,
|
||||
const size_t length) {
|
||||
xe_mmap_ref mmap =
|
||||
xe_mmap_open(file_mode, local_path_.c_str(), offset, length);
|
||||
auto mmap = poly::MappedMemory::Open(
|
||||
local_path_,
|
||||
map_mode == Mode::READ ? poly::MappedMemory::Mode::READ
|
||||
: poly::MappedMemory::Mode::READ_WRITE,
|
||||
offset, length);
|
||||
if (!mmap) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HostPathMemoryMapping* lfmm = new HostPathMemoryMapping(
|
||||
(uint8_t*)xe_mmap_get_addr(mmap), xe_mmap_get_length(mmap),
|
||||
mmap);
|
||||
xe_mmap_release(mmap);
|
||||
HostPathMemoryMapping* lfmm = new HostPathMemoryMapping(std::move(mmap));
|
||||
|
||||
return lfmm;
|
||||
}
|
||||
|
||||
X_STATUS HostPathEntry::Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file) {
|
||||
X_STATUS HostPathEntry::Open(KernelState* kernel_state, Mode mode,
|
||||
bool async, XFile** out_file) {
|
||||
DWORD desired_access =
|
||||
mode == Mode::READ ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
|
||||
DWORD share_mode = FILE_SHARE_READ;
|
||||
DWORD creation_disposition = OPEN_EXISTING;
|
||||
DWORD flags_and_attributes = async ? FILE_FLAG_OVERLAPPED : 0;
|
||||
HANDLE file = CreateFile(
|
||||
local_path_.c_str(),
|
||||
desired_access,
|
||||
share_mode,
|
||||
NULL,
|
||||
creation_disposition,
|
||||
flags_and_attributes | FILE_FLAG_BACKUP_SEMANTICS,
|
||||
NULL);
|
||||
HANDLE file =
|
||||
CreateFile(local_path_.c_str(), desired_access, share_mode, NULL,
|
||||
creation_disposition,
|
||||
flags_and_attributes | FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
// TODO(benvanik): pick correct response.
|
||||
return X_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
*out_file = new HostPathFile(kernel_state, desired_access, this, file);
|
||||
*out_file = new HostPathFile(kernel_state, mode, this, file);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/fs/entry.h>
|
||||
|
||||
namespace xe {
|
||||
|
@ -32,12 +31,11 @@ class HostPathEntry : public Entry {
|
|||
const char* file_name, bool restart);
|
||||
|
||||
virtual bool can_map() { return true; }
|
||||
virtual MemoryMapping* CreateMemoryMapping(xe_file_mode file_mode,
|
||||
const size_t offset,
|
||||
virtual MemoryMapping* CreateMemoryMapping(Mode map_mode, const size_t offset,
|
||||
const size_t length);
|
||||
|
||||
virtual X_STATUS Open(KernelState* kernel_state, uint32_t desired_access,
|
||||
bool async, XFile** out_file);
|
||||
virtual X_STATUS Open(KernelState* kernel_state, Mode mode, bool async,
|
||||
XFile** out_file);
|
||||
|
||||
private:
|
||||
std::wstring local_path_;
|
||||
|
|
|
@ -9,44 +9,35 @@
|
|||
|
||||
#include <xenia/kernel/fs/devices/host_path_file.h>
|
||||
|
||||
#include <xenia/kernel/fs/device.h>
|
||||
#include <xenia/kernel/fs/devices/host_path_entry.h>
|
||||
|
||||
#include <xenia/kernel/fs/device.h>
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::fs;
|
||||
HostPathFile::HostPathFile(KernelState* kernel_state, Mode mode,
|
||||
HostPathEntry* entry, HANDLE file_handle)
|
||||
: entry_(entry),
|
||||
file_handle_(file_handle),
|
||||
XFile(kernel_state, mode) {}
|
||||
|
||||
HostPathFile::~HostPathFile() { CloseHandle(file_handle_); }
|
||||
|
||||
HostPathFile::HostPathFile(
|
||||
KernelState* kernel_state, uint32_t desired_access,
|
||||
HostPathEntry* entry, HANDLE file_handle) :
|
||||
entry_(entry), file_handle_(file_handle),
|
||||
XFile(kernel_state, desired_access) {
|
||||
}
|
||||
|
||||
HostPathFile::~HostPathFile() {
|
||||
CloseHandle(file_handle_);
|
||||
}
|
||||
|
||||
const std::string& HostPathFile::path() const {
|
||||
return entry_->path();
|
||||
}
|
||||
const std::string& HostPathFile::path() const { return entry_->path(); }
|
||||
|
||||
const std::string& HostPathFile::absolute_path() const {
|
||||
return entry_->absolute_path();
|
||||
}
|
||||
|
||||
const std::string& HostPathFile::name() const {
|
||||
return entry_->name();
|
||||
}
|
||||
const std::string& HostPathFile::name() const { return entry_->name(); }
|
||||
|
||||
X_STATUS HostPathFile::QueryInfo(XFileInfo* out_info) {
|
||||
return entry_->QueryInfo(out_info);
|
||||
}
|
||||
|
||||
X_STATUS HostPathFile::QueryDirectory(XDirectoryInfo* out_info,
|
||||
size_t length, const char* file_name, bool restart) {
|
||||
X_STATUS HostPathFile::QueryDirectory(XDirectoryInfo* out_info, size_t length,
|
||||
const char* file_name, bool restart) {
|
||||
return entry_->QueryDirectory(out_info, length, file_name, restart);
|
||||
}
|
||||
|
||||
|
@ -54,19 +45,19 @@ X_STATUS HostPathFile::QueryVolume(XVolumeInfo* out_info, size_t length) {
|
|||
return entry_->device()->QueryVolume(out_info, length);
|
||||
}
|
||||
|
||||
X_STATUS HostPathFile::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
X_STATUS HostPathFile::QueryFileSystemAttributes(
|
||||
XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
return entry_->device()->QueryFileSystemAttributes(out_info, length);
|
||||
}
|
||||
|
||||
X_STATUS HostPathFile::ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
X_STATUS HostPathFile::ReadSync(void* buffer, size_t buffer_length,
|
||||
size_t byte_offset, size_t* out_bytes_read) {
|
||||
OVERLAPPED overlapped;
|
||||
overlapped.Pointer = (PVOID)byte_offset;
|
||||
overlapped.hEvent = NULL;
|
||||
DWORD bytes_read = 0;
|
||||
BOOL read = ReadFile(
|
||||
file_handle_, buffer, (DWORD)buffer_length, &bytes_read, &overlapped);
|
||||
BOOL read = ReadFile(file_handle_, buffer, (DWORD)buffer_length, &bytes_read,
|
||||
&overlapped);
|
||||
if (read) {
|
||||
*out_bytes_read = bytes_read;
|
||||
return X_STATUS_SUCCESS;
|
||||
|
@ -74,3 +65,7 @@ X_STATUS HostPathFile::ReadSync(
|
|||
return X_STATUS_END_OF_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/objects/xfile.h>
|
||||
|
||||
namespace xe {
|
||||
|
@ -25,8 +24,8 @@ class HostPathEntry;
|
|||
|
||||
class HostPathFile : public XFile {
|
||||
public:
|
||||
HostPathFile(KernelState* kernel_state, uint32_t desired_access,
|
||||
HostPathEntry* entry, HANDLE file_handle);
|
||||
HostPathFile(KernelState* kernel_state, Mode mode, HostPathEntry* entry,
|
||||
HANDLE file_handle);
|
||||
~HostPathFile() override;
|
||||
|
||||
const std::string& path() const override;
|
||||
|
|
|
@ -13,28 +13,24 @@
|
|||
#include <xenia/kernel/fs/stfs.h>
|
||||
#include <xenia/kernel/fs/devices/stfs_container_entry.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::fs;
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
STFSContainerDevice::STFSContainerDevice(const std::string& path,
|
||||
const std::wstring& local_path)
|
||||
: Device(path), local_path_(local_path), mmap_(nullptr), stfs_(nullptr) {}
|
||||
: Device(path), local_path_(local_path), stfs_(nullptr) {}
|
||||
|
||||
STFSContainerDevice::~STFSContainerDevice() {
|
||||
delete stfs_;
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
STFSContainerDevice::~STFSContainerDevice() { delete stfs_; }
|
||||
|
||||
int STFSContainerDevice::Init() {
|
||||
mmap_ = xe_mmap_open(kXEFileModeRead, local_path_.c_str(), 0, 0);
|
||||
mmap_ = poly::MappedMemory::Open(local_path_, poly::MappedMemory::Mode::READ);
|
||||
if (!mmap_) {
|
||||
XELOGE("STFS container could not be mapped");
|
||||
return 1;
|
||||
}
|
||||
|
||||
stfs_ = new STFS(mmap_);
|
||||
stfs_ = new STFS(mmap_.get());
|
||||
STFS::Error error = stfs_->Load();
|
||||
if (error != STFS::kSuccess) {
|
||||
XELOGE("STFS init failed: %d", error);
|
||||
|
@ -65,19 +61,24 @@ Entry* STFSContainerDevice::ResolvePath(const char* path) {
|
|||
}
|
||||
}
|
||||
|
||||
Entry::Type type = stfs_entry->attributes & X_FILE_ATTRIBUTE_DIRECTORY ?
|
||||
Entry::kTypeDirectory : Entry::kTypeFile;
|
||||
return new STFSContainerEntry(
|
||||
type, this, path, mmap_, stfs_entry);
|
||||
Entry::Type type = stfs_entry->attributes & X_FILE_ATTRIBUTE_DIRECTORY
|
||||
? Entry::Type::DIRECTORY
|
||||
: Entry::Type::FILE;
|
||||
return new STFSContainerEntry(type, this, path, mmap_.get(), stfs_entry);
|
||||
}
|
||||
|
||||
|
||||
X_STATUS STFSContainerDevice::QueryVolume(XVolumeInfo* out_info, size_t length) {
|
||||
X_STATUS STFSContainerDevice::QueryVolume(XVolumeInfo* out_info,
|
||||
size_t length) {
|
||||
assert_always();
|
||||
return X_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
X_STATUS STFSContainerDevice::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
X_STATUS STFSContainerDevice::QueryFileSystemAttributes(
|
||||
XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
assert_always();
|
||||
return X_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
#ifndef XENIA_KERNEL_FS_DEVICES_STFS_CONTAINER_DEVICE_H_
|
||||
#define XENIA_KERNEL_FS_DEVICES_STFS_CONTAINER_DEVICE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <poly/mapped_memory.h>
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/fs/device.h>
|
||||
|
||||
namespace xe {
|
||||
|
@ -38,7 +39,7 @@ class STFSContainerDevice : public Device {
|
|||
|
||||
private:
|
||||
std::wstring local_path_;
|
||||
xe_mmap_ref mmap_;
|
||||
std::unique_ptr<poly::MappedMemory> mmap_;
|
||||
STFS* stfs_;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,39 +12,37 @@
|
|||
#include <xenia/kernel/fs/stfs.h>
|
||||
#include <xenia/kernel/fs/devices/stfs_container_file.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::fs;
|
||||
STFSContainerEntry::STFSContainerEntry(Type type, Device* device,
|
||||
const char* path,
|
||||
poly::MappedMemory* mmap,
|
||||
STFSEntry* stfs_entry)
|
||||
: stfs_entry_(stfs_entry),
|
||||
stfs_entry_iterator_(stfs_entry->children.end()),
|
||||
mmap_(mmap),
|
||||
Entry(type, device, path) {}
|
||||
|
||||
|
||||
STFSContainerEntry::STFSContainerEntry(
|
||||
Type type, Device* device, const char* path,
|
||||
xe_mmap_ref mmap, STFSEntry* stfs_entry) :
|
||||
stfs_entry_(stfs_entry),
|
||||
stfs_entry_iterator_(stfs_entry->children.end()),
|
||||
Entry(type, device, path) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
}
|
||||
|
||||
STFSContainerEntry::~STFSContainerEntry() {
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
STFSContainerEntry::~STFSContainerEntry() {}
|
||||
|
||||
X_STATUS STFSContainerEntry::QueryInfo(XFileInfo* out_info) {
|
||||
assert_not_null(out_info);
|
||||
out_info->creation_time = stfs_entry_->update_timestamp;
|
||||
out_info->last_access_time = stfs_entry_->access_timestamp;
|
||||
out_info->last_write_time = stfs_entry_->update_timestamp;
|
||||
out_info->change_time = stfs_entry_->update_timestamp;
|
||||
out_info->allocation_size = 4096;
|
||||
out_info->file_length = stfs_entry_->size;
|
||||
out_info->attributes = stfs_entry_->attributes;
|
||||
out_info->creation_time = stfs_entry_->update_timestamp;
|
||||
out_info->last_access_time = stfs_entry_->access_timestamp;
|
||||
out_info->last_write_time = stfs_entry_->update_timestamp;
|
||||
out_info->change_time = stfs_entry_->update_timestamp;
|
||||
out_info->allocation_size = 4096;
|
||||
out_info->file_length = stfs_entry_->size;
|
||||
out_info->attributes = stfs_entry_->attributes;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS STFSContainerEntry::QueryDirectory(
|
||||
XDirectoryInfo* out_info, size_t length, const char* file_name, bool restart) {
|
||||
X_STATUS STFSContainerEntry::QueryDirectory(XDirectoryInfo* out_info,
|
||||
size_t length,
|
||||
const char* file_name,
|
||||
bool restart) {
|
||||
assert_not_null(out_info);
|
||||
|
||||
if (restart && stfs_entry_iterator_ != stfs_entry_->children.end()) {
|
||||
|
@ -73,24 +71,26 @@ X_STATUS STFSContainerEntry::QueryDirectory(
|
|||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
out_info->file_index = 0xCDCDCDCD;
|
||||
out_info->creation_time = entry->update_timestamp;
|
||||
out_info->file_index = 0xCDCDCDCD;
|
||||
out_info->creation_time = entry->update_timestamp;
|
||||
out_info->last_access_time = entry->access_timestamp;
|
||||
out_info->last_write_time = entry->update_timestamp;
|
||||
out_info->change_time = entry->update_timestamp;
|
||||
out_info->end_of_file = entry->size;
|
||||
out_info->allocation_size = 4096;
|
||||
out_info->attributes = entry->attributes;
|
||||
out_info->last_write_time = entry->update_timestamp;
|
||||
out_info->change_time = entry->update_timestamp;
|
||||
out_info->end_of_file = entry->size;
|
||||
out_info->allocation_size = 4096;
|
||||
out_info->attributes = entry->attributes;
|
||||
out_info->file_name_length = static_cast<uint32_t>(entry_name.size());
|
||||
memcpy(out_info->file_name, entry_name.c_str(), entry_name.size());
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS STFSContainerEntry::Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file) {
|
||||
*out_file = new STFSContainerFile(kernel_state, desired_access, this);
|
||||
X_STATUS STFSContainerEntry::Open(KernelState* kernel_state, Mode mode,
|
||||
bool async, XFile** out_file) {
|
||||
*out_file = new STFSContainerFile(kernel_state, mode, this);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -12,47 +12,41 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <poly/mapped_memory.h>
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/kernel/fs/entry.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
class STFSEntry;
|
||||
|
||||
|
||||
class STFSContainerEntry : public Entry {
|
||||
public:
|
||||
public:
|
||||
STFSContainerEntry(Type type, Device* device, const char* path,
|
||||
xe_mmap_ref mmap, STFSEntry* stfs_entry);
|
||||
poly::MappedMemory* mmap, STFSEntry* stfs_entry);
|
||||
virtual ~STFSContainerEntry();
|
||||
|
||||
xe_mmap_ref mmap() const { return mmap_; }
|
||||
poly::MappedMemory* mmap() const { return mmap_; }
|
||||
STFSEntry* stfs_entry() const { return stfs_entry_; }
|
||||
|
||||
virtual X_STATUS QueryInfo(XFileInfo* out_info);
|
||||
virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info,
|
||||
size_t length, const char* file_name, bool restart);
|
||||
virtual X_STATUS QueryDirectory(XDirectoryInfo* out_info, size_t length,
|
||||
const char* file_name, bool restart);
|
||||
|
||||
virtual X_STATUS Open(
|
||||
KernelState* kernel_state,
|
||||
uint32_t desired_access, bool async,
|
||||
XFile** out_file);
|
||||
virtual X_STATUS Open(KernelState* kernel_state, Mode desired_access,
|
||||
bool async, XFile** out_file);
|
||||
|
||||
private:
|
||||
xe_mmap_ref mmap_;
|
||||
STFSEntry* stfs_entry_;
|
||||
private:
|
||||
poly::MappedMemory* mmap_;
|
||||
STFSEntry* stfs_entry_;
|
||||
std::vector<std::unique_ptr<STFSEntry>>::iterator stfs_entry_iterator_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_FS_DEVICES_STFS_CONTAINER_ENTRY_H_
|
||||
|
|
|
@ -15,39 +15,31 @@
|
|||
#include <xenia/kernel/fs/devices/stfs_container_entry.h>
|
||||
#include <xenia/kernel/fs/stfs.h>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
using namespace xe::kernel::fs;
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace fs {
|
||||
|
||||
STFSContainerFile::STFSContainerFile(KernelState* kernel_state, Mode mode,
|
||||
STFSContainerEntry* entry)
|
||||
: entry_(entry), XFile(kernel_state, mode) {}
|
||||
|
||||
STFSContainerFile::STFSContainerFile(
|
||||
KernelState* kernel_state, uint32_t desired_access,
|
||||
STFSContainerEntry* entry) :
|
||||
entry_(entry),
|
||||
XFile(kernel_state, desired_access) {
|
||||
}
|
||||
STFSContainerFile::~STFSContainerFile() {}
|
||||
|
||||
STFSContainerFile::~STFSContainerFile() {
|
||||
}
|
||||
|
||||
const std::string& STFSContainerFile::path() const {
|
||||
return entry_->path();
|
||||
}
|
||||
const std::string& STFSContainerFile::path() const { return entry_->path(); }
|
||||
|
||||
const std::string& STFSContainerFile::absolute_path() const {
|
||||
return entry_->absolute_path();
|
||||
}
|
||||
|
||||
const std::string& STFSContainerFile::name() const {
|
||||
return entry_->name();
|
||||
}
|
||||
const std::string& STFSContainerFile::name() const { return entry_->name(); }
|
||||
|
||||
X_STATUS STFSContainerFile::QueryInfo(XFileInfo* out_info) {
|
||||
return entry_->QueryInfo(out_info);
|
||||
}
|
||||
|
||||
X_STATUS STFSContainerFile::QueryDirectory(XDirectoryInfo* out_info,
|
||||
size_t length, const char* file_name, bool restart) {
|
||||
size_t length, const char* file_name,
|
||||
bool restart) {
|
||||
return entry_->QueryDirectory(out_info, length, file_name, restart);
|
||||
}
|
||||
|
||||
|
@ -55,16 +47,15 @@ X_STATUS STFSContainerFile::QueryVolume(XVolumeInfo* out_info, size_t length) {
|
|||
return entry_->device()->QueryVolume(out_info, length);
|
||||
}
|
||||
|
||||
X_STATUS STFSContainerFile::QueryFileSystemAttributes(XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
X_STATUS STFSContainerFile::QueryFileSystemAttributes(
|
||||
XFileSystemAttributeInfo* out_info, size_t length) {
|
||||
return entry_->device()->QueryFileSystemAttributes(out_info, length);
|
||||
}
|
||||
|
||||
X_STATUS STFSContainerFile::ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
X_STATUS STFSContainerFile::ReadSync(void* buffer, size_t buffer_length,
|
||||
size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
STFSEntry* stfs_entry = entry_->stfs_entry();
|
||||
xe_mmap_ref mmap = entry_->mmap();
|
||||
uint8_t* map_ptr = xe_mmap_get_addr(mmap);
|
||||
if (byte_offset >= stfs_entry->size) {
|
||||
return X_STATUS_END_OF_FILE;
|
||||
}
|
||||
|
@ -87,10 +78,14 @@ X_STATUS STFSContainerFile::ReadSync(
|
|||
offset += byte_offset % 4096;
|
||||
read_length = std::min(read_length, record.length - (byte_offset % 4096));
|
||||
}
|
||||
xe_copy_struct(dest_ptr, map_ptr + offset, read_length);
|
||||
xe_copy_struct(dest_ptr, entry_->mmap()->data() + offset, read_length);
|
||||
dest_ptr += read_length;
|
||||
remaining_length -= read_length;
|
||||
}
|
||||
*out_bytes_read = real_length;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace fs
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -23,7 +23,7 @@ class STFSContainerEntry;
|
|||
|
||||
class STFSContainerFile : public XFile {
|
||||
public:
|
||||
STFSContainerFile(KernelState* kernel_state, uint32_t desired_access,
|
||||
STFSContainerFile(KernelState* kernel_state, Mode mode,
|
||||
STFSContainerEntry* entry);
|
||||
~STFSContainerFile() override;
|
||||
|
||||
|
|
|
@ -32,6 +32,11 @@ namespace fs {
|
|||
|
||||
class Device;
|
||||
|
||||
enum class Mode {
|
||||
READ,
|
||||
READ_WRITE,
|
||||
};
|
||||
|
||||
class MemoryMapping {
|
||||
public:
|
||||
MemoryMapping(uint8_t* address, size_t length);
|
||||
|
@ -47,9 +52,9 @@ class MemoryMapping {
|
|||
|
||||
class Entry {
|
||||
public:
|
||||
enum Type {
|
||||
kTypeFile,
|
||||
kTypeDirectory,
|
||||
enum class Type {
|
||||
FILE,
|
||||
DIRECTORY,
|
||||
};
|
||||
|
||||
Entry(Type type, Device* device, const std::string& path);
|
||||
|
@ -66,14 +71,14 @@ class Entry {
|
|||
const char* file_name, bool restart) = 0;
|
||||
|
||||
virtual bool can_map() { return false; }
|
||||
virtual MemoryMapping* CreateMemoryMapping(xe_file_mode file_mode,
|
||||
const size_t offset,
|
||||
|
||||
virtual MemoryMapping* CreateMemoryMapping(Mode map_mode, const size_t offset,
|
||||
const size_t length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual X_STATUS Open(KernelState* kernel_state, uint32_t desired_access,
|
||||
bool async, XFile** out_file) = 0;
|
||||
virtual X_STATUS Open(KernelState* kernel_state, Mode mode, bool async,
|
||||
XFile** out_file) = 0;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
|
|
|
@ -50,16 +50,12 @@ void GDFXEntry::Dump(int indent) {
|
|||
}
|
||||
}
|
||||
|
||||
GDFX::GDFX(xe_mmap_ref mmap) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
|
||||
root_entry_ = NULL;
|
||||
GDFX::GDFX(poly::MappedMemory* mmap) : mmap_(mmap) {
|
||||
root_entry_ = nullptr;
|
||||
}
|
||||
|
||||
GDFX::~GDFX() {
|
||||
delete root_entry_;
|
||||
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
|
||||
GDFXEntry* GDFX::root_entry() { return root_entry_; }
|
||||
|
@ -68,8 +64,8 @@ GDFX::Error GDFX::Load() {
|
|||
ParseState state;
|
||||
xe_zero_struct(&state, sizeof(state));
|
||||
|
||||
state.ptr = (uint8_t*)xe_mmap_get_addr(mmap_);
|
||||
state.size = xe_mmap_get_length(mmap_);
|
||||
state.ptr = mmap_->data();
|
||||
state.size = mmap_->size();
|
||||
|
||||
auto result = Verify(state);
|
||||
if (result != kSuccess) {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <poly/mapped_memory.h>
|
||||
#include <xenia/core.h>
|
||||
#include <xenia/xbox.h>
|
||||
#include <xenia/kernel/fs/entry.h>
|
||||
|
@ -49,7 +50,7 @@ class GDFX {
|
|||
kErrorDamagedFile = -31,
|
||||
};
|
||||
|
||||
GDFX(xe_mmap_ref mmap);
|
||||
GDFX(poly::MappedMemory* mmap);
|
||||
virtual ~GDFX();
|
||||
|
||||
GDFXEntry* root_entry();
|
||||
|
@ -81,7 +82,7 @@ class GDFX {
|
|||
bool ReadEntry(ParseState& state, const uint8_t* buffer,
|
||||
uint16_t entry_ordinal, GDFXEntry* parent);
|
||||
|
||||
xe_mmap_ref mmap_;
|
||||
poly::MappedMemory* mmap_;
|
||||
|
||||
GDFXEntry* root_entry_;
|
||||
};
|
||||
|
|
|
@ -117,17 +117,12 @@ void STFSEntry::Dump(int indent) {
|
|||
}
|
||||
}
|
||||
|
||||
STFS::STFS(xe_mmap_ref mmap) {
|
||||
mmap_ = xe_mmap_retain(mmap);
|
||||
}
|
||||
STFS::STFS(poly::MappedMemory* mmap) : mmap_(mmap) {}
|
||||
|
||||
STFS::~STFS() {
|
||||
xe_mmap_release(mmap_);
|
||||
}
|
||||
STFS::~STFS() {}
|
||||
|
||||
STFS::Error STFS::Load() {
|
||||
uint8_t* map_ptr = (uint8_t*)xe_mmap_get_addr(mmap_);
|
||||
size_t map_size = xe_mmap_get_length(mmap_);
|
||||
uint8_t* map_ptr = mmap_->data();
|
||||
|
||||
auto result = ReadHeaderAndVerify(map_ptr);
|
||||
if (result != kSuccess) {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <poly/mapped_memory.h>
|
||||
#include <xenia/core.h>
|
||||
#include <xenia/xbox.h>
|
||||
#include <xenia/kernel/fs/entry.h>
|
||||
|
@ -160,7 +161,7 @@ class STFS {
|
|||
kErrorDamagedFile = -31,
|
||||
};
|
||||
|
||||
STFS(xe_mmap_ref mmap);
|
||||
STFS(poly::MappedMemory* mmap);
|
||||
virtual ~STFS();
|
||||
|
||||
const STFSHeader* header() const { return &header_; }
|
||||
|
@ -182,7 +183,7 @@ class STFS {
|
|||
BlockHash_t GetBlockHash(const uint8_t* map_ptr, uint32_t block_index,
|
||||
uint32_t table_offset);
|
||||
|
||||
xe_mmap_ref mmap_;
|
||||
poly::MappedMemory* mmap_;
|
||||
|
||||
STFSPackageType package_type_;
|
||||
STFSHeader header_;
|
||||
|
|
|
@ -17,8 +17,8 @@ using namespace xe;
|
|||
using namespace xe::kernel;
|
||||
|
||||
|
||||
XFile::XFile(KernelState* kernel_state, uint32_t desired_access) :
|
||||
desired_access_(desired_access), position_(0),
|
||||
XFile::XFile(KernelState* kernel_state, fs::Mode mode) :
|
||||
mode_(mode), position_(0),
|
||||
XObject(kernel_state, kTypeFile) {
|
||||
async_event_ = new XEvent(kernel_state);
|
||||
async_event_->Initialize(false, false);
|
||||
|
|
|
@ -149,13 +149,13 @@ public:
|
|||
virtual void* GetWaitHandle();
|
||||
|
||||
protected:
|
||||
XFile(KernelState* kernel_state, uint32_t desired_access);
|
||||
XFile(KernelState* kernel_state, fs::Mode mode);
|
||||
virtual X_STATUS ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) = 0;
|
||||
|
||||
private:
|
||||
uint32_t desired_access_;
|
||||
fs::Mode mode_;
|
||||
XEvent* async_event_;
|
||||
|
||||
// TODO(benvanik): create flags, open state, etc.
|
||||
|
|
|
@ -50,7 +50,7 @@ X_STATUS XUserModule::LoadFromFile(const char* path) {
|
|||
result = X_STATUS_NO_SUCH_FILE;
|
||||
XEFAIL();
|
||||
}
|
||||
if (fs_entry->type() != fs::Entry::kTypeFile) {
|
||||
if (fs_entry->type() != fs::Entry::Type::FILE) {
|
||||
XELOGE("Invalid file type: %s", path);
|
||||
result = X_STATUS_NO_SUCH_FILE;
|
||||
XEFAIL();
|
||||
|
@ -59,7 +59,8 @@ X_STATUS XUserModule::LoadFromFile(const char* path) {
|
|||
// If the FS supports mapping, map the file in and load from that.
|
||||
if (fs_entry->can_map()) {
|
||||
// Map.
|
||||
fs::MemoryMapping* mmap = fs_entry->CreateMemoryMapping(kXEFileModeRead, 0, 0);
|
||||
fs::MemoryMapping* mmap =
|
||||
fs_entry->CreateMemoryMapping(fs::Mode::READ, 0, 0);
|
||||
XEEXPECTNOTNULL(mmap);
|
||||
|
||||
// Load the module.
|
||||
|
@ -76,7 +77,7 @@ X_STATUS XUserModule::LoadFromFile(const char* path) {
|
|||
buffer = (uint8_t*)xe_malloc(buffer_length);
|
||||
|
||||
// Open file for reading.
|
||||
result = fs_entry->Open(kernel_state(), kXEFileModeRead, false, &file);
|
||||
result = fs_entry->Open(kernel_state(), fs::Mode::READ, false, &file);
|
||||
XEEXPECTZERO(result);
|
||||
|
||||
// Read entire file into memory.
|
||||
|
|
|
@ -81,12 +81,15 @@ SHIM_CALL NtCreateFile_shim(
|
|||
entry = fs->ResolvePath(object_name);
|
||||
}
|
||||
|
||||
auto mode =
|
||||
desired_access & GENERIC_WRITE ? fs::Mode::READ_WRITE : fs::Mode::READ;
|
||||
|
||||
XFile* file = NULL;
|
||||
if (entry && entry->type() == Entry::kTypeFile) {
|
||||
if (entry && entry->type() == Entry::Type::FILE) {
|
||||
// Open the file.
|
||||
result = entry->Open(
|
||||
state,
|
||||
desired_access,
|
||||
mode,
|
||||
false, // TODO(benvanik): pick async mode, if needed.
|
||||
&file);
|
||||
} else {
|
||||
|
@ -150,15 +153,18 @@ SHIM_CALL NtOpenFile_shim(
|
|||
assert_always();
|
||||
}
|
||||
|
||||
auto mode =
|
||||
desired_access & GENERIC_WRITE ? fs::Mode::READ_WRITE : fs::Mode::READ;
|
||||
|
||||
// Resolve the file using the virtual file system.
|
||||
FileSystem* fs = state->file_system();
|
||||
Entry* entry = fs->ResolvePath(object_name);
|
||||
XFile* file = NULL;
|
||||
if (entry && entry->type() == Entry::kTypeFile) {
|
||||
if (entry && entry->type() == Entry::Type::FILE) {
|
||||
// Open the file.
|
||||
result = entry->Open(
|
||||
state,
|
||||
desired_access,
|
||||
mode,
|
||||
false, // TODO(benvanik): pick async mode, if needed.
|
||||
&file);
|
||||
}
|
||||
|
@ -495,7 +501,7 @@ SHIM_CALL NtQueryFullAttributesFile_shim(
|
|||
// Resolve the file using the virtual file system.
|
||||
FileSystem* fs = state->file_system();
|
||||
Entry* entry = fs->ResolvePath(object_name);
|
||||
if (entry && entry->type() == Entry::kTypeFile) {
|
||||
if (entry && entry->type() == Entry::Type::FILE) {
|
||||
// Found.
|
||||
XFileInfo file_info;
|
||||
result = entry->QueryInfo(&file_info);
|
||||
|
|
Loading…
Reference in New Issue