Browse Source

[WIP] WinRT Refactor 1

1. folder change, winphone -> winrt
2. Split files into different folder models
3. Split I/O simulation layer and utils
4. Using library orders to make simulation layer work rather than macro definitions
louyihua 8 years ago
parent
commit
e8fdfd0f07
33 changed files with 890 additions and 171 deletions
  1. 4 3
      .gitignore
  2. 0 145
      winphone/SDLPal/WinPhoneUtil.cpp
  3. 0 0
      winrt/SDL2/README.txt
  4. 106 0
      winrt/SDLPal.Common/AsyncHelper.h
  5. 309 0
      winrt/SDLPal.Common/WinRTIO.cpp
  6. 21 3
      winphone/SDLPal.sln
  7. 0 0
      winrt/SDLPal.WindowsPhone/Assets/Logo.scale-100.png
  8. 0 0
      winrt/SDLPal.WindowsPhone/Assets/Logo.scale-140.png
  9. 0 0
      winrt/SDLPal.WindowsPhone/Assets/Logo.scale-240.png
  10. 0 0
      winrt/SDLPal.WindowsPhone/Assets/SmallLogo.scale-100.png
  11. 0 0
      winrt/SDLPal.WindowsPhone/Assets/SmallLogo.scale-140.png
  12. 0 0
      winrt/SDLPal.WindowsPhone/Assets/SmallLogo.scale-240.png
  13. 0 0
      winrt/SDLPal.WindowsPhone/Assets/SplashScreen.scale-100.png
  14. 0 0
      winrt/SDLPal.WindowsPhone/Assets/SplashScreen.scale-140.png
  15. 0 0
      winrt/SDLPal.WindowsPhone/Assets/SplashScreen.scale-240.png
  16. 0 0
      winrt/SDLPal.WindowsPhone/Assets/Square71x71Logo.scale-100.png
  17. 0 0
      winrt/SDLPal.WindowsPhone/Assets/Square71x71Logo.scale-140.png
  18. 0 0
      winrt/SDLPal.WindowsPhone/Assets/Square71x71Logo.scale-240.png
  19. 0 0
      winrt/SDLPal.WindowsPhone/Assets/StoreLogo.scale-100.png
  20. 0 0
      winrt/SDLPal.WindowsPhone/Assets/StoreLogo.scale-140.png
  21. 0 0
      winrt/SDLPal.WindowsPhone/Assets/StoreLogo.scale-240.png
  22. 0 0
      winrt/SDLPal.WindowsPhone/Assets/WideLogo.scale-100.png
  23. 0 0
      winrt/SDLPal.WindowsPhone/Assets/WideLogo.scale-140.png
  24. 0 0
      winrt/SDLPal.WindowsPhone/Assets/WideLogo.scale-240.png
  25. 0 0
      winrt/SDLPal.WindowsPhone/Package.appxmanifest
  26. 16 0
      winrt/SDLPal.WindowsPhone/SDLPal.Common.def
  27. 144 0
      winrt/SDLPal.WindowsPhone/SDLPal.Common.vcxproj
  28. 18 0
      winrt/SDLPal.WindowsPhone/SDLPal.Common.vcxproj.filters
  29. 6 5
      winphone/SDLPalCore/SDLPalCore.vcxproj
  30. 3 0
      winphone/SDLPalCore/SDLPalCore.vcxproj.filters
  31. 18 7
      winphone/SDLPal/SDLPal.vcxproj
  32. 1 8
      winphone/SDLPal/SDLPal.vcxproj.filters
  33. 244 0
      winrt/SDLPal.WindowsPhone/WinRTUtil.cpp

+ 4 - 3
.gitignore

@@ -25,6 +25,9 @@ bld/
 # Visual Studio 2015 cache/options directory
 .vs/
 
+# Visual Studio 2015 intellisense database
+*.VC.db
+
 # MSTest test Results
 [Tt]est[Rr]esult*/
 [Bb]uild[Ll]og.*
@@ -212,7 +215,5 @@ _Pvt_Extensions/
 ModelManifest.xml
 
 # Windows Phone associated file
