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("USBSUPPORT LoadModules\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("USBSUPPORT Modules loaded\n");
121 LOG("USBSUPPORT Init\n");
123 memset(usbModifiedCDPrev
, 0, 8);
124 memset(usbModifiedDVDPrev
, 0, 8);
127 configGetInt(configGetByType(CONFIG_OPL
), "usb_frames_delay", &usbGameList
.delay
);
128 ioPutRequest(IO_CUSTOM_SIMPLEACTION
, &usbInitModules
);
129 usbGameList
.enabled
= 1;
132 item_list_t
* usbGetObject(int initOnly
) {
133 if (initOnly
&& !usbGameList
.enabled
)
138 static int usbNeedsUpdate(void) {
143 usbFindPartition(usbPrefix
, "ul.cfg");
145 sprintf(path
, "%sCD", usbPrefix
);
146 if (fioGetstat(path
, &stat
) != 0)
147 memset(stat
.mtime
, 0, 8);
148 if (memcmp(usbModifiedCDPrev
, stat
.mtime
, 8)) {
149 memcpy(usbModifiedCDPrev
, stat
.mtime
, 8);
153 sprintf(path
, "%sDVD", usbPrefix
);
154 if (fioGetstat(path
, &stat
) != 0)
155 memset(stat
.mtime
, 0, 8);
156 if (memcmp(usbModifiedDVDPrev
, stat
.mtime
, 8)) {
157 memcpy(usbModifiedDVDPrev
, stat
.mtime
, 8);
161 if (!sbIsSameSize(usbPrefix
, usbULSizePrev
))
167 static int usbUpdateGameList(void) {
168 sbReadList(&usbGames
, usbPrefix
, &usbULSizePrev
, &usbGameCount
);
172 static int usbGetGameCount(void) {
176 static void* usbGetGame(int id
) {
177 return (void*) &usbGames
[id
];
180 static char* usbGetGameName(int id
) {
181 return usbGames
[id
].name
;
184 static int usbGetGameNameLength(int id
) {
185 if (usbGames
[id
].isISO
)
186 return ISO_GAME_NAME_MAX
+ 1;
188 return UL_GAME_NAME_MAX
+ 1;
191 static char* usbGetGameStartup(int id
) {
192 return usbGames
[id
].startup
;
196 static void usbDeleteGame(int id
) {
197 sbDelete(&usbGames
, usbPrefix
, "/", usbGameCount
, id
);
201 /*static void usbRenameGame(int id, char* newName) {
202 // TODO when/if Jimmi add rename functionnality to usbhdfs, then we should use the above method
203 //sbRename(&usbGames, usbPrefix, "/", usbGameCount, id, newName);
208 static void usbLaunchGame(int id
, config_set_t
* configSet
) {
209 int i
, fd
, val
, index
, compatmask
= 0;
210 char partname
[255], filename
[32];
211 base_game_info_t
* game
= &usbGames
[id
];
213 fd
= fioDopen(usbPrefix
);
215 guiMsgBox(_l(_STR_ERR_FILE_INVALID
), 0, NULL
);
220 char vmc_name
[32], vmc_path
[255];
221 int vmc_id
, have_error
= 0, size_mcemu_irx
= 0;
222 usb_vmc_infos_t usb_vmc_infos
;
223 vmc_superblock_t vmc_superblock
;
225 for (vmc_id
= 0; vmc_id
< 2; vmc_id
++) {
226 memset(&usb_vmc_infos
, 0, sizeof(usb_vmc_infos_t
));
227 configGetVMC(configSet
, vmc_name
, vmc_id
);
230 if (sysCheckVMC(usbPrefix
, "/", vmc_name
, 0, &vmc_superblock
) > 0) {
231 usb_vmc_infos
.flags
= vmc_superblock
.mc_flag
& 0xFF;
232 usb_vmc_infos
.flags
|= 0x100;
233 usb_vmc_infos
.specs
.page_size
= vmc_superblock
.page_size
;
234 usb_vmc_infos
.specs
.block_size
= vmc_superblock
.pages_per_block
;
235 usb_vmc_infos
.specs
.card_size
= vmc_superblock
.pages_per_cluster
* vmc_superblock
.clusters_per_card
;
237 // Check vmc cluster chain (write operation can cause dammage)
238 sprintf(vmc_path
, "%s/VMC/%s.bin", gUSBPrefix
, vmc_name
);
239 if (fioIoctl(fd
, 0xCAFEC0DE, vmc_path
)) {
240 LOG("USBSUPPORT Cluster Chain OK\n");
241 if ((i
= fioIoctl(fd
, 0xBEEFC0DE, vmc_path
)) != 0) {
243 usb_vmc_infos
.active
= 1;
244 usb_vmc_infos
.start_sector
= i
;
245 LOG("USBSUPPORT Start Sector: 0x%X\n", usb_vmc_infos
.start_sector
);
253 snprintf(error
, 255, _l(_STR_ERR_VMC_CONTINUE
), vmc_name
, (vmc_id
+ 1));
254 if (!guiMsgBox(error
, 1, NULL
)) {
260 for (i
= 0; i
< size_usb_mcemu_irx
; i
++) {
261 if (((u32
*)&usb_mcemu_irx
)[i
] == (0xC0DEFAC0 + vmc_id
)) {
262 if (usb_vmc_infos
.active
)
263 size_mcemu_irx
= size_usb_mcemu_irx
;
264 memcpy(&((u32
*)&usb_mcemu_irx
)[i
], &usb_vmc_infos
, sizeof(usb_vmc_infos_t
));
271 void** irx
= &usb_cdvdman_irx
;
272 int irx_size
= size_usb_cdvdman_irx
;
273 for (i
= 0; i
< game
->parts
; i
++) {
275 sprintf(partname
, "%s/%s/%s.%s%s", gUSBPrefix
, (game
->media
== 0x12) ? "CD" : "DVD", game
->startup
, game
->name
, game
->extension
);
277 sprintf(partname
, "%s/ul.%08X.%s.%02x", gUSBPrefix
, USBA_crc32(game
->name
), game
->startup
, i
);
279 if (gCheckUSBFragmentation
) {
280 if (fioIoctl(fd
, 0xCAFEC0DE, partname
) == 0) {
282 guiMsgBox(_l(_STR_ERR_FRAGMENTED
), 0, NULL
);
288 val
= fioIoctl(fd
, 0xDEADC0DE, partname
);
289 LOG("USBSUPPORT Mass storage device sector size = %d\n", val
);
291 irx
= &usb_4Ksectors_cdvdman_irx
;
292 irx_size
= size_usb_4Ksectors_cdvdman_irx
;
294 compatmask
= sbPrepare(game
, configSet
, irx_size
, irx
, &index
);
297 val
= fioIoctl(fd
, 0xBEEFC0DE, partname
);
298 memcpy((void*)((u32
)irx
+ index
+ 44 + 4 * i
), &val
, 4);
301 if (gRememberLastPlayed
) {
302 configSetStr(configGetByType(CONFIG_LAST
), "last_played", game
->startup
);
303 saveConfig(CONFIG_LAST
, 0);
308 char *altStartup
= NULL
;
309 if (configGetStr(configSet
, CONFIG_ITEM_ALTSTARTUP
, &altStartup
))
310 strncpy(filename
, altStartup
, 32);
312 sprintf(filename
, "%s", game
->startup
);
313 shutdown(NO_EXCEPTION
); // CAREFUL: shutdown will call usbCleanUp, so usbGames/game will be freed
317 sysLaunchLoaderElf(filename
, "USB_MODE", irx_size
, irx
, size_mcemu_irx
, &usb_mcemu_irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
319 sysLaunchLoaderElf(filename
, "USB_MODE", irx_size
, irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
323 static config_set_t
* usbGetConfig(int id
) {
324 return sbPopulateConfig(&usbGames
[id
], usbPrefix
, "/");
327 static int usbGetImage(char* folder
, int isRelative
, char* value
, char* suffix
, GSTEXTURE
* resultTex
, short psm
) {
330 sprintf(path
, "%s%s/%s_%s", usbPrefix
, folder
, value
, suffix
);
332 sprintf(path
, "%s%s_%s", folder
, value
, suffix
);
333 return texDiscoverLoad(resultTex
, path
, -1, psm
);
336 static void usbCleanUp(int exception
) {
337 if (usbGameList
.enabled
) {
338 LOG("USBSUPPORT CleanUp\n");
345 static int usbCheckVMC(char* name
, int createSize
) {
346 return sysCheckVMC(usbPrefix
, "/", name
, createSize
, NULL
);
350 static item_list_t usbGameList
= {
351 USB_MODE
, 0, COMPAT
, 0, MENU_MIN_INACTIVE_FRAMES
, "USB Games", _STR_USB_GAMES
, &usbInit
, &usbNeedsUpdate
,
353 &usbUpdateGameList
, &usbGetGameCount
, &usbGetGame
, &usbGetGameName
, &usbGetGameNameLength
, &usbGetGameStartup
, NULL
, NULL
,
355 &usbUpdateGameList
, &usbGetGameCount
, &usbGetGame
, &usbGetGameName
, &usbGetGameNameLength
, &usbGetGameStartup
, &usbDeleteGame
, NULL
,
358 &usbLaunchGame
, &usbGetConfig
, &usbGetImage
, &usbCleanUp
, &usbCheckVMC
, USB_ICON
360 &usbLaunchGame
, &usbGetConfig
, &usbGetImage
, &usbCleanUp
, USB_ICON