Updates
This commit is contained in:
parent
aa48eeb98e
commit
e727e85b1d
|
@ -87,7 +87,7 @@ dylib_t dylib_load(const char *path)
|
||||||
fill_pathname_abbreviate_special(relative_path_abbrev, path, PATH_MAX_LENGTH * sizeof(char));
|
fill_pathname_abbreviate_special(relative_path_abbrev, path, PATH_MAX_LENGTH * sizeof(char));
|
||||||
|
|
||||||
char *relative_path = relative_path_abbrev;
|
char *relative_path = relative_path_abbrev;
|
||||||
if (relative_path[0] != ':' || !path_char_is_slash(relative_path[1]))
|
if (relative_path[0] != ':' || !PATH_CHAR_IS_SLASH(relative_path[1]))
|
||||||
{
|
{
|
||||||
/* Path to dylib_load is not inside app install directory.
|
/* Path to dylib_load is not inside app install directory.
|
||||||
* Loading will probably fail. */
|
* Loading will probably fail. */
|
||||||
|
|
|
@ -571,7 +571,7 @@ void path_parent_dir(char *path)
|
||||||
|
|
||||||
len = strlen(path);
|
len = strlen(path);
|
||||||
|
|
||||||
if (len && path_char_is_slash(path[len - 1]))
|
if (len && PATH_CHAR_IS_SLASH(path[len - 1]))
|
||||||
{
|
{
|
||||||
bool path_was_absolute = path_is_absolute(path);
|
bool path_was_absolute = path_is_absolute(path);
|
||||||
|
|
||||||
|
@ -1004,7 +1004,7 @@ void fill_pathname_expand_special(char *out_path,
|
||||||
out_path += src_size;
|
out_path += src_size;
|
||||||
size -= src_size;
|
size -= src_size;
|
||||||
|
|
||||||
if (!path_char_is_slash(out_path[-1]))
|
if (!PATH_CHAR_IS_SLASH(out_path[-1]))
|
||||||
{
|
{
|
||||||
src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size);
|
src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size);
|
||||||
retro_assert(src_size < size);
|
retro_assert(src_size < size);
|
||||||
|
@ -1035,7 +1035,7 @@ void fill_pathname_expand_special(char *out_path,
|
||||||
out_path += src_size;
|
out_path += src_size;
|
||||||
size -= src_size;
|
size -= src_size;
|
||||||
|
|
||||||
if (!path_char_is_slash(out_path[-1]))
|
if (!PATH_CHAR_IS_SLASH(out_path[-1]))
|
||||||
{
|
{
|
||||||
src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size);
|
src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size);
|
||||||
retro_assert(src_size < size);
|
retro_assert(src_size < size);
|
||||||
|
@ -1098,7 +1098,7 @@ void fill_pathname_abbreviate_special(char *out_path,
|
||||||
size -= src_size;
|
size -= src_size;
|
||||||
in_path += strlen(candidates[i]);
|
in_path += strlen(candidates[i]);
|
||||||
|
|
||||||
if (!path_char_is_slash(*in_path))
|
if (!PATH_CHAR_IS_SLASH(*in_path))
|
||||||
{
|
{
|
||||||
retro_assert(strlcpy(out_path,
|
retro_assert(strlcpy(out_path,
|
||||||
PATH_DEFAULT_SLASH(), size) < size);
|
PATH_DEFAULT_SLASH(), size) < size);
|
||||||
|
@ -1286,7 +1286,9 @@ bool is_path_accessible_using_standard_io(const char *path)
|
||||||
char *relative_path_abbrev = (char*)malloc(path_sizeof);
|
char *relative_path_abbrev = (char*)malloc(path_sizeof);
|
||||||
fill_pathname_abbreviate_special(relative_path_abbrev, path, path_sizeof);
|
fill_pathname_abbreviate_special(relative_path_abbrev, path, path_sizeof);
|
||||||
|
|
||||||
result = strlen(relative_path_abbrev) >= 2 && (relative_path_abbrev[0] == ':' || relative_path_abbrev[0] == '~') && path_char_is_slash(relative_path_abbrev[1]);
|
result = (strlen(relative_path_abbrev) >= 2 )
|
||||||
|
&& (relative_path_abbrev[0] == ':' || relative_path_abbrev[0] == '~')
|
||||||
|
&& PATH_CHAR_IS_SLASH(relative_path_abbrev[1]);
|
||||||
|
|
||||||
free(relative_path_abbrev);
|
free(relative_path_abbrev);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -460,9 +460,9 @@ void path_basedir_wrapper(char *path);
|
||||||
* Returns: true (1) if character is a slash, otherwise false (0).
|
* Returns: true (1) if character is a slash, otherwise false (0).
|
||||||
*/
|
*/
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define path_char_is_slash(c) (((c) == '/') || ((c) == '\\'))
|
#define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\'))
|
||||||
#else
|
#else
|
||||||
#define path_char_is_slash(c) ((c) == '/')
|
#define PATH_CHAR_IS_SLASH(c) ((c) == '/')
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -59,10 +59,13 @@ namespace
|
||||||
{
|
{
|
||||||
void windowsize_path(wchar_t* path)
|
void windowsize_path(wchar_t* path)
|
||||||
{
|
{
|
||||||
/* UWP deals with paths containing / instead of \ way worse than normal Windows */
|
/* UWP deals with paths containing / instead of
|
||||||
/* and RetroArch may sometimes mix them (e.g. on archive extraction) */
|
* \ way worse than normal Windows */
|
||||||
|
/* and RetroArch may sometimes mix them
|
||||||
|
* (e.g. on archive extraction) */
|
||||||
if (!path)
|
if (!path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (*path)
|
while (*path)
|
||||||
{
|
{
|
||||||
if (*path == '/')
|
if (*path == '/')
|
||||||
|
@ -139,15 +142,21 @@ namespace
|
||||||
/* Look for a matching directory we can use */
|
/* Look for a matching directory we can use */
|
||||||
for each (StorageFolder^ folder in accessible_directories)
|
for each (StorageFolder^ folder in accessible_directories)
|
||||||
{
|
{
|
||||||
|
std::wstring file_path;
|
||||||
std::wstring folder_path = folder->Path->Data();
|
std::wstring folder_path = folder->Path->Data();
|
||||||
|
size_t folder_path_size = folder_path.size();
|
||||||
/* Could be C:\ or C:\Users\somebody - remove the trailing slash to unify them */
|
/* Could be C:\ or C:\Users\somebody - remove the trailing slash to unify them */
|
||||||
if (folder_path[folder_path.size() - 1] == '\\')
|
if (folder_path[folder_path_size - 1] == '\\')
|
||||||
folder_path.erase(folder_path.size() - 1);
|
folder_path.erase(folder_path_size - 1);
|
||||||
std::wstring file_path = path->Data();
|
|
||||||
|
file_path = path->Data();
|
||||||
|
|
||||||
if (file_path.find(folder_path) == 0)
|
if (file_path.find(folder_path) == 0)
|
||||||
{
|
{
|
||||||
/* Found a match */
|
/* Found a match */
|
||||||
file_path = file_path.length() > folder_path.length() ? file_path.substr(folder_path.length() + 1) : L"";
|
file_path = file_path.length() > folder_path.length()
|
||||||
|
? file_path.substr(folder_path.length() + 1)
|
||||||
|
: L"";
|
||||||
return concurrency::create_task(GetItemInFolderFromPathAsync<T>(folder, ref new Platform::String(file_path.data())));
|
return concurrency::create_task(GetItemInFolderFromPathAsync<T>(folder, ref new Platform::String(file_path.data())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +235,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT __stdcall RuntimeClassInitialize(byte *buffer, uint32_t capacity, uint32_t length)
|
HRESULT __stdcall RuntimeClassInitialize(
|
||||||
|
byte *buffer, uint32_t capacity, uint32_t length)
|
||||||
{
|
{
|
||||||
m_buffer = buffer;
|
m_buffer = buffer;
|
||||||
m_capacity = capacity;
|
m_capacity = capacity;
|
||||||
|
@ -292,33 +302,38 @@ struct libretro_vfs_implementation_file
|
||||||
size_t buffer_fill;
|
size_t buffer_fill;
|
||||||
};
|
};
|
||||||
|
|
||||||
libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints)
|
libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
||||||
|
const char *path, unsigned mode, unsigned hints)
|
||||||
{
|
{
|
||||||
|
char *dirpath, *filename;
|
||||||
|
wchar_t *dirpath_wide;
|
||||||
|
wchar_t *filename_wide;
|
||||||
|
Platform::String^ filename_str;
|
||||||
|
Platform::String^ dirpath_str;
|
||||||
if (!path || !*path)
|
if (!path || !*path)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* Something tried to access files from current directory.
|
||||||
|
* This is not allowed on UWP. */
|
||||||
if (!path_is_absolute(path))
|
if (!path_is_absolute(path))
|
||||||
{
|
|
||||||
/* Something tried to access files from current directory. This is not allowed on UWP. */
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* Trying to open a directory as file?! */
|
/* Trying to open a directory as file?! */
|
||||||
if (path_char_is_slash(path[strlen(path) - 1]))
|
if (PATH_CHAR_IS_SLASH(path[strlen(path) - 1]))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
char* dirpath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
dirpath = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||||
fill_pathname_basedir(dirpath, path, PATH_MAX_LENGTH);
|
fill_pathname_basedir(dirpath, path, PATH_MAX_LENGTH);
|
||||||
wchar_t *dirpath_wide = utf8_to_utf16_string_alloc(dirpath);
|
dirpath_wide = utf8_to_utf16_string_alloc(dirpath);
|
||||||
windowsize_path(dirpath_wide);
|
windowsize_path(dirpath_wide);
|
||||||
Platform::String^ dirpath_str = ref new Platform::String(dirpath_wide);
|
dirpath_str = ref new Platform::String(dirpath_wide);
|
||||||
free(dirpath_wide);
|
free(dirpath_wide);
|
||||||
free(dirpath);
|
free(dirpath);
|
||||||
|
|
||||||
char* filename = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
filename = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||||
fill_pathname_base(filename, path, PATH_MAX_LENGTH);
|
fill_pathname_base(filename, path, PATH_MAX_LENGTH);
|
||||||
wchar_t *filename_wide = utf8_to_utf16_string_alloc(filename);
|
filename_wide = utf8_to_utf16_string_alloc(filename);
|
||||||
Platform::String^ filename_str = ref new Platform::String(filename_wide);
|
filename_str = ref new Platform::String(filename_wide);
|
||||||
free(filename_wide);
|
free(filename_wide);
|
||||||
free(filename);
|
free(filename);
|
||||||
|
|
||||||
|
@ -332,7 +347,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns
|
||||||
return dir->CreateFileAsync(filename_str, (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ?
|
return dir->CreateFileAsync(filename_str, (mode & RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING) != 0 ?
|
||||||
CreationCollisionOption::OpenIfExists : CreationCollisionOption::ReplaceExisting);
|
CreationCollisionOption::OpenIfExists : CreationCollisionOption::ReplaceExisting);
|
||||||
}).then([&](StorageFile^ file) {
|
}).then([&](StorageFile^ file) {
|
||||||
FileAccessMode accessMode = mode == RETRO_VFS_FILE_ACCESS_READ ?
|
FileAccessMode accessMode = (mode == RETRO_VFS_FILE_ACCESS_READ) ?
|
||||||
FileAccessMode::Read : FileAccessMode::ReadWrite;
|
FileAccessMode::Read : FileAccessMode::ReadWrite;
|
||||||
return file->OpenAsync(accessMode);
|
return file->OpenAsync(accessMode);
|
||||||
}).then([&](IRandomAccessStream^ fpstream) {
|
}).then([&](IRandomAccessStream^ fpstream) {
|
||||||
|
@ -343,7 +358,8 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns
|
||||||
stream->orig_path = strdup(path);
|
stream->orig_path = strdup(path);
|
||||||
stream->fp = fpstream;
|
stream->fp = fpstream;
|
||||||
stream->fp->Seek(0);
|
stream->fp->Seek(0);
|
||||||
// Preallocate a small buffer for manually buffered IO, makes short read faster
|
/* Preallocate a small buffer for manually buffered I/O,
|
||||||
|
* makes short read faster */
|
||||||
int buf_size = 8 * 1024;
|
int buf_size = 8 * 1024;
|
||||||
stream->buffer = (char*)malloc(buf_size);
|
stream->buffer = (char*)malloc(buf_size);
|
||||||
stream->bufferp = CreateNativeBuffer(stream->buffer, buf_size, 0);
|
stream->bufferp = CreateNativeBuffer(stream->buffer, buf_size, 0);
|
||||||
|
@ -395,7 +411,9 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
|
||||||
return stream->fp->Position - stream->buffer_left;
|
return stream->fp->Position - stream->buffer_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int seek_position)
|
int64_t retro_vfs_file_seek_impl(
|
||||||
|
libretro_vfs_implementation_file *stream,
|
||||||
|
int64_t offset, int seek_position)
|
||||||
{
|
{
|
||||||
if (!stream || !stream->fp)
|
if (!stream || !stream->fp)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -421,23 +439,30 @@ int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void *s, uint64_t len)
|
int64_t retro_vfs_file_read_impl(
|
||||||
|
libretro_vfs_implementation_file *stream, void *s, uint64_t len)
|
||||||
{
|
{
|
||||||
|
int64_t ret;
|
||||||
|
int64_t bytes_read = 0;
|
||||||
|
IBuffer^ buffer;
|
||||||
|
|
||||||
if (!stream || !stream->fp || !s)
|
if (!stream || !stream->fp || !s)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int64_t bytes_read = 0;
|
if (len <= stream->buffer_size)
|
||||||
|
{
|
||||||
if (len <= stream->buffer_size) {
|
/* Small read, use manually buffered I/O */
|
||||||
// Small read, use manually buffered IO
|
if (stream->buffer_left < len)
|
||||||
if (stream->buffer_left < len) {
|
{
|
||||||
// Exhaust the buffer
|
/* Exhaust the buffer */
|
||||||
memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left);
|
memcpy(s,
|
||||||
|
&stream->buffer[stream->buffer_fill - stream->buffer_left],
|
||||||
|
stream->buffer_left);
|
||||||
len -= stream->buffer_left;
|
len -= stream->buffer_left;
|
||||||
bytes_read += stream->buffer_left;
|
bytes_read += stream->buffer_left;
|
||||||
stream->buffer_left = 0;
|
stream->buffer_left = 0;
|
||||||
|
|
||||||
// Fill buffer
|
/* Fill buffer */
|
||||||
stream->buffer_left = RunAsyncAndCatchErrors<int64_t>([&]() {
|
stream->buffer_left = RunAsyncAndCatchErrors<int64_t>([&]() {
|
||||||
return concurrency::create_task(stream->fp->ReadAsync(stream->bufferp, stream->bufferp->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) {
|
return concurrency::create_task(stream->fp->ReadAsync(stream->bufferp, stream->bufferp->Capacity, InputStreamOptions::None)).then([&](IBuffer^ buf) {
|
||||||
retro_assert(stream->bufferp == buf);
|
retro_assert(stream->bufferp == buf);
|
||||||
|
@ -446,15 +471,18 @@ int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void
|
||||||
}, -1);
|
}, -1);
|
||||||
stream->buffer_fill = stream->buffer_left;
|
stream->buffer_fill = stream->buffer_left;
|
||||||
|
|
||||||
if (stream->buffer_left == -1) {
|
if (stream->buffer_left == -1)
|
||||||
|
{
|
||||||
stream->buffer_left = 0;
|
stream->buffer_left = 0;
|
||||||
stream->buffer_fill = 0;
|
stream->buffer_fill = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->buffer_left < len) {
|
if (stream->buffer_left < len)
|
||||||
// EOF
|
{
|
||||||
memcpy(&((char*)s)[bytes_read], stream->buffer, stream->buffer_left);
|
/* EOF */
|
||||||
|
memcpy(&((char*)s)[bytes_read],
|
||||||
|
stream->buffer, stream->buffer_left);
|
||||||
bytes_read += stream->buffer_left;
|
bytes_read += stream->buffer_left;
|
||||||
stream->buffer_left = 0;
|
stream->buffer_left = 0;
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
|
@ -466,40 +494,43 @@ int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal buffer already contains requested amount
|
/* Internal buffer already contains requested amount */
|
||||||
memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], len);
|
memcpy(s,
|
||||||
|
&stream->buffer[stream->buffer_fill - stream->buffer_left],
|
||||||
|
len);
|
||||||
stream->buffer_left -= len;
|
stream->buffer_left -= len;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Big read exceeding buffer size, exhaust small buffer and read rest in one go
|
/* Big read exceeding buffer size,
|
||||||
|
* exhaust small buffer and read rest in one go */
|
||||||
memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left);
|
memcpy(s, &stream->buffer[stream->buffer_fill - stream->buffer_left], stream->buffer_left);
|
||||||
len -= stream->buffer_left;
|
len -= stream->buffer_left;
|
||||||
bytes_read += stream->buffer_left;
|
bytes_read += stream->buffer_left;
|
||||||
stream->buffer_left = 0;
|
stream->buffer_left = 0;
|
||||||
|
|
||||||
IBuffer^ buffer = CreateNativeBuffer(&((char*)s)[bytes_read], len, 0);
|
buffer = CreateNativeBuffer(&((char*)s)[bytes_read], len, 0);
|
||||||
|
ret = RunAsyncAndCatchErrors<int64_t>([&]() {
|
||||||
int64_t ret = RunAsyncAndCatchErrors<int64_t>([&]() {
|
|
||||||
return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity - bytes_read, InputStreamOptions::None)).then([&](IBuffer^ buf) {
|
return concurrency::create_task(stream->fp->ReadAsync(buffer, buffer->Capacity - bytes_read, InputStreamOptions::None)).then([&](IBuffer^ buf) {
|
||||||
retro_assert(buf == buffer);
|
retro_assert(buf == buffer);
|
||||||
return (int64_t)buffer->Length;
|
return (int64_t)buffer->Length;
|
||||||
});
|
});
|
||||||
}, -1);
|
}, -1);
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
return bytes_read + ret;
|
return bytes_read + ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file *stream, const void *s, uint64_t len)
|
int64_t retro_vfs_file_write_impl(
|
||||||
|
libretro_vfs_implementation_file *stream, const void *s, uint64_t len)
|
||||||
{
|
{
|
||||||
|
IBuffer^ buffer;
|
||||||
if (!stream || !stream->fp || !s)
|
if (!stream || !stream->fp || !s)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// const_cast to remove const modifier is undefined behaviour, but the buffer is only read, should be safe
|
/* const_cast to remove const modifier is undefined behaviour, but the buffer is only read, should be safe */
|
||||||
IBuffer^ buffer = CreateNativeBuffer(const_cast<void*>(s), len, len);
|
buffer = CreateNativeBuffer(const_cast<void*>(s), len, len);
|
||||||
return RunAsyncAndCatchErrors<int64_t>([&]() {
|
return RunAsyncAndCatchErrors<int64_t>([&]() {
|
||||||
return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) {
|
return concurrency::create_task(stream->fp->WriteAsync(buffer)).then([&](unsigned int written) {
|
||||||
return (int64_t)written;
|
return (int64_t)written;
|
||||||
|
@ -523,12 +554,15 @@ int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream)
|
||||||
|
|
||||||
int retro_vfs_file_remove_impl(const char *path)
|
int retro_vfs_file_remove_impl(const char *path)
|
||||||
{
|
{
|
||||||
|
wchar_t *path_wide;
|
||||||
|
Platform::String^ path_str;
|
||||||
|
|
||||||
if (!path || !*path)
|
if (!path || !*path)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wchar_t *path_wide = utf8_to_utf16_string_alloc(path);
|
path_wide = utf8_to_utf16_string_alloc(path);
|
||||||
windowsize_path(path_wide);
|
windowsize_path(path_wide);
|
||||||
Platform::String^ path_str = ref new Platform::String(path_wide);
|
path_str = ref new Platform::String(path_wide);
|
||||||
free(path_wide);
|
free(path_wide);
|
||||||
|
|
||||||
return RunAsyncAndCatchErrors<int>([&]() {
|
return RunAsyncAndCatchErrors<int>([&]() {
|
||||||
|
@ -543,25 +577,33 @@ int retro_vfs_file_remove_impl(const char *path)
|
||||||
/* TODO: this may not work if trying to move a directory */
|
/* TODO: this may not work if trying to move a directory */
|
||||||
int retro_vfs_file_rename_impl(const char *old_path, const char *new_path)
|
int retro_vfs_file_rename_impl(const char *old_path, const char *new_path)
|
||||||
{
|
{
|
||||||
|
char *new_file_name;
|
||||||
|
char *new_dir_path;
|
||||||
|
wchar_t *new_file_name_wide;
|
||||||
|
wchar_t *old_path_wide, *new_dir_path_wide;
|
||||||
|
Platform::String^ old_path_str;
|
||||||
|
Platform::String^ new_dir_path_str;
|
||||||
|
Platform::String^ new_file_name_str;
|
||||||
|
|
||||||
if (!old_path || !*old_path || !new_path || !*new_path)
|
if (!old_path || !*old_path || !new_path || !*new_path)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wchar_t* old_path_wide = utf8_to_utf16_string_alloc(old_path);
|
old_path_wide = utf8_to_utf16_string_alloc(old_path);
|
||||||
Platform::String^ old_path_str = ref new Platform::String(old_path_wide);
|
old_path_str = ref new Platform::String(old_path_wide);
|
||||||
free(old_path_wide);
|
free(old_path_wide);
|
||||||
|
|
||||||
char* new_dir_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
new_dir_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||||
fill_pathname_basedir(new_dir_path, new_path, PATH_MAX_LENGTH);
|
fill_pathname_basedir(new_dir_path, new_path, PATH_MAX_LENGTH);
|
||||||
wchar_t *new_dir_path_wide = utf8_to_utf16_string_alloc(new_dir_path);
|
new_dir_path_wide = utf8_to_utf16_string_alloc(new_dir_path);
|
||||||
windowsize_path(new_dir_path_wide);
|
windowsize_path(new_dir_path_wide);
|
||||||
Platform::String^ new_dir_path_str = ref new Platform::String(new_dir_path_wide);
|
new_dir_path_str = ref new Platform::String(new_dir_path_wide);
|
||||||
free(new_dir_path_wide);
|
free(new_dir_path_wide);
|
||||||
free(new_dir_path);
|
free(new_dir_path);
|
||||||
|
|
||||||
char* new_file_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
new_file_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||||
fill_pathname_base(new_file_name, new_path, PATH_MAX_LENGTH);
|
fill_pathname_base(new_file_name, new_path, PATH_MAX_LENGTH);
|
||||||
wchar_t *new_file_name_wide = utf8_to_utf16_string_alloc(new_file_name);
|
new_file_name_wide = utf8_to_utf16_string_alloc(new_file_name);
|
||||||
Platform::String^ new_file_name_str = ref new Platform::String(new_file_name_wide);
|
new_file_name_str = ref new Platform::String(new_file_name_wide);
|
||||||
free(new_file_name_wide);
|
free(new_file_name_wide);
|
||||||
free(new_file_name);
|
free(new_file_name);
|
||||||
|
|
||||||
|
@ -595,15 +637,19 @@ const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *strea
|
||||||
|
|
||||||
int retro_vfs_stat_impl(const char *path, int32_t *size)
|
int retro_vfs_stat_impl(const char *path, int32_t *size)
|
||||||
{
|
{
|
||||||
|
wchar_t *path_wide;
|
||||||
|
Platform::String^ path_str;
|
||||||
|
IStorageItem^ item;
|
||||||
|
|
||||||
if (!path || !*path)
|
if (!path || !*path)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
wchar_t *path_wide = utf8_to_utf16_string_alloc(path);
|
path_wide = utf8_to_utf16_string_alloc(path);
|
||||||
windowsize_path(path_wide);
|
windowsize_path(path_wide);
|
||||||
Platform::String^ path_str = ref new Platform::String(path_wide);
|
path_str = ref new Platform::String(path_wide);
|
||||||
free(path_wide);
|
free(path_wide);
|
||||||
|
|
||||||
IStorageItem^ item = LocateStorageFileOrFolder(path_str);
|
item = LocateStorageFileOrFolder(path_str);
|
||||||
if (!item)
|
if (!item)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -618,36 +664,44 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
|
||||||
|
|
||||||
int retro_vfs_mkdir_impl(const char *dir)
|
int retro_vfs_mkdir_impl(const char *dir)
|
||||||
{
|
{
|
||||||
|
Platform::String^ parent_path_str;
|
||||||
|
Platform::String^ dir_name_str;
|
||||||
|
wchar_t *dir_name_wide, *parent_path_wide;
|
||||||
|
char *dir_local, *tmp, *dir_name, *parent_path;
|
||||||
if (!dir || !*dir)
|
if (!dir || !*dir)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
char* dir_local = strdup(dir);
|
/* If the path ends with a slash, we have to remove
|
||||||
/* If the path ends with a slash, we have to remove it for basename to work */
|
* it for basename to work */
|
||||||
char* tmp = dir_local + strlen(dir_local) - 1;
|
dir_local = strdup(dir);
|
||||||
if (path_char_is_slash(*tmp))
|
tmp = dir_local + strlen(dir_local) - 1;
|
||||||
|
|
||||||
|
if (PATH_CHAR_IS_SLASH(*tmp))
|
||||||
*tmp = 0;
|
*tmp = 0;
|
||||||
|
|
||||||
char* dir_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
dir_name = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||||
fill_pathname_base(dir_name, dir_local, PATH_MAX_LENGTH);
|
fill_pathname_base(dir_name, dir_local, PATH_MAX_LENGTH);
|
||||||
wchar_t *dir_name_wide = utf8_to_utf16_string_alloc(dir_name);
|
dir_name_wide = utf8_to_utf16_string_alloc(dir_name);
|
||||||
Platform::String^ dir_name_str = ref new Platform::String(dir_name_wide);
|
dir_name_str = ref new Platform::String(dir_name_wide);
|
||||||
free(dir_name_wide);
|
free(dir_name_wide);
|
||||||
free(dir_name);
|
free(dir_name);
|
||||||
|
|
||||||
char* parent_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
parent_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
||||||
fill_pathname_parent_dir(parent_path, dir_local, PATH_MAX_LENGTH);
|
fill_pathname_parent_dir(parent_path, dir_local, PATH_MAX_LENGTH);
|
||||||
wchar_t *parent_path_wide = utf8_to_utf16_string_alloc(parent_path);
|
parent_path_wide = utf8_to_utf16_string_alloc(parent_path);
|
||||||
windowsize_path(parent_path_wide);
|
windowsize_path(parent_path_wide);
|
||||||
Platform::String^ parent_path_str = ref new Platform::String(parent_path_wide);
|
parent_path_str = ref new Platform::String(parent_path_wide);
|
||||||
free(parent_path_wide);
|
free(parent_path_wide);
|
||||||
free(parent_path);
|
free(parent_path);
|
||||||
|
|
||||||
retro_assert(!dir_name_str->IsEmpty() && !parent_path_str->IsEmpty());
|
retro_assert(!dir_name_str->IsEmpty()
|
||||||
|
&& !parent_path_str->IsEmpty());
|
||||||
|
|
||||||
free(dir_local);
|
free(dir_local);
|
||||||
|
|
||||||
return RunAsyncAndCatchErrors<int>([&]() {
|
return RunAsyncAndCatchErrors<int>([&]() {
|
||||||
return concurrency::create_task(LocateStorageItem<StorageFolder>(parent_path_str)).then([&](StorageFolder^ parent) {
|
return concurrency::create_task(LocateStorageItem<StorageFolder>(
|
||||||
|
parent_path_str)).then([&](StorageFolder^ parent) {
|
||||||
return parent->CreateFolderAsync(dir_name_str);
|
return parent->CreateFolderAsync(dir_name_str);
|
||||||
}).then([&](concurrency::task<StorageFolder^> new_dir) {
|
}).then([&](concurrency::task<StorageFolder^> new_dir) {
|
||||||
try
|
try
|
||||||
|
@ -678,6 +732,8 @@ struct libretro_vfs_implementation_dir
|
||||||
|
|
||||||
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool include_hidden)
|
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool include_hidden)
|
||||||
{
|
{
|
||||||
|
wchar_t *name_wide;
|
||||||
|
Platform::String^ name_str;
|
||||||
libretro_vfs_implementation_dir *rdir;
|
libretro_vfs_implementation_dir *rdir;
|
||||||
|
|
||||||
if (!name || !*name)
|
if (!name || !*name)
|
||||||
|
@ -687,9 +743,9 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i
|
||||||
if (!rdir)
|
if (!rdir)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wchar_t *name_wide = utf8_to_utf16_string_alloc(name);
|
name_wide = utf8_to_utf16_string_alloc(name);
|
||||||
windowsize_path(name_wide);
|
windowsize_path(name_wide);
|
||||||
Platform::String^ name_str = ref new Platform::String(name_wide);
|
name_str = ref new Platform::String(name_wide);
|
||||||
free(name_wide);
|
free(name_wide);
|
||||||
|
|
||||||
rdir->directory = RunAsyncAndCatchErrors<IVectorView<IStorageItem^>^>([&]() {
|
rdir->directory = RunAsyncAndCatchErrors<IVectorView<IStorageItem^>^>([&]() {
|
||||||
|
@ -712,17 +768,16 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *rdir)
|
||||||
rdir->entry = rdir->directory->First();
|
rdir->entry = rdir->directory->First();
|
||||||
return rdir->entry->HasCurrent;
|
return rdir->entry->HasCurrent;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return rdir->entry->MoveNext();
|
return rdir->entry->MoveNext();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *rdir)
|
const char *retro_vfs_dirent_get_name_impl(
|
||||||
|
libretro_vfs_implementation_dir *rdir)
|
||||||
{
|
{
|
||||||
if (rdir->entry_name)
|
if (rdir->entry_name)
|
||||||
free(rdir->entry_name);
|
free(rdir->entry_name);
|
||||||
rdir->entry_name = utf16_to_utf8_string_alloc(rdir->entry->Current->Name->Data());
|
rdir->entry_name = utf16_to_utf8_string_alloc(
|
||||||
|
rdir->entry->Current->Name->Data());
|
||||||
return rdir->entry_name;
|
return rdir->entry_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,11 +802,13 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir)
|
||||||
|
|
||||||
bool uwp_drive_exists(const char *path)
|
bool uwp_drive_exists(const char *path)
|
||||||
{
|
{
|
||||||
|
wchar_t *path_wide;
|
||||||
|
Platform::String^ path_str;
|
||||||
if (!path || !*path)
|
if (!path || !*path)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
wchar_t *path_wide = utf8_to_utf16_string_alloc(path);
|
path_wide = utf8_to_utf16_string_alloc(path);
|
||||||
Platform::String^ path_str = ref new Platform::String(path_wide);
|
path_str = ref new Platform::String(path_wide);
|
||||||
free(path_wide);
|
free(path_wide);
|
||||||
|
|
||||||
return RunAsyncAndCatchErrors<bool>([&]() {
|
return RunAsyncAndCatchErrors<bool>([&]() {
|
||||||
|
|
Loading…
Reference in New Issue