-winphone/SDLPal/Assets/Data/*
-!winphone/SDLPal/Assets/Data/README.txt
-winphone/SDL2/*
+winrt/SDL2/*
 !winphone/SDL2/README.txt

+ 0 - 145
winphone/SDLPal/WinPhoneUtil.cpp

@@ -1,145 +0,0 @@
-#include <wrl.h>
-#include <string>
-#include <DXGI.h>
-#include <ppltasks.h>
-
-#define PAL_PATH_NAME	"SDLPAL"
-
-static std::string g_savepath, g_basepath;
-
-template<typename T>
-static bool WaitOnTask(T task, int64 wait_timeout)
-{
-	auto start = GetTickCount64();
-	while (!task.is_done() && (int64)(GetTickCount64() - start) <= wait_timeout)
-		Sleep(1);
-	return task.is_done();
-}
-
-static void ConvertString(Platform::String^ src, std::string& dst)
-{
-	int len = WideCharToMultiByte(CP_ACP, 0, src->Begin(), -1, nullptr, 0, nullptr, nullptr);
-	dst.resize(len - 1);
-	WideCharToMultiByte(CP_ACP, 0, src->Begin(), -1, (char*)dst.data(), len, nullptr, nullptr);
-}
-
-static bool CheckGamePath(Windows::Storage::StorageFolder^ root)
-{
-	Platform::String^ required_files[] = {
-		L"ABC.MKF", L"BALL.MKF", L"DATA.MKF", L"F.MKF", L"FBP.MKF",
-		L"FIRE.MKF", L"GOP.MKF", L"MAP.MKF", L"MGO.MKF", L"PAT.MKF",
-		L"RGM.MKF", L"RNG.MKF", L"SSS.MKF"
-	};
-	Platform::String^ optional_required_files[] = {
-		L"VOC.MKF", L"SOUNDS.MKF"
-	};
-	/* The words.dat & m.msg may be configurable in the future, so not check here */
-
-	/* Try to get the path */
-	auto foldertask = concurrency::create_task(root->GetFolderAsync(PAL_PATH_NAME));
-	if (!WaitOnTask(foldertask, 500)) return false;		// Wait for 500ms max
-
-	try
-	{
-		/* Check the access right of necessary files */
-		auto folder = foldertask.get();
-		for (int i = 0; i < 13; i++)
-		{
-			auto filetask = concurrency::create_task(foldertask.get()->GetFileAsync(required_files[i]));
-			if (!WaitOnTask(filetask, 500) || _waccess_s(filetask.get()->Path->Begin(), 2)) return false;
-		}
-		for (int i = 0; i < 2; i++)
-		{
-			auto filetask = concurrency::create_task(foldertask.get()->GetFileAsync(optional_required_files[i]));
-			try { if (WaitOnTask(filetask, 500) && _waccess_s(filetask.get()->Path->Begin(), 2) == 0) return true; }
-			catch(Platform::Exception^) {}
-		}
-	}
-	catch(Platform::Exception^)
-	{ /* Accessing SD card failed, or required file is missing, or access is denied */ }
-	return false;
-}
-
-extern "C"
-LPCSTR UTIL_BasePath(VOID)
-{
-	if (g_basepath.empty())
-	{
-		auto enumtask = concurrency::create_task(Windows::Storage::KnownFolders::RemovableDevices->GetFoldersAsync());
-		if (WaitOnTask(enumtask, 1000))		// Wait for 1000ms max
-		{
-			auto folderiter = enumtask.get()->First();
-			while (folderiter->HasCurrent)
-			{
-				if (CheckGamePath(folderiter->Current))
-				{
-					/* Folder examination succeeded */
-					auto folder = folderiter->Current->Path;
-					if (folder->End()[-1] != L'\\') folder += "\\";
-					folder += PAL_PATH_NAME "\\";
-					ConvertString(folder, g_basepath);
-
-					/* Check whether the folder is writable */
-					FILE* fp;
-					if (_wfopen_s(&fp, (folder + "sdlpal.rpg")->Begin(), L"w") == 0)
-					{
-						g_savepath = g_basepath;
-						fclose(fp);
-					}
-					break;
-				}
-				folderiter->MoveNext();
-			}
-		}
-
-		if (g_basepath.empty())
-		{
-			g_basepath.assign("Assets\\Data\\");
-		}
-	}
-	return g_basepath.c_str();
-}
-
-extern "C"
-LPCSTR UTIL_SavePath(VOID)
-{
-	if (g_savepath.empty())
-	{
-		auto localfolder = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
-		if (localfolder->End()[-1] != L'\\') localfolder += "\\";
-		ConvertString(localfolder, g_savepath);
-	}
-	return g_savepath.c_str();
-}
-
-extern "C"
-BOOL UTIL_GetScreenSize(DWORD *pdwScreenWidth, DWORD *pdwScreenHeight)
-{
-	DXGI_OUTPUT_DESC desc;
-	IDXGIFactory1* pFactory = nullptr;
-	IDXGIAdapter1* pAdapter = nullptr;
-	IDXGIOutput* pOutput = nullptr;
-	DWORD retval = FALSE;
-
-	if (!pdwScreenWidth || !pdwScreenHeight) return FALSE;
-
-	if (FAILED(CreateDXGIFactory1(IID_IDXGIFactory1, (void**)&pFactory))) goto UTIL_WP_GetScreenSize_exit;
-
-	if (FAILED(pFactory->EnumAdapters1(0, &pAdapter))) goto UTIL_WP_GetScreenSize_exit;
-
-	if (FAILED(pAdapter->EnumOutputs(0, &pOutput))) goto UTIL_WP_GetScreenSize_exit;
-
-	if (SUCCEEDED(pOutput->GetDesc(&desc)))
-	{
-		*pdwScreenWidth = (desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top);
-		*pdwScreenHeight = (desc.DesktopCoordinates.right - desc.DesktopCoordinates.left);
-		retval = TRUE;
-	}
-
-UTIL_WP_GetScreenSize_exit:
-	if (pOutput) pOutput->Release();
-	if (pAdapter) pAdapter->Release();
-	if (pFactory) pFactory->Release();
-
-	return retval;
-}

winphone/SDL2/README.txt → winrt/SDL2/README.txt


+ 106 - 0
winrt/SDLPal.Common/AsyncHelper.h

@@ -0,0 +1,106 @@
+/*
+*   AsyncHelper.h
+*
+*   Date: 1st July, 2014   Author: David Huang
+*   (C) 2014 Light Studio. All Rights Reserved.
+*   Modified by louyihua@2016
+*/
+#pragma once
+#include <ppltasks.h>
+#include <Windows.h>
+#include <synchapi.h>
+using namespace Platform;
+
+template <typename TResult>
+inline TResult AWait(Windows::Foundation::IAsyncOperation<TResult>^ asyncOp, HANDLE eventHandle)
+{
+	TResult result;
+	Exception^ exceptionObj = nullptr;
+	ResetEvent(eventHandle);
+	asyncOp->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<TResult>([&]
+		(Windows::Foundation::IAsyncOperation<TResult>^ asyncInfo, Windows::Foundation::AsyncStatus asyncStatus)
+	{
+		try
+		{
+			result = asyncInfo->GetResults();
+		}
+		catch (Exception^ e)
+		{
+			exceptionObj = e;
+		}
+		SetEvent(eventHandle);
+	});
+	WaitForSingleObjectEx(eventHandle, INFINITE, FALSE);
+	if (exceptionObj != nullptr) throw exceptionObj;
+	return result;
+}
+
+template <typename TResult, typename TProgress>
+inline TResult AWait(Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>^ asyncOp, HANDLE eventHandle)
+{
+	TResult result;
+	Exception^ exceptionObj = nullptr;
+	ResetEvent(eventHandle);
+	asyncOp->Completed = ref new Windows::Foundation::AsyncOperationWithProgressCompletedHandler<TResult, TProgress>([&]
+		(Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>^ asyncInfo, Windows::Foundation::AsyncStatus asyncStatus)
+	{
+		try
+		{
+			result = asyncInfo->GetResults();
+		}
+		catch (Exception^ e)
+		{
+			exceptionObj = e;
+		}
+		SetEvent(eventHandle);
+	});
+	WaitForSingleObjectEx(eventHandle, INFINITE, FALSE);
+	if (exceptionObj != nullptr) throw exceptionObj;
+	return result;
+}
+
+
+inline void AWait(Windows::Foundation::IAsyncAction^ asyncAc, HANDLE eventHandle)
+{
+	Exception^ exceptionObj = nullptr;
+	asyncAc->Completed = ref new Windows::Foundation::AsyncActionCompletedHandler([&]
+		(Windows::Foundation::IAsyncAction^ asyncInfo, Windows::Foundation::AsyncStatus asyncStatus)
+	{
+		try
+		{
+			asyncInfo->GetResults();
+		}
+		catch (Exception^ e)
+		{
+			exceptionObj = e;
+		}
+		SetEvent(eventHandle);
+	});
+	WaitForSingleObjectEx(eventHandle, INFINITE, FALSE);
+	if (exceptionObj != nullptr) throw exceptionObj;
+}
+
+template <typename TResult>
+inline TResult AWait(Windows::Foundation::IAsyncOperation<TResult>^ asyncOp)
+{
+	HANDLE handle = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
+	auto result = AWait(asyncOp, handle);
+	CloseHandle(handle);
+	return result;
+}
+
+template <typename TResult, typename TProgress>
+inline TResult AWait(Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>^ asyncOp)
+{
+	HANDLE handle = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
+	auto result = AWait(asyncOp, handle);
+	CloseHandle(handle);
+	return result;
+}
+
+inline void AWait(Windows::Foundation::IAsyncAction^ asyncAc)
+{
+	HANDLE handle = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
+	AWait(asyncAc, handle);
+	CloseHandle(handle);
+}

