PageRenderTime 38ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/vmc/mcman/ps1mc_io.c

https://bitbucket.org/ifcaro/open-ps2-loader/
C | 717 lines | 523 code | 170 blank | 24 comment | 194 complexity | b2e2cabdaeb8ab0cf7da9bee589c12de MD5 | raw file
Possible License(s): CC-BY-SA-3.0, MPL-2.0-no-copyleft-exception, GPL-2.0
  1. /*
  2. Copyright 2009-2010, jimmikaelkael
  3. Licenced under Academic Free License version 3.0
  4. Review Open PS2 Loader README & LICENSE files for further details.
  5. */
  6. #include "mcman.h"
  7. extern int sio2man_type;
  8. //--------------------------------------------------------------
  9. int mcman_format1(int port, int slot)
  10. {
  11. register int r, i;
  12. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  13. #ifdef DEBUG
  14. DPRINTF("mcman: mcman_format1 port%d slot%d\n", port, slot);
  15. #endif
  16. mcman_invhandles(port, slot);
  17. for (i = 0; i < 56; i++) {
  18. r = mcman_PS1pagetest(port, slot, i);
  19. if (r == 0)
  20. return sceMcResNoFormat;
  21. if (r != 1)
  22. return -41;
  23. }
  24. memset(mcman_PS1PDApagebuf, 0, 128);
  25. *((u32 *)&mcman_PS1PDApagebuf) = 0xa0;
  26. *((u16 *)&mcman_PS1PDApagebuf+4) = 0xffff;
  27. mcman_PS1PDApagebuf[127] = mcman_calcEDC(mcman_PS1PDApagebuf, 127);
  28. for (i = 1; i < 15; i++) {
  29. r = McWritePS1PDACard(port, slot, i, mcman_PS1PDApagebuf);
  30. if (r != sceMcResSucceed)
  31. return -42;
  32. }
  33. memset(mcman_PS1PDApagebuf, 0, 128);
  34. *((u32 *)&mcman_PS1PDApagebuf) = 0xffffffff;
  35. for (i = 0; i < 20; i++) {
  36. *((u32 *)&mcman_PS1PDApagebuf) = mcdi->bad_block_list[i];
  37. mcman_PS1PDApagebuf[127] = mcman_calcEDC(mcman_PS1PDApagebuf, 127);
  38. r = McWritePS1PDACard(port, slot, i + 16, mcman_PS1PDApagebuf);
  39. if (r != sceMcResSucceed)
  40. return -43;
  41. }
  42. mcman_wmemset(mcman_PS1PDApagebuf, 128, 0);
  43. mcman_PS1PDApagebuf[0] = 0x4d;
  44. mcman_PS1PDApagebuf[1] = 0x43;
  45. mcman_PS1PDApagebuf[127] = 0x0e;
  46. r = McWritePS1PDACard(port, slot, 0, mcman_PS1PDApagebuf);
  47. if (r != sceMcResSucceed)
  48. return -44;
  49. mcdi->cardform = 1;
  50. return sceMcResSucceed;
  51. }
  52. //--------------------------------------------------------------
  53. int mcman_open1(int port, int slot, char *filename, int flags)
  54. {
  55. register int r, i, fd, cluster, temp;
  56. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  57. McFsEntryPS1 *fse; //sp18
  58. McCacheEntry *mce;
  59. char *p = (char *)filename;
  60. #ifdef DEBUG
  61. DPRINTF("mcman: mcman_open1 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
  62. #endif
  63. if ((flags & sceMcFileCreateFile) != 0)
  64. flags |= sceMcFileAttrWriteable;
  65. for (fd = 0; fd < MAX_FDHANDLES; fd++) {
  66. fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  67. if (fh->status == 0)
  68. break;
  69. }
  70. if (fd == MAX_FDHANDLES)
  71. return -7;
  72. mcman_wmemset((void *)fh, sizeof (MC_FHANDLE), 0);
  73. fh->port = port;
  74. fh->slot = slot;
  75. if (*p == '/')
  76. p++;
  77. if ((*p == 0) || ((*p == '.') && (p[1] == 0))) {
  78. fh->filesize = 15;
  79. fh->drdflag = 1;
  80. fh->status = 1;
  81. return fd;
  82. }
  83. r = mcman_getPS1direntry(port, slot, p, &fse, 1);
  84. if ((fse->mode & 0xf0) == 0xa0)
  85. r = -4;
  86. fh->freeclink = r;
  87. if (r >= 0) {
  88. if (fse->field_7d == 1)
  89. fh->filesize = fse->field_38;
  90. else
  91. fh->filesize = fse->length;
  92. }
  93. else
  94. fh->filesize = 0;
  95. fh->rdflag = flags & sceMcFileAttrReadable;
  96. fh->wrflag = flags & sceMcFileAttrWriteable;
  97. fh->unknown1 = 0;
  98. if ((flags & sceMcFileCreateFile) == 0) {
  99. if (r < 0)
  100. return sceMcResNoEntry;
  101. fh->status = 1;
  102. return fd;
  103. }
  104. for (i = 0; i < MAX_FDHANDLES; i++) {
  105. if ((mcman_fdhandles[i].status != 0) && \
  106. (mcman_fdhandles[i].port == port) && (mcman_fdhandles[i].slot == slot) && \
  107. (mcman_fdhandles[i].freeclink == r) && (fh->wrflag != 0))
  108. return sceMcResDeniedPermit;
  109. }
  110. if (r >= 0) {
  111. r = mcman_clearPS1direntry(port, slot, r, 0);
  112. if (r != sceMcResSucceed)
  113. return r;
  114. }
  115. cluster = -1;
  116. for (i = 0; i < 15; i++) {
  117. r = mcman_readdirentryPS1(port, slot, i, &fse);
  118. if (r != sceMcResSucceed)
  119. return r;
  120. if ((fse->mode & 0xf0) == 0xa0) {
  121. if (cluster < 0)
  122. cluster = i;
  123. if (fse->mode != 0xa0) {
  124. mcman_wmemset((void *)fse, sizeof(McFsEntryPS1), 0);
  125. fse->mode = 0xa0;
  126. fse->linked_block = -1;
  127. fse->edc = mcman_calcEDC((void *)fse, 127);
  128. mce = mcman_get1stcacheEntp();
  129. if ((i + 1) < 0)
  130. temp = i + 8;
  131. else
  132. temp = i + 1;
  133. mce->wr_flag |= 1 << ((i + 1) - ((temp >> 3) << 3));
  134. }
  135. }
  136. }
  137. r = mcman_flushmccache(port, slot);
  138. if (r != sceMcResSucceed)
  139. return r;
  140. if (cluster < 0)
  141. return sceMcResFullDevice;
  142. r = mcman_readdirentryPS1(port, slot, cluster, &fse);
  143. if (r != sceMcResSucceed)
  144. return r;
  145. mcman_wmemset((void *)fse, sizeof(McFsEntryPS1), 0);
  146. fse->mode = 0x51;
  147. fse->length = 0;
  148. fse->linked_block = -1;
  149. strncpy(fse->name, p, 20);
  150. if ((flags & sceMcFileAttrPDAExec) != 0)
  151. fse->field_7e = 1;
  152. fse->edc = mcman_calcEDC((void *)fse, 127);
  153. fh->freeclink = cluster;
  154. mce = mcman_get1stcacheEntp();
  155. if ((cluster + 1) < 0)
  156. temp = cluster + 8;
  157. else
  158. temp = cluster + 1;
  159. mce->wr_flag |= 1 << ((cluster + 1) - ((temp >> 3) << 3));
  160. r = mcman_flushmccache(port, slot);
  161. if (r != sceMcResSucceed)
  162. return r;
  163. fh->unknown2 = 1;
  164. fh->status = 1;
  165. return fd;
  166. }
  167. //--------------------------------------------------------------
  168. int mcman_read1(int fd, void *buffer, int nbyte)
  169. {
  170. register int r, size, temp, rpos, offset, maxsize;
  171. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  172. McCacheEntry *mce;
  173. u8 *p = (u8 *)buffer;
  174. if (fh->position >= fh->filesize)
  175. return 0;
  176. if (nbyte >= (fh->filesize - fh->position))
  177. nbyte = fh->filesize - fh->position;
  178. rpos = 0;
  179. if (nbyte) {
  180. do {
  181. if (fh->position < 0)
  182. temp = fh->position + 0x3ff;
  183. else
  184. temp = fh->position;
  185. offset = (fh->position - ((temp >> 10) << 10));
  186. maxsize = MCMAN_CLUSTERSIZE - offset;
  187. if (maxsize < nbyte)
  188. size = maxsize;
  189. else
  190. size = nbyte;
  191. r = mcman_fatRseekPS1(fd);
  192. if (r < 0)
  193. return r;
  194. r = mcman_readclusterPS1(fh->port, fh->slot, r, &mce);
  195. if (r != sceMcResSucceed)
  196. return r;
  197. memcpy(&p[rpos], (void *)(mce->cl_data + offset), size);
  198. rpos += size;
  199. nbyte -= size;
  200. fh->position += size;
  201. } while (nbyte);
  202. }
  203. return rpos;
  204. }
  205. //--------------------------------------------------------------
  206. int mcman_write1(int fd, void *buffer, int nbyte)
  207. {
  208. register int r, size, temp, wpos, offset, maxsize;
  209. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  210. McCacheEntry *mce;
  211. u8 *p = (u8 *)buffer;
  212. if (nbyte) {
  213. if (fh->unknown2 == 0) {
  214. fh->unknown2 = 1;
  215. r = mcman_close1(fd);
  216. if (r != sceMcResSucceed)
  217. return r;
  218. r = mcman_flushmccache(fh->port, fh->slot);
  219. if (r != sceMcResSucceed)
  220. return r;
  221. }
  222. }
  223. wpos = 0;
  224. if (nbyte) {
  225. do {
  226. r = mcman_fatRseekPS1(fd);
  227. if (r == sceMcResFullDevice) {
  228. r = mcman_fatWseekPS1(fd);
  229. if (r == sceMcResFullDevice)
  230. return r;
  231. if (r!= sceMcResSucceed)
  232. return r;
  233. r = mcman_fatRseekPS1(fd);
  234. }
  235. else {
  236. if (r < 0)
  237. return r;
  238. }
  239. r = mcman_readclusterPS1(fh->port, fh->slot, r, &mce);
  240. if (r != sceMcResSucceed)
  241. return r;
  242. if (fh->position < 0)
  243. temp = fh->position + 0x3ff;
  244. else
  245. temp = fh->position;
  246. offset = fh->position - ((temp >> 10) << 10);
  247. maxsize = MCMAN_CLUSTERSIZE - offset;
  248. if (maxsize < nbyte)
  249. size = maxsize;
  250. else
  251. size = nbyte;
  252. memcpy((void *)(mce->cl_data + offset), &p[wpos], size);
  253. mce->wr_flag = -1;
  254. fh->position += size;
  255. if (fh->position >= fh->filesize)
  256. fh->filesize = fh->position;
  257. nbyte -= size;
  258. wpos += size;
  259. } while (nbyte);
  260. }
  261. mcman_close1(fd);
  262. return wpos;
  263. }
  264. //--------------------------------------------------------------
  265. int mcman_dread1(int fd, fio_dirent_t *dirent)
  266. {
  267. register int r;
  268. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  269. McFsEntryPS1 *fse;
  270. if (fh->position < fh->filesize) {
  271. do {
  272. r = mcman_readdirentryPS1(fh->port, fh->slot, fh->position, &fse);
  273. if (r != sceMcResSucceed)
  274. return r;
  275. if (fse->mode == 0x51)
  276. break;
  277. } while (++fh->position < fh->filesize);
  278. }
  279. if (fh->position >= fh->filesize)
  280. return 0;
  281. fh->position++;
  282. mcman_wmemset((void *)dirent, sizeof(fio_dirent_t), 0);
  283. strncpy(dirent->name, fse->name, 20);
  284. dirent->name[20] = 0;
  285. dirent->stat.mode = 0x101f;
  286. if (fse->field_7e == 1)
  287. dirent->stat.mode = 0x181f;
  288. if (fse->field_7d == 1) {
  289. *((u32 *)&dirent->stat.ctime) = *((u32 *)&fse->created);
  290. *((u32 *)&dirent->stat.ctime + 1) = *((u32 *)&fse->created + 1);
  291. *((u32 *)&dirent->stat.mtime) = *((u32 *)&fse->modified);
  292. *((u32 *)&dirent->stat.mtime + 1) = *((u32 *)&fse->modified + 1);
  293. dirent->stat.size = fse->field_38;
  294. dirent->stat.attr = fse->field_28;
  295. }
  296. else {
  297. dirent->stat.size = fse->length;
  298. }
  299. return 1;
  300. }
  301. //--------------------------------------------------------------
  302. int mcman_getstat1(int port, int slot, char *filename, fio_stat_t *stat)
  303. {
  304. register int r;
  305. McFsEntryPS1 *fse;
  306. #ifdef DEBUG
  307. DPRINTF("mcman: mcman_getstat1 port%d slot%d filename %s\n", port, slot, filename);
  308. #endif
  309. r = mcman_getPS1direntry(port, slot, filename, &fse, 1);
  310. if ((fse->mode & 0xf0) == 0xa0)
  311. r = -4;
  312. if (r < 0)
  313. return sceMcResNoEntry;
  314. mcman_wmemset(stat, sizeof(fio_stat_t), 0);
  315. stat->mode = 0x1f;
  316. if (fse->field_7d == 1) {
  317. if ((fse->field_2c & sceMcFileAttrClosed) != 0)
  318. stat->mode = 0x9f;
  319. *((u32 *)&stat->ctime) = *((u32 *)&fse->created);
  320. *((u32 *)&stat->ctime+1) = *((u32 *)&fse->created+1);
  321. *((u32 *)&stat->mtime) = *((u32 *)&fse->modified);
  322. *((u32 *)&stat->mtime+1) = *((u32 *)&fse->modified+1);
  323. stat->size = fse->field_38;
  324. stat->attr = fse->field_28;
  325. return sceMcResSucceed;
  326. }
  327. stat->size = fse->length;
  328. return sceMcResSucceed;
  329. }
  330. //--------------------------------------------------------------
  331. int mcman_setinfo1(int port, int slot, char *filename, sceMcTblGetDir *info, int flags)
  332. {
  333. register int r, temp, ret;
  334. McFsEntryPS1 *fse1, *fse2;
  335. McCacheEntry *mce;
  336. #ifdef DEBUG
  337. DPRINTF("mcman: mcman_setinfo1 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
  338. #endif
  339. ret = 0;
  340. if (sio2man_type == XSIO2MAN) {
  341. if ((flags & sceMcFileAttrFile) != 0) {
  342. r = mcman_getPS1direntry(port, slot, info->EntryName, &fse1, 1);
  343. if (r < 0) {
  344. if (r != sceMcResNoEntry) {
  345. ret = r;
  346. }
  347. else {
  348. if ((!strcmp(".", info->EntryName)) || (!strcmp("..", info->EntryName)) || (info->EntryName[0] == 0))
  349. ret = sceMcResNoEntry;
  350. }
  351. }
  352. }
  353. }
  354. r = mcman_getPS1direntry(port, slot, filename, &fse2, 1);
  355. if ((fse2->mode & 0xf0) == 0)
  356. r = sceMcResNoEntry;
  357. if (r < 0)
  358. return r;
  359. if (sio2man_type == XSIO2MAN) {
  360. if (ret != sceMcResSucceed)
  361. return sceMcResNoEntry;
  362. }
  363. mce = mcman_get1stcacheEntp();
  364. temp = r + 1;
  365. if ((r + 1) < 0)
  366. temp = r + 8;
  367. mce->wr_flag |= 1 << ((r + 1) - ((temp >> 3) << 3));
  368. if (sio2man_type == XSIO2MAN) {
  369. fse2->field_7d = 0;
  370. fse2->field_2c = 0;
  371. flags &= -12;
  372. }
  373. else {
  374. if(fse2->field_7d != 1) {
  375. fse2->field_7d = 1;
  376. fse2->field_38 = fse2->length;
  377. }
  378. }
  379. if ((flags & sceMcFileAttrExecutable) != 0) {
  380. if ((info->AttrFile & sceMcFileAttrPDAExec) != 0)
  381. fse2->field_7e = 1;
  382. else
  383. fse2->field_7e = 0;
  384. }
  385. //Special fix clause for file managers (like uLaunchELF)
  386. //This allows writing most entries that can be read by mcGetDir
  387. //and without usual restrictions. This flags value should cause no conflict
  388. //as Sony code never uses it, and the value is changed after its use here.
  389. //This is primarily needed for PS2 MC backups, but must be implemented here
  390. //too since the 'flags' argument may be used indiscriminately for both
  391. if(flags == 0xFEED){
  392. flags = sceMcFileAttrReadable|sceMcFileAttrWriteable;
  393. //The changed flags value allows more entries to be copied below
  394. }
  395. if ((flags & sceMcFileAttrDupProhibit) != 0)
  396. fse2->field_28 = info->Reserve2;
  397. if ((flags & sceMcFileAttrReadable) != 0)
  398. fse2->created = info->_Create;
  399. if ((flags & sceMcFileAttrWriteable) != 0)
  400. fse2->modified = info->_Modify;
  401. if ((flags & sceMcFileAttrFile) != 0)
  402. strncpy(fse2->name, info->EntryName, 20);
  403. fse2->field_1e = 0;
  404. r = mcman_flushmccache(port, slot);
  405. return r;
  406. }
  407. //--------------------------------------------------------------
  408. int mcman_getdir1(int port, int slot, char *dirname, int flags, int maxent, sceMcTblGetDir *info)
  409. {
  410. register int r, i;
  411. char *p;
  412. McFsEntryPS1 *fse;
  413. #ifdef DEBUG
  414. DPRINTF("mcman: mcman_getdir1 port%d slot%d dirname %s maxent %d flags %x\n", port, slot, dirname, maxent, flags);
  415. #endif
  416. flags &= 0xffff;
  417. i = 0;
  418. if (!flags) {
  419. mcman_PS1curcluster = 0;
  420. p = dirname;
  421. do {
  422. r = mcman_chrpos(p, '/');
  423. if (r < 0)
  424. break;
  425. p += mcman_chrpos(p, '/') + 1;
  426. } while (1);
  427. strncpy(mcman_PS1curdir, p, 63);
  428. }
  429. if (maxent) {
  430. do {
  431. if (mcman_PS1curcluster >= 15)
  432. break;
  433. r = mcman_readdirentryPS1(port, slot, mcman_PS1curcluster, &fse);
  434. if (r != sceMcResSucceed)
  435. return r;
  436. mcman_PS1curcluster++;
  437. if (fse->mode != 0x51)
  438. continue;
  439. if (!mcman_checkdirpath(fse->name, mcman_PS1curdir))
  440. continue;
  441. memset((void *)info, 0, sizeof (sceMcTblGetDir));
  442. info->AttrFile = 0x9417;
  443. if (fse->field_7e == 1)
  444. info->AttrFile = 0x9c17; //MC_ATTR_PDAEXEC set !!!
  445. if (fse->field_7d == 1) {
  446. if ((fse->field_2c & sceMcFileAttrClosed) != 0) {
  447. info->AttrFile |= sceMcFileAttrClosed;
  448. }
  449. info->Reserve1 = fse->field_2e;
  450. info->_Create = fse->created;
  451. info->_Modify = fse->modified;
  452. info->FileSizeByte = fse->field_38;
  453. info->Reserve2 = fse->field_28;
  454. }
  455. else {
  456. info->FileSizeByte = fse->length;
  457. }
  458. strncpy(info->EntryName, fse->name, 20);
  459. info->EntryName[20] = 0;
  460. i++;
  461. info++;
  462. maxent--;
  463. } while (maxent);
  464. }
  465. return i;
  466. }
  467. //--------------------------------------------------------------
  468. int mcman_delete1(int port, int slot, char *filename, int flags)
  469. {
  470. register int r;
  471. McFsEntryPS1 *fse;
  472. #ifdef DEBUG
  473. DPRINTF("mcman: mcman_delete1 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
  474. #endif
  475. r = mcman_getPS1direntry(port, slot, filename, &fse, ((u32)flags < 1) ? 1 : 0);
  476. if (r < 0)
  477. return r;
  478. r = mcman_clearPS1direntry(port, slot, r, flags);
  479. return r;
  480. }
  481. //--------------------------------------------------------------
  482. int mcman_close1(int fd)
  483. {
  484. register int r, temp;
  485. MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  486. McFsEntryPS1 *fse;
  487. McCacheEntry *mce;
  488. #ifdef DEBUG
  489. DPRINTF("mcman: mcman_close1 fd %d\n", fd);
  490. #endif
  491. r = mcman_readdirentryPS1(fh->port, fh->slot, fh->freeclink, &fse);
  492. if (r != sceMcResSucceed)
  493. return -31;
  494. mce = mcman_get1stcacheEntp();
  495. if (fh->freeclink + 1 < 0)
  496. temp = fh->freeclink + 8;
  497. else
  498. temp = fh->freeclink + 1;
  499. mce->wr_flag |= 1 << ((fh->freeclink + 1) - ((temp >> 3) << 3));
  500. if (fh->filesize == 0) {
  501. fse->length = 0x2000;
  502. }
  503. else {
  504. if ((fh->filesize - 1) < 0)
  505. temp = (fh->filesize + 8190) >> 13;
  506. else
  507. temp = (fh->filesize - 1) >> 13;
  508. temp++;
  509. fse->length = temp << 13;
  510. }
  511. if (sio2man_type == XSIO2MAN) {
  512. fse->field_7d = 0; // <--- To preserve for XMCMAN
  513. fse->field_2c = 0; //
  514. fse->field_38 = 0; //
  515. memset((void *)&fse->created, 0, 8); //
  516. memset((void *)&fse->modified, 0, 8); //
  517. }
  518. else { // MCMAN does as following
  519. fse->field_7d = 1;
  520. fse->field_38 = fh->filesize;
  521. mcman_getmcrtime(&fse->modified);
  522. }
  523. fse->edc = mcman_calcEDC((void *)fse, 127);
  524. r = mcman_flushmccache(fh->port, fh->slot);
  525. if (r != sceMcResSucceed)
  526. return r;
  527. return sceMcResSucceed;
  528. }
  529. //--------------------------------------------------------------
  530. int mcman_unformat1(int port, int slot)
  531. {
  532. register int r, i;
  533. u32 *p;
  534. #ifdef DEBUG
  535. DPRINTF("mcman: mcman_unformat1 port%d slot%d\n", port, slot);
  536. #endif
  537. p = (u32 *)&mcman_PS1PDApagebuf;
  538. for (i = 0; i < 32; i++)
  539. *p++ = 0;
  540. for (i = 0; i < 1024; i++) {
  541. r = McWritePS1PDACard(port, slot, i, mcman_PS1PDApagebuf);
  542. if (r != sceMcResSucceed)
  543. return -41;
  544. }
  545. return r;
  546. }
  547. //--------------------------------------------------------------