Merge pull request #15847 from Xbox-Homebrew/master

Remove storage fileloader and storage folderbrowser, also re-add bin and elf [UWP]
This commit is contained in:
Henrik Rydgård
2022-08-16 12:51:43 +02:00
committed by GitHub
7 changed files with 6 additions and 464 deletions
+4 -9
View File
@@ -32,7 +32,6 @@
#include "XAudioSoundStream.h"
#include "UWPHost.h"
#include "UWPUtil.h"
#include "StorageFileLoader.h"
#include "App.h"
using namespace UWP;
@@ -304,11 +303,6 @@ void PPSSPP_UWPMain::OnSuspend() {
// TODO
}
void PPSSPP_UWPMain::LoadStorageFile(StorageFile ^file) {
std::unique_ptr<FileLoaderFactory> factory(new StorageFileLoaderFactory(file, IdentifiedFileType::PSP_ISO));
RegisterFileLoaderFactory("override://", std::move(factory));
NativeMessageReceived("boot", "override://file");
}
UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> resources) {
std::vector<std::string> adapterNames;
@@ -457,13 +451,14 @@ void System_SendMessage(const char *command, const char *parameter) {
picker->FileTypeFilter->Append(".iso");
// Can't load these this way currently, they require mounting the underlying folder.
// picker->FileTypeFilter->Append(".bin");
// picker->FileTypeFilter->Append(".elf");
picker->FileTypeFilter->Append(".bin");
picker->FileTypeFilter->Append(".elf");
picker->SuggestedStartLocation = Pickers::PickerLocationId::DocumentsLibrary;
create_task(picker->PickSingleFileAsync()).then([](StorageFile ^file){
if (file) {
g_main->LoadStorageFile(file);
std::string path = FromPlatformString(file->Path);
NativeMessageReceived("boot", path.c_str());
}
});
} else if (!strcmp(command, "toggle_fullscreen")) {
-185
View File
@@ -1,185 +0,0 @@
#include "pch.h"
#include "ppltasks.h"
#include "Common/Log.h"
#include "Common/File/FileUtil.h"
#include "Common/File/Path.h"
#include "Common/File/DirListing.h"
#include "Common/Thread/ThreadUtil.h"
#include "StorageFileLoader.h"
#include "Common/Log.h"
#include "UWPUtil.h"
using namespace Concurrency;
using namespace Windows::Storage;
using namespace Windows::Storage::Streams;
// Not sure how necessary this one is.
static std::mutex initMutex;
StorageFileLoader::StorageFileLoader(Windows::Storage::StorageFile ^file) {
active_ = false;
file_ = file;
path_ = Path(FromPlatformString(file_->Path));
thread_.reset(new std::thread([this]() { this->threadfunc(); }));
// Before we proceed, we need to block until the thread has found the size.
// Hacky way:
while (size_ < 0) {
Sleep(10);
}
}
StorageFileLoader::~StorageFileLoader() {
{
std::unique_lock<std::mutex> lock(mutex_);
active_ = false;
operationRequested_ = false;
cond_.notify_one();
}
thread_->join();
}
void StorageFileLoader::threadfunc() {
SetCurrentThreadName("StorageFileLoader");
{
std::unique_lock<std::mutex> lock(initMutex);
_assert_(!active_);
auto opentask = create_task(file_->OpenReadAsync()).then([this](IRandomAccessStreamWithContentType ^stream) {
stream_ = stream;
active_ = true;
});
try {
opentask.wait();
} catch (const std::exception& e) {
operationFailed_ = true;
// TODO: What do we do?
const char *what = e.what();
INFO_LOG(SYSTEM, "%s", what);
} catch (Platform::COMException ^e) {
}
auto sizetask = create_task(file_->GetBasicPropertiesAsync()).then([this](Windows::Storage::FileProperties::BasicProperties ^props) {
size_ = props->Size;
});
try {
sizetask.wait();
} catch (const std::exception& e) {
const char *what = e.what();
INFO_LOG(SYSTEM, "%s", what);
} catch (Platform::COMException ^e) {
std::string what = FromPlatformString(e->ToString());
INFO_LOG(SYSTEM, "%s", what.c_str());
}
}
std::unique_lock<std::mutex> lock(mutex_);
while (active_) {
if (!operationRequested_) {
cond_.wait(lock);
}
if (operationRequested_) {
switch (operation_.type) {
case OpType::READ_AT: {
Streams::Buffer ^buf = ref new Streams::Buffer((unsigned int)operation_.size);
operationFailed_ = false;
stream_->Seek(operation_.offset);
auto task = create_task(stream_->ReadAsync(buf, (unsigned int)operation_.size, Streams::InputStreamOptions::None));
Streams::IBuffer ^output = nullptr;
try {
task.wait();
output = task.get();
} catch (const std::exception& e) {
operationFailed_ = true;
const char *what = e.what();
INFO_LOG(SYSTEM, "%s", what);
}
std::unique_lock<std::mutex> lock(mutexResponse_);
operationRequested_ = false;
response_.buffer = output;
responseAvailable_ = true;
condResponse_.notify_one();
break;
}
default:
operationRequested_ = false;
break;
}
}
}
}
bool StorageFileLoader::Exists() {
return file_ != nullptr;
}
bool StorageFileLoader::ExistsFast() {
return file_ != nullptr;
}
bool StorageFileLoader::IsDirectory() {
return (file_->Attributes & Windows::Storage::FileAttributes::Directory) != Windows::Storage::FileAttributes::Normal;
}
s64 StorageFileLoader::FileSize() {
EnsureOpen();
if (size_ == -1)
__debugbreak(); // crude race condition detection
return size_;
}
Path StorageFileLoader::GetPath() const {
return path_;
}
void StorageFileLoader::EnsureOpen() {
while (size_ == -1)
Sleep(50);
}
size_t StorageFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags) {
// We can't handle multiple of these at a time, so serialize the easy way.
std::unique_lock<std::mutex> lock(operationMutex_);
EnsureOpen();
_assert_(!operationRequested_);
_assert_(!responseAvailable_)
{
std::unique_lock<std::mutex> lock(mutex_);
operation_.type = OpType::READ_AT;
operation_.offset = absolutePos;
operation_.size = (int64_t)(bytes * count);
operationRequested_ = true;
cond_.notify_one();
}
// OK, now wait for response...
{
std::unique_lock<std::mutex> responseLock(mutexResponse_);
while (!responseAvailable_) {
condResponse_.wait(responseLock);
}
// still under mutexResponse_ lock here.
responseAvailable_ = false;
if (operationFailed_) {
return 0;
}
DataReader ^rd = DataReader::FromBuffer(response_.buffer);
size_t len = response_.buffer->Length;
Platform::Array<uint8_t> ^bytearray = ref new Platform::Array<uint8_t>((unsigned int)len);
rd->ReadBytes(bytearray);
memcpy(data, bytearray->Data, len);
response_.buffer = nullptr;
return len / bytes;
}
}
FileLoader *StorageFileLoaderFactory::ConstructFileLoader(const Path &filename) {
return file_ ? new StorageFileLoader(file_) : nullptr;
}
-90
View File
@@ -1,90 +0,0 @@
#pragma once
#include "pch.h"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <string>
#include "Common/CommonTypes.h"
#include "Common/File/Path.h"
#include "Core/Loaders.h"
// This thing is a terrible abomination that wraps asynchronous file access behind a synchronous interface,
// completely defeating MS' design goals for StorageFile. But hey, you gotta do what you gotta do.
// This opens a stream attached to the passed-in file. Multiple of these can be created against one StorageFile.
class StorageFileLoader : public FileLoader {
public:
StorageFileLoader(Windows::Storage::StorageFile ^file);
~StorageFileLoader();
bool Exists() override;
bool ExistsFast() override;
bool IsDirectory() override;
s64 FileSize() override;
Path GetPath() const override;
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override;
private:
void threadfunc();
void EnsureOpen();
enum class OpType {
NONE,
READ_AT,
};
struct Operation {
OpType type;
int64_t offset;
int64_t size;
};
struct Response {
Windows::Storage::Streams::IBuffer ^buffer;
};
bool active_ = false;
int64_t size_ = -1;
std::unique_ptr<std::thread> thread_;
Windows::Storage::StorageFile ^file_;
Windows::Storage::Streams::IRandomAccessStreamWithContentType ^stream_;
Path path_;
std::mutex operationMutex_;
bool operationRequested_ = false;
Operation operation_{ OpType::NONE, 0, 0 };
std::condition_variable cond_;
std::mutex mutex_;
bool operationFailed_ = false;
bool responseAvailable_ = false;
Response response_;
std::condition_variable condResponse_;
std::mutex mutexResponse_;
int64_t seekPos_ = 0;
};
class StorageFileLoaderFactory : public FileLoaderFactory {
public:
StorageFileLoaderFactory(Windows::Storage::StorageFile ^file, IdentifiedFileType fileType) : file_(file), fileType_(fileType) { }
FileLoader *ConstructFileLoader(const Path &filename) override;
private:
Windows::Storage::StorageFile ^file_;
IdentifiedFileType fileType_;
};
// Similar to StorageFileLoader but for directory browsing.
class StorageDirectoryWrapper {
private:
std::thread thread_;
};
-100
View File
@@ -1,100 +0,0 @@
#include "pch.h"
#include "ppltasks.h"
#include "Common/Thread/ThreadUtil.h"
#include "StorageFolderBrowser.h"
#include "UWPUtil.h"
using namespace Concurrency;
using namespace Windows::Storage;
using namespace Windows::Storage::Streams;
static std::mutex initMutex;
StorageFolderBrowser::StorageFolderBrowser(Windows::Storage::StorageFolder ^folder) : folder_(folder) {
thread_.reset(new std::thread([this]() { this->threadfunc(); }));
path_ = FromPlatformString(folder->Path);
displayName_ = FromPlatformString(folder->DisplayName);
}
void StorageFolderBrowser::threadfunc() {
SetCurrentThreadName("StorageFileLoader");
initMutex.lock();
/*
auto opentask = create_task(folder_->GetItemsAsync()->OpenReadAsync()).then([this](IRandomAccessStreamWithContentType ^stream) {
stream_ = stream;
active_ = true;
});
try {
opentask.wait();
}
catch (const std::exception& e) {
operationFailed_ = true;
// TODO: What do we do?
const char *what = e.what();
ILOG("%s", what);
}
catch (Platform::COMException ^e) {
}
auto sizetask = create_task(file_->GetBasicPropertiesAsync()).then([this](Windows::Storage::FileProperties::BasicProperties ^props) {
size_ = props->Size;
});
try {
sizetask.wait();
}
catch (const std::exception& e) {
const char *what = e.what();
ILOG("%s", what);
}
catch (Platform::COMException ^e) {
std::string what = FromPlatformString(e->ToString());
ILOG("%s", what.c_str());
}
*/
initMutex.unlock();
std::unique_lock<std::mutex> lock(mutex_);
while (active_) {
if (!operationRequested_) {
cond_.wait(lock);
}
if (operationRequested_) {
switch (operation_.type) {
case OpType::LIST_DIRECTORY: {
/*
Streams::Buffer ^buf = ref new Streams::Buffer(operation_.size);
operationFailed_ = false;
stream_->Seek(operation_.offset);
auto task = create_task(stream_->ReadAsync(buf, operation_.size, Streams::InputStreamOptions::None));
Streams::IBuffer ^output = nullptr;
try {
task.wait();
output = task.get();
}
catch (const std::exception& e) {
operationFailed_ = true;
const char *what = e.what();
ILOG("%s", what);
}
operationRequested_ = false;
std::unique_lock<std::mutex> lock(mutexResponse_);
response_.buffer = output;
responseAvailable_ = true;
condResponse_.notify_one();
break;*/
}
default:
operationRequested_ = false;
break;
}
}
}
}
-70
View File
@@ -1,70 +0,0 @@
#pragma once
#pragma once
#include "pch.h"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <string>
#include "Common/CommonTypes.h"
#include "Core/Loaders.h"
// This thing is a terrible abomination that wraps asynchronous file access behind a synchronous interface,
// completely defeating MS' design goals for StorageFile. But hey, you gotta do what you gotta do.
// This opens a stream attached to the passed-in file. Multiple of these can be created against one StorageFile.
class StorageFolderBrowser {
public:
StorageFolderBrowser(Windows::Storage::StorageFolder ^folder);
~StorageFolderBrowser();
std::string GetPath() const {
return path_;
}
std::string DisplayName() const {
return displayName_;
}
private:
void threadfunc();
enum class OpType {
NONE,
LIST_DIRECTORY,
CHANGE_FOLDER,
};
struct Operation {
OpType type;
};
struct Response {
};
std::string path_;
std::string displayName_;
bool active_ = false;
std::unique_ptr<std::thread> thread_;
Windows::Storage::StorageFolder ^folder_;
bool operationRequested_ = false;
Operation operation_{ OpType::NONE };
std::condition_variable cond_;
std::mutex mutex_;
bool operationFailed_ = false;
bool responseAvailable_ = false;
Response response_;
std::condition_variable condResponse_;
std::mutex mutexResponse_;
int64_t seekPos_ = 0;
};
+1 -5
View File
@@ -538,8 +538,6 @@
<ClInclude Include="PPSSPP_UWPMain.h" />
<ClInclude Include="Common\DirectXHelper.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="StorageFileLoader.h" />
<ClInclude Include="StorageFolderBrowser.h" />
<ClInclude Include="UWPHost.h" />
<ClInclude Include="UWPUtil.h" />
<ClInclude Include="XAudioSoundStream.h" />
@@ -579,8 +577,6 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UWP Gold|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="StorageFileLoader.cpp" />
<ClCompile Include="StorageFolderBrowser.cpp" />
<ClCompile Include="UWPHost.cpp" />
<ClCompile Include="XAudioSoundStream.cpp" />
</ItemGroup>
@@ -1778,4 +1774,4 @@
<Import Project="$(VSINSTALLDIR)\Common7\IDE\Extensions\Microsoft\VsGraphics\MeshContentTask.targets" />
<Import Project="$(VSINSTALLDIR)\Common7\IDE\Extensions\Microsoft\VsGraphics\ShaderGraphContentTask.targets" />
</ImportGroup>
</Project>
</Project>
+1 -5
View File
@@ -61,10 +61,8 @@
<ClCompile Include="XAudioSoundStream.cpp" />
<ClCompile Include="PPSSPP_UWPMain.cpp" />
<ClCompile Include="NKCodeFromWindowsSystem.cpp" />
<ClCompile Include="StorageFileLoader.cpp" />
<ClCompile Include="UWPHost.cpp" />
<ClCompile Include="..\Windows\XinputDevice.cpp" />
<ClCompile Include="StorageFolderBrowser.cpp" />
<ClCompile Include="..\Windows\InputDevice.cpp" />
</ItemGroup>
<ItemGroup>
@@ -74,11 +72,9 @@
<ClInclude Include="XAudioSoundStream.h" />
<ClInclude Include="PPSSPP_UWPMain.h" />
<ClInclude Include="NKCodeFromWindowsSystem.h" />
<ClInclude Include="StorageFileLoader.h" />
<ClInclude Include="UWPHost.h" />
<ClInclude Include="..\Windows\XinputDevice.h" />
<ClInclude Include="UWPUtil.h" />
<ClInclude Include="StorageFolderBrowser.h" />
<ClInclude Include="..\Windows\InputDevice.h" />
</ItemGroup>
<ItemGroup>
@@ -381,4 +377,4 @@
<Filter>Content</Filter>
</Font>
</ItemGroup>
</Project>
</Project>