FreeShop.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #include <sys/stat.h>
  2. #include "FreeShop.hpp"
  3. #include "States/TitleState.hpp"
  4. #include "Notification.hpp"
  5. #include "States/DialogState.hpp"
  6. #include "States/LoadingState.hpp"
  7. #include "States/SyncState.hpp"
  8. #include "States/BrowseState.hpp"
  9. #include "States/NewsState.hpp"
  10. #include "TitleKeys.hpp"
  11. #include "Util.hpp"
  12. #include "States/SleepState.hpp"
  13. #include "States/QrScannerState.hpp"
  14. #include "GUI/Settings.hpp"
  15. #ifndef EMULATION
  16. #include <3ds.h>
  17. #endif
  18. using namespace cpp3ds;
  19. using namespace TweenEngine;
  20. namespace FreeShop {
  21. cpp3ds::Uint64 g_requestJump = 0;
  22. bool g_requestShutdown = false;
  23. FreeShop::FreeShop()
  24. : Game(0x100000)
  25. {
  26. m_stateStack = new StateStack(State::Context(m_text, m_data));
  27. m_stateStack->registerState<TitleState>(States::Title);
  28. m_stateStack->registerState<LoadingState>(States::Loading);
  29. m_stateStack->registerState<SyncState>(States::Sync);
  30. m_stateStack->registerState<BrowseState>(States::Browse);
  31. m_stateStack->registerState<SleepState>(States::Sleep);
  32. m_stateStack->registerState<QrScannerState>(States::QrScanner);
  33. m_stateStack->registerState<DialogState>(States::Dialog);
  34. m_stateStack->registerState<NewsState>(States::News);
  35. #ifdef EMULATION
  36. m_stateStack->pushState(States::Browse);
  37. #else
  38. m_stateStack->pushState(States::Loading);
  39. m_stateStack->pushState(States::Sync);
  40. m_stateStack->pushState(States::Title);
  41. #endif
  42. textFPS.setFillColor(cpp3ds::Color::Red);
  43. textFPS.setCharacterSize(20);
  44. // Set up directory structure, if necessary
  45. std::string path = cpp3ds::FileSystem::getFilePath(FREESHOP_DIR);
  46. if (!pathExists(path.c_str(), false))
  47. makeDirectory(path.c_str());
  48. path = cpp3ds::FileSystem::getFilePath(FREESHOP_DIR "/tmp");
  49. if (pathExists(path.c_str(), false))
  50. removeDirectory(path.c_str());
  51. mkdir(path.c_str(), 0777);
  52. path = cpp3ds::FileSystem::getFilePath(FREESHOP_DIR "/cache");
  53. if (!pathExists(path.c_str(), false))
  54. mkdir(path.c_str(), 0777);
  55. path = cpp3ds::FileSystem::getFilePath(FREESHOP_DIR "/keys");
  56. if (!pathExists(path.c_str(), false))
  57. mkdir(path.c_str(), 0777);
  58. path = cpp3ds::FileSystem::getFilePath(FREESHOP_DIR "/news");
  59. if (!pathExists(path.c_str(), false))
  60. mkdir(path.c_str(), 0777);
  61. path = cpp3ds::FileSystem::getFilePath(FREESHOP_DIR "/music");
  62. if (!pathExists(path.c_str(), false))
  63. mkdir(path.c_str(), 0777);
  64. path = cpp3ds::FileSystem::getFilePath(FREESHOP_DIR "/music/eshop");
  65. if (!pathExists(path.c_str(), false))
  66. mkdir(path.c_str(), 0777);
  67. Config::loadFromFile();
  68. // Load chosen language, correct auto-detect with separate Spanish/Portuguese
  69. std::string langCode = Config::get(Config::Language).GetString();
  70. #ifdef _3DS
  71. u8 region;
  72. CFGU_SecureInfoGetRegion(&region);
  73. if (langCode == "auto")
  74. {
  75. if (cpp3ds::I18n::getLanguage() == cpp3ds::Language::Spanish)
  76. langCode = (region == CFG_REGION_USA) ? "es_US" : "es_ES";
  77. else if (cpp3ds::I18n::getLanguage() == cpp3ds::Language::Portuguese)
  78. langCode = (region == CFG_REGION_USA) ? "pt_BR" : "pt_PT";
  79. }
  80. #endif
  81. if (langCode != "auto")
  82. cpp3ds::I18n::loadLanguageFile(_("lang/%s.lang", langCode.c_str()));
  83. // If override.lang exists, use it instead of chosen language
  84. std::string testLangFilename(FREESHOP_DIR "/override.lang");
  85. if (pathExists(testLangFilename.c_str()))
  86. cpp3ds::I18n::loadLanguageFile(testLangFilename);
  87. // Used to theme the loading background
  88. if (pathExists(FREESHOP_DIR "/theme/images/topBG.png", true)) {
  89. m_rectTopBG.setTexture(&AssetManager<cpp3ds::Texture>::get(FREESHOP_DIR "/theme/images/topBG.png"));
  90. m_rectTopBG.setPosition(0.f, 0.f);
  91. m_topBG = true;
  92. }
  93. if (pathExists(FREESHOP_DIR "/theme/images/botBG.png", true)) {
  94. m_rectBotBG.setTexture(&AssetManager<cpp3ds::Texture>::get(FREESHOP_DIR "/theme/images/botBG.png"));
  95. m_rectBotBG.setPosition(0.f, 0.f);
  96. m_botBG = true;
  97. }
  98. }
  99. FreeShop::~FreeShop()
  100. {
  101. delete m_stateStack;
  102. }
  103. void FreeShop::update(float delta)
  104. {
  105. #ifndef EMULATION
  106. // 3DSX version need to do this here...
  107. if (g_requestJump != 0 || g_requestShutdown) {
  108. prepareToCloseApp();
  109. if (g_requestShutdown && envIsHomebrew()) {
  110. //Init the services and turn off the console
  111. ptmSysmInit();
  112. PTMSYSM_ShutdownAsync(0);
  113. ptmSysmExit();
  114. } else if (g_requestJump != 0) {
  115. //Var initialization
  116. Result res = 0;
  117. u8 hmac[0x20];
  118. memset(hmac, 0, sizeof(hmac));
  119. //Check on which media launch the title
  120. FS_MediaType mediaType = ((g_requestJump >> 32) == TitleKeys::DSiWare) ? MEDIATYPE_NAND : MEDIATYPE_SD;
  121. FS_CardType type;
  122. bool cardInserted;
  123. cardInserted = (R_SUCCEEDED(FSUSER_CardSlotIsInserted(&cardInserted)) && cardInserted && R_SUCCEEDED(FSUSER_GetCardType(&type)) && type == CARD_CTR);
  124. if (cardInserted)
  125. {
  126. // Retry a bunch of times. When the card is newly inserted,
  127. // it sometimes takes a short while before title can be read.
  128. int retryCount = 100;
  129. u64 cardTitleId;
  130. while (retryCount-- > 0)
  131. if (R_SUCCEEDED(AM_GetTitleList(nullptr, MEDIATYPE_GAME_CARD, 1, &cardTitleId)))
  132. {
  133. try
  134. {
  135. if (cardTitleId == g_requestJump)
  136. mediaType = MEDIATYPE_GAME_CARD;
  137. }
  138. catch (int e)
  139. {
  140. //
  141. }
  142. break;
  143. }
  144. else
  145. cpp3ds::sleep(cpp3ds::milliseconds(5));
  146. }
  147. //Do the application jump
  148. if (R_SUCCEEDED(res = APT_PrepareToDoApplicationJump(0, g_requestJump, mediaType)))
  149. res = APT_DoApplicationJump(0, 0, hmac);
  150. }
  151. }
  152. #endif
  153. // Need to update before checking if empty
  154. m_stateStack->update(delta);
  155. if (m_stateStack->isEmpty() || g_requestJump != 0 || g_requestShutdown) {
  156. prepareToCloseApp();
  157. exit();
  158. }
  159. Notification::update(delta);
  160. #ifndef NDEBUG
  161. static int i;
  162. if (i++ % 10 == 0) {
  163. textFPS.setString(_("%.1f fps", 1.f / delta));
  164. textFPS.setPosition(395 - textFPS.getGlobalBounds().width, 2.f);
  165. }
  166. #endif
  167. }
  168. void FreeShop::processEvent(Event& event)
  169. {
  170. m_stateStack->processEvent(event);
  171. }
  172. void FreeShop::renderTopScreen(Window& window)
  173. {
  174. if (m_topBG)
  175. window.draw(m_rectTopBG);
  176. else
  177. window.clear(Color::White);
  178. m_stateStack->renderTopScreen(window);
  179. for (auto& notification : Notification::notifications)
  180. window.draw(*notification);
  181. #ifndef NDEBUG
  182. window.draw(textFPS);
  183. #endif
  184. }
  185. void FreeShop::renderBottomScreen(Window& window)
  186. {
  187. if (m_botBG)
  188. window.draw(m_rectBotBG);
  189. else
  190. window.clear(Color::White);
  191. m_stateStack->renderBottomScreen(window);
  192. }
  193. void FreeShop::prepareToCloseApp()
  194. {
  195. DownloadQueue::getInstance().suspend();
  196. DownloadQueue::getInstance().save();
  197. if (g_browseState)
  198. g_browseState->settingsSaveToConfig();
  199. Config::set(Config::CleanExit, true);
  200. Config::saveToFile();
  201. }
  202. } // namespace FreeShop