summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2016-11-10 13:13:51 +0100
committer Miodrag Milanovic <mmicko@gmail.com>2016-11-10 13:13:51 +0100
commita18497e7a24d931e7ab1dda9d79fee484e5aa170 (patch)
treeca2314adb3c00fe78937bb646b4775921cb207ab
parent9d184119993471958397324fcc4c38040cd0096b (diff)
Some more work on UWP (nw)
-rw-r--r--3rdparty/lua-linenoise/linenoise_none.c6
-rw-r--r--scripts/src/3rdparty.lua6
-rw-r--r--scripts/src/main.lua30
-rw-r--r--scripts/src/osd/uwp.lua18
-rw-r--r--scripts/toolchain.lua3
-rw-r--r--src/osd/modules/file/winrtdir.cpp142
-rw-r--r--src/osd/modules/file/winrtfile.cpp465
-rw-r--r--src/osd/modules/file/winrtfile.h34
-rw-r--r--src/osd/modules/file/winrtptty.cpp87
-rw-r--r--src/osd/modules/file/winrtsocket.cpp274
-rw-r--r--src/osd/modules/lib/osdlib_uwp.cpp383
-rw-r--r--src/osd/strconv.cpp4
-rw-r--r--src/osd/uwp/Package.appxmanifest36
-rw-r--r--src/osd/uwp/assets/LockScreenLogo.scale-200.pngbin0 -> 1430 bytes
-rw-r--r--src/osd/uwp/assets/SplashScreen.scale-200.pngbin0 -> 7700 bytes
-rw-r--r--src/osd/uwp/assets/Square150x150Logo.scale-200.pngbin0 -> 2937 bytes
-rw-r--r--src/osd/uwp/assets/Square44x44Logo.scale-200.pngbin0 -> 1647 bytes
-rw-r--r--src/osd/uwp/assets/Square44x44Logo.targetsize-24_altform-unplated.pngbin0 -> 1255 bytes
-rw-r--r--src/osd/uwp/assets/StoreLogo.pngbin0 -> 1451 bytes
-rw-r--r--src/osd/uwp/assets/Wide310x150Logo.scale-200.pngbin0 -> 3204 bytes
-rw-r--r--src/osd/uwp/uwpcompat.cpp14
-rw-r--r--src/osd/uwp/uwpmain.cpp186
-rw-r--r--src/osd/uwp/uwpmain.h52
23 files changed, 1723 insertions, 17 deletions
diff --git a/3rdparty/lua-linenoise/linenoise_none.c b/3rdparty/lua-linenoise/linenoise_none.c
new file mode 100644
index 00000000000..1cb1564f595
--- /dev/null
+++ b/3rdparty/lua-linenoise/linenoise_none.c
@@ -0,0 +1,6 @@
+#include <lua.h>
+
+int luaopen_linenoise(lua_State *L)
+{
+ return 1;
+}
diff --git a/scripts/src/3rdparty.lua b/scripts/src/3rdparty.lua
index c1bb26e8e6d..79d131a63dc 100644
--- a/scripts/src/3rdparty.lua
+++ b/scripts/src/3rdparty.lua
@@ -594,7 +594,11 @@ end
MAME_DIR .. "3rdparty/lua-zlib/lua_zlib.c",
MAME_DIR .. "3rdparty/luafilesystem/src/lfs.c",
}
-if (_OPTIONS["osd"] ~= "uwp") then
+if (_OPTIONS["osd"] == "uwp") then
+ files {
+ MAME_DIR .. "3rdparty/lua-linenoise/linenoise_none.c",
+ }
+else
files {
MAME_DIR .. "3rdparty/lua-linenoise/linenoise.c",
}
diff --git a/scripts/src/main.lua b/scripts/src/main.lua
index f1c33edd84b..84458f9fe89 100644
--- a/scripts/src/main.lua
+++ b/scripts/src/main.lua
@@ -48,6 +48,10 @@ end
"ppapi_gles2",
"pthread",
}
+
+ configuration { "winstore*" }
+ kind "WindowedApp"
+
configuration { }
addprojectflags()
@@ -69,6 +73,32 @@ end
"Unicode",
}
+ configuration { "winstore*" }
+ -- Windows Required Files
+ files {
+ -- Manifest file
+ MAME_DIR .. "src/osd/uwp/Package.appxmanifest",
+ }
+
+ configuration { "winstore*" }
+ files {
+ MAME_DIR .. "src/osd/uwp/assets/*.png"
+ }
+ configuration "**/src/osd/uwp/assets/*.png"
+ flags { "DeploymentContent" }
+
+ -- Effects and Shaders
+ configuration { "winstore*" }
+ files {
+ MAME_DIR .. "artwork/**/*",
+ MAME_DIR .. "bgfx/**/*",
+ MAME_DIR .. "hash/*",
+ MAME_DIR .. "language/**/*",
+ MAME_DIR .. "plugins/**/*",
+ }
+ configuration "**/*"
+ flags { "DeploymentContent" }
+
configuration { "x64", "Release" }
targetsuffix "64"
if _OPTIONS["PROFILE"] then
diff --git a/scripts/src/osd/uwp.lua b/scripts/src/osd/uwp.lua
index 20540fbe477..fdaec08a3c7 100644
--- a/scripts/src/osd/uwp.lua
+++ b/scripts/src/osd/uwp.lua
@@ -70,6 +70,8 @@ project ("osd_" .. _OPTIONS["osd"])
MAME_DIR .. "src/osd/modules/render/drawnone.h",
MAME_DIR .. "src/osd/uwp/uwpcompat.cpp",
MAME_DIR .. "src/osd/uwp/uwpcompat.h",
+ MAME_DIR .. "src/osd/uwp/uwpmain.cpp",
+ MAME_DIR .. "src/osd/uwp/uwpmain.h",
MAME_DIR .. "src/osd/osdepend.h",
}
@@ -93,17 +95,21 @@ project ("ocore_" .. _OPTIONS["osd"])
}
files {
- MAME_DIR .. "src/osd/osdnet.cpp",
- MAME_DIR .. "src/osd/osdnet.h",
+ MAME_DIR .. "src/osd/osdcomm.h",
MAME_DIR .. "src/osd/osdcore.cpp",
MAME_DIR .. "src/osd/osdcore.h",
- MAME_DIR .. "src/osd/modules/osdmodule.cpp",
- MAME_DIR .. "src/osd/modules/osdmodule.h",
MAME_DIR .. "src/osd/strconv.cpp",
MAME_DIR .. "src/osd/strconv.h",
MAME_DIR .. "src/osd/osdsync.cpp",
- MAME_DIR .. "src/osd/osdsync.h",
+ MAME_DIR .. "src/osd/osdsync.h",
MAME_DIR .. "src/osd/windows/winutil.cpp",
MAME_DIR .. "src/osd/windows/winutil.h",
- --MAME_DIR .. "src/osd/modules/lib/osdlib_uwp.cpp",
+ MAME_DIR .. "src/osd/modules/osdmodule.cpp",
+ MAME_DIR .. "src/osd/modules/osdmodule.h",
+ MAME_DIR .. "src/osd/modules/file/winrtdir.cpp",
+ MAME_DIR .. "src/osd/modules/file/winrtfile.cpp",
+ MAME_DIR .. "src/osd/modules/file/winrtfile.h",
+ MAME_DIR .. "src/osd/modules/file/winrtptty.cpp",
+ MAME_DIR .. "src/osd/modules/file/winrtsocket.cpp",
+ MAME_DIR .. "src/osd/modules/lib/osdlib_uwp.cpp",
}
diff --git a/scripts/toolchain.lua b/scripts/toolchain.lua
index 6f5476bdd0a..99a3647b6ec 100644
--- a/scripts/toolchain.lua
+++ b/scripts/toolchain.lua
@@ -468,6 +468,9 @@ function toolchain(_buildDir, _subDir)
"StaticRuntime",
"NoExceptions",
}
+ flags {
+ "WinMain"
+ }
configuration { "mingw*" }
defines { "WIN32" }
diff --git a/src/osd/modules/file/winrtdir.cpp b/src/osd/modules/file/winrtdir.cpp
new file mode 100644
index 00000000000..ac5c9ecaabb
--- /dev/null
+++ b/src/osd/modules/file/winrtdir.cpp
@@ -0,0 +1,142 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+//============================================================
+//
+// windir.c - Win32 OSD core directory access functions
+//
+//============================================================
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <shlwapi.h>
+#include <tchar.h>
+
+// MAME headers
+#include "osdcore.h"
+#include "strformat.h"
+
+// MAMEOS headers
+#include "strconv.h"
+#include "../../windows/winutil.h"
+
+// standard C headers
+#include <stdio.h>
+#include <ctype.h>
+#include <cassert>
+#include <cstring>
+
+
+namespace osd {
+namespace {
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+class win_directory : public directory
+{
+public:
+ win_directory();
+ virtual ~win_directory() override;
+
+ virtual const entry *read() override;
+
+ bool open_impl(std::string const &dirname);
+
+private:
+ HANDLE m_find; // handle to the finder
+ bool m_is_first; // true if this is the first entry
+ entry m_entry; // current entry's data
+ WIN32_FIND_DATA m_data; // current raw data
+ std::string m_name; // converted name of directory
+};
+
+//============================================================
+// win_directory::win_directory
+//============================================================
+
+win_directory::win_directory()
+ : m_find(INVALID_HANDLE_VALUE)
+ , m_is_first(true)
+{
+ m_entry.name = nullptr;
+ std::memset(&m_data, 0, sizeof(m_data));
+}
+
+
+//============================================================
+// win_directory::~win_directory
+//============================================================
+
+win_directory::~win_directory()
+{
+ // free any data associated
+ if (m_find != INVALID_HANDLE_VALUE)
+ FindClose(m_find);
+}
+
+
+//============================================================
+// win_directory::read
+//============================================================
+
+const directory::entry *win_directory::read()
+{
+ // if this isn't the first file, do a find next
+ if (!m_is_first)
+ {
+ if (!FindNextFile(m_find, &m_data))
+ return nullptr;
+ }
+ m_is_first = false;
+
+ // extract the data
+ osd::text::from_tstring(m_name, m_data.cFileName);
+ m_entry.name = m_name.c_str();
+ m_entry.type = win_attributes_to_entry_type(m_data.dwFileAttributes);
+ m_entry.size = m_data.nFileSizeLow | (std::uint64_t(m_data.nFileSizeHigh) << 32);
+ m_entry.last_modified = win_time_point_from_filetime(&m_data.ftLastWriteTime);
+ return (m_entry.name != nullptr) ? &m_entry : nullptr;
+}
+
+
+//============================================================
+// win_directory::open_impl
+//============================================================
+
+bool win_directory::open_impl(std::string const &dirname)
+{
+ assert(m_find == INVALID_HANDLE_VALUE);
+
+ // append \*.* to the directory name
+ std::string dirfilter = string_format("%s\\*.*", dirname);
+
+ // convert the path to TCHARs
+ osd::text::tstring t_dirfilter = osd::text::to_tstring(dirfilter);
+
+ // attempt to find the first file
+ m_find = FindFirstFileEx(t_dirfilter.c_str(), FindExInfoStandard, &m_data, FindExSearchNameMatch, nullptr, 0);
+ return m_find != INVALID_HANDLE_VALUE;
+}
+
+} // anonymous namespace
+
+
+//============================================================
+// osd::directory::open
+//============================================================
+
+directory::ptr directory::open(std::string const &dirname)
+{
+ // allocate memory to hold the osd_tool_directory structure
+ std::unique_ptr<win_directory> dir;
+ try { dir.reset(new win_directory()); }
+ catch (...) { return nullptr; }
+
+ if (!dir->open_impl(dirname))
+ return nullptr;
+
+ return ptr(std::move(dir));
+}
+
+} // namesapce osd
diff --git a/src/osd/modules/file/winrtfile.cpp b/src/osd/modules/file/winrtfile.cpp
new file mode 100644
index 00000000000..14cb08aa7c4
--- /dev/null
+++ b/src/osd/modules/file/winrtfile.cpp
@@ -0,0 +1,465 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// winfile.c - Win32 OSD core file access functions
+//
+//============================================================
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "winfile.h"
+
+#include "../../windows/winutil.h"
+
+// MAMEOS headers
+#include "strconv.h"
+#include "unicode.h"
+
+// MAME headers
+#include "osdcore.h"
+
+#include <cassert>
+#include <cstring>
+
+// standard windows headers
+#include <windows.h>
+#include <winioctl.h>
+#include <tchar.h>
+#include <shlwapi.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+
+namespace {
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+class win_osd_file : public osd_file
+{
+public:
+ win_osd_file(win_osd_file const &) = delete;
+ win_osd_file(win_osd_file &&) = delete;
+ win_osd_file& operator=(win_osd_file const &) = delete;
+ win_osd_file& operator=(win_osd_file &&) = delete;
+
+ win_osd_file(HANDLE handle) : m_handle(handle)
+ {
+ assert(m_handle);
+ assert(INVALID_HANDLE_VALUE != m_handle);
+ }
+
+ virtual ~win_osd_file() override
+ {
+ FlushFileBuffers(m_handle);
+ CloseHandle(m_handle);
+ }
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ // attempt to set the file pointer
+ LARGE_INTEGER largeOffset;
+ largeOffset.QuadPart = offset;
+ if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN))
+ return win_error_to_file_error(GetLastError());
+
+ // then perform the read
+ DWORD result = 0;
+ if (!ReadFile(m_handle, buffer, length, &result, nullptr))
+ return win_error_to_file_error(GetLastError());
+
+ actual = result;
+ return error::NONE;
+ }
+
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ // attempt to set the file pointer
+ LARGE_INTEGER largeOffset;
+ largeOffset.QuadPart = offset;
+ if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN))
+ return win_error_to_file_error(GetLastError());
+
+ // then perform the write
+ DWORD result = 0;
+ if (!WriteFile(m_handle, buffer, length, &result, nullptr))
+ return win_error_to_file_error(GetLastError());
+
+ actual = result;
+ return error::NONE;
+ }
+
+ virtual error truncate(std::uint64_t offset) override
+ {
+ // attempt to set the file pointer
+ LARGE_INTEGER largeOffset;
+ largeOffset.QuadPart = offset;
+ if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN))
+ return win_error_to_file_error(GetLastError());
+
+ // then perform the truncation
+ if (!SetEndOfFile(m_handle))
+ return win_error_to_file_error(GetLastError());
+ else
+ return error::NONE;
+ }
+
+ virtual error flush() override
+ {
+ // shouldn't be any userspace buffers on the file handle
+ return error::NONE;
+ }
+
+private:
+ HANDLE m_handle;
+};
+
+
+
+//============================================================
+// INLINE FUNCTIONS
+//============================================================
+
+inline bool is_path_to_physical_drive(char const *path)
+{
+ return (_strnicmp(path, "\\\\.\\physicaldrive", 17) == 0);
+}
+
+
+
+//============================================================
+// create_path_recursive
+//============================================================
+
+DWORD create_path_recursive(TCHAR *path)
+{
+ // if there's still a separator, and it's not the root, nuke it and recurse
+ TCHAR *sep = _tcsrchr(path, '\\');
+ if (sep && (sep > path) && (sep[0] != ':') && (sep[-1] != '\\'))
+ {
+ *sep = 0;
+ create_path_recursive(path);
+ *sep = '\\';
+ }
+
+ // if the path already exists, we're done
+ WIN32_FILE_ATTRIBUTE_DATA fileinfo;
+ if (GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo))
+ return NO_ERROR;
+ else if (!CreateDirectory(path, nullptr))
+ return GetLastError();
+ else
+ return NO_ERROR;
+}
+
+} // anonymous namespace
+
+
+
+//============================================================
+// osd_open
+//============================================================
+
+osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize)
+{
+ std::string path;
+ try { osd_subst_env(path, orig_path); }
+ catch (...) { return error::OUT_OF_MEMORY; }
+
+ if (win_check_socket_path(path))
+ return win_open_socket(path, openflags, file, filesize);
+ else if (win_check_ptty_path(path))
+ return win_open_ptty(path, openflags, file, filesize);
+
+ // convert path to TCHAR
+ osd::text::tstring t_path = osd::text::to_tstring(path);
+
+ // convert the path into something Windows compatible (the actual interesting part appears
+ // to have been commented out???)
+ for (auto iter = t_path.begin(); iter != t_path.end(); iter++)
+ *iter = /* ('/' == *iter) ? '\\' : */ *iter;
+
+ // select the file open modes
+ DWORD disposition, access, sharemode;
+ if (openflags & OPEN_FLAG_WRITE)
+ {
+ disposition = (!is_path_to_physical_drive(path.c_str()) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING;
+ access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE;
+ sharemode = FILE_SHARE_READ;
+ }
+ else if (openflags & OPEN_FLAG_READ)
+ {
+ disposition = OPEN_EXISTING;
+ access = GENERIC_READ;
+ sharemode = FILE_SHARE_READ;
+ }
+ else
+ {
+ return error::INVALID_ACCESS;
+ }
+
+ // attempt to open the file
+ HANDLE h = CreateFile2(t_path.c_str(), access, sharemode, disposition, nullptr);
+ if (INVALID_HANDLE_VALUE == h)
+ {
+ DWORD err = GetLastError();
+ // create the path if necessary
+ if ((ERROR_PATH_NOT_FOUND == err) && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
+ {
+ auto pathsep = t_path.rfind('\\');
+ if (pathsep != decltype(t_path)::npos)
+ {
+ // create the path up to the file
+ t_path[pathsep] = 0;
+ err = create_path_recursive(&t_path[0]);
+ t_path[pathsep] = '\\';
+
+ // attempt to reopen the file
+ if (err == NO_ERROR)
+ {
+ h = CreateFile2(t_path.c_str(), access, sharemode, disposition, nullptr);
+ err = GetLastError();
+ }
+ }
+ }
+
+ // if we still failed, clean up and free
+ if (INVALID_HANDLE_VALUE == h)
+ return win_error_to_file_error(err);
+ }
+
+ // get the file size
+ FILE_STANDARD_INFO file_info;
+ GetFileInformationByHandleEx(h, FileStandardInfo, &file_info, sizeof(file_info));
+ auto lower = file_info.EndOfFile.QuadPart;
+
+ if (INVALID_FILE_SIZE == lower)
+ {
+ DWORD const err = GetLastError();
+ if (NO_ERROR != err)
+ {
+ CloseHandle(h);
+ return win_error_to_file_error(err);
+ }
+ }
+
+ try
+ {
+ file = std::make_unique<win_osd_file>(h);
+ filesize = lower;
+ return error::NONE;
+ }
+ catch (...)
+ {
+ CloseHandle(h);
+ return error::OUT_OF_MEMORY;
+ }
+}
+
+
+
+//============================================================
+// osd_openpty
+//============================================================
+
+osd_file::error osd_file::openpty(ptr &file, std::string &name)
+{
+ return error::FAILURE;
+}
+
+
+
+//============================================================
+// osd_rmfile
+//============================================================
+
+osd_file::error osd_file::remove(std::string const &filename)
+{
+ osd::text::tstring tempstr = osd::text::to_tstring(filename);
+
+ error filerr = error::NONE;
+ if (!DeleteFile(tempstr.c_str()))
+ filerr = win_error_to_file_error(GetLastError());
+
+ return filerr;
+}
+
+
+
+//============================================================
+// osd_get_physical_drive_geometry
+//============================================================
+
+bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps)
+{
+ return false;
+}
+
+
+
+//============================================================
+// osd_stat
+//============================================================
+
+std::unique_ptr<osd::directory::entry> osd_stat(const std::string &path)
+{
+ // convert the path to TCHARs
+ osd::text::tstring t_path = osd::text::to_tstring(path);
+
+ // is this path a root directory (e.g. - C:)?
+ WIN32_FIND_DATA find_data;
+ std::memset(&find_data, 0, sizeof(find_data));
+ if (isalpha(path[0]) && (path[1] == ':') && (path[2] == '\0'))
+ {
+ // need to do special logic for root directories
+ if (!GetFileAttributesEx(t_path.c_str(), GetFileExInfoStandard, &find_data.dwFileAttributes))
+ find_data.dwFileAttributes = INVALID_FILE_ATTRIBUTES;
+ }
+ else
+ {
+ // attempt to find the first file
+ HANDLE find = FindFirstFileEx(t_path.c_str(), FindExInfoStandard, &find_data, FindExSearchNameMatch, nullptr, 0);
+ if (find == INVALID_HANDLE_VALUE)
+ return nullptr;
+ FindClose(find);
+ }
+
+ // create an osd::directory::entry; be sure to make sure that the caller can
+ // free all resources by just freeing the resulting osd::directory::entry
+ osd::directory::entry *result;
+ try { result = reinterpret_cast<osd::directory::entry *>(::operator new(sizeof(*result) + path.length() + 1)); }
+ catch (...) { return nullptr; }
+ new (result) osd::directory::entry;
+
+ strcpy(((char *) result) + sizeof(*result), path.c_str());
+ result->name = ((char *) result) + sizeof(*result);
+ result->type = win_attributes_to_entry_type(find_data.dwFileAttributes);
+ result->size = find_data.nFileSizeLow | ((uint64_t) find_data.nFileSizeHigh << 32);
+ result->last_modified = win_time_point_from_filetime(&find_data.ftLastWriteTime);
+
+ return std::unique_ptr<osd::directory::entry>(result);
+}
+
+
+//============================================================
+// osd_get_full_path
+//============================================================
+
+osd_file::error osd_get_full_path(std::string &dst, std::string const &path)
+{
+ // convert the path to TCHARs
+ osd::text::tstring t_path = osd::text::to_tstring(path);
+
+ // cannonicalize the path
+ TCHAR buffer[MAX_PATH];
+ if (!GetFullPathName(t_path.c_str(), ARRAY_LENGTH(buffer), buffer, nullptr))
+ return win_error_to_file_error(GetLastError());
+
+ // convert the result back to UTF-8
+ osd::text::from_tstring(dst, buffer);
+ return osd_file::error::NONE;
+}
+
+
+
+//============================================================
+// osd_is_absolute_path
+//============================================================
+
+bool osd_is_absolute_path(std::string const &path)
+{
+ // very dumb hack here that will be imprecise
+ if (strlen(path.c_str()) >= 2 && path[1] == ':')
+ return true;
+
+ return false;
+
+}
+
+
+
+//============================================================
+// osd_get_volume_name
+//============================================================
+
+const char *osd_get_volume_name(int idx)
+{
+ return nullptr;
+}
+
+
+
+//============================================================
+// osd_is_valid_filename_char
+//============================================================
+
+bool osd_is_valid_filename_char(char32_t uchar)
+{
+ return osd_is_valid_filepath_char(uchar)
+ && uchar != '/'
+ && uchar != '\\'
+ && uchar != ':';
+}
+
+
+
+//============================================================
+// osd_is_valid_filepath_char
+//============================================================
+
+bool osd_is_valid_filepath_char(char32_t uchar)
+{
+ return uchar >= 0x20
+ && uchar != '<'
+ && uchar != '>'
+ && uchar != '\"'
+ && uchar != '|'
+ && uchar != '?'
+ && uchar != '*'
+ && !(uchar >= '\x7F' && uchar <= '\x9F')
+ && uchar_isvalid(uchar);
+}
+
+
+
+//============================================================
+// win_error_to_file_error
+//============================================================
+
+osd_file::error win_error_to_file_error(DWORD error)
+{
+ osd_file::error filerr;
+
+ // convert a Windows error to a osd_file::error
+ switch (error)
+ {
+ case ERROR_SUCCESS:
+ filerr = osd_file::error::NONE;
+ break;
+
+ case ERROR_OUTOFMEMORY:
+ filerr = osd_file::error::OUT_OF_MEMORY;
+ break;
+
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_FILENAME_EXCED_RANGE:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_NAME:
+ filerr = osd_file::error::NOT_FOUND;
+ break;
+
+ case ERROR_ACCESS_DENIED:
+ filerr = osd_file::error::ACCESS_DENIED;
+ break;
+
+ case ERROR_SHARING_VIOLATION:
+ filerr = osd_file::error::ALREADY_OPEN;
+ break;
+
+ default:
+ filerr = osd_file::error::FAILURE;
+ break;
+ }
+ return filerr;
+}
diff --git a/src/osd/modules/file/winrtfile.h b/src/osd/modules/file/winrtfile.h
new file mode 100644
index 00000000000..9a6f1b8fc34
--- /dev/null
+++ b/src/osd/modules/file/winrtfile.h
@@ -0,0 +1,34 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// winfile.h - File access functions
+//
+//============================================================
+#ifndef MAME_OSD_WINDOWS_WINFILE_H
+#define MAME_OSD_WINDOWS_WINFILE_H
+
+#include "osdcore.h"
+
+#include <cstdint>
+#include <string>
+
+#include <winsock2.h>
+
+
+//============================================================
+// PROTOTYPES
+//============================================================
+
+bool win_init_sockets();
+void win_cleanup_sockets();
+
+bool win_check_socket_path(std::string const &path);
+osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize);
+
+bool win_check_ptty_path(std::string const &path);
+osd_file::error win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize);
+
+osd_file::error win_error_to_file_error(DWORD error);
+
+#endif // MAME_OSD_WINDOWS_WINFILE_H
diff --git a/src/osd/modules/file/winrtptty.cpp b/src/osd/modules/file/winrtptty.cpp
new file mode 100644
index 00000000000..e32f035582d
--- /dev/null
+++ b/src/osd/modules/file/winrtptty.cpp
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "winrtfile.h"
+
+#include "strconv.h"
+
+#include <cassert>
+
+#include <windows.h>
+#include <stdlib.h>
+
+
+namespace {
+char const *const winfile_ptty_identifier = "\\\\.\\pipe\\";
+
+
+class win_osd_ptty : public osd_file
+{
+public:
+ win_osd_ptty(win_osd_ptty const &) = delete;
+ win_osd_ptty(win_osd_ptty &&) = delete;
+ win_osd_ptty& operator=(win_osd_ptty const &) = delete;
+ win_osd_ptty& operator=(win_osd_ptty &&) = delete;
+
+ win_osd_ptty(HANDLE handle) : m_handle(handle)
+ {
+ assert(m_handle);
+ assert(INVALID_HANDLE_VALUE != m_handle);
+ }
+
+ ~win_osd_ptty()
+ {
+ }
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ {
+ DWORD bytes_read;
+ if (!ReadFile(m_handle, buffer, count, &bytes_read, nullptr))
+ return win_error_to_file_error(GetLastError());
+
+ actual = bytes_read;
+ return error::NONE;
+ }
+
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ {
+ DWORD bytes_written;
+ if (!WriteFile(m_handle, buffer, count, &bytes_written, nullptr))
+ return win_error_to_file_error(GetLastError());
+
+ actual = bytes_written;
+ return error::NONE;
+ }
+
+ virtual error truncate(std::uint64_t offset) override
+ {
+ // doesn't make sense for a PTTY
+ return error::INVALID_ACCESS;
+ }
+
+ virtual error flush() override
+ {
+ // don't want to wait for client to read all data as implied by FlushFileBuffers
+ return error::NONE;
+ }
+
+private:
+ HANDLE m_handle;
+};
+
+} // anonymous namespace
+
+
+bool win_check_ptty_path(std::string const &path)
+{
+ if (strncmp(path.c_str(), winfile_ptty_identifier, strlen(winfile_ptty_identifier)) == 0) return true;
+ return false;
+}
+
+
+osd_file::error win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize)
+{
+ return osd_file::error::ACCESS_DENIED;
+}
diff --git a/src/osd/modules/file/winrtsocket.cpp b/src/osd/modules/file/winrtsocket.cpp
new file mode 100644
index 00000000000..94a8c3c3dc0
--- /dev/null
+++ b/src/osd/modules/file/winrtsocket.cpp
@@ -0,0 +1,274 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// winsocket.c - Windows socket (inet) access functions
+//
+//============================================================
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "winfile.h"
+
+// MAME headers
+#include "osdcore.h"
+
+#include <cassert>
+#include <cstdio>
+
+// standard windows headers
+#include <windows.h>
+#include <winioctl.h>
+#include <tchar.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+
+namespace {
+char const *const winfile_socket_identifier = "socket.";
+
+
+class win_osd_socket : public osd_file
+{
+public:
+ win_osd_socket(win_osd_socket const &) = delete;
+ win_osd_socket(win_osd_socket &&) = delete;
+ win_osd_socket& operator=(win_osd_socket const &) = delete;
+ win_osd_socket& operator=(win_osd_socket &&) = delete;
+
+ win_osd_socket(SOCKET s, bool l)
+ : m_socket(s)
+ , m_listening(l)
+ {
+ assert(INVALID_SOCKET != m_socket);
+ }
+
+ virtual ~win_osd_socket() override
+ {
+ closesocket(m_socket);
+ }
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(m_socket, &readfds);
+
+ struct timeval timeout;
+ timeout.tv_sec = timeout.tv_usec = 0;
+
+ if (select(m_socket + 1, &readfds, nullptr, nullptr, &timeout) < 0)
+ {
+ char line[80];
+ std::sprintf(line, "win_read_socket : %s : %d ", __FILE__, __LINE__);
+ std::perror(line);
+ return error::FAILURE;
+ }
+ else if (FD_ISSET(m_socket, &readfds))
+ {
+ if (!m_listening)
+ {
+ // connected socket
+ int const result = recv(m_socket, (char*)buffer, length, 0);
+ if (result < 0)
+ {
+ return wsa_error_to_file_error(WSAGetLastError());
+ }
+ else
+ {
+ actual = result;
+ return error::NONE;
+ }
+ }
+ else
+ {
+ // listening socket
+ SOCKET const accepted = accept(m_socket, nullptr, nullptr);
+ if (INVALID_SOCKET == accepted)
+ {
+ return wsa_error_to_file_error(WSAGetLastError());
+ }
+ else
+ {
+ closesocket(m_socket);
+ m_socket = accepted;
+ m_listening = false;
+ actual = 0;
+
+ return error::NONE;
+ }
+ }
+ }
+ else
+ {
+ return error::FAILURE;
+ }
+ }
+
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ auto const result = send(m_socket, reinterpret_cast<const char *>(buffer), length, 0);
+ if (result < 0)
+ return wsa_error_to_file_error(WSAGetLastError());
+
+ actual = result;
+ return error::NONE;
+ }
+
+ virtual error truncate(std::uint64_t offset) override
+ {
+ // doesn't make sense for a socket
+ return error::INVALID_ACCESS;
+ }
+
+ virtual error flush() override
+ {
+ // no buffers to flush
+ return error::NONE;
+ }
+
+ static error wsa_error_to_file_error(int err)
+ {
+ switch (err)
+ {
+ case 0: return error::NONE;
+ case WSAEACCES: return error::ACCESS_DENIED;
+ case WSAEADDRINUSE: return error::ALREADY_OPEN;
+ case WSAEADDRNOTAVAIL: return error::NOT_FOUND;
+ case WSAECONNREFUSED: return error::NOT_FOUND;
+ case WSAEHOSTUNREACH: return error::NOT_FOUND;
+ case WSAENETUNREACH: return error::NOT_FOUND;
+ default: return error::FAILURE;
+ }
+ }
+
+private:
+ SOCKET m_socket;
+ bool m_listening;
+};
+
+} // anonymous namespace
+
+
+bool win_init_sockets()
+{
+ WSADATA wsaData;
+ WORD const version = MAKEWORD(2, 0);
+ int const error = WSAStartup(version, &wsaData);
+
+ // check for error
+ if (error)
+ {
+ // error occurred
+ return false;
+ }
+
+ // check for correct version
+ if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion ) != 0)
+ {
+ // incorrect WinSock version
+ WSACleanup();
+ return false;
+ }
+
+ // WinSock has been initialized
+ return true;
+}
+
+
+void win_cleanup_sockets()
+{
+ WSACleanup();
+}
+
+
+bool win_check_socket_path(std::string const &path)
+{
+ if (strncmp(path.c_str(), winfile_socket_identifier, strlen(winfile_socket_identifier)) == 0 &&
+ strchr(path.c_str(), ':') != nullptr) return true;
+ return false;
+}
+
+
+osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize)
+{
+ char hostname[256];
+ int port;
+ std::sscanf(&path[strlen(winfile_socket_identifier)], "%255[^:]:%d", hostname, &port);
+
+ struct hostent const *const localhost = gethostbyname(hostname);
+ if (!localhost)
+ return osd_file::error::NOT_FOUND;
+
+ struct sockaddr_in sai;
+ memset(&sai, 0, sizeof(sai));
+ sai.sin_family = AF_INET;
+ sai.sin_port = htons(port);
+ sai.sin_addr = *reinterpret_cast<struct in_addr *>(localhost->h_addr);
+
+ SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (INVALID_SOCKET == sock)
+ return win_osd_socket::wsa_error_to_file_error(WSAGetLastError());
+
+ int const flag = 1;
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&flag), sizeof(flag)) == SOCKET_ERROR)
+ {
+ int const err = WSAGetLastError();
+ closesocket(sock);
+ return win_osd_socket::wsa_error_to_file_error(err);
+ }
+
+ // listening socket support
+ if (openflags & OPEN_FLAG_CREATE)
+ {
+ //printf("Listening for client at '%s' on port '%d'\n", hostname, port);
+ // bind socket...
+ if (bind(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) == SOCKET_ERROR)
+ {
+ int const err = WSAGetLastError();
+ closesocket(sock);
+ return win_osd_socket::wsa_error_to_file_error(err);
+ }
+
+ // start to listen...
+ if (listen(sock, 1) == SOCKET_ERROR)
+ {
+ int const err = WSAGetLastError();
+ closesocket(sock);
+ return win_osd_socket::wsa_error_to_file_error(err);
+ }
+
+ // mark socket as "listening"
+ try
+ {
+ file = std::make_unique<win_osd_socket>(sock, true);
+ filesize = 0;
+ return osd_file::error::NONE;
+ }
+ catch (...)
+ {
+ closesocket(sock);
+ return osd_file::error::OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ //printf("Connecting to server '%s' on port '%d'\n", hostname, port);
+ if (connect(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) == SOCKET_ERROR)
+ {
+ closesocket(sock);
+ return osd_file::error::ACCESS_DENIED; // have to return this value or bitb won't try to bind on connect failure
+ }
+ try
+ {
+ file = std::make_unique<win_osd_socket>(sock, false);
+ filesize = 0;
+ return osd_file::error::NONE;
+ }
+ catch (...)
+ {
+ closesocket(sock);
+ return osd_file::error::OUT_OF_MEMORY;
+ }
+ }
+}
diff --git a/src/osd/modules/lib/osdlib_uwp.cpp b/src/osd/modules/lib/osdlib_uwp.cpp
new file mode 100644
index 00000000000..66f753444b6
--- /dev/null
+++ b/src/osd/modules/lib/osdlib_uwp.cpp
@@ -0,0 +1,383 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont
+//============================================================
+//
+// sdlos_*.c - OS specific low level code
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+//============================================================
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <mmsystem.h>
+
+#include <stdlib.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+
+#include <cstdio>
+#include <memory>
+
+// MAME headers
+#include "osdlib.h"
+#include "osdcomm.h"
+#include "osdcore.h"
+#include "strconv.h"
+
+#include <windows.h>
+#include <wrl\client.h>
+
+#include "strconv.h"
+
+using namespace Platform;
+using namespace Windows::ApplicationModel::DataTransfer;
+using namespace Windows::Foundation;
+
+#include <map>
+//============================================================
+// MACROS
+//============================================================
+
+// presumed size of a page of memory
+#define PAGE_SIZE 4096
+
+// align allocations to start or end of the page?
+#define GUARD_ALIGN_START 0
+
+#if defined(__BIGGEST_ALIGNMENT__)
+#define MAX_ALIGNMENT __BIGGEST_ALIGNMENT__
+#elif defined(__AVX__)
+#define MAX_ALIGNMENT 32
+#elif defined(__SSE__) || defined(__x86_64__) || defined(_M_X64)
+#define MAX_ALIGNMENT 16
+#else
+#define MAX_ALIGNMENT sizeof(int64_t)
+#endif
+
+
+//============================================================
+// GLOBAL VARIABLES
+//============================================================
+
+std::map<const char *, std::unique_ptr<char>> g_runtime_environment;
+
+//============================================================
+// osd_getenv
+//============================================================
+
+const char *osd_getenv(const char *name)
+{
+ for (auto iter = g_runtime_environment.begin(); iter != g_runtime_environment.end(); iter++)
+ {
+ if (stricmp(iter->first, name) == 0)
+ {
+ osd_printf_debug("ENVIRONMENT: Get %s = value: '%s'", name, iter->second.get());
+ return iter->second.get();
+ }
+ }
+
+ return nullptr;
+}
+
+
+//============================================================
+// osd_setenv
+//============================================================
+
+int osd_setenv(const char *name, const char *value, int overwrite)
+{
+ if (!overwrite)
+ {
+ if (osd_getenv(name) != nullptr)
+ return 0;
+ }
+
+ auto buf = std::make_unique<char>(strlen(name) + strlen(value) + 2);
+ sprintf(buf.get(), "%s=%s", name, value);
+
+ g_runtime_environment[name] = std::move(buf);
+ osd_printf_debug("ENVIRONMENT: Set %s to value: '%s'", name, buf.get());
+
+ return 0;
+}
+
+//============================================================
+// osd_process_kill
+//============================================================
+
+void osd_process_kill()
+{
+ std::fflush(stdout);
+ std::fflush(stderr);
+ TerminateProcess(GetCurrentProcess(), -1);
+}
+
+//============================================================
+// osd_malloc
+//============================================================
+
+void *osd_malloc(size_t size)
+{
+#ifndef MALLOC_DEBUG
+ return malloc(size);
+#else
+ // add in space for the size and offset
+ size += MAX_ALIGNMENT + sizeof(size_t) + 2;
+ size &= ~size_t(1);
+
+ // basic objects just come from the heap
+ uint8_t *const block = reinterpret_cast<uint8_t *>(HeapAlloc(GetProcessHeap(), 0, size));
+ if (block == nullptr)
+ return nullptr;
+ uint8_t *const result = reinterpret_cast<uint8_t *>(reinterpret_cast<uintptr_t>(block + sizeof(size_t) + MAX_ALIGNMENT) & ~(uintptr_t(MAX_ALIGNMENT) - 1));
+
+ // store the size and return and pointer to the data afterward
+ *reinterpret_cast<size_t *>(block) = size;
+ *(result - 1) = result - block;
+ return result;
+#endif
+}
+
+
+//============================================================
+// osd_malloc_array
+//============================================================
+
+void *osd_malloc_array(size_t size)
+{
+#ifndef MALLOC_DEBUG
+ return malloc(size);
+#else
+ // add in space for the size and offset
+ size += MAX_ALIGNMENT + sizeof(size_t) + 2;
+ size &= ~size_t(1);
+
+ // round the size up to a page boundary
+ size_t const rounded_size = ((size + sizeof(void *) + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
+
+ // reserve that much memory, plus two guard pages
+ void *page_base = VirtualAlloc(nullptr, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS);
+ if (page_base == nullptr)
+ return nullptr;
+
+ // now allow access to everything but the first and last pages
+ page_base = VirtualAlloc(reinterpret_cast<uint8_t *>(page_base) + PAGE_SIZE, rounded_size, MEM_COMMIT, PAGE_READWRITE);
+ if (page_base == nullptr)
+ return nullptr;
+
+ // work backwards from the page base to get to the block base
+ uint8_t *const block = GUARD_ALIGN_START ? reinterpret_cast<uint8_t *>(page_base) : (reinterpret_cast<uint8_t *>(page_base) + rounded_size - size);
+ uint8_t *const result = reinterpret_cast<uint8_t *>(reinterpret_cast<uintptr_t>(block + sizeof(size_t) + MAX_ALIGNMENT) & ~(uintptr_t(MAX_ALIGNMENT) - 1));
+
+ // store the size at the start with a flag indicating it has a guard page
+ *reinterpret_cast<size_t *>(block) = size | 1;
+ *(result - 1) = result - block;
+ return result;
+#endif
+}
+
+
+//============================================================
+// osd_free
+//============================================================
+
+void osd_free(void *ptr)
+{
+#ifndef MALLOC_DEBUG
+ free(ptr);
+#else
+ uint8_t const offset = *(reinterpret_cast<uint8_t *>(ptr) - 1);
+ uint8_t *const block = reinterpret_cast<uint8_t *>(ptr) - offset;
+ size_t const size = *reinterpret_cast<size_t *>(block);
+
+ if ((size & 0x1) == 0)
+ {
+ // if no guard page, just free the pointer
+ HeapFree(GetProcessHeap(), 0, block);
+ }
+ else
+ {
+ // large items need more care
+ ULONG_PTR const page_base = reinterpret_cast<ULONG_PTR>(block) & ~(PAGE_SIZE - 1);
+ VirtualFree(reinterpret_cast<void *>(page_base - PAGE_SIZE), 0, MEM_RELEASE);
+ }
+#endif
+}
+
+
+//============================================================
+// osd_alloc_executable
+//
+// allocates "size" bytes of executable memory. this must take
+// things like NX support into account.
+//============================================================
+
+void *osd_alloc_executable(size_t size)
+{
+ return nullptr;
+}
+
+
+//============================================================
+// osd_free_executable
+//
+// frees memory allocated with osd_alloc_executable
+//============================================================
+
+void osd_free_executable(void *ptr, size_t size)
+{
+}
+
+
+//============================================================
+// osd_break_into_debugger
+//============================================================
+
+void osd_break_into_debugger(const char *message)
+{
+#ifdef OSD_WINDOWS
+ if (IsDebuggerPresent())
+ {
+ win_output_debug_string_utf8(message);
+ DebugBreak();
+ }
+ else if (s_debugger_stack_crawler != nullptr)
+ (*s_debugger_stack_crawler)();
+#else
+ if (IsDebuggerPresent())
+ {
+ OutputDebugStringA(message);
+ __debugbreak();
+ }
+#endif
+}
+
+//============================================================
+// get_clipboard_text_by_format
+//============================================================
+
+static char *get_clipboard_text_by_format(UINT format, std::string (*convert)(LPCVOID data))
+{
+ /*DataPackageView^ dataPackageView;
+ IAsyncOperation<String^>^ getTextOp;
+ String^ clipboardText;
+
+ dataPackageView = Clipboard::GetContent();
+ getTextOp = dataPackageView->GetTextAsync();
+ clipboardText = getTextOp->GetResults();
+
+ return osd::text::from_wstring(clipboardText->Data()).c_str();*/
+ return nullptr;
+}
+
+//============================================================
+// convert_wide
+//============================================================
+
+static std::string convert_wide(LPCVOID data)
+{
+ return osd::text::from_wstring((LPCWSTR) data);
+}
+
+//============================================================
+// convert_ansi
+//============================================================
+
+static std::string convert_ansi(LPCVOID data)
+{
+ return osd::text::from_astring((LPCSTR) data);
+}
+
+//============================================================
+// osd_get_clipboard_text
+//============================================================
+
+char *osd_get_clipboard_text(void)
+{
+ // try to access unicode text
+ char *result = get_clipboard_text_by_format(CF_UNICODETEXT, convert_wide);
+
+ // try to access ANSI text
+ if (result == nullptr)
+ result = get_clipboard_text_by_format(CF_TEXT, convert_ansi);
+
+ return result;
+}
+
+//============================================================
+// osd_dynamic_bind
+//============================================================
+
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+// for classic desktop applications
+#define load_library(filename) LoadLibrary(filename)
+#else
+// for Windows Store universal applications
+#define load_library(filename) LoadPackagedLibrary(filename, 0)
+#endif
+
+namespace osd {
+class dynamic_module_win32_impl : public dynamic_module
+{
+public:
+ dynamic_module_win32_impl(std::vector<std::string> &libraries)
+ : m_module(nullptr)
+ {
+ m_libraries = libraries;
+ }
+
+ virtual ~dynamic_module_win32_impl() override
+ {
+ if (m_module != nullptr)
+ FreeLibrary(m_module);
+ };
+
+protected:
+ virtual generic_fptr_t get_symbol_address(char const *symbol) override
+ {
+ /*
+ * given a list of libraries, if a first symbol is successfully loaded from
+ * one of them, all additional symbols will be loaded from the same library
+ */
+ if (m_module)
+ {
+ return reinterpret_cast<generic_fptr_t>(GetProcAddress(m_module, symbol));
+ }
+
+ for (auto const &library : m_libraries)
+ {
+ osd::text::tstring tempstr = osd::text::to_tstring(library);
+ HMODULE module = load_library(tempstr.c_str());
+
+ if (module != nullptr)
+ {
+ generic_fptr_t function = reinterpret_cast<generic_fptr_t>(GetProcAddress(module, symbol));
+
+ if (function != nullptr)
+ {
+ m_module = module;
+ return function;
+ }
+ else
+ {
+ FreeLibrary(module);
+ }
+ }
+ }
+
+ return nullptr;
+ }
+
+private:
+ std::vector<std::string> m_libraries;
+ HMODULE m_module;
+};
+
+dynamic_module::ptr dynamic_module::open(std::vector<std::string> &&names)
+{
+ return std::make_unique<dynamic_module_win32_impl>(names);
+}
+
+} // namespace osd
diff --git a/src/osd/strconv.cpp b/src/osd/strconv.cpp
index b8c6b999c19..d8fed98d687 100644
--- a/src/osd/strconv.cpp
+++ b/src/osd/strconv.cpp
@@ -5,7 +5,7 @@
// strconv.cpp - Win32 string conversion
//
//============================================================
-#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
+#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) || defined(OSD_UWP)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
@@ -16,7 +16,7 @@
// MAMEOS headers
#include "strconv.h"
-#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS)
+#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) || defined(OSD_UWP)
namespace
{
diff --git a/src/osd/uwp/Package.appxmanifest b/src/osd/uwp/Package.appxmanifest
new file mode 100644
index 00000000000..466e8c2a084
--- /dev/null
+++ b/src/osd/uwp/Package.appxmanifest
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
+ <Identity Name="f0273023-de0a-46a5-b0db-1514f3a84c71" Publisher="CN=bradhugh" Version="1.0.0.0" />
+ <mp:PhoneIdentity PhoneProductId="f0273023-de0a-46a5-b0db-1514f3a84c71" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
+ <Properties>
+ <DisplayName>MAME</DisplayName>
+ <PublisherDisplayName>MAME Team</PublisherDisplayName>
+ <Logo>src\osd\uwp\assets\StoreLogo.png</Logo>
+ </Properties>
+ <Dependencies>
+ <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
+ </Dependencies>
+ <Resources>
+ <Resource Language="x-generate" />
+ </Resources>
+ <Applications>
+ <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="Mameuwp.App">
+ <uap:VisualElements DisplayName="MAME" Square150x150Logo="src\osd\uwp\assets\Square150x150Logo.png" Square44x44Logo="src\osd\uwp\assets\Square44x44Logo.png" Description="MAME for Windows 10" BackgroundColor="transparent">
+ <uap:DefaultTile Wide310x150Logo="src\osd\uwp\assets\Wide310x150Logo.png">
+ <uap:ShowNameOnTiles>
+ <uap:ShowOn Tile="square150x150Logo" />
+ </uap:ShowNameOnTiles>
+ </uap:DefaultTile>
+ <uap:SplashScreen Image="src\osd\uwp\assets\SplashScreen.scale-200.png" />
+ <uap:InitialRotationPreference>
+ <uap:Rotation Preference="landscape" />
+ </uap:InitialRotationPreference>
+ </uap:VisualElements>
+ </Application>
+ </Applications>
+ <Capabilities>
+ <Capability Name="internetClient" />
+ <Capability Name="codeGeneration" />
+ <Capability Name="privateNetworkClientServer" />
+ </Capabilities>
+</Package> \ No newline at end of file
diff --git a/src/osd/uwp/assets/LockScreenLogo.scale-200.png b/src/osd/uwp/assets/LockScreenLogo.scale-200.png
new file mode 100644
index 00000000000..735f57adb5d
--- /dev/null
+++ b/src/osd/uwp/assets/LockScreenLogo.scale-200.png
Binary files differ
diff --git a/src/osd/uwp/assets/SplashScreen.scale-200.png b/src/osd/uwp/assets/SplashScreen.scale-200.png
new file mode 100644
index 00000000000..023e7f1feda
--- /dev/null
+++ b/src/osd/uwp/assets/SplashScreen.scale-200.png
Binary files differ
diff --git a/src/osd/uwp/assets/Square150x150Logo.scale-200.png b/src/osd/uwp/assets/Square150x150Logo.scale-200.png
new file mode 100644
index 00000000000..af49fec1a54
--- /dev/null
+++ b/src/osd/uwp/assets/Square150x150Logo.scale-200.png
Binary files differ
diff --git a/src/osd/uwp/assets/Square44x44Logo.scale-200.png b/src/osd/uwp/assets/Square44x44Logo.scale-200.png
new file mode 100644
index 00000000000..ce342a2ec8a
--- /dev/null
+++ b/src/osd/uwp/assets/Square44x44Logo.scale-200.png
Binary files differ
diff --git a/src/osd/uwp/assets/Square44x44Logo.targetsize-24_altform-unplated.png b/src/osd/uwp/assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 00000000000..f6c02ce97e0
--- /dev/null
+++ b/src/osd/uwp/assets/Square44x44Logo.targetsize-24_altform-unplated.png
Binary files differ
diff --git a/src/osd/uwp/assets/StoreLogo.png b/src/osd/uwp/assets/StoreLogo.png
new file mode 100644
index 00000000000..7385b56c0e4
--- /dev/null
+++ b/src/osd/uwp/assets/StoreLogo.png
Binary files differ
diff --git a/src/osd/uwp/assets/Wide310x150Logo.scale-200.png b/src/osd/uwp/assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 00000000000..288995b397f
--- /dev/null
+++ b/src/osd/uwp/assets/Wide310x150Logo.scale-200.png
Binary files differ
diff --git a/src/osd/uwp/uwpcompat.cpp b/src/osd/uwp/uwpcompat.cpp
index ffd6623ca7d..0358d65bcf8 100644
--- a/src/osd/uwp/uwpcompat.cpp
+++ b/src/osd/uwp/uwpcompat.cpp
@@ -16,15 +16,13 @@
#include "emu.h"
extern "C" {
-
- int __cdecl system(const char *command)
- {
- return ENOENT;
- }
-
- const char *getenv(const char *varname)
+
+ BOOL WINAPI GetVersionEx(
+ _Inout_ LPOSVERSIONINFO lpVersionInfo
+ )
{
- return osd_getenv(varname);
+ lpVersionInfo->dwMajorVersion = 10;
+ return TRUE;
}
HANDLE
diff --git a/src/osd/uwp/uwpmain.cpp b/src/osd/uwp/uwpmain.cpp
new file mode 100644
index 00000000000..173cf7ab536
--- /dev/null
+++ b/src/osd/uwp/uwpmain.cpp
@@ -0,0 +1,186 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+//============================================================
+//
+// main.c - Win32 main program
+//
+//============================================================
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <tchar.h>
+#include <stdlib.h>
+#include <vector>
+#include <string>
+
+#include "uwpmain.h"
+#include <wrl\client.h>
+#undef interface
+
+using namespace Windows::ApplicationModel;
+using namespace Windows::ApplicationModel::Core;
+using namespace Windows::ApplicationModel::Activation;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Input;
+using namespace Windows::System;
+using namespace Windows::Foundation;
+using namespace Windows::Graphics::Display;
+
+using namespace MameUWP;
+
+Platform::Array<Platform::String^>^ g_command_args;
+
+// The main function is only used to initialize our IFrameworkView class.
+[Platform::MTAThread]
+int main(Platform::Array<Platform::String^>^ args)
+{
+ g_command_args = args;
+ auto direct3DApplicationSource = ref new Direct3DApplicationSource();
+ CoreApplication::Run(direct3DApplicationSource);
+ return 0;
+}
+
+IFrameworkView^ Direct3DApplicationSource::CreateView()
+{
+ return ref new App();
+}
+
+App::App() :
+ m_windowClosed(false),
+ m_windowVisible(true)
+{
+}
+
+// The first method called when the IFrameworkView is being created.
+void App::Initialize(CoreApplicationView^ applicationView)
+{
+ // Register event handlers for app lifecycle. This example includes Activated, so that we
+ // can make the CoreWindow active and start rendering on the window.
+ applicationView->Activated +=
+ ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
+
+ CoreApplication::Suspending +=
+ ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
+
+ CoreApplication::Resuming +=
+ ref new EventHandler<Platform::Object^>(this, &App::OnResuming);
+}
+
+// Called when the CoreWindow object is created (or re-created).
+void App::SetWindow(CoreWindow^ window)
+{
+ window->SizeChanged +=
+ ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);
+
+ window->VisibilityChanged +=
+ ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
+
+ window->Closed +=
+ ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
+
+ DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
+
+ currentDisplayInformation->DpiChanged +=
+ ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged);
+
+ currentDisplayInformation->OrientationChanged +=
+ ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged);
+
+ DisplayInformation::DisplayContentsInvalidated +=
+ ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated);
+}
+
+// Initializes scene resources, or loads a previously saved app state.
+void App::Load(Platform::String^ entryPoint)
+{
+}
+
+// This method is called after the window becomes active.
+void App::Run()
+{
+ // parse config and cmdline options
+// DWORD result;
+ {
+/* winrt_options options;
+ winrt_osd_interface osd(options);
+
+ char exe_path[MAX_PATH];
+ GetModuleFileNameA(NULL, exe_path, MAX_PATH);
+ char* args[2] = { exe_path, (char*)"-verbose" };
+
+ osd.register_options();
+ cli_frontend frontend(options, osd);
+ result = frontend.execute(ARRAY_LENGTH(args), args);*/
+ }
+}
+
+// Required for IFrameworkView.
+// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
+// class is torn down while the app is in the foreground.
+void App::Uninitialize()
+{
+}
+
+// Application lifecycle event handlers.
+
+void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
+{
+ // Run() won't start until the CoreWindow is activated.
+}
+
+void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
+{
+ // Save app state asynchronously after requesting a deferral. Holding a deferral
+ // indicates that the application is busy performing suspending operations. Be
+ // aware that a deferral may not be held indefinitely. After about five seconds,
+ // the app will be forced to exit.
+ SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
+
+ //create_task([this, deferral]()
+ //{
+ // //m_deviceResources->Trim();
+
+ // // Insert your code here.
+
+ // deferral->Complete();
+ //});
+}
+
+void App::OnResuming(Platform::Object^ sender, Platform::Object^ args)
+{
+ // Restore any data or state that was unloaded on suspend. By default, data
+ // and state are persisted when resuming from suspend. Note that this event
+ // does not occur if the app was previously terminated.
+
+ // Insert your code here.
+}
+
+// Window event handlers.
+
+void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
+{
+}
+
+void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
+{
+ m_windowVisible = args->Visible;
+}
+
+void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
+{
+ m_windowClosed = true;
+}
+
+// DisplayInformation event handlers.
+void App::OnDpiChanged(DisplayInformation^ sender, Object^ args)
+{
+}
+
+void App::OnOrientationChanged(DisplayInformation^ sender, Object^ args)
+{
+}
+
+void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args)
+{
+}
diff --git a/src/osd/uwp/uwpmain.h b/src/osd/uwp/uwpmain.h
new file mode 100644
index 00000000000..20f82e2430e
--- /dev/null
+++ b/src/osd/uwp/uwpmain.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Brad Hughes
+//============================================================
+//
+// uwpmain.h - Universal Windows Paltform
+//
+//============================================================
+
+#pragma once
+
+namespace MameUWP
+{
+ // Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events.
+ ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
+ {
+ public:
+ App();
+
+ // IFrameworkView Methods.
+ virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
+ virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
+ virtual void Load(Platform::String^ entryPoint);
+ virtual void Run();
+ virtual void Uninitialize();
+
+ protected:
+ // Application lifecycle event handlers.
+ void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
+ void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args);
+ void OnResuming(Platform::Object^ sender, Platform::Object^ args);
+
+ // Window event handlers.
+ void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
+ void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
+ void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
+
+ // DisplayInformation event handlers.
+ void OnDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
+ void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
+ void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
+
+ private:
+ bool m_windowClosed;
+ bool m_windowVisible;
+ };
+}
+
+ref class Direct3DApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
+{
+public:
+ virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView();
+};