WinPhoneUtil.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. try { if (WaitOnTask(filetask, 500) && _waccess_s(filetask.get()->Path->Begin(), 2) == 0) return true; }
  48. catch(Platform::Exception^) {}
  49. }
  50. }
  51. catch(Platform::Exception^)
  52. { /* Accessing SD card failed, or required file is missing, or access is denied */ }
  53. return false;
  54. }
  55. extern "C"
  56. LPCSTR UTIL_BasePath(VOID)
  57. {
  58. if (g_basepath.empty())
  59. {
  60. auto enumtask = concurrency::create_task(Windows::Storage::KnownFolders::RemovableDevices->GetFoldersAsync());
  61. if (WaitOnTask(enumtask, 1000)) // Wait for 1000ms max
  62. {
  63. auto folderiter = enumtask.get()->First();
  64. while (folderiter->HasCurrent)
  65. {
  66. if (CheckGamePath(folderiter->Current))
  67. {
  68. /* Folder examination succeeded */
  69. auto folder = folderiter->Current->Path;
  70. if (folder->End()[-1] != L'\\') folder += "\\";
  71. folder += PAL_PATH_NAME "\\";
  72. ConvertString(folder, g_basepath);
  73. /* Check whether the folder is writable */
  74. FILE* fp;
  75. if (_wfopen_s(&fp, (folder + "sdlpal.rpg")->Begin(), L"w") == 0)
  76. {
  77. g_savepath = g_basepath;
  78. fclose(fp);
  79. }
  80. break;
  81. }
  82. folderiter->MoveNext();
  83. }
  84. }
  85. if (g_basepath.empty())
  86. {
  87. g_basepath.assign("Assets\\Data\\");
  88. }
  89. }
  90. return g_basepath.c_str();
  91. }
  92. extern "C"
  93. LPCSTR UTIL_SavePath(VOID)
  94. {
  95. if (g_savepath.empty())
  96. {
  97. auto localfolder = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
  98. if (localfolder->End()[-1] != L'\\') localfolder += "\\";
  99. ConvertString(localfolder, g_savepath);
  100. }
  101. return g_savepath.c_str();
  102. }
  103. extern "C"
  104. BOOL UTIL_GetScreenSize(DWORD *pdwScreenWidth, DWORD *pdwScreenHeight)
  105. {
  106. DXGI_OUTPUT_DESC desc;
  107. IDXGIFactory1* pFactory = nullptr;
  108. IDXGIAdapter1* pAdapter = nullptr;
  109. IDXGIOutput* pOutput = nullptr;
  110. DWORD retval = FALSE;
  111. if (!pdwScreenWidth || !pdwScreenHeight) return FALSE;
  112. if (FAILED(CreateDXGIFactory1(IID_IDXGIFactory1, (void**)&pFactory))) goto UTIL_WP_GetScreenSize_exit;
  113. if (FAILED(pFactory->EnumAdapters1(0, &pAdapter))) goto UTIL_WP_GetScreenSize_exit;
  114. if (FAILED(pAdapter->EnumOutputs(0, &pOutput))) goto UTIL_WP_GetScreenSize_exit;
  115. if (SUCCEEDED(pOutput->GetDesc(&desc)))
  116. {
  117. *pdwScreenWidth = (desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top);
  118. *pdwScreenHeight = (desc.DesktopCoordinates.right - desc.DesktopCoordinates.left);
  119. retval = TRUE;
  120. }
  121. UTIL_WP_GetScreenSize_exit:
  122. if (pOutput) pOutput->Release();
  123. if (pAdapter) pAdapter->Release();
  124. if (pFactory) pFactory->Release();
  125. return retval;
  126. }