WinPhoneUtil.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include <wrl.h>
  2. #include <string>
  3. #include <DXGI.h>
  4. #include <ppltasks.h>
  5. #define PAL_PATH_NAME "SDLPAL"
  6. static std::string g_savepath, g_basepath;
  7. template<typename T>
  8. static bool WaitOnTask(T task, int64 wait_timeout)
  9. {
  10. auto start = GetTickCount64();
  11. while (!task.is_done() && (int64)(GetTickCount64() - start) <= wait_timeout)
  12. Sleep(1);
  13. return task.is_done();
  14. }
  15. static void ConvertString(Platform::String^ src, std::string& dst)
  16. {
  17. int len = WideCharToMultiByte(CP_ACP, 0, src->Begin(), -1, nullptr, 0, nullptr, nullptr);
  18. dst.resize(len - 1);
  19. WideCharToMultiByte(CP_ACP, 0, src->Begin(), -1, (char*)dst.data(), len, nullptr, nullptr);
  20. }
  21. static bool CheckGamePath(Windows::Storage::StorageFolder^ root)
  22. {
  23. Platform::String^ required_files[] = {
  24. L"ABC.MKF", L"BALL.MKF", L"DATA.MKF", L"F.MKF", L"FBP.MKF",
  25. L"FIRE.MKF", L"GOP.MKF", L"MAP.MKF", L"MGO.MKF", L"PAT.MKF",
  26. L"RGM.MKF", L"RNG.MKF", L"SSS.MKF"
  27. };
  28. Platform::String^ optional_required_files[] = {
  29. L"VOC.MKF", L"SOUNDS.MKF"
  30. };
  31. /* The words.dat & m.msg may be configurable in the future, so not check here */
  32. /* Try to get the path */
  33. auto foldertask = concurrency::create_task(root->GetFolderAsync(PAL_PATH_NAME));
  34. if (!WaitOnTask(foldertask, 500)) return false; // Wait for 500ms max
  35. try
  36. {
  37. /* Check the access right of necessary files */
  38. auto folder = foldertask.get();
  39. for (int i = 0; i < 13; i++)
  40. {
  41. auto filetask = concurrency::create_task(foldertask.get()->GetFileAsync(required_files[i]));
  42. if (!WaitOnTask(filetask, 500) || _waccess_s(filetask.get()->Path->Begin(), 2)) return false;
  43. }
  44. for (int i = 0; i < 2; i++)
  45. {
  46. auto filetask = concurrency::create_task(foldertask.get()->GetFileAsync(optional_required_files[i]));
  47. if (WaitOnTask(filetask, 500) && _waccess_s(filetask.get()->Path->Begin(), 2) == 0) return true;
  48. }
  49. }
  50. catch(Platform::Exception^)
  51. { /* Accessing SD card failed, or required file is missing, or access is denied */ }
  52. return false;
  53. }
  54. extern "C"
  55. LPCSTR UTIL_BasePath(VOID)
  56. {
  57. if (g_basepath.empty())
  58. {
  59. auto enumtask = concurrency::create_task(Windows::Storage::KnownFolders::RemovableDevices->GetFoldersAsync());
  60. if (WaitOnTask(enumtask, 1000)) // Wait for 1000ms max
  61. {
  62. auto folderiter = enumtask.get()->First();
  63. while (folderiter->HasCurrent)
  64. {
  65. if (CheckGamePath(folderiter->Current))
  66. {
  67. /* Folder examination succeeded */
  68. auto folder = folderiter->Current->Path;
  69. if (folder->End()[-1] != L'\\') folder += "\\";
  70. folder += PAL_PATH_NAME "\\";
  71. ConvertString(folder, g_basepath);
  72. /* Check whether the folder is writable */
  73. FILE* fp;
  74. if (_wfopen_s(&fp, (folder + "sdlpal.rpg")->Begin(), L"w") == 0)
  75. {
  76. g_savepath = g_basepath;
  77. fclose(fp);
  78. }
  79. break;
  80. }
  81. folderiter->MoveNext();
  82. }
  83. }
  84. if (g_basepath.empty())
  85. {
  86. g_basepath.assign("Assets\\Data\\");
  87. }
  88. }
  89. return g_basepath.c_str();
  90. }
  91. extern "C"
  92. LPCSTR UTIL_SavePath(VOID)
  93. {
  94. if (g_savepath.empty())
  95. {
  96. auto localfolder = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
  97. if (localfolder->End()[-1] != L'\\') localfolder += "\\";
  98. ConvertString(localfolder, g_savepath);
  99. }
  100. return g_savepath.c_str();
  101. }
  102. extern "C"
  103. BOOL UTIL_GetScreenSize(DWORD *pdwScreenWidth, DWORD *pdwScreenHeight)
  104. {
  105. DXGI_OUTPUT_DESC desc;
  106. IDXGIFactory1* pFactory = nullptr;
  107. IDXGIAdapter1* pAdapter = nullptr;
  108. IDXGIOutput* pOutput = nullptr;
  109. DWORD retval = FALSE;
  110. if (!pdwScreenWidth || !pdwScreenHeight) return FALSE;
  111. if (FAILED(CreateDXGIFactory1(IID_IDXGIFactory1, (void**)&pFactory))) goto UTIL_WP_GetScreenSize_exit;
  112. if (FAILED(pFactory->EnumAdapters1(0, &pAdapter))) goto UTIL_WP_GetScreenSize_exit;
  113. if (FAILED(pAdapter->EnumOutputs(0, &pOutput))) goto UTIL_WP_GetScreenSize_exit;
  114. if (SUCCEEDED(pOutput->GetDesc(&desc)))
  115. {
  116. *pdwScreenWidth = (desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top);
  117. *pdwScreenHeight = (desc.DesktopCoordinates.right - desc.DesktopCoordinates.left);
  118. retval = TRUE;
  119. }
  120. UTIL_WP_GetScreenSize_exit:
  121. if (pOutput) pOutput->Release();
  122. if (pAdapter) pAdapter->Release();
  123. if (pFactory) pFactory->Release();
  124. return retval;
  125. }