+ 309 - 0
winrt/SDLPal.Common/WinRTIO.cpp

@@ -0,0 +1,309 @@
+#include <wrl.h>
+#include <string>
+#include <DXGI.h>
+#include <ppltasks.h>
+#include <AsyncHelper.h>
+#include <shcore.h>
+#include <unordered_set>
+
+#pragma comment(lib, "ShCore.lib")
+
+#define PAL_PATH_NAME	"SDLPAL"
+
+static const LARGE_INTEGER liZero = { 0 };
+static const void* const _SIGNATURE = &liZero;
+
+static void ConvertString(const std::string& src, std::wstring& dst)
+{
+	int len = MultiByteToWideChar(CP_ACP, 0, src.c_str(), -1, nullptr, 0);
+	dst.resize(len - 1);
+	MultiByteToWideChar(CP_ACP, 0, src.c_str(), -1, (wchar_t*)dst.data(), len);
+}
+
+/*========================*/
+
+typedef struct WRT_FILE WRT_FILE;
+
+struct WRT_FILE
+{
+	const void* sig;
+	IStream* stream;
+	CRITICAL_SECTION cs;
+	bool readable;
+	bool writable;
+	bool binary;
+
+	WRT_FILE() : sig(&liZero), stream(nullptr), readable(false), writable(false), binary(false) { InitializeCriticalSectionEx(&cs, 4000, 0); }
+	WRT_FILE(Windows::Storage::Streams::IRandomAccessStream^ s, bool r, bool w, bool b)
+		: sig(&liZero), stream(nullptr), readable(r), writable(w), binary(b)
+	{
+		HRESULT hr;
+		InitializeCriticalSectionEx(&cs, 4000, 0);
+		if (FAILED(hr = CreateStreamOverRandomAccessStream(s, IID_PPV_ARGS(&stream))))
+			throw ref new Platform::Exception(hr);
+	}
+	~WRT_FILE() { if (stream) stream->Release(); DeleteCriticalSection(&cs); }
+};
+
+class CriticalSection
+{
+public:
+	CriticalSection(CRITICAL_SECTION& cs) : m_cs(cs) { EnterCriticalSection(&m_cs); }
+	~CriticalSection() { LeaveCriticalSection(&m_cs); }
+
+private:
+	CRITICAL_SECTION& m_cs;
+};
+
+extern "C"
+errno_t WRT_fopen_s(WRT_FILE ** pFile, const char * _Filename, const char * _Mode)
+{
+	if (nullptr == _Filename || nullptr == _Mode || nullptr == pFile) return EINVAL;
+
+	HANDLE eventHandle = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
+	std::wstring path;
+	Platform::String^ filename;
+	ConvertString(_Filename, path);
+	auto ptr = (wchar_t*)path.c_str() + path.length();
+	while (ptr >= path.c_str() && *ptr != L'/' && *ptr != L'\\') ptr--;
+	filename = ref new Platform::String(ptr + 1);
+	path = path.substr(0, ptr - path.c_str());
+	size_t offset = 0;
+	while ((offset = path.find(L'/', offset)) != std::wstring::npos)
+		path[offset++] = L'\\';
+
+	Windows::Storage::StorageFolder^ folder;
+	try
+	{
+		folder = AWait(Windows::Storage::StorageFolder::GetFolderFromPathAsync(ref new Platform::String(path.c_str())), eventHandle);
+	}
+	catch (Platform::AccessDeniedException^)
+	{
+		//int index = path.length() - 1;
+		//if (_wcsnicmp(g_basefolder->Path->Begin(), path.c_str(), g_basefolder->Path->Length()) == 0)
+		//	folder = g_basefolder;
+		//else if (_wcsnicmp(g_savefolder->Path->Begin(), path.c_str(), g_savefolder->Path->Length()) == 0)
+		//	folder = g_savefolder;
+		//else
+			return EACCES;
+
+		if (path.length() > folder->Path->Length())
+		{
+			auto folder_length = folder->Path->Length();
+			if (path[folder_length] == L'\\') folder_length++;
+			try
+			{
+				for (auto next = path.find(L'\\', folder_length); next != std::wstring::npos; next = path.find(L'\\', (folder_length = next + 1)))
+					folder = AWait(folder->GetFolderAsync(ref new Platform::String(path.substr(folder_length, next - folder_length).c_str())), eventHandle);
+				folder = AWait(folder->GetFolderAsync(ref new Platform::String(path.substr(folder_length).c_str())), eventHandle);
+			}
+			catch (Platform::Exception^)
+			{
+				return EIO;
+			}
+		}
+	}
+	catch (Platform::Exception^)
+	{
+		return EIO;
+	}
+
+	WRT_FILE* ret = nullptr;
+	try
+	{
+		Windows::Storage::StorageFile^ file;
+		bool r, w;
+		switch (*_Mode)
+		{
+		case 'a': file = AWait(folder->CreateFileAsync(filename, Windows::Storage::CreationCollisionOption::OpenIfExists), eventHandle); w = true; r = false; break;
+		case 'w': file = AWait(folder->CreateFileAsync(filename, Windows::Storage::CreationCollisionOption::ReplaceExisting), eventHandle); w = true; r = false; break;
+		case 'r': file = AWait(folder->GetFileAsync(filename), eventHandle); w = false; r = true; break;
+		default: CloseHandle(eventHandle); return EINVAL;
+		}
+		if (file)
+		{
+			bool b = false;
+			for (size_t i = 1; i < strlen(_Mode); i++)
+			{
+				switch (_Mode[i])
+				{
+				case '+': r = w = true; break;
+				case 'b': b = true; break;
+				case 't': b = false; break;
+				default: return EINVAL;
+				}
+			}
+			ret = new WRT_FILE(AWait(file->OpenAsync(w ? Windows::Storage::FileAccessMode::ReadWrite : Windows::Storage::FileAccessMode::Read), eventHandle), r, w, b);
+		}
+		CloseHandle(eventHandle);
+	}
+	catch (Platform::Exception^)
+	{
+		return EIO;
+	}
+	*pFile = ret;
+	return 0;
+}
+
+extern "C"
+WRT_FILE* WRT_fopen(const char * _Filename, const char * _Mode)
+{
+	WRT_FILE* ret;
+	int err = WRT_fopen_s(&ret, _Filename, _Mode);
+	_set_errno(err);
+	return err ? nullptr : ret;
+}
+
+extern "C"
+int WRT_fclose(WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return fclose((FILE*)_File);
+	delete _File;
+	return 0;
+}
+
+extern "C"
+int WRT_feof(WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return feof((FILE*)_File);
+
+	STATSTG st;
+	ULARGE_INTEGER uli;
+	CriticalSection cs(_File->cs);
+
+	if (SUCCEEDED(_File->stream->Seek(liZero, STREAM_SEEK_CUR, &uli)) &&
+		SUCCEEDED(_File->stream->Stat(&st, STATFLAG_NONAME)))
+		return uli.QuadPart >= st.cbSize.QuadPart;
+	else
+		return 1;
+}
+
+extern "C"
+int WRT_fseeki64(WRT_FILE * _File, long long _Offset, int _Origin)
+{
+	if (!_File || _File->sig != _SIGNATURE) return _fseeki64((FILE*)_File, _Offset, _Origin);
+
+	CriticalSection cs(_File->cs);
+	LARGE_INTEGER liOffset;
+	liOffset.QuadPart = _Offset;
+	return SUCCEEDED(_File->stream->Seek(liOffset, _Origin, NULL)) ? 0 : -1;
+}
+
+extern "C"
+int WRT_fseek(WRT_FILE * _File, long _Offset, int _Origin)
+{
+	return WRT_fseeki64(_File, _Offset, _Origin);
+}
+
+extern "C"
+long long WRT_ftelli64(WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return _ftelli64((FILE*)_File);
+
+	CriticalSection cs(_File->cs);
+	unsigned long long pos;
+	return SUCCEEDED(_File->stream->Seek(liZero, STREAM_SEEK_CUR, (PULARGE_INTEGER)&pos)) ? pos : -1;
+}
+
+extern "C"
+size_t WRT_ftell(WRT_FILE * _File)
+{
+	return (size_t)WRT_ftelli64(_File);
+}
+
+extern "C"
+size_t WRT_fread(void * _DstBuf, size_t _ElementSize, size_t _Count, WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return fread(_DstBuf, _ElementSize, _Count, (FILE*)_File);
+	if (!_File->readable || _ElementSize == 0 || _Count == 0 || !_DstBuf) return 0;
+
+	CriticalSection cs(_File->cs);
+	unsigned long cbRead;
+	return SUCCEEDED(_File->stream->Read(_DstBuf, _ElementSize * _Count, &cbRead)) ? cbRead / _ElementSize : 0;
+}
+
+extern "C"
+size_t WRT_fwrite(const void * _Str, size_t _Size, size_t _Count, WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return fwrite(_Str, _Size, _Count, (FILE*)_File);
+	if (!_File->writable || !_Str || _Size == 0 || _Count == 0) return 0;
+
+	CriticalSection cs(_File->cs);
+	unsigned long cbWrite;
+	return SUCCEEDED(_File->stream->Write(_Str, _Size * _Count, &cbWrite)) ? cbWrite / _Size : 0;
+}
+
+extern "C"
+int WRT_fflush(WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return fflush((FILE*)_File);
+	if (!_File->writable) return 0;
+
+	CriticalSection cs(_File->cs);
+	return SUCCEEDED(_File->stream->Commit(STGC_DEFAULT)) ? 0 : EOF;
+}
+
+static int WRT_fgetc_nolock(WRT_FILE * _File)
+{
+	unsigned long cbRead;
+	unsigned char buf;
+	return _File->stream->Read(&buf, 1, &cbRead) == S_OK ? buf : EOF;
+}
+
+extern "C"
+int WRT_fgetc(WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return fgetc((FILE*)_File);
+
+	CriticalSection cs(_File->cs);
+	return _File->readable ? WRT_fgetc_nolock(_File) : EOF;
+}
+
+extern "C"
+char* WRT_fgets(char * _Buf, int _MaxCount, WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return fgets(_Buf, _MaxCount, (FILE*)_File);
+	if (!_File->readable || !_Buf || _MaxCount <= 0) return nullptr;
+
+	CriticalSection cs(_File->cs);
+	int n = 0, flag = 0, ch;
+	while (n < _MaxCount - 1 && EOF != (ch = WRT_fgetc_nolock(_File)))
+	{
+		if (flag)
+		{
+			if (ch != '\n')
+				_Buf[n++] = '\r';
+			flag = 0;
+		}
+		if (ch != '\r')
+		{
+			_Buf[n++] = ch;
+			if (ch == '\n') break;
+		}
+		else
+			flag = 1;
+	}
+	if (n > 0)
+	{
+		_Buf[n] = '\0';
+		return _Buf;
+	}
+	else
+		return nullptr;
+}
+
+extern "C"
+int WRT_fputc(int _Ch, WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return fputc(_Ch, (FILE*)_File);
+
+	return EOF;
+}
+
+extern "C"
+int WRT_fputs(const char * _Str, WRT_FILE * _File)
+{
+	if (!_File || _File->sig != _SIGNATURE) return fputs(_Str, (FILE*)_File);
+
+	return EOF;
+}

