diff --git a/CMakeLists.txt b/CMakeLists.txt
index 36f71bfb8b..95f44d9753 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -898,6 +898,8 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/HLE/scePauth.h
Core/HW/atrac3plus.cpp
Core/HW/atrac3plus.h
+ Core/HW/AsyncIOManager.cpp
+ Core/HW/AsyncIOManager.h
Core/HW/MediaEngine.cpp
Core/HW/MediaEngine.h
Core/HW/MpegDemux.cpp
diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt
index 9d1b4bf89c..90dbf87d39 100644
--- a/Core/CMakeLists.txt
+++ b/Core/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SRCS
HLE/sceParseHttp.cpp
HLE/sceVaudio.cpp
HLE/sceAudiocodec.cpp
+ HW/AsyncIOManager.cpp
HW/MemoryStick.cpp
HW/MediaEngine.cpp
HW/SasAudio.cpp
diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 1416bbb4d0..60a98ee845 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -251,6 +251,7 @@
+
@@ -437,6 +438,7 @@
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index d9861b0b99..e96aaf9a55 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -451,6 +451,9 @@
FileSystems
+
+ HW
+
@@ -840,6 +843,9 @@
Core
+
+ HW
+
diff --git a/Core/HW/AsyncIOManager.cpp b/Core/HW/AsyncIOManager.cpp
new file mode 100644
index 0000000000..062fab6880
--- /dev/null
+++ b/Core/HW/AsyncIOManager.cpp
@@ -0,0 +1,97 @@
+// Copyright (c) 2012- PPSSPP Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0 or later versions.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official git repository and contact information can be found at
+// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+
+#include "Core/Reporting.h"
+#include "Core/System.h"
+#include "Core/HW/AsyncIOManager.h"
+#include "Core/FileSystems/MetaFileSystem.h"
+
+void AsyncIOManager::ScheduleOperation(AsyncIOEvent ev) {
+ lock_guard guard(resultsLock_);
+ resultsPending_.insert(ev.handle);
+ ScheduleEvent(ev);
+}
+
+bool AsyncIOManager::PopResult(u32 handle, AsyncIOResult &result) {
+ lock_guard guard(resultsLock_);
+ if (results_.find(handle) != results_.end()) {
+ result = results_[handle];
+ results_.erase(handle);
+ resultsPending_.erase(handle);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AsyncIOManager::WaitResult(u32 handle, AsyncIOResult &result) {
+ lock_guard guard(resultsLock_);
+ ScheduleEvent(IO_EVENT_SYNC);
+ while (HasEvents() && resultsPending_.find(handle) != resultsPending_.end()) {
+ if (PopResult(handle, result)) {
+ return true;
+ }
+ resultsWait_.wait_for(resultsLock_, 16);
+ }
+ if (PopResult(handle, result)) {
+ return true;
+ }
+
+ return false;
+}
+
+void AsyncIOManager::ProcessEvent(AsyncIOEvent ev) {
+ switch (ev.type) {
+ case IO_EVENT_READ:
+ Read(ev.handle, ev.buf, ev.bytes);
+ break;
+
+ case IO_EVENT_WRITE:
+ Write(ev.handle, ev.buf, ev.bytes);
+ break;
+
+ default:
+ ERROR_LOG(HLE, "Unsupported IO event type");
+ }
+}
+
+void AsyncIOManager::Read(u32 handle, u8 *buf, size_t bytes) {
+ size_t result = pspFileSystem.ReadFile(handle, buf, bytes);
+ EventResult(handle, result);
+}
+
+void AsyncIOManager::Write(u32 handle, u8 *buf, size_t bytes) {
+ size_t result = pspFileSystem.WriteFile(handle, buf, bytes);
+ EventResult(handle, result);
+}
+
+void AsyncIOManager::EventResult(u32 handle, AsyncIOResult result) {
+ lock_guard guard(resultsLock_);
+ if (results_.find(handle) != results_.end()) {
+ ERROR_LOG_REPORT(HLE, "Overwriting previous result for file action on handle %d", handle);
+ }
+ results_[handle] = result;
+ resultsWait_.notify_one();
+}
+
+void AsyncIOManager::DoState(PointerWrap &p) {
+ SyncThread();
+ lock_guard guard(resultsLock_);
+ p.Do(resultsPending_);
+ p.Do(results_);
+ p.DoMarker("AsyncIOManager");
+}
diff --git a/Core/HW/AsyncIOManager.h b/Core/HW/AsyncIOManager.h
new file mode 100644
index 0000000000..6c057da9b1
--- /dev/null
+++ b/Core/HW/AsyncIOManager.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2012- PPSSPP Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0 or later versions.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official git repository and contact information can be found at
+// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+
+#include