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("HDDSUPPORT HD Pro Kit detected!\n");
123 void hddLoadModules(void) {
125 static char hddarg
[] = "-o" "\0" "4" "\0" "-n" "\0" "20";
127 LOG("HDDSUPPORT LoadModules\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("HDDSUPPORT 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
);
181 LOG("HDDSUPPORT Init\n");
183 configGetInt(configGetByType(CONFIG_OPL
), "hdd_frames_delay", &hddGameList
.delay
);
184 ioPutRequest(IO_CUSTOM_SIMPLEACTION
, &hddInitModules
);
185 hddGameList
.enabled
= 1;
188 item_list_t
* hddGetObject(int initOnly
) {
189 if (initOnly
&& !hddGameList
.enabled
)
194 static int hddNeedsUpdate(void) {
195 if (hddForceUpdate
) {
203 static int hddUpdateGameList(void) {
204 int ret
= hddGetHDLGamelist(&hddGames
);
208 hddGameCount
= hddGames
->count
;
212 static int hddGetGameCount(void) {
216 static void* hddGetGame(int id
) {
217 return (void*) &hddGames
->games
[id
];
220 static char* hddGetGameName(int id
) {
221 return hddGames
->games
[id
].name
;
224 static int hddGetGameNameLength(int id
) {
225 return HDL_GAME_NAME_MAX
+ 1;
228 static char* hddGetGameStartup(int id
) {
229 return hddGames
->games
[id
].startup
;
233 static void hddDeleteGame(int id
) {
234 hddDeleteHDLGame(&hddGames
->games
[id
]);
238 static void hddRenameGame(int id
, char* newName
) {
239 hdl_game_info_t
* game
= &hddGames
->games
[id
];
240 strcpy(game
->name
, newName
);
241 hddSetHDLGameInfo(&hddGames
->games
[id
]);
246 static void hddLaunchGame(int id
, config_set_t
* configSet
) {
250 hdl_game_info_t
* game
= &hddGames
->games
[id
];
254 char vmc_name
[2][32];
255 int fd
, part_valid
= 0, size_mcemu_irx
= 0;
256 hdd_vmc_infos_t hdd_vmc_infos
;
257 memset(&hdd_vmc_infos
, 0, sizeof(hdd_vmc_infos_t
));
259 configGetVMC(configSet
, vmc_name
[0], 0);
260 configGetVMC(configSet
, vmc_name
[1], 1);
262 if(vmc_name
[0][0] || vmc_name
[1][0]) {
263 fileXioUmount(hddPrefix
);
264 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
);
266 if (fileXioIoctl2(fd
, APA_IOCTL2_GETHEADER
, NULL
, 0, (void*)&part_hdr
, sizeof(apa_header
)) == sizeof(apa_header
)) {
267 if (part_hdr
.nsub
<= 4) {
268 hdd_vmc_infos
.parts
[0].start
= part_hdr
.start
;
269 hdd_vmc_infos
.parts
[0].length
= part_hdr
.length
;
270 LOG("HDDSUPPORT hdd_vmc_infos.parts[0].start : 0x%X\n", hdd_vmc_infos
.parts
[0].start
);
271 LOG("HDDSUPPORT hdd_vmc_infos.parts[0].length : 0x%X\n", hdd_vmc_infos
.parts
[0].length
);
272 for (i
= 0; i
< part_hdr
.nsub
; i
++) {
273 hdd_vmc_infos
.parts
[i
+1].start
= part_hdr
.subs
[i
].start
;
274 hdd_vmc_infos
.parts
[i
+1].length
= part_hdr
.subs
[i
].length
;
275 LOG("HDDSUPPORT hdd_vmc_infos.parts[%d].start : 0x%X\n", i
+1, hdd_vmc_infos
.parts
[i
+1].start
);
276 LOG("HDDSUPPORT hdd_vmc_infos.parts[%d].length : 0x%X\n", i
+1, hdd_vmc_infos
.parts
[i
+1].length
);
284 fileXioMount(hddPrefix
, oplPart
, FIO_MT_RDWR
); // if this fails, something is really screwed up
289 int vmc_id
, have_error
= 0;
290 vmc_superblock_t vmc_superblock
;
291 pfs_inode_t pfs_inode
;
293 for (vmc_id
= 0; vmc_id
< 2; vmc_id
++) {
294 if (vmc_name
[vmc_id
][0]) {
296 hdd_vmc_infos
.active
= 0;
297 if (sysCheckVMC(hddPrefix
, "/", vmc_name
[vmc_id
], 0, &vmc_superblock
) > 0) {
298 hdd_vmc_infos
.flags
= vmc_superblock
.mc_flag
& 0xFF;
299 hdd_vmc_infos
.flags
|= 0x100;
300 hdd_vmc_infos
.specs
.page_size
= vmc_superblock
.page_size
;
301 hdd_vmc_infos
.specs
.block_size
= vmc_superblock
.pages_per_block
;
302 hdd_vmc_infos
.specs
.card_size
= vmc_superblock
.pages_per_cluster
* vmc_superblock
.clusters_per_card
;
304 // Check vmc inode block chain (write operation can cause damage)
305 snprintf(vmc_path
, 255, "%sVMC/%s.bin", hddPrefix
, vmc_name
[vmc_id
]);
306 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
);
307 if (fileXioIoctl2(fd
, PFS_IOCTL2_GET_INODE
, NULL
, 0, (void*)&pfs_inode
, sizeof(pfs_inode_t
)) == sizeof(pfs_inode_t
)) {
308 if (pfs_inode
.number_data
<= 11) {
310 hdd_vmc_infos
.active
= 1;
311 for (i
= 0; i
< pfs_inode
.number_data
- 1; i
++) {
312 hdd_vmc_infos
.blocks
[i
].number
= pfs_inode
.data
[i
+1].number
;
313 hdd_vmc_infos
.blocks
[i
].subpart
= pfs_inode
.data
[i
+1].subpart
;
314 hdd_vmc_infos
.blocks
[i
].count
= pfs_inode
.data
[i
+1].count
;
315 LOG("HDDSUPPORT hdd_vmc_infos.blocks[%d].number : 0x%X\n", i
, hdd_vmc_infos
.blocks
[i
].number
);
316 LOG("HDDSUPPORT hdd_vmc_infos.blocks[%d].subpart : 0x%X\n", i
, hdd_vmc_infos
.blocks
[i
].subpart
);
317 LOG("HDDSUPPORT hdd_vmc_infos.blocks[%d].count : 0x%X\n", i
, hdd_vmc_infos
.blocks
[i
].count
);
319 } // else Vmc file too much fragmented
327 snprintf(error
, 255, _l(_STR_ERR_VMC_CONTINUE
), vmc_name
[vmc_id
], (vmc_id
+ 1));
328 if (!guiMsgBox(error
, 1, NULL
))
332 for (i
= 0; i
< size_hdd_mcemu_irx
; i
++) {
333 if (((u32
*)&hdd_mcemu_irx
)[i
] == (0xC0DEFAC0 + vmc_id
)) {
334 if (hdd_vmc_infos
.active
)
335 size_mcemu_irx
= size_hdd_mcemu_irx
;
336 memcpy(&((u32
*)&hdd_mcemu_irx
)[i
], &hdd_vmc_infos
, sizeof(hdd_vmc_infos_t
));
344 if (gRememberLastPlayed
) {
345 configSetStr(configGetByType(CONFIG_LAST
), "last_played", game
->startup
);
346 saveConfig(CONFIG_LAST
, 0);
350 configGetDiscIDBinary(configSet
, gid
);
352 int dmaType
= 0, dmaMode
= 0, compatMode
= 0;
353 configGetInt(configSet
, CONFIG_ITEM_COMPAT
, &compatMode
);
354 configGetInt(configSet
, CONFIG_ITEM_DMA
, &dmaMode
);
361 hddSetTransferMode(dmaType
, dmaMode
);
362 hddSetIdleTimeout(gHDDSpindown
* 12);
364 if (hddHDProKitDetected
) {
365 size_irx
= size_hdd_hdpro_cdvdman_irx
;
366 irx
= &hdd_hdpro_cdvdman_irx
;
368 else if (sysPcmciaCheck()) {
369 size_irx
= size_hdd_pcmcia_cdvdman_irx
;
370 irx
= &hdd_pcmcia_cdvdman_irx
;
373 size_irx
= size_hdd_cdvdman_irx
;
374 irx
= &hdd_cdvdman_irx
;
377 for (i
= 0; i
< size_irx
; i
++) {
378 if(!strcmp((const char*)((u32
)irx
+ i
), "###### GAMESETTINGS ######")) {
384 u8 flag_48bit
= hddIs48bit() & 0xff;
385 memcpy((void*)((u32
)irx
+ i
+ 34), &flag_48bit
, 1);
387 if (compatMode
& COMPAT_MODE_2
) {
388 u32 alt_read_mode
= 1;
389 memcpy((void*)((u32
)irx
+ i
+ 35), &alt_read_mode
, 1);
392 if (compatMode
& COMPAT_MODE_5
) {
394 memcpy((void*)((u32
)irx
+ i
+ 36), &no_dvddl
, 2);
397 if (compatMode
& COMPAT_MODE_4
) {
399 memcpy((void*)((u32
)irx
+ i
+ 38), &no_pss
, 2);
402 // patch cdvdman timer
404 if (configGetInt(configSet
, CONFIG_ITEM_CDVDMAN_TIMER
, &timer
)) {
405 u32 cdvdmanTimer
= timer
* 250;
406 memcpy((void*)((u32
)irx
+ i
+ 40), &cdvdmanTimer
, 4);
409 // patch start_sector
410 memcpy((void*)((u32
)irx
+ i
+ 44), &game
->start_sector
, 4);
412 for (i
=0;i
<size_irx
;i
++) {
413 if(!strcmp((const char*)((u32
)irx
+ i
), "B00BS")) {
418 memcpy((void*)((u32
)irx
+ i
), &gid
, 5);
422 int size_cdvdfsv_irx;
424 sysGetCDVDFSV(&cdvdfsv_irx, &size_cdvdfsv_irx);
425 u32 *p = (u32 *)cdvdfsv_irx;
426 for (i = 0; i < (size_cdvdfsv_irx >> 2); i++) {
427 if (*p == 0xC0DEC0DE) {
428 if (compatMode & COMPAT_MODE_7)
437 char *altStartup
= NULL
;
438 if (configGetStr(configSet
, CONFIG_ITEM_ALTSTARTUP
, &altStartup
))
439 strncpy(filename
, altStartup
, 32);
441 sprintf(filename
, "%s", game
->startup
);
442 shutdown(NO_EXCEPTION
); // CAREFUL: shutdown will call hddCleanUp, so hddGames/game will be freed
446 sysLaunchLoaderElf(filename
, "HDD_MODE", size_irx
, irx
, size_mcemu_irx
, &hdd_mcemu_irx
, compatMode
, compatMode
& COMPAT_MODE_1
);
448 sysLaunchLoaderElf(filename
, "HDD_MODE", size_irx
, irx
, compatMode
, compatMode
& COMPAT_MODE_1
);
452 static config_set_t
* hddGetConfig(int id
) {
454 hdl_game_info_t
* game
= &hddGames
->games
[id
];
456 snprintf(path
, 255, "%sCFG/%s.cfg", hddPrefix
, game
->startup
);
457 config_set_t
* config
= configAlloc(0, NULL
, path
);
460 configSetStr(config
, CONFIG_ITEM_NAME
, game
->name
);
461 configSetInt(config
, CONFIG_ITEM_SIZE
, game
->total_size_in_kb
>> 10);
462 configSetStr(config
, CONFIG_ITEM_FORMAT
, "HDL");
463 if (game
->disctype
== 0x12)
464 configSetStr(config
, CONFIG_ITEM_MEDIA
, "CD");
466 configSetStr(config
, CONFIG_ITEM_MEDIA
, "DVD");
467 configSetStr(config
, CONFIG_ITEM_STARTUP
, game
->startup
);
472 static int hddGetImage(char* folder
, int isRelative
, char* value
, char* suffix
, GSTEXTURE
* resultTex
, short psm
) {
475 sprintf(path
, "%s%s/%s_%s", hddPrefix
, folder
, value
, suffix
);
477 sprintf(path
, "%s%s_%s", folder
, value
, suffix
);
478 return texDiscoverLoad(resultTex
, path
, -1, psm
);
481 static void hddCleanUp(int exception
) {
482 if (hddGameList
.enabled
) {
483 LOG("HDDSUPPORT CleanUp\n");
485 hddFreeHDLGamelist(hddGames
);
487 if ((exception
& UNMOUNT_EXCEPTION
) == 0)
488 fileXioUmount(hddPrefix
);
493 static int hddCheckVMC(char* name
, int createSize
) {
494 return sysCheckVMC(hddPrefix
, "/", name
, createSize
, NULL
);
498 static item_list_t hddGameList
= {
499 HDD_MODE
, 0, COMPAT_FULL
, 0, MENU_MIN_INACTIVE_FRAMES
, "HDD Games", _STR_HDD_GAMES
, &hddInit
, &hddNeedsUpdate
, &hddUpdateGameList
,
501 &hddGetGameCount
, &hddGetGame
, &hddGetGameName
, &hddGetGameNameLength
, &hddGetGameStartup
, NULL
, NULL
,
503 &hddGetGameCount
, &hddGetGame
, &hddGetGameName
, &hddGetGameNameLength
, &hddGetGameStartup
, &hddDeleteGame
, &hddRenameGame
,
506 &hddLaunchGame
, &hddGetConfig
, &hddGetImage
, &hddCleanUp
, &hddCheckVMC
, HDD_ICON
508 &hddLaunchGame
, &hddGetConfig
, &hddGetImage
, &hddCleanUp
, HDD_ICON