+ 21 - 3
winphone/SDLPal.sln

@@ -1,13 +1,21 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 14
-VisualStudioVersion = 14.0.23107.0
+VisualStudioVersion = 14.0.25123.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2-WinPhone81", "SDL2\VisualC-WinRT\WinPhone81_VS2013\SDL-WinPhone81.vcxproj", "{48FADC0E-964D-4DAB-BCED-372E0AD19577}"
+	ProjectSection(ProjectDependencies) = postProject
+		{35839F1B-8B1C-4858-91FA-807A693E703F} = {35839F1B-8B1C-4858-91FA-807A693E703F}
+	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDLPalCore", "SDLPalCore\SDLPalCore.vcxproj", "{704D3871-2E86-42EF-A607-CBCFB7A7EBAB}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDLPal.Core", "SDLPal.WindowsPhone\SDLPal.Core.vcxproj", "{704D3871-2E86-42EF-A607-CBCFB7A7EBAB}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDLPal", "SDLPal\SDLPal.vcxproj", "{4C240E16-F6F6-4D60-B29B-7F7ACB4815D7}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDLPal", "SDLPal.WindowsPhone\SDLPal.vcxproj", "{4C240E16-F6F6-4D60-B29B-7F7ACB4815D7}"
+	ProjectSection(ProjectDependencies) = postProject
+		{35839F1B-8B1C-4858-91FA-807A693E703F} = {35839F1B-8B1C-4858-91FA-807A693E703F}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDLPal.Common", "SDLPal.WindowsPhone\SDLPal.Common.vcxproj", "{35839F1B-8B1C-4858-91FA-807A693E703F}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -57,6 +65,16 @@ Global
 		{4C240E16-F6F6-4D60-B29B-7F7ACB4815D7}.Release|Win32.Build.0 = Release|Win32
 		{4C240E16-F6F6-4D60-B29B-7F7ACB4815D7}.Release|Win32.Deploy.0 = Release|Win32
 		{4C240E16-F6F6-4D60-B29B-7F7ACB4815D7}.Release|x64.ActiveCfg = Release|Win32
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Debug|ARM.ActiveCfg = Debug|ARM
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Debug|ARM.Build.0 = Debug|ARM
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Debug|Win32.ActiveCfg = Debug|Win32
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Debug|Win32.Build.0 = Debug|Win32
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Debug|x64.ActiveCfg = Debug|Win32
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Release|ARM.ActiveCfg = Release|ARM
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Release|ARM.Build.0 = Release|ARM
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Release|Win32.ActiveCfg = Release|Win32
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Release|Win32.Build.0 = Release|Win32
+		{35839F1B-8B1C-4858-91FA-807A693E703F}.Release|x64.ActiveCfg = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

