1 #include "include/usbld.h"
2 #include "include/lang.h"
3 #include "include/gui.h"
4 #include "include/supportbase.h"
5 #include "include/usbsupport.h"
6 #include "include/util.h"
7 #include "include/themes.h"
8 #include "include/textures.h"
9 #include "include/ioman.h"
10 #include "include/system.h"
12 extern void *usb_cdvdman_irx
;
13 extern int size_usb_cdvdman_irx
;
15 extern void *usb_4Ksectors_cdvdman_irx
;
16 extern int size_usb_4Ksectors_cdvdman_irx
;
18 extern void *usbd_ps2_irx
;
19 extern int size_usbd_ps2_irx
;
21 extern void *usbd_ps3_irx
;
22 extern int size_usbd_ps3_irx
;
24 extern void *usbhdfsd_irx
;
25 extern int size_usbhdfsd_irx
;
28 extern void *usb_mcemu_irx
;
29 extern int size_usb_mcemu_irx
;
35 static char usbPrefix
[40];
36 static int usbULSizePrev
= -2;
37 static unsigned char usbModifiedCDPrev
[8];
38 static unsigned char usbModifiedDVDPrev
[8];
39 static int usbGameCount
= 0;
40 static base_game_info_t
*usbGames
;
42 // forward declaration
43 static item_list_t usbGameList
;
45 int usbFindPartition(char *target
, char *name
) {
50 if (gUSBPrefix
[0] != '\0')
51 sprintf(path
, "mass%d:%s/%s", i
, gUSBPrefix
, name
);
53 sprintf(path
, "mass%d:%s", i
, name
);
54 fd
= fioOpen(path
, O_RDONLY
);
57 if (gUSBPrefix
[0] != '\0')
58 sprintf(target
, "mass%d:%s/", i
, gUSBPrefix
);
60 sprintf(target
, "mass%d:", i
);
66 // default to first partition (for themes, ...)
67 if (gUSBPrefix
[0] != '\0')
68 sprintf(target
, "mass0:%s/", gUSBPrefix
);
70 sprintf(target
, "mass0:");
74 static void usbInitModules(void) {
78 usbFindPartition(usbPrefix
, "ul.cfg");
80 sprintf(path
, "%sTHM", usbPrefix
);
81 thmAddElements(path
, "/", usbGameList
.mode
);
83 sprintf(path
, "%sCFG", usbPrefix
);
87 sprintf(path
, "%sVMC", usbPrefix
);
92 void usbLoadModules(void) {
93 LOG("usbLoadModules()\n");
94 //first it search for custom usbd in MC?
95 usbd_irx
= readFile("mc?:BEDATA-SYSTEM/USBD.IRX", -1, &size_usbd_irx
);
97 usbd_irx
= readFile("mc?:BADATA-SYSTEM/USBD.IRX", -1, &size_usbd_irx
);
99 usbd_irx
= readFile("mc?:BIDATA-SYSTEM/USBD.IRX", -1, &size_usbd_irx
);
100 if (!usbd_irx
) { // If don't exist it uses embedded
101 if (sysPS3Detect() == 0) {
102 usbd_irx
= (void *) &usbd_ps2_irx
;
103 size_usbd_irx
= size_usbd_ps2_irx
;
105 usbd_irx
= (void *) &usbd_ps3_irx
;
106 size_usbd_irx
= size_usbd_ps3_irx
;
112 sysLoadModuleBuffer(usbd_irx
, size_usbd_irx
, 0, NULL
);
113 sysLoadModuleBuffer(&usbhdfsd_irx
, size_usbhdfsd_irx
, 0, NULL
);
117 LOG("usbLoadModules: modules loaded\n");
123 memset(usbModifiedCDPrev
, 0, 8);
124 memset(usbModifiedDVDPrev
, 0, 8);
128 ioPutRequest(IO_CUSTOM_SIMPLEACTION
, &usbInitModules
);
130 usbGameList
.enabled
= 1;
133 item_list_t
* usbGetObject(int initOnly
) {
134 if (initOnly
&& !usbGameList
.enabled
)
139 static int usbNeedsUpdate(void) {
144 usbFindPartition(usbPrefix
, "ul.cfg");
146 sprintf(path
, "%sCD", usbPrefix
);
147 if (fioGetstat(path
, &stat
) != 0)
148 memset(stat
.mtime
, 0, 8);
149 if (memcmp(usbModifiedCDPrev
, stat
.mtime
, 8)) {
150 memcpy(usbModifiedCDPrev
, stat
.mtime
, 8);
154 sprintf(path
, "%sDVD", usbPrefix
);
155 if (fioGetstat(path
, &stat
) != 0)
156 memset(stat
.mtime
, 0, 8);
157 if (memcmp(usbModifiedDVDPrev
, stat
.mtime
, 8)) {
158 memcpy(usbModifiedDVDPrev
, stat
.mtime
, 8);
162 if (!sbIsSameSize(usbPrefix
, usbULSizePrev
))
168 static int usbUpdateGameList(void) {
169 sbReadList(&usbGames
, usbPrefix
, &usbULSizePrev
, &usbGameCount
);
173 static int usbGetGameCount(void) {
177 static void* usbGetGame(int id
) {
178 return (void*) &usbGames
[id
];
181 static char* usbGetGameName(int id
) {
182 return usbGames
[id
].name
;
185 static int usbGetGameNameLength(int id
) {
186 if (usbGames
[id
].isISO
)
187 return ISO_GAME_NAME_MAX
+ 1;
189 return UL_GAME_NAME_MAX
+ 1;
192 static char* usbGetGameStartup(int id
) {
193 return usbGames
[id
].startup
;
197 static void usbDeleteGame(int id
) {
198 sbDelete(&usbGames
, usbPrefix
, "/", usbGameCount
, id
);
202 /*static void usbRenameGame(int id, char* newName) {
203 // TODO when/if Jimmi add rename functionnality to usbhdfs, then we should use the above method
204 //sbRename(&usbGames, usbPrefix, "/", usbGameCount, id, newName);
210 static int usbPrepareMcemu(base_game_info_t
* game
, config_set_t
* configSet
) {
214 int i
, j
, fd
, size_mcemu_irx
= 0;
215 usb_vmc_infos_t usb_vmc_infos
;
216 vmc_superblock_t vmc_superblock
;
218 configGetVMC(configSet
, vmc
[0], 0);
219 configGetVMC(configSet
, vmc
[1], 1);
222 if(!vmc
[i
][0]) // skip if empty
225 memset(&usb_vmc_infos
, 0, sizeof(usb_vmc_infos_t
));
226 memset(&vmc_superblock
, 0, sizeof(vmc_superblock_t
));
228 sprintf(vmc_path
, "%sVMC/%s.bin", usbPrefix
, vmc
[i
]);
230 fd
= fioOpen(vmc_path
, O_RDWR
);
233 LOG("%s open\n", vmc_path
);
235 vmc_size
= fioLseek(fd
, 0, SEEK_END
);
236 fioLseek(fd
, 0, SEEK_SET
);
237 fioRead(fd
, (void*)&vmc_superblock
, sizeof(vmc_superblock_t
));
239 LOG("File size : 0x%X\n", vmc_size
);
240 LOG("Magic : %s\n", vmc_superblock
.magic
);
241 LOG("Card type : %d\n", vmc_superblock
.mc_type
);
243 if(!strncmp(vmc_superblock
.magic
, "Sony PS2 Memory Card Format", 27) && vmc_superblock
.mc_type
== 0x2) {
244 usb_vmc_infos
.flags
= vmc_superblock
.mc_flag
& 0xFF;
245 usb_vmc_infos
.flags
|= 0x100;
246 usb_vmc_infos
.specs
.page_size
= vmc_superblock
.page_size
;
247 usb_vmc_infos
.specs
.block_size
= vmc_superblock
.pages_per_block
;
248 usb_vmc_infos
.specs
.card_size
= vmc_superblock
.pages_per_cluster
* vmc_superblock
.clusters_per_card
;
250 LOG("flags : 0x%X\n", usb_vmc_infos
.flags
);
251 LOG("specs.page_size : 0x%X\n", usb_vmc_infos
.specs
.page_size
);
252 LOG("specs.block_size : 0x%X\n", usb_vmc_infos
.specs
.block_size
);
253 LOG("specs.card_size : 0x%X\n", usb_vmc_infos
.specs
.card_size
);
255 if(vmc_size
== usb_vmc_infos
.specs
.card_size
* usb_vmc_infos
.specs
.page_size
) {
256 int fd1
= fioDopen(usbPrefix
);
259 sprintf(vmc_path
, "%s/VMC/%s.bin", gUSBPrefix
, vmc
[i
]);
260 // Check vmc cluster chain (write operation can cause dammage)
261 if(fioIoctl(fd1
, 0xCAFEC0DE, vmc_path
)) {
262 LOG("Cluster Chain OK\n");
263 if((j
= fioIoctl(fd1
, 0xBEEFC0DE, vmc_path
)) != 0) {
264 usb_vmc_infos
.active
= 1;
265 usb_vmc_infos
.start_sector
= j
;
266 LOG("Start Sector: 0x%X\n", usb_vmc_infos
.start_sector
);
268 } // else Vmc file fragmented
275 for (j
=0; j
<size_usb_mcemu_irx
; j
++) {
276 if (((u32
*)&usb_mcemu_irx
)[j
] == (0xC0DEFAC0 + i
)) {
277 if(usb_vmc_infos
.active
)
278 size_mcemu_irx
= size_usb_mcemu_irx
;
279 memcpy(&((u32
*)&usb_mcemu_irx
)[j
], &usb_vmc_infos
, sizeof(usb_vmc_infos_t
));
284 return size_mcemu_irx
;
288 static void usbLaunchGame(int id
, config_set_t
* configSet
) {
289 int fd
, r
, index
, i
, compatmask
;
290 char isoname
[32], partname
[255], filename
[32];
291 base_game_info_t
* game
= &usbGames
[id
];
293 fd
= fioDopen(usbPrefix
);
295 guiMsgBox(_l(_STR_ERR_FILE_INVALID
), 0, NULL
);
300 sprintf(partname
, "%s/%s/%s.%s.iso", gUSBPrefix
, (game
->media
== 0x12) ? "CD" : "DVD", game
->startup
, game
->name
);
302 sprintf(partname
, "%s/%s.00", gUSBPrefix
, isoname
);
303 r
= fioIoctl(fd
, 0xDEADC0DE, partname
);
304 LOG("mass storage device sectorsize = %d\n", r
);
306 void *irx
= &usb_cdvdman_irx
;
307 int irx_size
= size_usb_cdvdman_irx
;
309 irx
= &usb_4Ksectors_cdvdman_irx
;
310 irx_size
= size_usb_4Ksectors_cdvdman_irx
;
313 compatmask
= sbPrepare(game
, configSet
, isoname
, irx_size
, irx
, &index
);
315 if (gCheckUSBFragmentation
)
316 for (i
= 0; i
< game
->parts
; i
++) {
318 sprintf(partname
, "%s/%s.%02x", gUSBPrefix
, isoname
, i
);
320 if (fioIoctl(fd
, 0xCAFEC0DE, partname
) == 0) {
322 guiMsgBox(_l(_STR_ERR_FRAGMENTED
), 0, NULL
);
327 if (gRememberLastPlayed
) {
328 configSetStr(configGetByType(CONFIG_LAST
), "last_played", game
->startup
);
329 saveConfig(CONFIG_LAST
, 0);
333 for (i
= 0; i
< game
->parts
; i
++) {
335 sprintf(partname
, "%s/%s.%02x", gUSBPrefix
, isoname
, i
);
337 r
= fioIoctl(fd
, 0xBEEFC0DE, partname
);
338 memcpy((void*)((u32
)&usb_cdvdman_irx
+ index
+ offset
), &r
, 4);
345 int size_mcemu_irx
= usbPrepareMcemu(game
, configSet
);
346 if (size_mcemu_irx
== -1) {
347 if (guiMsgBox(_l(_STR_ERR_VMC_CONTINUE
), 1, NULL
))
354 char *altStartup
= NULL
;
355 if (configGetStr(configSet
, CONFIG_ITEM_ALTSTARTUP
, &altStartup
))
356 strncpy(filename
, altStartup
, 32);
358 sprintf(filename
, "%s", game
->startup
);
359 shutdown(NO_EXCEPTION
); // CAREFUL: shutdown will call usbCleanUp, so usbGames/game will be freed
363 sysLaunchLoaderElf(filename
, "USB_MODE", irx_size
, irx
, size_mcemu_irx
, &usb_mcemu_irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
365 sysLaunchLoaderElf(filename
, "USB_MODE", irx_size
, irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
369 static config_set_t
* usbGetConfig(int id
) {
370 return sbPopulateConfig(&usbGames
[id
], usbPrefix
, "/");
373 static int usbGetImage(char* folder
, int isRelative
, char* value
, char* suffix
, GSTEXTURE
* resultTex
, short psm
) {
376 sprintf(path
, "%s%s/%s_%s", usbPrefix
, folder
, value
, suffix
);
378 sprintf(path
, "%s%s_%s", folder
, value
, suffix
);
379 return texDiscoverLoad(resultTex
, path
, -1, psm
);
382 static void usbCleanUp(int exception
) {
383 if (usbGameList
.enabled
) {
384 LOG("usbCleanUp()\n");
391 static int usbCheckVMC(char* name
, int createSize
) {
392 return sysCheckVMC(usbPrefix
, "/", name
, createSize
);
396 static item_list_t usbGameList
= {
397 USB_MODE
, 0, COMPAT
, 0, MENU_MIN_INACTIVE_FRAMES
, "USB Games", _STR_USB_GAMES
, &usbInit
, &usbNeedsUpdate
,
399 &usbUpdateGameList
, &usbGetGameCount
, &usbGetGame
, &usbGetGameName
, &usbGetGameNameLength
, &usbGetGameStartup
, NULL
, NULL
,
401 &usbUpdateGameList
, &usbGetGameCount
, &usbGetGame
, &usbGetGameName
, &usbGetGameNameLength
, &usbGetGameStartup
, &usbDeleteGame
, NULL
,
404 &usbLaunchGame
, &usbGetConfig
, &usbGetImage
, &usbCleanUp
, &usbCheckVMC
, USB_ICON
406 &usbLaunchGame
, &usbGetConfig
, &usbGetImage
, &usbCleanUp
, USB_ICON