Some more work on UWP (nw)
6
3rdparty/lua-linenoise/linenoise_none.c
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#include <lua.h>
|
||||
|
||||
int luaopen_linenoise(lua_State *L)
|
||||
{
|
||||
return 1;
|
||||
}
|
@ -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",
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
}
|
||||
|
@ -468,6 +468,9 @@ function toolchain(_buildDir, _subDir)
|
||||
"StaticRuntime",
|
||||
"NoExceptions",
|
||||
}
|
||||
flags {
|
||||
"WinMain"
|
||||
}
|
||||
|
||||
configuration { "mingw*" }
|
||||
defines { "WIN32" }
|
||||
|
142
src/osd/modules/file/winrtdir.cpp
Normal file
@ -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
|
465
src/osd/modules/file/winrtfile.cpp
Normal file
@ -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;
|
||||
}
|
34
src/osd/modules/file/winrtfile.h
Normal file
@ -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
|
87
src/osd/modules/file/winrtptty.cpp
Normal file
@ -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;
|
||||
}
|
274
src/osd/modules/file/winrtsocket.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
383
src/osd/modules/lib/osdlib_uwp.cpp
Normal file
@ -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
|
@ -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
|
||||
{
|
||||
|
36
src/osd/uwp/Package.appxmanifest
Normal file
@ -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>
|
BIN
src/osd/uwp/assets/LockScreenLogo.scale-200.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
src/osd/uwp/assets/SplashScreen.scale-200.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
src/osd/uwp/assets/Square150x150Logo.scale-200.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
src/osd/uwp/assets/Square44x44Logo.scale-200.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
BIN
src/osd/uwp/assets/StoreLogo.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
src/osd/uwp/assets/Wide310x150Logo.scale-200.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
@ -16,15 +16,13 @@
|
||||
#include "emu.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int __cdecl system(const char *command)
|
||||
|
||||
BOOL WINAPI GetVersionEx(
|
||||
_Inout_ LPOSVERSIONINFO lpVersionInfo
|
||||
)
|
||||
{
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
const char *getenv(const char *varname)
|
||||
{
|
||||
return osd_getenv(varname);
|
||||
lpVersionInfo->dwMajorVersion = 10;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HANDLE
|
||||
|
186
src/osd/uwp/uwpmain.cpp
Normal file
@ -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)
|
||||
{
|
||||
}
|
52
src/osd/uwp/uwpmain.h
Normal file
@ -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();
|
||||
};
|