winphone/SDLPal/Assets/Logo.scale-100.png → winrt/SDLPal.WindowsPhone/Assets/Logo.scale-100.png


winphone/SDLPal/Assets/Logo.scale-140.png → winrt/SDLPal.WindowsPhone/Assets/Logo.scale-140.png


winphone/SDLPal/Assets/Logo.scale-240.png → winrt/SDLPal.WindowsPhone/Assets/Logo.scale-240.png


winphone/SDLPal/Assets/SmallLogo.scale-100.png → winrt/SDLPal.WindowsPhone/Assets/SmallLogo.scale-100.png


winphone/SDLPal/Assets/SmallLogo.scale-140.png → winrt/SDLPal.WindowsPhone/Assets/SmallLogo.scale-140.png


winphone/SDLPal/Assets/SmallLogo.scale-240.png → winrt/SDLPal.WindowsPhone/Assets/SmallLogo.scale-240.png


winphone/SDLPal/Assets/SplashScreen.scale-100.png → winrt/SDLPal.WindowsPhone/Assets/SplashScreen.scale-100.png


winphone/SDLPal/Assets/SplashScreen.scale-140.png → winrt/SDLPal.WindowsPhone/Assets/SplashScreen.scale-140.png


winphone/SDLPal/Assets/SplashScreen.scale-240.png → winrt/SDLPal.WindowsPhone/Assets/SplashScreen.scale-240.png


winphone/SDLPal/Assets/Square71x71Logo.scale-100.png → winrt/SDLPal.WindowsPhone/Assets/Square71x71Logo.scale-100.png


winphone/SDLPal/Assets/Square71x71Logo.scale-140.png → winrt/SDLPal.WindowsPhone/Assets/Square71x71Logo.scale-140.png


winphone/SDLPal/Assets/Square71x71Logo.scale-240.png → winrt/SDLPal.WindowsPhone/Assets/Square71x71Logo.scale-240.png


winphone/SDLPal/Assets/StoreLogo.scale-100.png → winrt/SDLPal.WindowsPhone/Assets/StoreLogo.scale-100.png


winphone/SDLPal/Assets/StoreLogo.scale-140.png → winrt/SDLPal.WindowsPhone/Assets/StoreLogo.scale-140.png


winphone/SDLPal/Assets/StoreLogo.scale-240.png → winrt/SDLPal.WindowsPhone/Assets/StoreLogo.scale-240.png


winphone/SDLPal/Assets/WideLogo.scale-100.png → winrt/SDLPal.WindowsPhone/Assets/WideLogo.scale-100.png


winphone/SDLPal/Assets/WideLogo.scale-140.png → winrt/SDLPal.WindowsPhone/Assets/WideLogo.scale-140.png


