1 /*
2 * This file is part of EasyRPG Player.
3 *
4 * EasyRPG Player is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * EasyRPG Player is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 // Headers
19 #include <cstdlib>
20 #include "main_data.h"
21 #include "filefinder.h"
22 #include "filefinder_rtp.h"
23 #include "filesystem.h"
24 #include "game_system.h"
25 #include "game_actors.h"
26 #include "game_party.h"
27 #include "game_enemyparty.h"
28 #include "game_ineluki.h"
29 #include "game_player.h"
30 #include "game_screen.h"
31 #include "game_pictures.h"
32 #include "game_map.h"
33 #include "game_variables.h"
34 #include "game_switches.h"
35 #include "game_targets.h"
36 #include "game_quit.h"
37 #include "font.h"
38 #include "player.h"
39 #include "system.h"
40 #include "output.h"
41
42 #ifndef _WIN32
43 # include <unistd.h>
44 #endif
45 #if defined(USE_SDL) && defined(__ANDROID__)
46 # include <jni.h>
47 # include <SDL_system.h>
48 #elif defined(_3DS)
49 # include <3ds.h>
50 # include <cstdio>
51 #elif defined(PSP2)
52 # include <cstdio>
53 # include <psp2/io/stat.h>
54 #elif defined(__APPLE__) && TARGET_OS_OSX
55 # include <sys/syslimits.h>
56 # include "platform/macos/utils.h"
57 #endif
58
59 // Global variables.
60 std::string project_path;
61
62 namespace Main_Data {
63 // Dynamic Game lcf::Data
64 std::unique_ptr<Game_System> game_system;
65 std::unique_ptr<Game_Switches> game_switches;
66 std::unique_ptr<Game_Variables> game_variables;
67 std::unique_ptr<Game_Screen> game_screen;
68 std::unique_ptr<Game_Pictures> game_pictures;
69 std::unique_ptr<Game_Actors> game_actors;
70 std::unique_ptr<Game_Player> game_player;
71 std::unique_ptr<Game_Party> game_party;
72 std::unique_ptr<Game_EnemyParty> game_enemyparty;
73 std::unique_ptr<Game_Targets> game_targets;
74 std::unique_ptr<Game_Quit> game_quit;
75 std::unique_ptr<Game_Ineluki> game_ineluki;
76 std::unique_ptr<FileFinder_RTP> filefinder_rtp;
77 }
78
Init()79 void Main_Data::Init() {
80 if (project_path.empty()) {
81 project_path =
82 getenv("RPG_TEST_GAME_PATH") ? getenv("RPG_TEST_GAME_PATH") :
83 getenv("RPG_GAME_PATH") ? getenv("RPG_GAME_PATH") :
84 "";
85
86 if (project_path.empty()) {
87 // first set to current directory for all platforms
88 project_path = "";
89
90 #if defined(GEKKO) || defined(__SWITCH__) || defined(__MORPHOS__) || defined(__amigaos4__) || defined(__AROS__)
91 // Working directory not correctly handled
92 char working_dir[256];
93 getcwd(working_dir, 255);
94 project_path = std::string(working_dir);
95 #elif defined(PSP2)
96 // Check if app0 filesystem contains the title id reference file
97 FILE* f = fopen("app0:/titleid.txt","r");
98 if (f == NULL)
99 project_path = "ux0:/data/easyrpg-player";
100 else {
101 char titleID[10];
102 char psp2_dir[256];
103 fread(titleID, 1, 9, f);
104 titleID[9] = 0;
105 sprintf(psp2_dir, "ux0:/data/%s",titleID);
106 fclose(f);
107 project_path = "app0:";
108 // Creating saves dir if it doesn't exist
109 sceIoMkdir(psp2_dir, 0777);
110 auto savefs = FileFinder::Root().Create(psp2_dir);
111 if (!savefs) {
112 Output::Error("PSP2: Invalid save path {}", psp2_dir);
113 }
114 FileFinder::SetSaveFilesystem(savefs);
115 }
116 #elif defined(_3DS)
117 // Check if romFs has some files inside or not
118 FILE* testfile = fopen("romfs:/RPG_RT.lmt","r");
119 if (testfile != NULL) {
120 Output::Debug("Detected a project on romFs filesystem...");
121 fclose(testfile);
122 project_path = "romfs:";
123
124 if (!Player::is_3dsx) {
125 // Create savepath for CIA - unique for any ID
126
127 // Generating save_path
128 u64 titleID;
129 APT_GetProgramID(&titleID);
130 char mainDir[64];
131 sprintf(mainDir,"sdmc:/easyrpg-player/%016llX",titleID);
132
133 // Creating dirs if they don't exist
134 FS_Archive archive;
135 FSUSER_OpenArchive(&archive, ARCHIVE_SDMC, {PATH_EMPTY, 1, (u8*)""});
136 FS_Path filePath=fsMakePath(PATH_ASCII, "/easyrpg-player");
137 FSUSER_CreateDirectory(archive,filePath, FS_ATTRIBUTE_DIRECTORY);
138 FS_Path filePath2=fsMakePath(PATH_ASCII, &mainDir[5]);
139 FSUSER_CreateDirectory(archive,filePath2, FS_ATTRIBUTE_DIRECTORY);
140 FSUSER_CloseArchive(archive);
141
142 auto savefs = FileFinder::Root().Create(mainDir);
143 if (!savefs) {
144 Output::Error("3DS: Invalid save path {}", mainDir);
145 }
146 FileFinder::SetSaveFilesystem(savefs);
147 }
148 } else if (!Player::is_3dsx) {
149 // No RomFS -> load games from hardcoded path
150 project_path = "sdmc:/3ds/easyrpg-player";
151 }
152 #elif defined(__APPLE__) && TARGET_OS_OSX
153 // Apple Finder does not set the working directory
154 // It points to HOME instead. When it is HOME change it to
155 // the application directory instead
156
157 char* home = getenv("HOME");
158 char current_dir[PATH_MAX] = { 0 };
159 getcwd(current_dir, sizeof(current_dir));
160 if (strcmp(current_dir, "/") == 0 || strcmp(current_dir, home) == 0) {
161 project_path = MacOSUtils::GetBundleDir();
162 }
163 #endif
164 }
165 }
166 }
167
168
Cleanup()169 void Main_Data::Cleanup() {
170 Game_Map::Quit();
171
172 game_switches.reset();
173 game_screen.reset();
174 game_pictures.reset();
175 game_player.reset();
176 game_party.reset();
177 game_enemyparty.reset();
178 game_actors.reset();
179 game_targets.reset();
180 game_quit.reset();
181 game_system.reset();
182 game_ineluki.reset();
183 }
184
GetDefaultProjectPath()185 const std::string& Main_Data::GetDefaultProjectPath() {
186 return project_path;
187 }
188