2 #include "include/usbld.h"
3 #include "include/lang.h"
4 #include "include/gui.h"
5 #include "include/supportbase.h"
6 #include "include/hddsupport.h"
7 #include "include/util.h"
8 #include "include/themes.h"
9 #include "include/textures.h"
10 #include "include/ioman.h"
11 #include "include/system.h"
13 extern void *hdd_cdvdman_irx
;
14 extern int size_hdd_cdvdman_irx
;
16 extern void *hdd_pcmcia_cdvdman_irx
;
17 extern int size_hdd_pcmcia_cdvdman_irx
;
19 extern void *hdd_hdpro_cdvdman_irx
;
20 extern int size_hdd_hdpro_cdvdman_irx
;
22 extern void *ps2dev9_irx
;
23 extern int size_ps2dev9_irx
;
25 extern void *ps2atad_irx
;
26 extern int size_ps2atad_irx
;
28 extern void *hdpro_atad_irx
;
29 extern int size_hdpro_atad_irx
;
31 extern void *ps2hdd_irx
;
32 extern int size_ps2hdd_irx
;
34 extern void *ps2fs_irx
;
35 extern int size_ps2fs_irx
;
38 extern void *hdd_mcemu_irx
;
39 extern int size_hdd_mcemu_irx
;
42 static int hddForceUpdate
= 1;
43 static char *hddPrefix
= "pfs0:";
44 static int hddGameCount
= 0;
45 static hdl_games_list_t
* hddGames
;
47 const char *oplPart
= "hdd0:+OPL";
49 static int hddHDProKitDetected
= 0;
51 // forward declaration
52 static item_list_t hddGameList
;
54 static void hddInitModules(void) {
60 sprintf(path
, "%sTHM", hddPrefix
);
61 thmAddElements(path
, "/", hddGameList
.mode
);
63 sprintf(path
, "%sCFG", hddPrefix
);
67 sprintf(path
, "%sVMC", hddPrefix
);
72 // HD Pro Kit is mapping the 1st word in ROM0 seg as a main ATA controller,
73 // The pseudo ATA controller registers are accessed (input/ouput) by writing
74 // an id to the main ATA controller
75 #define HDPROreg_IO8 (*(volatile unsigned char *)0xBFC00000)
76 #define CDVDreg_STATUS (*(volatile unsigned char *)0xBF40200A)
78 static int hddCheckHDProKit(void)
84 // HD Pro IO start commands sequence
91 u32 res
= HDPROreg_IO8
;
103 if ((res
& 0xff) == 0xe7) {
106 // HD Pro IO finish commands sequence
118 LOG("hddCheckHDPro() HD Pro Kit detected!\n");
123 void hddLoadModules(void) {
125 static char hddarg
[] = "-o" "\0" "4" "\0" "-n" "\0" "20";
127 LOG("hddLoadModules()\n");
131 ret
= sysLoadModuleBuffer(&ps2dev9_irx
, size_ps2dev9_irx
, 0, NULL
);
139 // try to detect HD Pro Kit (not the connected HDD),
140 // if detected it loads the specific ATAD module
141 hddHDProKitDetected
= hddCheckHDProKit();
142 if (hddHDProKitDetected
)
143 ret
= sysLoadModuleBuffer(&hdpro_atad_irx
, size_hdpro_atad_irx
, 0, NULL
);
145 ret
= sysLoadModuleBuffer(&ps2atad_irx
, size_ps2atad_irx
, 0, NULL
);
153 ret
= sysLoadModuleBuffer(&ps2hdd_irx
, size_ps2hdd_irx
, sizeof(hddarg
), hddarg
);
161 ret
= sysLoadModuleBuffer(&ps2fs_irx
, size_ps2fs_irx
, 0, NULL
);
167 LOG("hddLoadModules: modules loaded\n");
169 hddSetIdleTimeout(gHDDSpindown
* 12); // gHDDSpindown [0..20] -> spindown [0..240] -> seconds [0..1200]
171 ret
= fileXioMount(hddPrefix
, oplPart
, FIO_MT_RDWR
);
173 fileXioUmount(hddPrefix
);
174 fileXioMount(hddPrefix
, oplPart
, FIO_MT_RDWR
);
184 ioPutRequest(IO_CUSTOM_SIMPLEACTION
, &hddInitModules
);
186 hddGameList
.enabled
= 1;
189 item_list_t
* hddGetObject(int initOnly
) {
190 if (initOnly
&& !hddGameList
.enabled
)
195 static int hddNeedsUpdate(void) {
196 if (hddForceUpdate
) {
204 static int hddUpdateGameList(void) {
205 int ret
= hddGetHDLGamelist(&hddGames
);
209 hddGameCount
= hddGames
->count
;
213 static int hddGetGameCount(void) {
217 static void* hddGetGame(int id
) {
218 return (void*) &hddGames
->games
[id
];
221 static char* hddGetGameName(int id
) {
222 return hddGames
->games
[id
].name
;
225 static int hddGetGameNameLength(int id
) {
226 return HDL_GAME_NAME_MAX
+ 1;
229 static char* hddGetGameStartup(int id
) {
230 return hddGames
->games
[id
].startup
;
234 static void hddDeleteGame(int id
) {
235 hddDeleteHDLGame(&hddGames
->games
[id
]);
239 static void hddRenameGame(int id
, char* newName
) {
240 hdl_game_info_t
* game
= &hddGames
->games
[id
];
241 strcpy(game
->name
, newName
);
242 hddSetHDLGameInfo(&hddGames
->games
[id
]);
248 static int hddPrepareMcemu(hdl_game_info_t
* game
, config_set_t
* configSet
) {
252 pfs_inode_t pfs_inode
;
254 hdd_vmc_infos_t hdd_vmc_infos
;
255 vmc_superblock_t vmc_superblock
;
256 int i
, j
, fd
, part_valid
= 0, size_mcemu_irx
= 0;
258 configGetVMC(configSet
, vmc
[0], 0);
259 configGetVMC(configSet
, vmc
[1], 1);
261 if(!vmc
[0][0] && !vmc
[1][0]) return 0; // skip if both empty
263 // virtual mc informations
264 memset(&hdd_vmc_infos
, 0, sizeof(hdd_vmc_infos_t
));
266 fileXioUmount(hddPrefix
);
267 fd
= fileXioOpen(oplPart
, O_RDONLY
, FIO_S_IRUSR
| FIO_S_IWUSR
| FIO_S_IXUSR
| FIO_S_IRGRP
| FIO_S_IWGRP
| FIO_S_IXGRP
| FIO_S_IROTH
| FIO_S_IWOTH
| FIO_S_IXOTH
);
269 if(fileXioIoctl2(fd
, APA_IOCTL2_GETHEADER
, NULL
, 0, (void*)&part_hdr
, sizeof(apa_header
)) == sizeof(apa_header
)) {
270 if(part_hdr
.nsub
<= 4) {
271 hdd_vmc_infos
.parts
[0].start
= part_hdr
.start
;
272 hdd_vmc_infos
.parts
[0].length
= part_hdr
.length
;
273 LOG("hdd_vmc_infos.parts[0].start : 0x%X\n", hdd_vmc_infos
.parts
[0].start
);
274 LOG("hdd_vmc_infos.parts[0].length : 0x%X\n", hdd_vmc_infos
.parts
[0].length
);
275 for(i
= 0; i
< part_hdr
.nsub
; i
++) {
276 hdd_vmc_infos
.parts
[i
+1].start
= part_hdr
.subs
[i
].start
;
277 hdd_vmc_infos
.parts
[i
+1].length
= part_hdr
.subs
[i
].length
;
278 LOG("hdd_vmc_infos.parts[%d].start : 0x%X\n", i
+1, hdd_vmc_infos
.parts
[i
+1].start
);
279 LOG("hdd_vmc_infos.parts[%d].length : 0x%X\n", i
+1, hdd_vmc_infos
.parts
[i
+1].length
);
288 if(!part_valid
) return -1;
290 fileXioMount(hddPrefix
, oplPart
, FIO_MT_RDWR
); // if this fails, something is really screwed up
292 if(!vmc
[i
][0]) // skip if empty
295 memset(&vmc_superblock
, 0, sizeof(vmc_superblock_t
));
296 hdd_vmc_infos
.active
= 0;
298 snprintf(vmc_path
, 255, "%sVMC/%s.bin", hddPrefix
, vmc
[i
]);
300 fd
= fileXioOpen(vmc_path
, O_RDWR
, FIO_S_IRUSR
| FIO_S_IWUSR
| FIO_S_IXUSR
| FIO_S_IRGRP
| FIO_S_IWGRP
| FIO_S_IXGRP
| FIO_S_IROTH
| FIO_S_IWOTH
| FIO_S_IXOTH
);
304 LOG("%s open\n", vmc_path
);
306 vmc_size
= fileXioLseek(fd
, 0, SEEK_END
);
307 fileXioLseek(fd
, 0, SEEK_SET
);
308 fileXioRead(fd
, (void*)&vmc_superblock
, sizeof(vmc_superblock_t
));
309 fileXioLseek(fd
, 0, SEEK_SET
);
311 LOG("File size : 0x%X\n", vmc_size
);
312 LOG("Magic : %s\n", vmc_superblock
.magic
);
313 LOG("Card type : %d\n", vmc_superblock
.mc_type
);
315 if(!strncmp(vmc_superblock
.magic
, "Sony PS2 Memory Card Format", 27) && vmc_superblock
.mc_type
== 0x2) {
316 hdd_vmc_infos
.flags
= vmc_superblock
.mc_flag
& 0xFF;
317 hdd_vmc_infos
.flags
|= 0x100;
318 hdd_vmc_infos
.specs
.page_size
= vmc_superblock
.page_size
;
319 hdd_vmc_infos
.specs
.block_size
= vmc_superblock
.pages_per_block
;
320 hdd_vmc_infos
.specs
.card_size
= vmc_superblock
.pages_per_cluster
* vmc_superblock
.clusters_per_card
;
322 LOG("hdd_vmc_infos.flags : 0x%X\n", hdd_vmc_infos
.flags
);
323 LOG("hdd_vmc_infos.specs.page_size : 0x%X\n", hdd_vmc_infos
.specs
.page_size
);
324 LOG("hdd_vmc_infos.specs.block_size : 0x%X\n", hdd_vmc_infos
.specs
.block_size
);
325 LOG("hdd_vmc_infos.specs.card_size : 0x%X\n", hdd_vmc_infos
.specs
.card_size
);
327 if(vmc_size
== hdd_vmc_infos
.specs
.card_size
* hdd_vmc_infos
.specs
.page_size
) {
328 // Check vmc inode block chain (write operation can cause damage)
329 if(fileXioIoctl2(fd
, PFS_IOCTL2_GET_INODE
, NULL
, 0, (void*)&pfs_inode
, sizeof(pfs_inode_t
)) == sizeof(pfs_inode_t
)) {
330 if(pfs_inode
.number_data
<= 11) {
331 for(j
= 0; j
< pfs_inode
.number_data
-1; j
++) {
332 hdd_vmc_infos
.active
= 1;
333 hdd_vmc_infos
.blocks
[j
].number
= pfs_inode
.data
[j
+1].number
;
334 hdd_vmc_infos
.blocks
[j
].subpart
= pfs_inode
.data
[j
+1].subpart
;
335 hdd_vmc_infos
.blocks
[j
].count
= pfs_inode
.data
[j
+1].count
;
336 LOG("hdd_vmc_infos.blocks[%d].number : 0x%X\n", j
, hdd_vmc_infos
.blocks
[j
].number
);
337 LOG("hdd_vmc_infos.blocks[%d].subpart : 0x%X\n", j
, hdd_vmc_infos
.blocks
[j
].subpart
);
338 LOG("hdd_vmc_infos.blocks[%d].count : 0x%X\n", j
, hdd_vmc_infos
.blocks
[j
].count
);
340 } // else Vmc file too much fragmented
346 for (j
=0; j
<size_hdd_mcemu_irx
; j
++) {
347 if (((u32
*)&hdd_mcemu_irx
)[j
] == (0xC0DEFAC0 + i
)) {
348 if(hdd_vmc_infos
.active
)
349 size_mcemu_irx
= size_hdd_mcemu_irx
;
350 memcpy(&((u32
*)&hdd_mcemu_irx
)[j
], &hdd_vmc_infos
, sizeof(hdd_vmc_infos_t
));
355 return size_mcemu_irx
;
359 static void hddLaunchGame(int id
, config_set_t
* configSet
) {
364 hdl_game_info_t
* game
= &hddGames
->games
[id
];
366 if (gRememberLastPlayed
) {
367 configSetStr(configGetByType(CONFIG_LAST
), "last_played", game
->startup
);
368 saveConfig(CONFIG_LAST
, 0);
372 configGetDiscIDBinary(configSet
, gid
);
374 int dmaType
= 0, dmaMode
= 0, compatMode
= 0;
375 configGetInt(configSet
, CONFIG_ITEM_DMA
, &dmaMode
);
376 configGetInt(configSet
, CONFIG_ITEM_COMPAT
, &compatMode
);
383 hddSetTransferMode(dmaType
, dmaMode
);
384 hddSetIdleTimeout(gHDDSpindown
* 12);
386 if (hddHDProKitDetected
) {
387 size_irx
= size_hdd_hdpro_cdvdman_irx
;
388 irx
= &hdd_hdpro_cdvdman_irx
;
390 else if (sysPcmciaCheck()) {
391 size_irx
= size_hdd_pcmcia_cdvdman_irx
;
392 irx
= &hdd_pcmcia_cdvdman_irx
;
395 size_irx
= size_hdd_cdvdman_irx
;
396 irx
= &hdd_cdvdman_irx
;
399 for (i
=0;i
<size_irx
;i
++){
400 if(!strcmp((const char*)((u32
)irx
+i
),"###### GAMESETTINGS ######")){
405 if (compatMode
& COMPAT_MODE_2
) {
406 u32 alt_read_mode
= 1;
407 memcpy((void*)((u32
)irx
+i
+35),&alt_read_mode
,1);
409 if (compatMode
& COMPAT_MODE_5
) {
411 memcpy((void*)((u32
)irx
+i
+36),&no_dvddl
,4);
413 if (compatMode
& COMPAT_MODE_4
) {
415 memcpy((void*)((u32
)irx
+i
+40),&no_pss
,4);
419 u8 flag_48bit
= hddIs48bit() & 0xff;
420 memcpy((void*)((u32
)irx
+i
+34), &flag_48bit
, 1);
422 // patch start_sector
423 memcpy((void*)((u32
)irx
+i
+44), &game
->start_sector
, 4);
425 for (i
=0;i
<size_irx
;i
++){
426 if(!strcmp((const char*)((u32
)irx
+i
),"B00BS")){
431 memcpy((void*)((u32
)irx
+i
), &gid
, 5);
435 int size_cdvdfsv_irx
;
437 sysGetCDVDFSV(&cdvdfsv_irx
, &size_cdvdfsv_irx
);
438 u32
*p
= (u32
*)cdvdfsv_irx
;
439 for (i
= 0; i
< (size_cdvdfsv_irx
>> 2); i
++) {
440 if (*p
== 0xC0DEC0DE) {
441 if (compatMode
& COMPAT_MODE_7
)
451 int size_mcemu_irx
= hddPrepareMcemu(game
, configSet
);
452 if (size_mcemu_irx
== -1) {
453 if (guiMsgBox(_l(_STR_ERR_VMC_CONTINUE
), 1, NULL
))
460 char *altStartup
= NULL
;
461 if (configGetStr(configSet
, CONFIG_ITEM_ALTSTARTUP
, &altStartup
))
462 strncpy(filename
, altStartup
, 32);
464 sprintf(filename
, "%s", game
->startup
);
465 shutdown(NO_EXCEPTION
); // CAREFUL: shutdown will call hddCleanUp, so hddGames/game will be freed
469 sysLaunchLoaderElf(filename
, "HDD_MODE", size_irx
, irx
, size_mcemu_irx
, &hdd_mcemu_irx
, compatMode
, compatMode
& COMPAT_MODE_1
);
471 sysLaunchLoaderElf(filename
, "HDD_MODE", size_irx
, irx
, compatMode
, compatMode
& COMPAT_MODE_1
);
475 static config_set_t
* hddGetConfig(int id
) {
477 hdl_game_info_t
* game
= &hddGames
->games
[id
];
479 snprintf(path
, 255, "%sCFG/%s.cfg", hddPrefix
, game
->startup
);
480 config_set_t
* config
= configAlloc(0, NULL
, path
);
483 configSetStr(config
, CONFIG_ITEM_NAME
, game
->name
);
484 configSetInt(config
, CONFIG_ITEM_SIZE
, game
->total_size_in_kb
>> 10);
485 configSetStr(config
, CONFIG_ITEM_FORMAT
, "HDL");
486 if (game
->disctype
== 0x12)
487 configSetStr(config
, CONFIG_ITEM_MEDIA
, "CD");
489 configSetStr(config
, CONFIG_ITEM_MEDIA
, "DVD");
490 configSetStr(config
, CONFIG_ITEM_STARTUP
, game
->startup
);
495 static int hddGetImage(char* folder
, int isRelative
, char* value
, char* suffix
, GSTEXTURE
* resultTex
, short psm
) {
498 sprintf(path
, "%s%s/%s_%s", hddPrefix
, folder
, value
, suffix
);
500 sprintf(path
, "%s%s_%s", folder
, value
, suffix
);
501 return texDiscoverLoad(resultTex
, path
, -1, psm
);
504 static void hddCleanUp(int exception
) {
505 if (hddGameList
.enabled
) {
506 LOG("hddCleanUp()\n");
508 hddFreeHDLGamelist(hddGames
);
510 if ((exception
& UNMOUNT_EXCEPTION
) == 0)
511 fileXioUmount(hddPrefix
);
516 static int hddCheckVMC(char* name
, int createSize
) {
517 return sysCheckVMC(hddPrefix
, "/", name
, createSize
);
521 static item_list_t hddGameList
= {
522 HDD_MODE
, 0, COMPAT_FULL
, 0, MENU_MIN_INACTIVE_FRAMES
, "HDD Games", _STR_HDD_GAMES
, &hddInit
, &hddNeedsUpdate
, &hddUpdateGameList
,
524 &hddGetGameCount
, &hddGetGame
, &hddGetGameName
, &hddGetGameNameLength
, &hddGetGameStartup
, NULL
, NULL
,
526 &hddGetGameCount
, &hddGetGame
, &hddGetGameName
, &hddGetGameNameLength
, &hddGetGameStartup
, &hddDeleteGame
, &hddRenameGame
,
529 &hddLaunchGame
, &hddGetConfig
, &hddGetImage
, &hddCleanUp
, &hddCheckVMC
, HDD_ICON
531 &hddLaunchGame
, &hddGetConfig
, &hddGetImage
, &hddCleanUp
, HDD_ICON