Moving all kernel files around just to fuck with whoever's keeping track ;)

This commit is contained in:
Ben Vanik
2014-01-04 17:12:46 -08:00
parent aad4d7bebf
commit 4d92720109
108 changed files with 449 additions and 677 deletions

View File

@@ -0,0 +1,28 @@
/**
******************************************************************************
* 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/kernel/fs/device.h>
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::fs;
Device::Device(const char* path) {
path_ = xestrdupa(path);
}
Device::~Device() {
xe_free(path_);
}
const char* Device::path() {
return path_;
}

View File

@@ -0,0 +1,43 @@
/**
******************************************************************************
* 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_KERNEL_FS_DEVICE_H_
#define XENIA_KERNEL_FS_DEVICE_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/fs/entry.h>
namespace xe {
namespace kernel {
namespace fs {
class Device {
public:
Device(const char* path);
virtual ~Device();
const char* path();
virtual Entry* ResolvePath(const char* path) = 0;
protected:
char* path_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_DEVICE_H_

View File

@@ -0,0 +1,98 @@
/**
******************************************************************************
* 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/kernel/fs/devices/disc_image_device.h>
#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;
DiscImageDevice::DiscImageDevice(const char* path, const xechar_t* local_path) :
Device(path) {
local_path_ = xestrdup(local_path);
mmap_ = NULL;
gdfx_ = NULL;
}
DiscImageDevice::~DiscImageDevice() {
delete gdfx_;
xe_mmap_release(mmap_);
xe_free(local_path_);
}
int DiscImageDevice::Init() {
mmap_ = xe_mmap_open(kXEFileModeRead, local_path_, 0, 0);
if (!mmap_) {
XELOGE("Disc image could not be mapped");
return 1;
}
gdfx_ = new GDFX(mmap_);
GDFX::Error error = gdfx_->Load();
if (error != GDFX::kSuccess) {
XELOGE("GDFX init failed: %d", error);
return 1;
}
//gdfx_->Dump();
return 0;
}
Entry* DiscImageDevice::ResolvePath(const char* path) {
// The filesystem will have stripped our prefix off already, so the path will
// be in the form:
// some\PATH.foo
XELOGFS("DiscImageDevice::ResolvePath(%s)", path);
GDFXEntry* gdfx_entry = gdfx_->root_entry();
// Walk the path, one separator at a time.
// We copy it into the buffer and shift it left over and over.
char remaining[XE_MAX_PATH];
XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), path));
while (remaining[0]) {
char* next_slash = xestrchra(remaining, '\\');
if (next_slash == remaining) {
// Leading slash - shift
XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), remaining + 1));
continue;
}
// Make the buffer just the name.
if (next_slash) {
*next_slash = 0;
}
// Look up in the entry.
gdfx_entry = gdfx_entry->GetChild(remaining);
if (!gdfx_entry) {
// Not found.
return NULL;
}
// Shift the buffer down, unless we are at the end.
if (!next_slash) {
break;
}
XEIGNORE(xestrcpya(remaining, XECOUNT(remaining), next_slash + 1));
}
Entry::Type type = gdfx_entry->attributes & X_FILE_ATTRIBUTE_DIRECTORY ?
Entry::kTypeDirectory : Entry::kTypeFile;
return new DiscImageEntry(
type, this, path, mmap_, gdfx_entry);
}

View File

@@ -0,0 +1,48 @@
/**
******************************************************************************
* 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_KERNEL_FS_DEVICES_DISC_IMAGE_DEVICE_H_
#define XENIA_KERNEL_FS_DEVICES_DISC_IMAGE_DEVICE_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/fs/device.h>
namespace xe {
namespace kernel {
namespace fs {
class GDFX;
class DiscImageDevice : public Device {
public:
DiscImageDevice(const char* path, const xechar_t* local_path);
virtual ~DiscImageDevice();
int Init();
virtual Entry* ResolvePath(const char* path);
private:
xechar_t* local_path_;
xe_mmap_ref mmap_;
GDFX* gdfx_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_DEVICES_DISC_IMAGE_DEVICE_H_

View File

@@ -0,0 +1,88 @@
/**
******************************************************************************
* 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/kernel/fs/devices/disc_image_entry.h>
#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 {
class DiscImageMemoryMapping : public MemoryMapping {
public:
DiscImageMemoryMapping(uint8_t* address, size_t length, xe_mmap_ref mmap) :
MemoryMapping(address, length) {
mmap_ = xe_mmap_retain(mmap);
}
virtual ~DiscImageMemoryMapping() {
xe_mmap_release(mmap_);
}
private:
xe_mmap_ref mmap_;
};
}
DiscImageEntry::DiscImageEntry(Type type, Device* device, const char* path,
xe_mmap_ref mmap, GDFXEntry* gdfx_entry) :
gdfx_entry_(gdfx_entry),
Entry(type, device, path) {
mmap_ = xe_mmap_retain(mmap);
}
DiscImageEntry::~DiscImageEntry() {
xe_mmap_release(mmap_);
}
X_STATUS DiscImageEntry::QueryInfo(XFileInfo* out_info) {
XEASSERTNOTNULL(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;
return X_STATUS_SUCCESS;
}
MemoryMapping* DiscImageEntry::CreateMemoryMapping(
xe_file_mode file_mode, const size_t offset, const size_t length) {
if (file_mode & kXEFileModeWrite) {
// Only allow reads.
return NULL;
}
size_t real_offset = gdfx_entry_->offset + offset;
size_t real_length = length ?
MIN(length, gdfx_entry_->size) : gdfx_entry_->size;
return new DiscImageMemoryMapping(
xe_mmap_get_addr(mmap_) + 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);
return X_STATUS_SUCCESS;
}

View File

@@ -0,0 +1,56 @@
/**
******************************************************************************
* 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_KERNEL_FS_DEVICES_DISC_IMAGE_ENTRY_H_
#define XENIA_KERNEL_FS_DEVICES_DISC_IMAGE_ENTRY_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:
DiscImageEntry(Type type, Device* device, const char* path,
xe_mmap_ref mmap, GDFXEntry* gdfx_entry);
virtual ~DiscImageEntry();
xe_mmap_ref mmap() const { return mmap_; }
GDFXEntry* gdfx_entry() const { return gdfx_entry_; }
virtual X_STATUS QueryInfo(XFileInfo* out_info);
virtual MemoryMapping* CreateMemoryMapping(
xe_file_mode file_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);
private:
xe_mmap_ref mmap_;
GDFXEntry* gdfx_entry_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_DEVICES_DISC_IMAGE_ENTRY_H_

View File

@@ -0,0 +1,47 @@
/**
******************************************************************************
* 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/kernel/fs/devices/disc_image_file.h>
#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;
DiscImageFile::DiscImageFile(
KernelState* kernel_state, uint32_t desired_access,
DiscImageEntry* entry) :
entry_(entry),
XFile(kernel_state, desired_access) {
}
DiscImageFile::~DiscImageFile() {
}
X_STATUS DiscImageFile::QueryInfo(XFileInfo* out_info) {
return entry_->QueryInfo(out_info);
}
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();
size_t real_offset = gdfx_entry->offset + byte_offset;
size_t real_length = MIN(buffer_length, gdfx_entry->size - byte_offset);
xe_copy_memory(
buffer, buffer_length,
xe_mmap_get_addr(mmap) + real_offset, real_length);
*out_bytes_read = real_length;
return X_STATUS_SUCCESS;
}

View File

@@ -0,0 +1,49 @@
/**
******************************************************************************
* 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_KERNEL_FS_DEVICES_DISC_IMAGE_FILE_H_
#define XENIA_KERNEL_FS_DEVICES_DISC_IMAGE_FILE_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/objects/xfile.h>
namespace xe {
namespace kernel {
namespace fs {
class DiscImageEntry;
class DiscImageFile : public XFile {
public:
DiscImageFile(KernelState* kernel_state, uint32_t desired_access,
DiscImageEntry* entry);
virtual ~DiscImageFile();
virtual X_STATUS QueryInfo(XFileInfo* out_info);
protected:
virtual X_STATUS ReadSync(
void* buffer, size_t buffer_length, size_t byte_offset,
size_t* out_bytes_read);
private:
DiscImageEntry* entry_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_DEVICES_DISC_IMAGE_FILE_H_

View File

@@ -0,0 +1,65 @@
/**
******************************************************************************
* 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/kernel/fs/devices/host_path_device.h>
#include <xenia/kernel/fs/devices/host_path_entry.h>
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::fs;
HostPathDevice::HostPathDevice(const char* path, const xechar_t* local_path) :
Device(path) {
local_path_ = xestrdup(local_path);
}
HostPathDevice::~HostPathDevice() {
xe_free(local_path_);
}
Entry* HostPathDevice::ResolvePath(const char* path) {
// The filesystem will have stripped our prefix off already, so the path will
// be in the form:
// some\PATH.foo
XELOGFS("HostPathDevice::ResolvePath(%s)", path);
#if XE_WCHAR
xechar_t rel_path[XE_MAX_PATH];
XEIGNORE(xestrwiden(rel_path, XECOUNT(rel_path), path));
#else
const xechar_t* rel_path = path;
#endif
xechar_t full_path[XE_MAX_PATH];
xe_path_join(local_path_, rel_path, full_path, XECOUNT(full_path));
// Swap around path separators.
if (XE_PATH_SEPARATOR != '\\') {
for (size_t n = 0; n < XECOUNT(full_path); n++) {
if (full_path[n] == 0) {
break;
}
if (full_path[n] == '\\') {
full_path[n] = XE_PATH_SEPARATOR;
}
}
}
// TODO(benvanik): get file info
// TODO(benvanik): fail if does not exit
// TODO(benvanik): switch based on type
Entry::Type type = Entry::kTypeFile;
HostPathEntry* entry = new HostPathEntry(type, this, path, full_path);
return entry;
}

View File

@@ -0,0 +1,41 @@
/**
******************************************************************************
* 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_KERNEL_FS_DEVICES_HOST_PATH_DEVICE_H_
#define XENIA_KERNEL_FS_DEVICES_HOST_PATH_DEVICE_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/fs/device.h>
namespace xe {
namespace kernel {
namespace fs {
class HostPathDevice : public Device {
public:
HostPathDevice(const char* path, const xechar_t* local_path);
virtual ~HostPathDevice();
virtual Entry* ResolvePath(const char* path);
private:
xechar_t* local_path_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_DEVICES_HOST_PATH_DEVICE_H_

View File

@@ -0,0 +1,107 @@
/**
******************************************************************************
* 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/kernel/fs/devices/host_path_entry.h>
#include <xenia/kernel/fs/devices/host_path_file.h>
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::fs;
namespace {
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_;
};
}
HostPathEntry::HostPathEntry(Type type, Device* device, const char* path,
const xechar_t* local_path) :
Entry(type, device, path) {
local_path_ = xestrdup(local_path);
}
HostPathEntry::~HostPathEntry() {
xe_free(local_path_);
}
X_STATUS HostPathEntry::QueryInfo(XFileInfo* out_info) {
XEASSERTNOTNULL(out_info);
WIN32_FILE_ATTRIBUTE_DATA data;
if (!GetFileAttributesEx(
local_path_, GetFileExInfoStandard, &data)) {
return X_STATUS_ACCESS_DENIED;
}
#define COMBINE_TIME(t) (((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime)
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;
return X_STATUS_SUCCESS;
}
MemoryMapping* HostPathEntry::CreateMemoryMapping(
xe_file_mode file_mode, const size_t offset, const size_t length) {
xe_mmap_ref mmap = xe_mmap_open(file_mode, local_path_, offset, length);
if (!mmap) {
return NULL;
}
HostPathMemoryMapping* lfmm = new HostPathMemoryMapping(
(uint8_t*)xe_mmap_get_addr(mmap), xe_mmap_get_length(mmap),
mmap);
xe_mmap_release(mmap);
return lfmm;
}
X_STATUS HostPathEntry::Open(
KernelState* kernel_state,
uint32_t desired_access, bool async,
XFile** out_file) {
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_,
desired_access,
share_mode,
NULL,
creation_disposition,
flags_and_attributes,
NULL);
if (!file) {
// TODO(benvanik): pick correct response.
return X_STATUS_ACCESS_DENIED;
}
*out_file = new HostPathFile(kernel_state, desired_access, this, file);
return X_STATUS_SUCCESS;
}

View File

@@ -0,0 +1,52 @@
/**
******************************************************************************
* 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_KERNEL_FS_DEVICES_HOST_PATH_ENTRY_H_
#define XENIA_KERNEL_FS_DEVICES_HOST_PATH_ENTRY_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/fs/entry.h>
namespace xe {
namespace kernel {
namespace fs {
class HostPathEntry : public Entry {
public:
HostPathEntry(Type type, Device* device, const char* path,
const xechar_t* local_path);
virtual ~HostPathEntry();
const xechar_t* local_path() { return local_path_; }
virtual X_STATUS QueryInfo(XFileInfo* out_info);
virtual MemoryMapping* CreateMemoryMapping(
xe_file_mode file_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);
private:
xechar_t* local_path_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_DEVICES_HOST_PATH_ENTRY_H_

View File

@@ -0,0 +1,50 @@
/**
******************************************************************************
* 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/kernel/fs/devices/host_path_file.h>
#include <xenia/kernel/fs/devices/host_path_entry.h>
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::fs;
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_);
}
X_STATUS HostPathFile::QueryInfo(XFileInfo* out_info) {
return entry_->QueryInfo(out_info);
}
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);
if (read) {
*out_bytes_read = bytes_read;
return X_STATUS_SUCCESS;
} else {
return X_STATUS_UNSUCCESSFUL;
}
}

View File

@@ -0,0 +1,50 @@
/**
******************************************************************************
* 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_KERNEL_FS_DEVICES_HOST_PATH_FILE_H_
#define XENIA_KERNEL_FS_DEVICES_HOST_PATH_FILE_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/kernel/objects/xfile.h>
namespace xe {
namespace kernel {
namespace fs {
class HostPathEntry;
class HostPathFile : public XFile {
public:
HostPathFile(KernelState* kernel_state, uint32_t desired_access,
HostPathEntry* entry, HANDLE file_handle);
virtual ~HostPathFile();
virtual X_STATUS QueryInfo(XFileInfo* out_info);
protected:
virtual X_STATUS ReadSync(
void* buffer, size_t buffer_length, size_t byte_offset,
size_t* out_bytes_read);
private:
HostPathEntry* entry_;
HANDLE file_handle_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_DEVICES_HOST_PATH_FILE_H_

View File

@@ -0,0 +1,17 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'disc_image_device.cc',
'disc_image_device.h',
'disc_image_entry.cc',
'disc_image_entry.h',
'disc_image_file.cc',
'disc_image_file.h',
'host_path_device.cc',
'host_path_device.h',
'host_path_entry.cc',
'host_path_entry.h',
'host_path_file.cc',
'host_path_file.h',
],
}

View File

@@ -0,0 +1,37 @@
/**
******************************************************************************
* 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/kernel/fs/entry.h>
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::fs;
MemoryMapping::MemoryMapping(uint8_t* address, size_t length) :
address_(address), length_(length) {
}
MemoryMapping::~MemoryMapping() {
}
Entry::Entry(Type type, Device* device, const char* path) :
type_(type),
device_(device) {
path_ = xestrdupa(path);
// TODO(benvanik): last index of \, unless \ at end, then before that
name_ = NULL;
}
Entry::~Entry() {
xe_free(path_);
xe_free(name_);
}

View File

@@ -0,0 +1,83 @@
/**
******************************************************************************
* 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_KERNEL_FS_ENTRY_H_
#define XENIA_KERNEL_FS_ENTRY_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/xbox.h>
XEDECLARECLASS2(xe, kernel, KernelState);
XEDECLARECLASS2(xe, kernel, XFile);
XEDECLARECLASS2(xe, kernel, XFileInfo);
namespace xe {
namespace kernel {
namespace fs {
class Device;
class MemoryMapping {
public:
MemoryMapping(uint8_t* address, size_t length);
virtual ~MemoryMapping();
uint8_t* address() const { return address_; }
size_t length() const { return length_; }
private:
uint8_t* address_;
size_t length_;
};
class Entry {
public:
enum Type {
kTypeFile,
kTypeDirectory,
};
Entry(Type type, Device* device, const char* path);
virtual ~Entry();
Type type() const { return type_; }
Device* device() const { return device_; }
const char* path() const { return path_; }
const char* name() const { return name_; }
virtual X_STATUS QueryInfo(XFileInfo* out_info) = 0;
virtual MemoryMapping* CreateMemoryMapping(
xe_file_mode file_mode, const size_t offset, const size_t length) = 0;
virtual X_STATUS Open(
KernelState* kernel_state,
uint32_t desired_access, bool async,
XFile** out_file) = 0;
private:
Type type_;
Device* device_;
char* path_;
char* name_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_ENTRY_H_

View File

@@ -0,0 +1,113 @@
/**
******************************************************************************
* 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/kernel/fs/filesystem.h>
#include <xenia/kernel/fs/devices/disc_image_device.h>
#include <xenia/kernel/fs/devices/host_path_device.h>
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::fs;
FileSystem::FileSystem() {
}
FileSystem::~FileSystem() {
// Delete all devices.
// This will explode if anyone is still using data from them.
for (std::vector<Device*>::iterator it = devices_.begin();
it != devices_.end(); ++it) {
delete *it;
}
devices_.clear();
symlinks_.clear();
}
int FileSystem::RegisterDevice(const char* path, Device* device) {
devices_.push_back(device);
return 0;
}
int FileSystem::RegisterHostPathDevice(
const char* path, const xechar_t* local_path) {
Device* device = new HostPathDevice(path, local_path);
return RegisterDevice(path, device);
}
int FileSystem::RegisterDiscImageDevice(
const char* path, const xechar_t* local_path) {
DiscImageDevice* device = new DiscImageDevice(path, local_path);
if (device->Init()) {
return 1;
}
return RegisterDevice(path, device);
}
int FileSystem::CreateSymbolicLink(const char* path, const char* target) {
symlinks_.insert(std::pair<const char*, const char*>(
xestrdupa(path),
xestrdupa(target)));
return 0;
}
int FileSystem::DeleteSymbolicLink(const char* path) {
std::tr1::unordered_map<std::string, std::string>::iterator it =
symlinks_.find(std::string(path));
if (it != symlinks_.end()) {
symlinks_.erase(it);
return 0;
}
return 1;
}
Entry* FileSystem::ResolvePath(const char* path) {
// Strip off prefix and pass to device.
// e.g., d:\some\PATH.foo -> some\PATH.foo
// Support both symlinks and device specifiers, like:
// \\Device\Foo\some\PATH.foo, d:\some\PATH.foo, etc.
// TODO(benvanik): normalize path/etc
// e.g., remove ..'s and such
// Resolve symlinks.
// TODO(benvanik): more robust symlink handling - right now we assume simple
// drive path -> device mappings with nothing nested.
char full_path[XE_MAX_PATH];
XEIGNORE(xestrcpya(full_path, XECOUNT(full_path), path));
for (std::tr1::unordered_map<std::string, std::string>::iterator it =
symlinks_.begin(); it != symlinks_.end(); ++it) {
if (xestrcasestra(path, it->first.c_str()) == path) {
// Found symlink, fixup.
const char* after_path = path + it->first.size();
XEIGNORE(xesnprintfa(full_path, XECOUNT(full_path), "%s%s",
it->second.c_str(), after_path));
break;
}
}
// Scan all devices.
for (std::vector<Device*>::iterator it = devices_.begin();
it != devices_.end(); ++it) {
Device* device = *it;
if (xestrcasestra(full_path, device->path()) == full_path) {
// Found!
// Trim the device prefix off and pass down.
char device_path[XE_MAX_PATH];
XEIGNORE(xestrcpya(device_path, XECOUNT(device_path),
full_path + xestrlena(device->path())));
return device->ResolvePath(device_path);
}
}
XELOGE("ResolvePath(%s) failed - no root found", path);
return NULL;
}

View File

@@ -0,0 +1,54 @@
/**
******************************************************************************
* 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_KERNEL_FS_FILESYSTEM_H_
#define XENIA_KERNEL_FS_FILESYSTEM_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <vector>
#include <xenia/kernel/fs/entry.h>
namespace xe {
namespace kernel {
namespace fs {
class Device;
class FileSystem {
public:
FileSystem();
~FileSystem();
int RegisterDevice(const char* path, Device* device);
int RegisterHostPathDevice(const char* path, const xechar_t* local_path);
int RegisterDiscImageDevice(const char* path, const xechar_t* local_path);
int CreateSymbolicLink(const char* path, const char* target);
int DeleteSymbolicLink(const char* path);
Entry* ResolvePath(const char* path);
private:
std::vector<Device*> devices_;
std::tr1::unordered_map<std::string, std::string> symlinks_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_FILESYSTEM_H_

209
src/xenia/kernel/fs/gdfx.cc Normal file
View File

@@ -0,0 +1,209 @@
/**
******************************************************************************
* 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. *
******************************************************************************
* Major contributions to this file from:
* - abgx360
*/
#include <xenia/kernel/fs/gdfx.h>
using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::fs;
namespace {
#define kXESectorSize 2048
}
GDFXEntry::GDFXEntry() :
attributes(X_FILE_ATTRIBUTE_NONE), offset(0), size(0) {
}
GDFXEntry::~GDFXEntry() {
for (std::vector<GDFXEntry*>::iterator it = children.begin();
it != children.end(); ++it) {
delete *it;
}
}
GDFXEntry* GDFXEntry::GetChild(const char* name) {
// TODO(benvanik): a faster search
for (std::vector<GDFXEntry*>::iterator it = children.begin();
it != children.end(); ++it) {
GDFXEntry* entry = *it;
if (xestrcasecmpa(entry->name.c_str(), name) == 0) {
return entry;
}
}
return NULL;
}
void GDFXEntry::Dump(int indent) {
printf("%s%s\n", std::string(indent, ' ').c_str(), name.c_str());
for (std::vector<GDFXEntry*>::iterator it = children.begin();
it != children.end(); ++it) {
GDFXEntry* entry = *it;
entry->Dump(indent + 2);
}
}
GDFX::GDFX(xe_mmap_ref mmap) {
mmap_ = xe_mmap_retain(mmap);
root_entry_ = NULL;
}
GDFX::~GDFX() {
delete root_entry_;
xe_mmap_release(mmap_);
}
GDFXEntry* GDFX::root_entry() {
return root_entry_;
}
GDFX::Error GDFX::Load() {
Error result = kErrorOutOfMemory;
ParseState state;
xe_zero_struct(&state, sizeof(state));
state.ptr = (uint8_t*)xe_mmap_get_addr(mmap_);
state.size = xe_mmap_get_length(mmap_);
result = Verify(state);
XEEXPECTZERO(result);
result = ReadAllEntries(state, state.ptr + state.root_offset);
XEEXPECTZERO(result);
result = kSuccess;
XECLEANUP:
return result;
}
void GDFX::Dump() {
if (root_entry_) {
root_entry_->Dump(0);
}
}
GDFX::Error GDFX::Verify(ParseState& state) {
// Find sector 32 of the game partition - try at a few points.
const static size_t likely_offsets[] = {
0x00000000, 0x0000FB20, 0x00020600, 0x0FD90000,
};
bool magic_found = false;
for (size_t n = 0; n < XECOUNT(likely_offsets); n++) {
state.game_offset = likely_offsets[n];
if (VerifyMagic(state, state.game_offset + (32 * kXESectorSize))) {
magic_found = true;
break;
}
}
if (!magic_found) {
// File doesn't have the magic values - likely not a real GDFX source.
return kErrorFileMismatch;
}
// Read sector 32 to get FS state.
if (state.size < state.game_offset + (32 * kXESectorSize)) {
return kErrorReadError;
}
uint8_t* fs_ptr = state.ptr + state.game_offset + (32 * kXESectorSize);
state.root_sector = XEGETUINT32LE(fs_ptr + 20);
state.root_size = XEGETUINT32LE(fs_ptr + 24);
state.root_offset = state.game_offset + (state.root_sector * kXESectorSize);
if (state.root_size < 13 ||
state.root_size > 32 * 1024 * 1024) {
return kErrorDamagedFile;
}
return kSuccess;
}
bool GDFX::VerifyMagic(ParseState& state, size_t offset) {
// Simple check to see if the given offset contains the magic value.
return memcmp(state.ptr + offset, "MICROSOFT*XBOX*MEDIA", 20) == 0;
}
GDFX::Error GDFX::ReadAllEntries(ParseState& state,
const uint8_t* root_buffer) {
root_entry_ = new GDFXEntry();
root_entry_->offset = 0;
root_entry_->size = 0;
root_entry_->name = "";
root_entry_->attributes = X_FILE_ATTRIBUTE_DIRECTORY;
if (!ReadEntry(state, root_buffer, 0, root_entry_)) {
return kErrorOutOfMemory;
}
return kSuccess;
}
bool GDFX::ReadEntry(ParseState& state, const uint8_t* buffer,
uint16_t entry_ordinal, GDFXEntry* parent) {
const uint8_t* p = buffer + (entry_ordinal * 4);
uint16_t node_l = XEGETUINT16LE(p + 0);
uint16_t node_r = XEGETUINT16LE(p + 2);
size_t sector = XEGETUINT32LE(p + 4);
size_t length = XEGETUINT32LE(p + 8);
uint8_t attributes = XEGETUINT8LE(p + 12);
uint8_t name_length = XEGETUINT8LE(p + 13);
char* name = (char*)(p + 14);
if (node_l && !ReadEntry(state, buffer, node_l, parent)) {
return false;
}
GDFXEntry* entry = new GDFXEntry();
entry->name = std::string(name, name_length);
entry->name.append(1, '\0');
entry->attributes = (X_FILE_ATTRIBUTES)attributes;
// Add to parent.
parent->children.push_back(entry);
if (attributes & X_FILE_ATTRIBUTE_DIRECTORY) {
// Folder.
entry->offset = 0;
entry->size = 0;
if (length) {
// Not a leaf - read in children.
if (state.size < state.game_offset + (sector * kXESectorSize)) {
// Out of bounds read.
return false;
}
// Read child list.
uint8_t* folder_ptr =
state.ptr + state.game_offset + (sector * kXESectorSize);
if (!ReadEntry(state, folder_ptr, 0, entry)) {
return false;
}
}
} else {
// File.
entry->offset = state.game_offset + (sector * kXESectorSize);
entry->size = length;
}
// Read next file in the list.
if (node_r && !ReadEntry(state, buffer, node_r, parent)) {
return false;
}
return true;
}

