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);
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);
209 static void usbLaunchGame(int id
, config_set_t
* configSet
) {
210 int i
, fd
, val
, index
, compatmask
= 0;
211 char partname
[255], filename
[32];
212 base_game_info_t
* game
= &usbGames
[id
];
214 fd
= fioDopen(usbPrefix
);
216 guiMsgBox(_l(_STR_ERR_FILE_INVALID
), 0, NULL
);
221 char vmc_name
[32], vmc_path
[255];
222 int vmc_id
, have_error
= 0, size_mcemu_irx
= 0;
223 usb_vmc_infos_t usb_vmc_infos
;
224 vmc_superblock_t vmc_superblock
;
226 for (vmc_id
= 0; vmc_id
< 2; vmc_id
++) {
227 memset(&usb_vmc_infos
, 0, sizeof(usb_vmc_infos_t
));
228 configGetVMC(configSet
, vmc_name
, vmc_id
);
231 if (sysCheckVMC(usbPrefix
, "/", vmc_name
, 0, &vmc_superblock
) > 0) {
232 usb_vmc_infos
.flags
= vmc_superblock
.mc_flag
& 0xFF;
233 usb_vmc_infos
.flags
|= 0x100;
234 usb_vmc_infos
.specs
.page_size
= vmc_superblock
.page_size
;
235 usb_vmc_infos
.specs
.block_size
= vmc_superblock
.pages_per_block
;
236 usb_vmc_infos
.specs
.card_size
= vmc_superblock
.pages_per_cluster
* vmc_superblock
.clusters_per_card
;
238 // Check vmc cluster chain (write operation can cause dammage)
239 sprintf(vmc_path
, "%s/VMC/%s.bin", gUSBPrefix
, vmc_name
);
240 if (fioIoctl(fd
, 0xCAFEC0DE, vmc_path
)) {
241 LOG("USBSUPPORT Cluster Chain OK\n");
242 if ((i
= fioIoctl(fd
, 0xBEEFC0DE, vmc_path
)) != 0) {
244 usb_vmc_infos
.active
= 1;
245 usb_vmc_infos
.start_sector
= i
;
246 LOG("USBSUPPORT Start Sector: 0x%X\n", usb_vmc_infos
.start_sector
);
254 snprintf(error
, 255, _l(_STR_ERR_VMC_CONTINUE
), vmc_name
, (vmc_id
+ 1));
255 if (!guiMsgBox(error
, 1, NULL
)) {
261 for (i
= 0; i
< size_usb_mcemu_irx
; i
++) {
262 if (((u32
*)&usb_mcemu_irx
)[i
] == (0xC0DEFAC0 + vmc_id
)) {
263 if (usb_vmc_infos
.active
)
264 size_mcemu_irx
= size_usb_mcemu_irx
;
265 memcpy(&((u32
*)&usb_mcemu_irx
)[i
], &usb_vmc_infos
, sizeof(usb_vmc_infos_t
));
272 void** irx
= &usb_cdvdman_irx
;
273 int irx_size
= size_usb_cdvdman_irx
;
274 for (i
= 0; i
< game
->parts
; i
++) {
276 sprintf(partname
, "%s/%s/%s.%s%s", gUSBPrefix
, (game
->media
== 0x12) ? "CD" : "DVD", game
->startup
, game
->name
, game
->extension
);
278 sprintf(partname
, "%s/ul.%08X.%s.%02x", gUSBPrefix
, USBA_crc32(game
->name
), game
->startup
, i
);
280 if (gCheckUSBFragmentation
) {
281 if (fioIoctl(fd
, 0xCAFEC0DE, partname
) == 0) {
283 guiMsgBox(_l(_STR_ERR_FRAGMENTED
), 0, NULL
);
289 val
= fioIoctl(fd
, 0xDEADC0DE, partname
);
290 LOG("USBSUPPORT Mass storage device sector size = %d\n", val
);
292 irx
= &usb_4Ksectors_cdvdman_irx
;
293 irx_size
= size_usb_4Ksectors_cdvdman_irx
;
295 compatmask
= sbPrepare(game
, configSet
, irx_size
, irx
, &index
);
298 val
= fioIoctl(fd
, 0xBEEFC0DE, partname
);
299 memcpy((void*)((u32
)irx
+ index
+ 44 + 4 * i
), &val
, 4);
302 if (gRememberLastPlayed
) {
303 configSetStr(configGetByType(CONFIG_LAST
), "last_played", game
->startup
);
304 saveConfig(CONFIG_LAST
, 0);
309 char *altStartup
= NULL
;
310 if (configGetStr(configSet
, CONFIG_ITEM_ALTSTARTUP
, &altStartup
))
311 strncpy(filename
, altStartup
, 32);
313 sprintf(filename
, "%s", game
->startup
);
314 shutdown(NO_EXCEPTION
); // CAREFUL: shutdown will call usbCleanUp, so usbGames/game will be freed
318 sysLaunchLoaderElf(filename
, "USB_MODE", irx_size
, irx
, size_mcemu_irx
, &usb_mcemu_irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
320 sysLaunchLoaderElf(filename
, "USB_MODE", irx_size
, irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
324 static config_set_t
* usbGetConfig(int id
) {
325 return sbPopulateConfig(&usbGames
[id
], usbPrefix
, "/");
328 static int usbGetImage(char* folder
, int isRelative
, char* value
, char* suffix
, GSTEXTURE
* resultTex
, short psm
) {
331 sprintf(path
, "%s%s/%s_%s", usbPrefix
, folder
, value
, suffix
);
333 sprintf(path
, "%s%s_%s", folder
, value
, suffix
);
334 return texDiscoverLoad(resultTex
, path
, -1, psm
);
337 static void usbCleanUp(int exception
) {
338 if (usbGameList
.enabled
) {
339 LOG("USBSUPPORT CleanUp\n");
346 static int usbCheckVMC(char* name
, int createSize
) {
347 return sysCheckVMC(usbPrefix
, "/", name
, createSize
, NULL
);
351 static item_list_t usbGameList
= {
352 USB_MODE
, 0, COMPAT
, 0, MENU_MIN_INACTIVE_FRAMES
, "USB Games", _STR_USB_GAMES
, &usbInit
, &usbNeedsUpdate
,
354 &usbUpdateGameList
, &usbGetGameCount
, &usbGetGame
, &usbGetGameName
, &usbGetGameNameLength
, &usbGetGameStartup
, NULL
, NULL
,
356 &usbUpdateGameList
, &usbGetGameCount
, &usbGetGame
, &usbGetGameName
, &usbGetGameNameLength
, &usbGetGameStartup
, &usbDeleteGame
, NULL
,
359 &usbLaunchGame
, &usbGetConfig
, &usbGetImage
, &usbCleanUp
, &usbCheckVMC
, USB_ICON
361 &usbLaunchGame
, &usbGetConfig
, &usbGetImage
, &usbCleanUp
, USB_ICON