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 10 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;
+}