winphone/SDLPal/Assets/WideLogo.scale-240.png → winrt/SDLPal.WindowsPhone/Assets/WideLogo.scale-240.png


winphone/SDLPal/Package.appxmanifest → winrt/SDLPal.WindowsPhone/Package.appxmanifest


+ 16 - 0
winrt/SDLPal.WindowsPhone/SDLPal.Common.def

@@ -0,0 +1,16 @@
+LIBRARY
+EXPORTS
+	fopen=WRT_fopen
+	fopen_s=WRT_fopen_s
+	fclose=WRT_fclose
+	fread=WRT_fread
+	fwrite=WRT_fwrite
+	feof=WRT_feof
+	_ftelli64=WRT_ftelli64
+	_fseeki64=WRT_fseeki64
+	fseek=WRT_fseek
+	ftell=WRT_ftell
+	fputc=WRT_fputc
+	fputs=WRT_fputs
+	fgetc=WRT_fgetc
+	fgets=WRT_fgets

+ 144 - 0
winrt/SDLPal.WindowsPhone/SDLPal.Common.vcxproj

@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|ARM">
+      <Configuration>Debug</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|ARM">
+      <Configuration>Release</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{35839f1b-8b1c-4858-91fa-807a693e703f}</ProjectGuid>
+    <Keyword>DynamicLibrary</Keyword>
+    <ProjectName>SDLPal.Common</ProjectName>
+    <RootNamespace>SDLPal_Common</RootNamespace>
+    <DefaultLanguage>zh-CN</DefaultLanguage>
+    <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+    <AppContainerApplication>true</AppContainerApplication>
+    <ApplicationType>Windows Phone</ApplicationType>
+    <ApplicationTypeRevision>8.1</ApplicationTypeRevision>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v120_wp81</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120_wp81</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v120_wp81</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v120_wp81</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <IgnoreImportLibrary>false</IgnoreImportLibrary>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <IgnoreImportLibrary>false</IgnoreImportLibrary>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+    <IgnoreImportLibrary>false</IgnoreImportLibrary>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+    <IgnoreImportLibrary>false</IgnoreImportLibrary>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+      <ModuleDefinitionFile>SDLPal.Common.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+      <ModuleDefinitionFile>SDLPal.Common.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+      <ModuleDefinitionFile>SDLPal.Common.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <SDLCheck>true</SDLCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+      <GenerateWindowsMetadata>false</GenerateWindowsMetadata>
+      <ModuleDefinitionFile>SDLPal.Common.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="WinRTIO.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="AsyncHelper.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="SDLPal.Common.def" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 18 - 0
winrt/SDLPal.WindowsPhone/SDLPal.Common.vcxproj.filters

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="资源文件">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="WinRTIO.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="AsyncHelper.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="SDLPal.Common.def" />
+  </ItemGroup>
+</Project>

+ 6 - 5
winphone/SDLPalCore/SDLPalCore.vcxproj

@@ -27,7 +27,7 @@
     <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
     <ApplicationType>Windows Phone</ApplicationType>
     <ApplicationTypeRevision>8.1</ApplicationTypeRevision>
