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
);
84 sprintf(path
, "%sVMC", usbPrefix
);
89 void usbLoadModules(void) {
90 LOG("usbLoadModules()\n");
91 //first it search for custom usbd in MC?
92 usbd_irx
= readFile("mc?:BEDATA-SYSTEM/USBD.IRX", -1, &size_usbd_irx
);
94 usbd_irx
= readFile("mc?:BADATA-SYSTEM/USBD.IRX", -1, &size_usbd_irx
);
96 usbd_irx
= readFile("mc?:BIDATA-SYSTEM/USBD.IRX", -1, &size_usbd_irx
);
97 if (!usbd_irx
) { // If don't exist it uses embedded
98 if (sysPS3Detect() == 0) {
99 usbd_irx
= (void *) &usbd_ps2_irx
;
100 size_usbd_irx
= size_usbd_ps2_irx
;
102 usbd_irx
= (void *) &usbd_ps3_irx
;
103 size_usbd_irx
= size_usbd_ps3_irx
;
109 sysLoadModuleBuffer(usbd_irx
, size_usbd_irx
, 0, NULL
);
110 sysLoadModuleBuffer(&usbhdfsd_irx
, size_usbhdfsd_irx
, 0, NULL
);
114 LOG("usbLoadModules: modules loaded\n");
120 memset(usbModifiedCDPrev
, 0, 8);
121 memset(usbModifiedDVDPrev
, 0, 8);
125 ioPutRequest(IO_CUSTOM_SIMPLEACTION
, &usbInitModules
);
127 usbGameList
.enabled
= 1;
130 item_list_t
* usbGetObject(int initOnly
) {
131 if (initOnly
&& !usbGameList
.enabled
)
136 static int usbNeedsUpdate(void) {
141 usbFindPartition(usbPrefix
, "ul.cfg");
143 sprintf(path
, "%sCD", usbPrefix
);
144 if (fioGetstat(path
, &stat
) != 0)
145 memset(stat
.mtime
, 0, 8);
146 if (memcmp(usbModifiedCDPrev
, stat
.mtime
, 8)) {
147 memcpy(usbModifiedCDPrev
, stat
.mtime
, 8);
151 sprintf(path
, "%sDVD", usbPrefix
);
152 if (fioGetstat(path
, &stat
) != 0)
153 memset(stat
.mtime
, 0, 8);
154 if (memcmp(usbModifiedDVDPrev
, stat
.mtime
, 8)) {
155 memcpy(usbModifiedDVDPrev
, stat
.mtime
, 8);
159 if (!sbIsSameSize(usbPrefix
, usbULSizePrev
))
165 static int usbUpdateGameList(void) {
166 sbReadList(&usbGames
, usbPrefix
, &usbULSizePrev
, &usbGameCount
);
170 static int usbGetGameCount(void) {
174 static void* usbGetGame(int id
) {
175 return (void*) &usbGames
[id
];
178 static char* usbGetGameName(int id
) {
179 return usbGames
[id
].name
;
182 static int usbGetGameNameLength(int id
) {
183 if (usbGames
[id
].isISO
)
184 return ISO_GAME_NAME_MAX
+ 1;
186 return UL_GAME_NAME_MAX
+ 1;
189 static char* usbGetGameStartup(int id
) {
190 return usbGames
[id
].startup
;
194 static void usbDeleteGame(int id
) {
195 sbDelete(&usbGames
, usbPrefix
, "/", usbGameCount
, id
);
199 /*static void usbRenameGame(int id, char* newName) {
200 // TODO when/if Jimmi add rename functionnality to usbhdfs, then we should use the above method
201 //sbRename(&usbGames, usbPrefix, "/", usbGameCount, id, newName);
206 static int usbGetGameCompatibility(int id
, int *dmaMode
) {
207 return configGetCompatibility(usbGames
[id
].startup
, usbGameList
.mode
, NULL
);
210 static void usbSetGameCompatibility(int id
, int compatMode
, int dmaMode
) {
211 configSetCompatibility(usbGames
[id
].startup
, usbGameList
.mode
, compatMode
, -1);
215 static int usbPrepareMcemu(base_game_info_t
* game
) {
219 int i
, j
, fd
, size_mcemu_irx
= 0;
220 usb_vmc_infos_t usb_vmc_infos
;
221 vmc_superblock_t vmc_superblock
;
223 configGetVMC(game
->startup
, vmc
[0], USB_MODE
, 0);
224 configGetVMC(game
->startup
, vmc
[1], USB_MODE
, 1);
227 if(!vmc
[i
][0]) // skip if empty
230 memset(&usb_vmc_infos
, 0, sizeof(usb_vmc_infos_t
));
231 memset(&vmc_superblock
, 0, sizeof(vmc_superblock_t
));
233 sprintf(vmc_path
, "%sVMC/%s.bin", usbPrefix
, vmc
[i
]);
235 fd
= fioOpen(vmc_path
, O_RDWR
);
238 LOG("%s open\n", vmc_path
);
240 vmc_size
= fioLseek(fd
, 0, SEEK_END
);
241 fioLseek(fd
, 0, SEEK_SET
);
242 fioRead(fd
, (void*)&vmc_superblock
, sizeof(vmc_superblock_t
));
244 LOG("File size : 0x%X\n", vmc_size
);
245 LOG("Magic : %s\n", vmc_superblock
.magic
);
246 LOG("Card type : %d\n", vmc_superblock
.mc_type
);
248 if(!strncmp(vmc_superblock
.magic
, "Sony PS2 Memory Card Format", 27) && vmc_superblock
.mc_type
== 0x2) {
249 usb_vmc_infos
.flags
= vmc_superblock
.mc_flag
& 0xFF;
250 usb_vmc_infos
.flags
|= 0x100;
251 usb_vmc_infos
.specs
.page_size
= vmc_superblock
.page_size
;
252 usb_vmc_infos
.specs
.block_size
= vmc_superblock
.pages_per_block
;
253 usb_vmc_infos
.specs
.card_size
= vmc_superblock
.pages_per_cluster
* vmc_superblock
.clusters_per_card
;
255 LOG("flags : 0x%X\n", usb_vmc_infos
.flags
);
256 LOG("specs.page_size : 0x%X\n", usb_vmc_infos
.specs
.page_size
);
257 LOG("specs.block_size : 0x%X\n", usb_vmc_infos
.specs
.block_size
);
258 LOG("specs.card_size : 0x%X\n", usb_vmc_infos
.specs
.card_size
);
260 if(vmc_size
== usb_vmc_infos
.specs
.card_size
* usb_vmc_infos
.specs
.page_size
) {
261 int fd1
= fioDopen(usbPrefix
);
264 sprintf(vmc_path
, "%s/VMC/%s.bin", gUSBPrefix
, vmc
[i
]);
265 // Check vmc cluster chain (write operation can cause dammage)
266 if(fioIoctl(fd1
, 0xCAFEC0DE, vmc_path
)) {
267 LOG("Cluster Chain OK\n");
268 if((j
= fioIoctl(fd1
, 0xBEEFC0DE, vmc_path
)) != 0) {
269 usb_vmc_infos
.active
= 1;
270 usb_vmc_infos
.start_sector
= j
;
271 LOG("Start Sector: 0x%X\n", usb_vmc_infos
.start_sector
);
273 } // else Vmc file fragmented
280 for (j
=0; j
<size_usb_mcemu_irx
; j
++) {
281 if (((u32
*)&usb_mcemu_irx
)[j
] == (0xC0DEFAC0 + i
)) {
282 if(usb_vmc_infos
.active
)
283 size_mcemu_irx
= size_usb_mcemu_irx
;
284 memcpy(&((u32
*)&usb_mcemu_irx
)[j
], &usb_vmc_infos
, sizeof(usb_vmc_infos_t
));
289 return size_mcemu_irx
;
293 static void usbLaunchGame(int id
) {
294 int fd
, r
, index
, i
, compatmask
;
295 char isoname
[32], partname
[255], filename
[32];
296 base_game_info_t
* game
= &usbGames
[id
];
298 fd
= fioDopen(usbPrefix
);
300 guiMsgBox(_l(_STR_ERR_FILE_INVALID
), 0, NULL
);
305 sprintf(partname
, "%s/%s/%s.%s.iso", gUSBPrefix
, (game
->media
== 0x12) ? "CD" : "DVD", game
->startup
, game
->name
);
307 sprintf(partname
, "%s/%s.00", gUSBPrefix
, isoname
);
308 r
= fioIoctl(fd
, 0xDEADC0DE, partname
);
309 LOG("mass storage device sectorsize = %d\n", r
);
311 void *irx
= &usb_cdvdman_irx
;
312 int irx_size
= size_usb_cdvdman_irx
;
314 irx
= &usb_4Ksectors_cdvdman_irx
;
315 irx_size
= size_usb_4Ksectors_cdvdman_irx
;
318 compatmask
= sbPrepare(game
, usbGameList
.mode
, isoname
, irx_size
, irx
, &index
);
320 if (gCheckUSBFragmentation
)
321 for (i
= 0; i
< game
->parts
; i
++) {
323 sprintf(partname
, "%s/%s.%02x", gUSBPrefix
, isoname
, i
);
325 if (fioIoctl(fd
, 0xCAFEC0DE, partname
) == 0) {
327 guiMsgBox(_l(_STR_ERR_FRAGMENTED
), 0, NULL
);
332 if (gRememberLastPlayed
) {
333 configSetStr(configGetByType(CONFIG_LAST
), "last_played", game
->startup
);
334 saveConfig(CONFIG_LAST
, 0);
338 for (i
= 0; i
< game
->parts
; i
++) {
340 sprintf(partname
, "%s/%s.%02x", gUSBPrefix
, isoname
, i
);
342 r
= fioIoctl(fd
, 0xBEEFC0DE, partname
);
343 memcpy((void*)((u32
)&usb_cdvdman_irx
+ index
+ offset
), &r
, 4);
350 int size_mcemu_irx
= usbPrepareMcemu(game
);
351 if (size_mcemu_irx
== -1) {
352 if (guiMsgBox(_l(_STR_ERR_VMC_CONTINUE
), 1, NULL
))
359 sprintf(filename
,"%s",game
->startup
);
360 shutdown(NO_EXCEPTION
); // CAREFUL: shutdown will call usbCleanUp, so usbGames/game will be freed
364 sysLaunchLoaderElf(filename
, "USB_MODE", irx_size
, irx
, size_mcemu_irx
, &usb_mcemu_irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
366 sysLaunchLoaderElf(filename
, "USB_MODE", irx_size
, irx
, compatmask
, compatmask
& COMPAT_MODE_1
);
370 static config_set_t
* usbGetConfig(int id
) {
371 return sbPopulateConfig(&usbGames
[id
], usbPrefix
, "/");
374 static int usbGetImage(char* folder
, int isRelative
, char* value
, char* suffix
, GSTEXTURE
* resultTex
, short psm
) {
377 sprintf(path
, "%s%s/%s_%s", usbPrefix
, folder
, value
, suffix
);
379 sprintf(path
, "%s%s_%s", folder
, value
, suffix
);
380 return texDiscoverLoad(resultTex
, path
, -1, psm
);
383 static void usbCleanUp(int exception
) {
384 if (usbGameList
.enabled
) {
385 LOG("usbCleanUp()\n");
392 static int usbCheckVMC(char* name
, int createSize
) {
393 return sysCheckVMC(usbPrefix
, "/", name
, createSize
);
397 static item_list_t usbGameList
= {
398 USB_MODE
, 0, 0, MENU_MIN_INACTIVE_FRAMES
, "USB Games", _STR_USB_GAMES
, &usbInit
, &usbNeedsUpdate
,
400 &usbUpdateGameList
, &usbGetGameCount
, &usbGetGame
, &usbGetGameName
, &usbGetGameNameLength
, &usbGetGameStartup
, NULL
, NULL
,
402 &usbUpdateGameList
, &usbGetGameCount
, &usbGetGame
, &usbGetGameName
, &usbGetGameNameLength
, &usbGetGameStartup
, &usbDeleteGame
, NULL
,
405 &usbGetGameCompatibility
, &usbSetGameCompatibility
, &usbLaunchGame
, &usbGetConfig
, &usbGetImage
, &usbCleanUp
, &usbCheckVMC
, USB_ICON
407 &usbGetGameCompatibility
, &usbSetGameCompatibility
, &usbLaunchGame
, &usbGetConfig
, &usbGetImage
, &usbCleanUp
, USB_ICON