View File

@@ -0,0 +1,96 @@
/**
******************************************************************************
* 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_KERNEL_FS_GDFX_H_
#define XENIA_KERNEL_FS_GDFX_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <vector>
#include <xenia/xbox.h>
#include <xenia/kernel/fs/entry.h>
namespace xe {
namespace kernel {
namespace fs {
class GDFX;
class GDFXEntry {
public:
GDFXEntry();
~GDFXEntry();
GDFXEntry* GetChild(const char* name);
void Dump(int indent);
std::string name;
X_FILE_ATTRIBUTES attributes;
size_t offset;
size_t size;
std::vector<GDFXEntry*> children;
};
class GDFX {
public:
enum Error {
kSuccess = 0,
kErrorOutOfMemory = -1,
kErrorReadError = -10,
kErrorFileMismatch = -30,
kErrorDamagedFile = -31,
};
GDFX(xe_mmap_ref mmap);
virtual ~GDFX();
GDFXEntry* root_entry();
Error Load();
void Dump();
private:
typedef struct {
uint8_t* ptr;
size_t size; // Size (bytes) of total image
size_t game_offset; // Offset (bytes) of game partition
size_t root_sector; // Offset (sector) of root
size_t root_offset; // Offset (bytes) of root
size_t root_size; // Size (bytes) of root
} ParseState;
Error Verify(ParseState& state);
bool VerifyMagic(ParseState& state, size_t offset);
Error ReadAllEntries(ParseState& state, const uint8_t* root_buffer);
bool ReadEntry(ParseState& state, const uint8_t* buffer,
uint16_t entry_ordinal, GDFXEntry* parent);
xe_mmap_ref mmap_;
GDFXEntry* root_entry_;
};
} // namespace fs
} // namespace kernel
} // namespace xe
#endif // XENIA_KERNEL_FS_GDFX_H_

View File

@@ -0,0 +1,17 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'device.cc',
'device.h',
'entry.cc',
'entry.h',
'filesystem.cc',
'filesystem.h',
'gdfx.cc',
'gdfx.h',
],
'includes': [
'devices/sources.gypi',
],
}