adding i18n strings
[open-ps2-loader.git] / src / hddsupport.c
blobfc55c9d8271583e10184b3785728b5fc9e1c01f8
1 #include "sys/fcntl.h"
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;
37 #ifdef VMC
38 extern void *hdd_mcemu_irx;
39 extern int size_hdd_mcemu_irx;
40 #endif
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) {
56 hddLoadModules();
58 // update Themes
59 char path[255];
60 sprintf(path, "%sTHM", hddPrefix);
61 thmAddElements(path, "/", hddGameList.mode);
63 sprintf(path, "%sCFG", hddPrefix);
64 checkCreateDir(path);
66 #ifdef VMC
67 sprintf(path, "%sVMC", hddPrefix);
68 checkCreateDir(path);
69 #endif
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)
80 int ret = 0;
82 DIntr();
83 ee_kmode_enter();
84 // HD Pro IO start commands sequence
85 HDPROreg_IO8 = 0x72;
86 CDVDreg_STATUS = 0;
87 HDPROreg_IO8 = 0x34;
88 CDVDreg_STATUS = 0;
89 HDPROreg_IO8 = 0x61;
90 CDVDreg_STATUS = 0;
91 u32 res = HDPROreg_IO8;
92 CDVDreg_STATUS = 0;
93 ee_kmode_exit();
94 EIntr();
96 FlushCache(0);
97 FlushCache(2);
99 DIntr();
100 ee_kmode_enter();
102 // check result
103 if ((res & 0xff) == 0xe7) {
104 HDPROreg_IO8 = 0xe3;
105 CDVDreg_STATUS = 0;
106 // HD Pro IO finish commands sequence
107 HDPROreg_IO8 = 0xf3;
108 CDVDreg_STATUS = 0;
109 ret = 1;
111 ee_kmode_exit();
112 EIntr();
114 FlushCache(0);
115 FlushCache(2);
117 if (ret)
118 LOG("HDDSUPPORT HD Pro Kit detected!\n");
120 return ret;
123 void hddLoadModules(void) {
124 int ret;
125 static char hddarg[] = "-o" "\0" "4" "\0" "-n" "\0" "20";
127 LOG("HDDSUPPORT LoadModules\n");
129 gHddStartup = 4;
131 ret = sysLoadModuleBuffer(&ps2dev9_irx, size_ps2dev9_irx, 0, NULL);
132 if (ret < 0) {
133 gHddStartup = -1;
134 return;
137 gHddStartup = 3;
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);
144 else
145 ret = sysLoadModuleBuffer(&ps2atad_irx, size_ps2atad_irx, 0, NULL);
146 if (ret < 0) {
147 gHddStartup = -1;
148 return;
151 gHddStartup = 2;
153 ret = sysLoadModuleBuffer(&ps2hdd_irx, size_ps2hdd_irx, sizeof(hddarg), hddarg);
154 if (ret < 0) {
155 gHddStartup = -1;
156 return;
159 gHddStartup = 1;
161 ret = sysLoadModuleBuffer(&ps2fs_irx, size_ps2fs_irx, 0, NULL);
162 if (ret < 0) {
163 gHddStartup = -1;
164 return;
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);
172 if (ret < 0) {
173 fileXioUmount(hddPrefix);
174 fileXioMount(hddPrefix, oplPart, FIO_MT_RDWR);
177 gHddStartup = 0;
180 void hddInit(void) {
181 LOG("HDDSUPPORT Init\n");
182 hddForceUpdate = 1;
184 ioPutRequest(IO_CUSTOM_SIMPLEACTION, &hddInitModules);
186 hddGameList.enabled = 1;
189 item_list_t* hddGetObject(int initOnly) {
190 if (initOnly && !hddGameList.enabled)
191 return NULL;
192 return &hddGameList;
195 static int hddNeedsUpdate(void) {
196 if (hddForceUpdate) {
197 hddForceUpdate = 0;
198 return 1;
201 return 0;
204 static int hddUpdateGameList(void) {
205 int ret = hddGetHDLGamelist(&hddGames);
206 if (ret != 0)
207 hddGameCount = 0;
208 else
209 hddGameCount = hddGames->count;
210 return hddGameCount;
213 static int hddGetGameCount(void) {
214 return hddGameCount;
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;
233 #ifndef __CHILDPROOF
234 static void hddDeleteGame(int id) {
235 hddDeleteHDLGame(&hddGames->games[id]);
236 hddForceUpdate = 1;
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]);
243 hddForceUpdate = 1;
245 #endif
247 static void hddLaunchGame(int id, config_set_t* configSet) {
248 int i, size_irx = 0;
249 void** irx = NULL;
250 char filename[32];
251 hdl_game_info_t* game = &hddGames->games[id];
253 #ifdef VMC
254 apa_header part_hdr;
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 fileXioUmount(hddPrefix);
260 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);
261 if (fd >= 0) {
262 if (fileXioIoctl2(fd, APA_IOCTL2_GETHEADER, NULL, 0, (void*)&part_hdr, sizeof(apa_header)) == sizeof(apa_header)) {
263 if (part_hdr.nsub <= 4) {
264 hdd_vmc_infos.parts[0].start = part_hdr.start;
265 hdd_vmc_infos.parts[0].length = part_hdr.length;
266 LOG("HDDSUPPORT hdd_vmc_infos.parts[0].start : 0x%X\n", hdd_vmc_infos.parts[0].start);
267 LOG("HDDSUPPORT hdd_vmc_infos.parts[0].length : 0x%X\n", hdd_vmc_infos.parts[0].length);
268 for (i = 0; i < part_hdr.nsub; i++) {
269 hdd_vmc_infos.parts[i+1].start = part_hdr.subs[i].start;
270 hdd_vmc_infos.parts[i+1].length = part_hdr.subs[i].length;
271 LOG("HDDSUPPORT hdd_vmc_infos.parts[%d].start : 0x%X\n", i+1, hdd_vmc_infos.parts[i+1].start);
272 LOG("HDDSUPPORT hdd_vmc_infos.parts[%d].length : 0x%X\n", i+1, hdd_vmc_infos.parts[i+1].length);
274 part_valid = 1;
278 fileXioClose(fd);
280 fileXioMount(hddPrefix, oplPart, FIO_MT_RDWR); // if this fails, something is really screwed up
282 if (part_valid) {
283 char vmc_name[32], vmc_path[255];
284 int vmc_id, have_error = 0;
285 vmc_superblock_t vmc_superblock;
286 pfs_inode_t pfs_inode;
288 for (vmc_id = 0; vmc_id < 2; vmc_id++) {
289 configGetVMC(configSet, vmc_name, vmc_id);
290 if (vmc_name[0]) {
291 have_error = 1;
292 hdd_vmc_infos.active = 0;
293 if (sysCheckVMC(hddPrefix, "/", vmc_name, 0, &vmc_superblock) > 0) {
294 hdd_vmc_infos.flags = vmc_superblock.mc_flag & 0xFF;
295 hdd_vmc_infos.flags |= 0x100;
296 hdd_vmc_infos.specs.page_size = vmc_superblock.page_size;
297 hdd_vmc_infos.specs.block_size = vmc_superblock.pages_per_block;
298 hdd_vmc_infos.specs.card_size = vmc_superblock.pages_per_cluster * vmc_superblock.clusters_per_card;
300 // Check vmc inode block chain (write operation can cause damage)
301 snprintf(vmc_path, 255, "%sVMC/%s.bin", hddPrefix, vmc_name);
302 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);
303 if (fileXioIoctl2(fd, PFS_IOCTL2_GET_INODE, NULL, 0, (void*)&pfs_inode, sizeof(pfs_inode_t)) == sizeof(pfs_inode_t)) {
304 if (pfs_inode.number_data <= 11) {
305 have_error = 0;
306 hdd_vmc_infos.active = 1;
307 for (i = 0; i < pfs_inode.number_data - 1; i++) {
308 hdd_vmc_infos.blocks[i].number = pfs_inode.data[i+1].number;
309 hdd_vmc_infos.blocks[i].subpart = pfs_inode.data[i+1].subpart;
310 hdd_vmc_infos.blocks[i].count = pfs_inode.data[i+1].count;
311 LOG("HDDSUPPORT hdd_vmc_infos.blocks[%d].number : 0x%X\n", i, hdd_vmc_infos.blocks[i].number);
312 LOG("HDDSUPPORT hdd_vmc_infos.blocks[%d].subpart : 0x%X\n", i, hdd_vmc_infos.blocks[i].subpart);
313 LOG("HDDSUPPORT hdd_vmc_infos.blocks[%d].count : 0x%X\n", i, hdd_vmc_infos.blocks[i].count);
315 } // else Vmc file too much fragmented
317 fileXioClose(fd);
321 if (have_error) {
322 char error[255];
323 snprintf(error, 255, _l(_STR_ERR_VMC_CONTINUE), vmc_name, (vmc_id + 1));
324 if (!guiMsgBox(error, 1, NULL))
325 return;
328 for (i = 0; i < size_hdd_mcemu_irx; i++) {
329 if (((u32*)&hdd_mcemu_irx)[i] == (0xC0DEFAC0 + vmc_id)) {
330 if (hdd_vmc_infos.active)
331 size_mcemu_irx = size_hdd_mcemu_irx;
332 memcpy(&((u32*)&hdd_mcemu_irx)[i], &hdd_vmc_infos, sizeof(hdd_vmc_infos_t));
333 break;
338 #endif
340 if (gRememberLastPlayed) {
341 configSetStr(configGetByType(CONFIG_LAST), "last_played", game->startup);
342 saveConfig(CONFIG_LAST, 0);
345 char gid[5];
346 configGetDiscIDBinary(configSet, gid);
348 int dmaType = 0, dmaMode = 0, compatMode = 0;
349 configGetInt(configSet, CONFIG_ITEM_DMA, &dmaMode);
350 configGetInt(configSet, CONFIG_ITEM_COMPAT, &compatMode);
351 if(dmaMode < 3)
352 dmaType = 0x20;
353 else {
354 dmaType = 0x40;
355 dmaMode -= 3;
357 hddSetTransferMode(dmaType, dmaMode);
358 hddSetIdleTimeout(gHDDSpindown * 12);
360 if (hddHDProKitDetected) {
361 size_irx = size_hdd_hdpro_cdvdman_irx;
362 irx = &hdd_hdpro_cdvdman_irx;
364 else if (sysPcmciaCheck()) {
365 size_irx = size_hdd_pcmcia_cdvdman_irx;
366 irx = &hdd_pcmcia_cdvdman_irx;
368 else {
369 size_irx = size_hdd_cdvdman_irx;
370 irx = &hdd_cdvdman_irx;
373 for (i=0;i<size_irx;i++){
374 if(!strcmp((const char*)((u32)irx+i),"###### GAMESETTINGS ######")){
375 break;
379 if (compatMode & COMPAT_MODE_2) {
380 u32 alt_read_mode = 1;
381 memcpy((void*)((u32)irx+i+35),&alt_read_mode,1);
383 if (compatMode & COMPAT_MODE_5) {
384 u32 no_dvddl = 1;
385 memcpy((void*)((u32)irx+i+36),&no_dvddl,4);
387 if (compatMode & COMPAT_MODE_4) {
388 u32 no_pss = 1;
389 memcpy((void*)((u32)irx+i+40),&no_pss,4);
392 // patch 48bit flag
393 u8 flag_48bit = hddIs48bit() & 0xff;
394 memcpy((void*)((u32)irx+i+34), &flag_48bit, 1);
396 // patch start_sector
397 memcpy((void*)((u32)irx+i+44), &game->start_sector, 4);
399 for (i=0;i<size_irx;i++){
400 if(!strcmp((const char*)((u32)irx+i),"B00BS")){
401 break;
404 // game id
405 memcpy((void*)((u32)irx+i), &gid, 5);
407 // patches cdvdfsv
408 /*void *cdvdfsv_irx;
409 int size_cdvdfsv_irx;
411 sysGetCDVDFSV(&cdvdfsv_irx, &size_cdvdfsv_irx);
412 u32 *p = (u32 *)cdvdfsv_irx;
413 for (i = 0; i < (size_cdvdfsv_irx >> 2); i++) {
414 if (*p == 0xC0DEC0DE) {
415 if (compatMode & COMPAT_MODE_7)
416 *p = 1;
417 else
418 *p = 0;
419 break;
421 p++;
424 char *altStartup = NULL;
425 if (configGetStr(configSet, CONFIG_ITEM_ALTSTARTUP, &altStartup))
426 strncpy(filename, altStartup, 32);
427 else
428 sprintf(filename, "%s", game->startup);
429 shutdown(NO_EXCEPTION); // CAREFUL: shutdown will call hddCleanUp, so hddGames/game will be freed
430 FlushCache(0);
432 #ifdef VMC
433 sysLaunchLoaderElf(filename, "HDD_MODE", size_irx, irx, size_mcemu_irx, &hdd_mcemu_irx, compatMode, compatMode & COMPAT_MODE_1);
434 #else
435 sysLaunchLoaderElf(filename, "HDD_MODE", size_irx, irx, compatMode, compatMode & COMPAT_MODE_1);
436 #endif
439 static config_set_t* hddGetConfig(int id) {
440 char path[255];
441 hdl_game_info_t* game = &hddGames->games[id];
443 snprintf(path, 255, "%sCFG/%s.cfg", hddPrefix, game->startup);
444 config_set_t* config = configAlloc(0, NULL, path);
445 configRead(config);
447 configSetStr(config, CONFIG_ITEM_NAME, game->name);
448 configSetInt(config, CONFIG_ITEM_SIZE, game->total_size_in_kb >> 10);
449 configSetStr(config, CONFIG_ITEM_FORMAT, "HDL");
450 if (game->disctype == 0x12)
451 configSetStr(config, CONFIG_ITEM_MEDIA, "CD");
452 else
453 configSetStr(config, CONFIG_ITEM_MEDIA, "DVD");
454 configSetStr(config, CONFIG_ITEM_STARTUP, game->startup);
456 return config;
459 static int hddGetImage(char* folder, int isRelative, char* value, char* suffix, GSTEXTURE* resultTex, short psm) {
460 char path[255];
461 if (isRelative)
462 sprintf(path, "%s%s/%s_%s", hddPrefix, folder, value, suffix);
463 else
464 sprintf(path, "%s%s_%s", folder, value, suffix);
465 return texDiscoverLoad(resultTex, path, -1, psm);
468 static void hddCleanUp(int exception) {
469 if (hddGameList.enabled) {
470 LOG("HDDSUPPORT CleanUp\n");
472 hddFreeHDLGamelist(hddGames);
474 if ((exception & UNMOUNT_EXCEPTION) == 0)
475 fileXioUmount(hddPrefix);
479 #ifdef VMC
480 static int hddCheckVMC(char* name, int createSize) {
481 return sysCheckVMC(hddPrefix, "/", name, createSize, NULL);
483 #endif
485 static item_list_t hddGameList = {
486 HDD_MODE, 0, COMPAT_FULL, 0, MENU_MIN_INACTIVE_FRAMES, "HDD Games", _STR_HDD_GAMES, &hddInit, &hddNeedsUpdate, &hddUpdateGameList,
487 #ifdef __CHILDPROOF
488 &hddGetGameCount, &hddGetGame, &hddGetGameName, &hddGetGameNameLength, &hddGetGameStartup, NULL, NULL,
489 #else
490 &hddGetGameCount, &hddGetGame, &hddGetGameName, &hddGetGameNameLength, &hddGetGameStartup, &hddDeleteGame, &hddRenameGame,
491 #endif
492 #ifdef VMC
493 &hddLaunchGame, &hddGetConfig, &hddGetImage, &hddCleanUp, &hddCheckVMC, HDD_ICON
494 #else
495 &hddLaunchGame, &hddGetConfig, &hddGetImage, &hddCleanUp, HDD_ICON
496 #endif