diff options
Diffstat (limited to 'src/osd/modules/lib/osdlib_uwp.cpp')
-rw-r--r-- | src/osd/modules/lib/osdlib_uwp.cpp | 383 |
1 files changed, 383 insertions, 0 deletions
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 |