Moving mmap to poly, cleaning up devices.

This commit is contained in:
Ben Vanik 2014-08-17 12:57:02 -07:00
parent 24fe169f36
commit 854bcdb60a
37 changed files with 568 additions and 653 deletions

46
src/poly/mapped_memory.h Normal file
View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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',
],
}],

View File

@ -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>

View File

@ -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_

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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',
],

View File

@ -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

View File

@ -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_;
};

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -14,7 +14,6 @@
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/fs/device.h>
namespace xe {

View File

@ -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

View File

@ -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_;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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_;
};

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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;

View File

@ -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_;

View File

@ -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) {

View File

@ -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_;
};

View File

@ -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) {

View File

@ -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_;

View File

@ -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);

View File

@ -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.

View File

@ -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.

View File

@ -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);