diff --git a/src/xenia/kernel/xfile.cc b/src/xenia/kernel/xfile.cc index c2e00e9a5..8de977a88 100644 --- a/src/xenia/kernel/xfile.cc +++ b/src/xenia/kernel/xfile.cc @@ -9,7 +9,10 @@ #include "xenia/kernel/xfile.h" +#include "xenia/base/byte_stream.h" +#include "xenia/base/logging.h" #include "xenia/base/math.h" +#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/xevent.h" namespace xe { @@ -17,15 +20,14 @@ namespace kernel { XFile::XFile(KernelState* kernel_state, vfs::File* file) : XObject(kernel_state, kTypeFile), file_(file) { - async_event_ = new XEvent(kernel_state); - async_event_->Initialize(false, false); + async_event_ = threading::Event::CreateAutoResetEvent(false); } +XFile::XFile() : XObject(kTypeFile) {} + XFile::~XFile() { // TODO(benvanik): signal that the file is closing? - async_event_->Set(0, false); - async_event_->Delete(); - + async_event_->Set(); file_->Destroy(); } @@ -107,7 +109,7 @@ X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset, *out_bytes_read = bytes_read; } - async_event_->Set(0, false); + async_event_->Set(); return result; } @@ -137,7 +139,7 @@ X_STATUS XFile::Write(const void* buffer, size_t buffer_length, *out_bytes_written = bytes_written; } - async_event_->Set(0, false); + async_event_->Set(); return result; } @@ -160,6 +162,50 @@ void XFile::RemoveIOCompletionPort(uint32_t key) { } } +bool XFile::Save(ByteStream* stream) { + XELOGD("XFile %.8X (%s)", handle(), file_->entry()->absolute_path().c_str()); + + if (!SaveObject(stream)) { + return false; + } + + stream->Write(file_->entry()->absolute_path()); + stream->Write(position_); + stream->Write(file_access()); + + return true; +} + +object_ref XFile::Restore(KernelState* kernel_state, + ByteStream* stream) { + auto file = new XFile(); + file->kernel_state_ = kernel_state; + if (!file->RestoreObject(stream)) { + delete file; + return nullptr; + } + + auto abs_path = stream->Read(); + uint64_t position = stream->Read(); + auto access = stream->Read(); + + XELOGD("XFile %.8X (%s)", file->handle(), abs_path.c_str()); + + vfs::File* vfs_file = nullptr; + vfs::FileAction action; + auto res = kernel_state->file_system()->OpenFile( + abs_path, vfs::FileDisposition::kOpen, access, &vfs_file, &action); + if (XFAILED(res)) { + XELOGE("Failed to open XFile: error %.8X", res); + return object_ref(file); + } + + file->file_ = vfs_file; + file->position_ = position; + + return object_ref(file); +} + void XFile::NotifyIOCompletionPorts( XIOCompletion::IONotification& notification) { std::lock_guard lock(completion_port_lock_); diff --git a/src/xenia/kernel/xfile.h b/src/xenia/kernel/xfile.h index 851ad6e05..cb7426cf1 100644 --- a/src/xenia/kernel/xfile.h +++ b/src/xenia/kernel/xfile.h @@ -87,7 +87,7 @@ class XFile : public XObject { vfs::Device* device() const { return file_->entry()->device(); } vfs::Entry* entry() const { return file_->entry(); } vfs::File* file() const { return file_; } - uint32_t file_access() const { return file_access_; } + uint32_t file_access() const { return file_->file_access(); } const std::string& path() const { return file_->entry()->path(); } const std::string& name() const { return file_->entry()->name(); } @@ -105,19 +105,24 @@ class XFile : public XObject { size_t* out_bytes_written, uint32_t apc_context); xe::threading::WaitHandle* GetWaitHandle() override { - return async_event_->GetWaitHandle(); + return async_event_.get(); } void RegisterIOCompletionPort(uint32_t key, object_ref port); void RemoveIOCompletionPort(uint32_t key); + bool Save(ByteStream* stream); + static object_ref Restore(KernelState* kernel_state, + ByteStream* stream); + protected: void NotifyIOCompletionPorts(XIOCompletion::IONotification& notification); private: + XFile(); + vfs::File* file_ = nullptr; - uint32_t file_access_ = 0; - XEvent* async_event_ = nullptr; + std::unique_ptr async_event_ = nullptr; std::mutex completion_port_lock_; std::vector>> completion_ports_; diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc index d6fc3398a..0e06f0200 100644 --- a/src/xenia/kernel/xobject.cc +++ b/src/xenia/kernel/xobject.cc @@ -133,7 +133,7 @@ object_ref XObject::Restore(KernelState* kernel_state, Type type, case kTypeEvent: return XEvent::Restore(kernel_state, stream); case kTypeFile: - break; + return XFile::Restore(kernel_state, stream); case kTypeIOCompletion: break; case kTypeModule: