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
11 base_game_info_t gameinfo
;
12 struct game_list_t
*next
;
15 int sbIsSameSize(const char* prefix
, int prevSize
) {
18 snprintf(path
, 255, "%sul.cfg", prefix
);
20 int fd
= openFile(path
, O_RDONLY
);
22 size
= getFileSize(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)) {
37 if (size
<= ISO_GAME_NAME_MAX
)
44 static int scanForISO(char* path
, char type
, struct game_list_t
** glist
) {
45 int fd
, size
, count
= 0;
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
));
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';
67 game
->sizeMB
= (record
.stat
.size
>> 20) | (record
.stat
.hisize
<< 12);
78 void sbReadList(base_game_info_t
**list
, const char* prefix
, int *fsize
, int* gamecount
) {
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
);
106 size
= getFileSize(fd
);
108 count
+= size
/ 0x040;
111 *list
= (base_game_info_t
*)malloc(sizeof(base_game_info_t
) * count
);
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);
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
));
149 int sbPrepare(base_game_info_t
* game
, config_set_t
* configSet
, int size_cdvdman
, void** cdvdman_irx
, int* patchindex
) {
152 unsigned int compatmask
= 0;
153 configGetInt(configSet
, CONFIG_ITEM_COMPAT
, &compatmask
);
156 configGetDiscIDBinary(configSet
, gameid
);
159 for (i
= 0; i
< size_cdvdman
; i
++) {
160 if (!strcmp((const char*)((u32
)cdvdman_irx
+ i
),"###### GAMESETTINGS ######")) {
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
) {
176 memcpy((void*)((u32
)cdvdman_irx
+ i
+ 36), &no_dvddl
, 2);
179 if (compatmask
& COMPAT_MODE_4
) {
181 memcpy((void*)((u32
)cdvdman_irx
+ i
+ 38), &no_pss
, 2);
184 // patch cdvdman timer
186 if (configGetInt(configSet
, CONFIG_ITEM_CDVDMAN_TIMER
, &timer
)) {
187 u32 cdvdmanTimer
= timer
* 250;
188 memcpy((void*)((u32
)cdvdman_irx
+ i
+ 40), &cdvdmanTimer
, 4);
193 for (i
= 0; i
< size_cdvdman
; i
++) {
194 if (!strcmp((const char*)((u32
)cdvdman_irx
+ i
),"B00BS")) {
199 memcpy((void*)((u32
)cdvdman_irx
+ i
), &gameid
, 5);
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)
221 static void sbRebuildULCfg(base_game_info_t
**list
, const char* prefix
, int gamecount
, int excludeID
) {
223 snprintf(path
, 255, "%sul.cfg", prefix
);
225 file_buffer_t
* fileBuffer
= openFileBuffer(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0, 4096);
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
++) {
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
) {
259 base_game_info_t
* game
= &(*list
)[id
];
262 if (game
->media
== 0x12)
263 snprintf(path
, 255, "%sCD%s%s.%s%s", prefix
, sep
, game
->startup
, game
->name
, game
->extension
);
265 snprintf(path
, 255, "%sDVD%s%s.%s%s", prefix
, sep
, game
->startup
, game
->name
, game
->extension
);
268 char *pathStr
= "%sul.%08X.%s.%02x";
269 unsigned int crc
= USBA_crc32(game
->name
);
272 snprintf(path
, 255, pathStr
, prefix
, crc
, game
->startup
, i
++);
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
];
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
);
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
);
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
);
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
) {
313 snprintf(path
, 255, "%sCFG%s%s.cfg", prefix
, sep
, game
->startup
);
314 config_set_t
* config
= configAlloc(0, NULL
, path
);
317 configSetStr(config
, CONFIG_ITEM_NAME
, game
->name
);
318 if (game
->sizeMB
!= -1)
319 configSetInt(config
, CONFIG_ITEM_SIZE
, game
->sizeMB
);
321 configSetStr(config
, CONFIG_ITEM_FORMAT
, "ISO");
323 configSetStr(config
, CONFIG_ITEM_FORMAT
, "UL");
325 if (game
->media
== 0x12)
326 configSetStr(config
, CONFIG_ITEM_MEDIA
, "CD");
328 configSetStr(config
, CONFIG_ITEM_MEDIA
, "DVD");
330 configSetStr(config
, CONFIG_ITEM_STARTUP
, game
->startup
);