-    <ProjectName>SDLPalCore</ProjectName>
+    <ProjectName>SDLPal.Core</ProjectName>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -75,7 +75,7 @@
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;__WINPHONE__=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;__WINPHONE__=1;PAL_HAS_TOUCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PrecompiledHeader>NotUsing</PrecompiledHeader>
       <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
       <AdditionalIncludeDirectories>..\..\liboggvorbis\include;$(IntermediateOutputPath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -91,7 +91,7 @@
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;__WINPHONE__=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;__WINPHONE__=1;PAL_HAS_TOUCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PrecompiledHeader>NotUsing</PrecompiledHeader>
       <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
       <AdditionalIncludeDirectories>..\..\liboggvorbis\include;$(IntermediateOutputPath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -107,7 +107,7 @@
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
     <ClCompile>
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;__WINPHONE__=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;__WINPHONE__=1;PAL_HAS_TOUCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PrecompiledHeader>NotUsing</PrecompiledHeader>
       <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
       <AdditionalIncludeDirectories>..\..\liboggvorbis\include;$(IntermediateOutputPath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -123,7 +123,7 @@
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
     <ClCompile>
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;__WINPHONE__=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;__WINPHONE__=1;PAL_HAS_TOUCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PrecompiledHeader>NotUsing</PrecompiledHeader>
       <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
       <AdditionalIncludeDirectories>..\..\liboggvorbis\include;$(IntermediateOutputPath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -311,6 +311,7 @@
     <ClCompile Include="..\..\map.c" />
     <ClCompile Include="..\..\mp3play.c" />
     <ClCompile Include="..\..\oggplay.c" />
+    <ClCompile Include="..\..\overlay.c" />
     <ClCompile Include="..\..\palcommon.c" />
     <ClCompile Include="..\..\palette.c" />
     <ClCompile Include="..\..\play.c" />

+ 3 - 0
winphone/SDLPalCore/SDLPalCore.vcxproj.filters

@@ -613,6 +613,9 @@
     <ClCompile Include="..\..\resampler.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\overlay.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\libmad\D.dat">

+ 18 - 7
winphone/SDLPal/SDLPal.vcxproj

@@ -27,6 +27,7 @@
     <AppContainerApplication>true</AppContainerApplication>
     <ApplicationType>Windows Phone</ApplicationType>
     <ApplicationTypeRevision>8.1</ApplicationTypeRevision>
+    <ProjectName>SDLPal</ProjectName>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -89,7 +90,9 @@
       <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>dxgi.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>dxgi.lib;dxguid.lib;sdlpal.common.lib;vccorlibd.lib;msvcrtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <IgnoreSpecificDefaultLibraries>vccorlibd.lib;msvcrtd.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <AdditionalLibraryDirectories>$(OutDir)../SDLPal.Common</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
@@ -100,7 +103,9 @@
       <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>dxgi.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>dxgi.lib;dxguid.lib;sdlpal.common.lib;vccorlib.lib;msvcrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <IgnoreSpecificDefaultLibraries>vccorlib.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <AdditionalLibraryDirectories>$(OutDir)../SDLPal.Common</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -111,7 +116,9 @@
       <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>dxgi.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>dxgi.lib;dxguid.lib;sdlpal.common.lib;vccorlibd.lib;msvcrtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <IgnoreSpecificDefaultLibraries>vccorlibd.lib;msvcrtd.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <AdditionalLibraryDirectories>$(OutDir)../SDLPal.Common</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -122,7 +129,9 @@
       <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>dxgi.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>dxgi.lib;dxguid.lib;sdlpal.common.lib;vccorlib.lib;msvcrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <IgnoreSpecificDefaultLibraries>vccorlib.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <AdditionalLibraryDirectories>$(OutDir)../SDLPal.Common</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
@@ -177,14 +186,16 @@
     <Image Include="Assets\WideLogo.scale-240.png" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\SDL2\src\main\winrt\SDL_winrt_main_NonXAML.cpp" />
-    <ClCompile Include="WinPhoneUtil.cpp" />
+    <ClCompile Include="WinRTUtil.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\SDL2\VisualC-WinRT\WinPhone81_VS2013\SDL-WinPhone81.vcxproj">
       <Project>{48fadc0e-964d-4dab-bced-372e0ad19577}</Project>
     </ProjectReference>
-    <ProjectReference Include="..\SDLPalCore\SDLPalCore.vcxproj">
+    <ProjectReference Include="..\SDLPal.WindowsPhone\SDLPal.Common.vcxproj">
+      <Project>{35839f1b-8b1c-4858-91fa-807a693e703f}</Project>
+    </ProjectReference>
+    <ProjectReference Include="SDLPal.Core.vcxproj">
       <Project>{704d3871-2e86-42ef-a607-cbcfb7a7ebab}</Project>
     </ProjectReference>
   </ItemGroup>

+ 1 - 8
winphone/SDLPal/SDLPal.vcxproj.filters

@@ -23,16 +23,9 @@
     <Image Include="Assets\WideLogo.scale-240.png">
       <Filter>资产</Filter>
     </Image>
-    <Filter Include="SDL2">
-      <UniqueIdentifier>{1b4126fa-ab18-4d2a-8fc0-dff551a94158}</UniqueIdentifier>
-      <SourceControlFiles>False</SourceControlFiles>
-    </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="WinPhoneUtil.cpp" />
-    <ClCompile Include="..\SDL2\src\main\winrt\SDL_winrt_main_NonXAML.cpp">
-      <Filter>SDL2</Filter>
-    </ClCompile>
+    <ClCompile Include="WinRTUtil.cpp" />
   </ItemGroup>
   <ItemGroup>
     <AppxManifest Include="Package.appxmanifest" />

+ 244 - 0
winrt/SDLPal.WindowsPhone/WinRTUtil.cpp

@@ -0,0 +1,244 @@
+#include <wrl.h>
+#include <string>
+#include <DXGI.h>
+#include <ppltasks.h>
+#include "../SDLPal.Common/AsyncHelper.h"
+
+extern "C" void TerminateOnError(const char *fmt, ...);
+
+#define PAL_PATH_NAME	"SDLPAL"
+
+static std::string g_savepath, g_basepath;
+static Windows::Storage::StorageFolder ^g_basefolder, ^g_savefolder;
+
+static void ConvertString(Platform::String^ src, std::string& dst)
+{
+	int len = WideCharToMultiByte(CP_ACP, 0, src->Begin(), -1, nullptr, 0, nullptr, nullptr);
+	dst.resize(len - 1);
+	WideCharToMultiByte(CP_ACP, 0, src->Begin(), -1, (char*)dst.data(), len, nullptr, nullptr);
+}
+
+static std::string ConvertString(Platform::String^ src)
+{
+	int len = WideCharToMultiByte(CP_ACP, 0, src->Begin(), -1, nullptr, 0, nullptr, nullptr);
+	std::string dst(len - 1, ' ');
+	WideCharToMultiByte(CP_ACP, 0, src->Begin(), -1, (char*)dst.data(), len, nullptr, nullptr);
+	return dst;
+}
+
+static void ConvertString(const std::string& src, std::wstring& dst)
+{
+	int len = MultiByteToWideChar(CP_ACP, 0, src.c_str(), -1, nullptr, 0);
+	dst.resize(len - 1);
+	MultiByteToWideChar(CP_ACP, 0, src.c_str(), -1, (wchar_t*)dst.data(), len);
+}
+
+static Platform::String^ ConvertString(const std::string& src)
+{
+	int len = MultiByteToWideChar(CP_ACP, 0, src.c_str(), -1, nullptr, 0);
+	auto wc = new wchar_t[len];
+	MultiByteToWideChar(CP_ACP, 0, src.c_str(), -1, wc, len);
+	auto dst = ref new Platform::String(wc);
+	delete[] wc;
+	return dst;
+}
+
+static Windows::Storage::StorageFolder^ CheckGamePath(Windows::Storage::StorageFolder^ root, HANDLE eventHandle)
+{
+	Platform::String^ required_files[] = {
+		L"ABC.MKF", L"BALL.MKF", L"DATA.MKF", L"F.MKF", L"FBP.MKF",
+		L"FIRE.MKF", L"GOP.MKF", L"MAP.MKF", L"MGO.MKF", L"PAT.MKF",
+		L"RGM.MKF", L"RNG.MKF", L"SSS.MKF"
+	};
+	Platform::String^ optional_required_files[] = {
+		L"VOC.MKF", L"SOUNDS.MKF"
+	};
+	/* The words.dat & m.msg may be configurable in the future, so not check here */
+
+	try
+	{
+		/* Try to get the path */
+		auto folder = AWait(root->GetFolderAsync(PAL_PATH_NAME), eventHandle);
+
+		/* Check the access right of necessary files */
+		for (int i = 0; i < 13; i++)
+		{
+			if (!AWait(AWait(folder->GetFileAsync(required_files[i]), eventHandle)->OpenReadAsync(), eventHandle)->CanRead)
+				return nullptr;
+		}
+
+		for (int i = 0; i < 2; i++)
+		{
+			try {
+				if (AWait(AWait(folder->GetFileAsync(optional_required_files[i]), eventHandle)->OpenReadAsync(), eventHandle)->CanRead)
+					return folder;
+			}
+			catch (Platform::Exception^) {}
+		}
+	}
+	catch (Platform::Exception^)
+	{ /* Accessing SD card failed, or required file is missing, or access is denied */
+	}
+	return nullptr;
+}
+
+extern "C"
+LPCSTR UTIL_BasePath(VOID)
+{
+	if (g_basepath.empty())
+	{
+		Windows::Storage::StorageFolder^ folder = nullptr;
+		HANDLE eventHandle = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
+		auto folders = AWait(Windows::Storage::KnownFolders::RemovableDevices->GetFoldersAsync())->First();
+		while (folders->HasCurrent)
+		{
+			if (folder = CheckGamePath(folders->Current, eventHandle))
+				break;
+			else
+				folders->MoveNext();
+		}
+
+		if (!folder)
+		{
+			Windows::Storage::StorageFolder^ search_folders[] = {
+				Windows::Storage::KnownFolders::PicturesLibrary,
+				Windows::Storage::KnownFolders::SavedPictures,
+				//Windows::Storage::KnownFolders::MusicLibrary,
+				//Windows::Storage::KnownFolders::VideosLibrary,
+			};
+			for (int i = 0; i < sizeof(search_folders) / sizeof(search_folders[0]); i++)
+			{
+				if (folder = CheckGamePath(search_folders[i], eventHandle))
+					break;
+			}
+		}
+
+		CloseHandle(eventHandle);
+
+		if (folder)
+		{
+			/* Folder examination succeeded */
+			auto path = folder->Path;
+			if (path->End()[-1] != L'\\') path += "\\";
+			ConvertString(path, g_basepath);
+			g_basefolder = folder;
+
+			/* Check whether the folder is writable */
+			FILE* fp = fopen(ConvertString(path + "sdlpal.rpg").c_str(), "wb");
+			if (fp)
+			{
+				g_savepath = g_basepath;
+				g_savefolder = g_basefolder;
+				fclose(fp);
+			}
+		}
+		else
+		{
+			TerminateOnError("Could not find PAL folder.\n");
+			//ConvertString(Windows::ApplicationModel::Package::Current->InstalledLocation->Path + "\\Assets\\Data\\", g_basepath);
+		}
+	}
+	return g_basepath.c_str();
+}
+
+extern "C"
+LPCSTR UTIL_SavePath(VOID)
+{
+	if (g_savepath.empty())
+	{
+		auto localfolder = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
+		if (localfolder->End()[-1] != L'\\') localfolder += "\\";
+		ConvertString(localfolder, g_savepath);
+		g_savefolder = Windows::Storage::ApplicationData::Current->LocalFolder;
+	}
+	return g_savepath.c_str();
+}
+
+static BOOL UTIL_IsMobile(VOID)
+{
+	auto rc = Windows::ApplicationModel::Resources::Core::ResourceContext::GetForCurrentView();
+	auto qv = rc->QualifierValues;
+	return qv->HasKey("DeviceFamily") && qv->Lookup("DeviceFamily") == "Mobile";
+}
+
+extern "C"
+BOOL UTIL_GetScreenSize(DWORD *pdwScreenWidth, DWORD *pdwScreenHeight)
+{
+	DXGI_OUTPUT_DESC desc;
+	IDXGIFactory1* pFactory = nullptr;
+	IDXGIAdapter1* pAdapter = nullptr;
+	IDXGIOutput* pOutput = nullptr;
+	DWORD retval = FALSE;
+
+	if (!UTIL_IsMobile()) return FALSE;
+
+	if (!pdwScreenWidth || !pdwScreenHeight) return FALSE;
+
+	if (FAILED(CreateDXGIFactory1(IID_IDXGIFactory1, (void**)&pFactory))) goto UTIL_WP_GetScreenSize_exit;
+
+	if (FAILED(pFactory->EnumAdapters1(0, &pAdapter))) goto UTIL_WP_GetScreenSize_exit;
+
+	if (FAILED(pAdapter->EnumOutputs(0, &pOutput))) goto UTIL_WP_GetScreenSize_exit;
+
+	if (SUCCEEDED(pOutput->GetDesc(&desc)))
+	{
+		*pdwScreenWidth = (desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top);
+		*pdwScreenHeight = (desc.DesktopCoordinates.right - desc.DesktopCoordinates.left);
+		retval = TRUE;
+	}
+
+UTIL_WP_GetScreenSize_exit:
+	if (pOutput) pOutput->Release();
+	if (pAdapter) pAdapter->Release();
+	if (pFactory) pFactory->Release();
+
+	return retval;
+}
+
+extern "C"
+BOOL UTIL_TouchEnabled(VOID)
+{
+	return (ref new Windows::Devices::Input::TouchCapabilities())->TouchPresent;
+}
+
+#include "SDL.h"
+#include "SDL_endian.h"
+
+# include <setjmp.h>
+
+static jmp_buf g_exit_jmp_env;
+# define LONGJMP_EXIT_CODE          0xff
+
+extern "C"
+INT UTIL_Platform_Init(int argc, char* argv[])
+{
+	//
+	// In windows phone, calling exit(0) directly will cause an abnormal exit.
+	// By using setjmp/longjmp to avoid this.
+	//
+	if (setjmp(g_exit_jmp_env) == LONGJMP_EXIT_CODE) return -1;
+
+	// We should first check the SD card before running actual codes
+	UTIL_BasePath();
+
+	SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeRight");
+	SDL_SetHint(SDL_HINT_WINRT_HANDLE_BACK_BUTTON, "1");
+
+	return 0;
+}
+
+extern "C"
+VOID UTIL_Platform_Quit(VOID)
+{
+	longjmp(g_exit_jmp_env, LONGJMP_EXIT_CODE);
+}
+
+int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
+{
+	if (FAILED(Windows::Foundation::Initialize(RO_INIT_MULTITHREADED))) {
+		return 1;
+	}
+
+	SDL_WinRTRunApp(SDL_main, NULL);
+	return 0;
+}