SilverBull: apply a delay to CDVDMAN functions (initially for Shadow Heart 2)
[open-ps2-loader.git] / src / supportbase.c
bloba48bd8800079b88b0d52cdffd81412fd895fbd58
1 #include "include/usbld.h"
2 #include "include/lang.h"
3 #include "include/util.h"
4 #include "include/iosupport.h"
5 #include "include/system.h"
6 #include "include/supportbase.h"
7 #include "include/ioman.h"
9 /// internal linked list used to populate the list from directory listing
10 struct game_list_t {
11 base_game_info_t gameinfo;
12 struct game_list_t *next;
15 int sbIsSameSize(const char* prefix, int prevSize) {
16 int size = -1;
17 char path[255];
18 snprintf(path, 255, "%sul.cfg", prefix);
20 int fd = openFile(path, O_RDONLY);
21 if (fd >= 0) {
22 size = getFileSize(fd);
23 fioClose(fd);
26 return size == prevSize;
29 static int isValidIsoName(char *name)
31 // SCUS_XXX.XX.ABCDEFGHIJKLMNOP.iso
33 // Minimum is 17 char, GameID (11) + "." (1) + filename (1 min.) + ".iso" (4)
34 int size = strlen(name);
35 if ((size >= 17) && (name[4] == '_') && (name[8] == '.') && (name[11] == '.') && (stricmp(&name[size - 4], ".iso") == 0)) {
36 size -= 16;
37 if (size <= ISO_GAME_NAME_MAX)
38 return size;
41 return 0;
44 static int scanForISO(char* path, char type, struct game_list_t** glist) {
45 int fd, size, count = 0;
46 fio_dirent_t record;
48 if ((fd = fioDopen(path)) > 0) {
49 while (fioDread(fd, &record) > 0) {
50 if ((size = isValidIsoName(record.name)) > 0) {
51 struct game_list_t *next = (struct game_list_t*)malloc(sizeof(struct game_list_t));
53 next->next = *glist;
54 *glist = next;
56 base_game_info_t *game = &(*glist)->gameinfo;
58 strncpy(game->name, &record.name[GAME_STARTUP_MAX], size);
59 game->name[size] = '\0';
60 strncpy(game->startup, record.name, GAME_STARTUP_MAX - 1);
61 game->startup[GAME_STARTUP_MAX - 1] = '\0';
62 strncpy(game->extension, &record.name[GAME_STARTUP_MAX + size], 4);
63 game->extension[4] = '\0';
64 game->parts = 0x01;
65 game->media = type;
66 game->isISO = 1;
67 game->sizeMB = (record.stat.size >> 20) | (record.stat.hisize << 12);
69 count++;
72 fioDclose(fd);
75 return count;
78 void sbReadList(base_game_info_t **list, const char* prefix, int *fsize, int* gamecount) {
79 int fd, size, id = 0;
80 size_t count = 0;
81 char path[255];
83 free(*list);
84 *list = NULL;
85 *fsize = -1;
86 *gamecount = 0;
88 // temporary storage for the game names
89 struct game_list_t *dlist_head = NULL;
91 // count iso games in "cd" directory
92 snprintf(path, 255, "%sCD", prefix);
93 count += scanForISO(path, 0x12, &dlist_head);
95 // count iso games in "dvd" directory
96 snprintf(path, 255, "%sDVD", prefix);
97 count += scanForISO(path, 0x14, &dlist_head);
100 // count and process games in ul.cfg
101 snprintf(path, 255, "%sul.cfg", prefix);
102 fd = openFile(path, O_RDONLY);
103 if(fd >= 0) {
104 char buffer[0x040];
106 size = getFileSize(fd);
107 *fsize = size;
108 count += size / 0x040;
110 if (count > 0) {
111 *list = (base_game_info_t*)malloc(sizeof(base_game_info_t) * count);
113 while (size > 0) {
114 fioRead(fd, buffer, 0x40);
116 base_game_info_t *g = &(*list)[id++];
118 // to ensure no leaks happen, we copy manually and pad the strings
119 memcpy(g->name, buffer, UL_GAME_NAME_MAX);
120 g->name[UL_GAME_NAME_MAX] = '\0';
121 memcpy(g->startup, &buffer[UL_GAME_NAME_MAX + 3], GAME_STARTUP_MAX);
122 g->startup[GAME_STARTUP_MAX] = '\0';
123 g->extension[0] = '\0';
124 memcpy(&g->parts, &buffer[47], 1);
125 memcpy(&g->media, &buffer[48], 1);
126 g->isISO = 0;
127 g->sizeMB = -1;
128 size -= 0x40;
131 fioClose(fd);
133 else if (count > 0)
134 *list = (base_game_info_t*)malloc(sizeof(base_game_info_t) * count);
136 // copy the dlist into the list
137 while ((id < count) && dlist_head) {
138 // copy one game, advance
139 struct game_list_t *cur = dlist_head;
140 dlist_head = dlist_head->next;
142 memcpy(&(*list)[id++], &cur->gameinfo, sizeof(base_game_info_t));
143 free(cur);
146 *gamecount = count;
149 int sbPrepare(base_game_info_t* game, config_set_t* configSet, int size_cdvdman, void** cdvdman_irx, int* patchindex) {
150 int i;
152 unsigned int compatmask = 0;
153 configGetInt(configSet, CONFIG_ITEM_COMPAT, &compatmask);
155 char gameid[5];
156 configGetDiscIDBinary(configSet, gameid);
159 for (i = 0; i < size_cdvdman; i++) {
160 if (!strcmp((const char*)((u32)cdvdman_irx + i),"###### GAMESETTINGS ######")) {
161 break;
165 memcpy((void*)((u32)cdvdman_irx + i + 33), &game->parts, 1);
167 memcpy((void*)((u32)cdvdman_irx + i + 34), &game->media, 1);
169 if (compatmask & COMPAT_MODE_2) {
170 u32 alt_read_mode = 1;
171 memcpy((void*)((u32)cdvdman_irx + i + 35), &alt_read_mode, 1);
174 if (compatmask & COMPAT_MODE_5) {
175 u32 no_dvddl = 1;
176 memcpy((void*)((u32)cdvdman_irx + i + 36), &no_dvddl, 2);
179 if (compatmask & COMPAT_MODE_4) {
180 u32 no_pss = 1;
181 memcpy((void*)((u32)cdvdman_irx + i + 38), &no_pss, 2);
184 // patch cdvdman timer
185 int timer = 0;
186 if (configGetInt(configSet, CONFIG_ITEM_CDVDMAN_TIMER, &timer)) {
187 u32 cdvdmanTimer = timer * 250;
188 memcpy((void*)((u32)cdvdman_irx + i + 40), &cdvdmanTimer, 4);
191 *patchindex = i;
193 for (i = 0; i < size_cdvdman; i++) {
194 if (!strcmp((const char*)((u32)cdvdman_irx + i),"B00BS")) {
195 break;
198 // game id
199 memcpy((void*)((u32)cdvdman_irx + i), &gameid, 5);
201 // patches cdvdfsv
202 /*void *cdvdfsv_irx;
203 int size_cdvdfsv_irx;
205 sysGetCDVDFSV(&cdvdfsv_irx, &size_cdvdfsv_irx);
206 u32 *p = (u32 *)cdvdfsv_irx;
207 for (i = 0; i < (size_cdvdfsv_irx >> 2); i++) {
208 if (*p == 0xC0DEC0DE) {
209 if (compatmask & COMPAT_MODE_7)
210 *p = 1;
211 else
212 *p = 0;
213 break;
215 p++;
218 return compatmask;
221 static void sbRebuildULCfg(base_game_info_t **list, const char* prefix, int gamecount, int excludeID) {
222 char path[255];
223 snprintf(path, 255, "%sul.cfg", prefix);
225 file_buffer_t* fileBuffer = openFileBuffer(path, O_WRONLY | O_CREAT | O_TRUNC, 0, 4096);
226 if (fileBuffer) {
227 int i;
228 char buffer[0x40];
229 base_game_info_t* game;
231 memset(buffer, 0, 0x40);
232 buffer[32] = 0x75; // u
233 buffer[33] = 0x6C; // l
234 buffer[34] = 0x2E; // .
235 buffer[53] = 0x08; // just to be compatible with original ul.cfg
237 for (i = 0; i < gamecount; i++) {
238 game = &(*list)[i];
240 if (!game->isISO && (i != excludeID)) {
241 memset(buffer, 0, UL_GAME_NAME_MAX);
242 memset(&buffer[UL_GAME_NAME_MAX + 3], 0, GAME_STARTUP_MAX);
244 memcpy(buffer, game->name, UL_GAME_NAME_MAX);
245 memcpy(&buffer[UL_GAME_NAME_MAX + 3], game->startup, GAME_STARTUP_MAX);
246 buffer[47] = game->parts;
247 buffer[48] = game->media;
249 writeFileBuffer(fileBuffer, buffer, 0x40);
253 closeFileBuffer(fileBuffer);
257 void sbDelete(base_game_info_t **list, const char* prefix, const char* sep, int gamecount, int id) {
258 char path[255];
259 base_game_info_t* game = &(*list)[id];
261 if (game->isISO) {
262 if (game->media == 0x12)
263 snprintf(path, 255, "%sCD%s%s.%s%s", prefix, sep, game->startup, game->name, game->extension);
264 else
265 snprintf(path, 255, "%sDVD%s%s.%s%s", prefix, sep, game->startup, game->name, game->extension);
266 fileXioRemove(path);
267 } else {
268 char *pathStr = "%sul.%08X.%s.%02x";
269 unsigned int crc = USBA_crc32(game->name);
270 int i = 0;
271 do {
272 snprintf(path, 255, pathStr, prefix, crc, game->startup, i++);
273 fileXioRemove(path);
274 } while(i < game->parts);
276 sbRebuildULCfg(list, prefix, gamecount, id);
280 void sbRename(base_game_info_t **list, const char* prefix, const char* sep, int gamecount, int id, char* newname) {
281 char oldpath[255], newpath[255];
282 base_game_info_t* game = &(*list)[id];
284 if (game->isISO) {
285 if (game->media == 0x12) {
286 snprintf(oldpath, 255, "%sCD%s%s.%s%s", prefix, sep, game->startup, game->name, game->extension);
287 snprintf(newpath, 255, "%sCD%s%s.%s%s", prefix, sep, game->startup, newname, game->extension);
288 } else {
289 snprintf(oldpath, 255, "%sDVD%s%s.%s%s", prefix, sep, game->startup, game->name, game->extension);
290 snprintf(newpath, 255, "%sDVD%s%s.%s%s", prefix, sep, game->startup, newname, game->extension);
292 fileXioRename(oldpath, newpath);
293 } else {
294 memset(game->name, 0, UL_GAME_NAME_MAX);
295 memcpy(game->name, newname, UL_GAME_NAME_MAX);
297 char *pathStr = "%sul.%08X.%s.%02x";
298 unsigned int oldcrc = USBA_crc32(game->name);
299 unsigned int newcrc = USBA_crc32(newname);
300 int i = 0;
301 do {
302 snprintf(oldpath, 255, pathStr, prefix, oldcrc, game->startup, i);
303 snprintf(newpath, 255, pathStr, prefix, newcrc, game->startup, i++);
304 fileXioRename(oldpath, newpath);
305 } while(i < game->parts);
307 sbRebuildULCfg(list, prefix, gamecount, -1);
311 config_set_t* sbPopulateConfig(base_game_info_t* game, const char* prefix, const char* sep) {
312 char path[255];
313 snprintf(path, 255, "%sCFG%s%s.cfg", prefix, sep, game->startup);
314 config_set_t* config = configAlloc(0, NULL, path);
315 configRead(config);
317 configSetStr(config, CONFIG_ITEM_NAME, game->name);
318 if (game->sizeMB != -1)
319 configSetInt(config, CONFIG_ITEM_SIZE, game->sizeMB);
320 if (game->isISO)
321 configSetStr(config, CONFIG_ITEM_FORMAT, "ISO");
322 else
323 configSetStr(config, CONFIG_ITEM_FORMAT, "UL");
325 if (game->media == 0x12)
326 configSetStr(config, CONFIG_ITEM_MEDIA, "CD");
327 else
328 configSetStr(config, CONFIG_ITEM_MEDIA, "DVD");
330 configSetStr(config, CONFIG_ITEM_STARTUP, game->startup);
332 return config;