PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/vmc/mcman/main.c

https://bitbucket.org/ifcaro/open-ps2-loader/
C | 2760 lines | 2117 code | 552 blank | 91 comment | 742 complexity | 74780b93695f13d830c9ce31099b852c MD5 | raw file
Possible License(s): CC-BY-SA-3.0, MPL-2.0-no-copyleft-exception, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  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. IRX_ID(MODNAME, 1, 1);
  8. struct modInfo_t mcman_modInfo = { "mcman_cex", 0x20b };
  9. char sio2man_modname[8] = "sio2man\0";
  10. int sio2man_type = SIO2MAN;
  11. char SUPERBLOCK_MAGIC[] = "Sony PS2 Memory Card Format ";
  12. char SUPERBLOCK_VERSION[] = "1.2.0.0";
  13. int mcman_wr_port = -1;
  14. int mcman_wr_slot = -1;
  15. int mcman_wr_block = -1;
  16. int mcman_wr_flag3 = -10;
  17. int mcman_curdircluster = -1;
  18. u32 DOT = 0x0000002e;
  19. u32 DOTDOT = 0x00002e2e;
  20. int timer_ID;
  21. int PS1CardFlag = 1;
  22. // mcman xor table
  23. u8 mcman_xortable[256] = {
  24. 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4,
  25. 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00,
  26. 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77,
  27. 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3,
  28. 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66,
  29. 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2,
  30. 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5,
  31. 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11,
  32. 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55,
  33. 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1,
  34. 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96,
  35. 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22,
  36. 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87,
  37. 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33,
  38. 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44,
  39. 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0,
  40. 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44,
  41. 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0,
  42. 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87,
  43. 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33,
  44. 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96,
  45. 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22,
  46. 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55,
  47. 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1,
  48. 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5,
  49. 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11,
  50. 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66,
  51. 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2,
  52. 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77,
  53. 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3,
  54. 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4,
  55. 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00
  56. };
  57. //--------------------------------------------------------------
  58. void long_multiply(u32 v1, u32 v2, u32 *HI, u32 *LO)
  59. {
  60. register long a, b, c, d;
  61. register long x, y;
  62. a = (v1 >> 16) & 0xffff;
  63. b = v1 & 0xffff;
  64. c = (v2 >> 16) & 0xffff;
  65. d = v2 & 0xffff;
  66. *LO = b * d;
  67. x = a * d + c * b;
  68. y = ((*LO >> 16) & 0xffff) + x;
  69. *LO = (*LO & 0xffff) | ((y & 0xffff) << 16);
  70. *HI = (y >> 16) & 0xffff;
  71. *HI += a * c;
  72. }
  73. //--------------------------------------------------------------
  74. int mcman_chrpos(char *str, int chr)
  75. {
  76. char *p;
  77. p = str;
  78. if (*str) {
  79. do {
  80. if (*p == (chr & 0xff))
  81. break;
  82. p++;
  83. } while (*p);
  84. }
  85. if (*p != (chr & 0xff))
  86. return -1;
  87. return p - str;
  88. }
  89. //--------------------------------------------------------------
  90. int _start(int argc, const char **argv)
  91. {
  92. iop_library_table_t *libtable;
  93. iop_library_t *libptr;
  94. register int i, sio2man_loaded;
  95. void **export_tab;
  96. #ifdef SIO_DEBUG
  97. sio_init(38400, 0, 0, 0, 0);
  98. #endif
  99. #ifdef DEBUG
  100. DPRINTF("mcman: _start...\n");
  101. #endif
  102. // Get sio2man lib ptr
  103. sio2man_loaded = 0;
  104. libtable = GetLibraryEntryTable();
  105. libptr = libtable->tail;
  106. while (libptr != 0) {
  107. for (i=0; i<8; i++) {
  108. if (libptr->name[i] != sio2man_modname[i])
  109. break;
  110. }
  111. if (i == 8) {
  112. sio2man_loaded = 1;
  113. break;
  114. }
  115. libptr = libptr->prev;
  116. }
  117. if (!sio2man_loaded) {
  118. #ifdef DEBUG
  119. DPRINTF("mcman: sio2man module is not loaded...\n");
  120. #endif
  121. return MODULE_NO_RESIDENT_END;
  122. }
  123. #ifdef DEBUG
  124. DPRINTF("mcman: sio2man version=0x%03x\n", libptr->version);
  125. #endif
  126. if (libptr->version > 0x101)
  127. sio2man_type = XSIO2MAN;
  128. // Get sio2man export table
  129. export_tab = (void **)(((struct irx_export_table *)libptr)->fptrs);
  130. // Set functions pointers to match SIO2MAN exports
  131. sio2_mc_transfer_init = export_tab[24];
  132. sio2_transfer = export_tab[25];
  133. // set internals function pointers for MCMAN
  134. mcman_sio2transfer = (void *)mcsio2_transfer;
  135. mc_detectcard = (void *)McDetectCard2;
  136. if (sio2man_type == XSIO2MAN) {
  137. // Set functions pointers to match XSIO2MAN exports
  138. sio2_transfer_reset = export_tab[26];
  139. sio2_func1 = export_tab[55];
  140. // set internals function pointers for XMCMAN
  141. mcman_sio2transfer = (void *)mcsio2_transfer2;
  142. mc_detectcard = (void *)mcman_detectcard;
  143. // Modify mcman export ver
  144. _exp_mcman.version = 0x203;
  145. // Get mcman export table
  146. export_tab = (void **)(struct irx_export_table *)&_exp_mcman.fptrs;
  147. export_tab[17] = (void *)McEraseBlock2;
  148. export_tab[21] = (void *)McDetectCard2;
  149. export_tab[22] = (void *)McGetFormat;
  150. export_tab[23] = (void *)McGetEntSpace;
  151. export_tab[24] = (void *)mcman_replacebadblock;
  152. export_tab[25] = (void *)McCloseAll;
  153. export_tab[42] = (void *)McGetModuleInfo;
  154. export_tab[43] = (void *)McGetCardSpec;
  155. export_tab[44] = (void *)mcman_getFATentry;
  156. export_tab[45] = (void *)McCheckBlock;
  157. export_tab[46] = (void *)mcman_setFATentry;
  158. export_tab[47] = (void *)mcman_readdirentry;
  159. export_tab[48] = (void *)mcman_1stcacheEntsetwrflagoff;
  160. export_tab[49] = (void *)mcman_createDirentry;
  161. export_tab[50] = (void *)mcman_readcluster;
  162. export_tab[51] = (void *)mcman_flushmccache;
  163. export_tab[52] = (void *)mcman_setdirentrystate;
  164. }
  165. #ifdef DEBUG
  166. DPRINTF("mcman: registering exports...\n");
  167. #endif
  168. if (RegisterLibraryEntries(&_exp_mcman) != 0)
  169. return MODULE_NO_RESIDENT_END;
  170. CpuEnableIntr();
  171. #ifdef DEBUG
  172. DPRINTF("mcman: initPS2com...\n");
  173. #endif
  174. mcman_initPS2com();
  175. #ifdef DEBUG
  176. DPRINTF("mcman: initPS1PDAcom...\n");
  177. #endif
  178. mcman_initPS1PDAcom();
  179. #ifdef DEBUG
  180. DPRINTF("mcman: initcache...\n");
  181. #endif
  182. mcman_initcache();
  183. #ifdef DEBUG
  184. DPRINTF("mcman: initdev...\n");
  185. #endif
  186. mcman_initdev();
  187. timer_ID = ReferHardTimer(1, 32, 0, 0x6309);
  188. if (timer_ID != -150)
  189. return MODULE_RESIDENT_END;
  190. timer_ID = AllocHardTimer(1, 32, 1);
  191. if (timer_ID > 0)
  192. SetTimerMode(timer_ID, 0);
  193. #ifdef DEBUG
  194. DPRINTF("mcman: _start returns MODULE_RESIDENT_END...\n");
  195. #endif
  196. return MODULE_RESIDENT_END;
  197. }
  198. //--------------------------------------------------------------
  199. int McGetFormat(int port, int slot) // Export #22 XMCMAN only
  200. {
  201. #ifdef DEBUG
  202. DPRINTF("mcman: McGetFormat port%d slot%d\n", port, slot);
  203. #endif
  204. return mcman_devinfos[port][slot].cardform;
  205. }
  206. //--------------------------------------------------------------
  207. int McGetMcType(int port, int slot) // Export #39
  208. {
  209. #ifdef DEBUG
  210. DPRINTF("mcman: McGetMcType port%d slot%d\n", port, slot);
  211. #endif
  212. return mcman_devinfos[port][slot].cardtype;
  213. }
  214. //--------------------------------------------------------------
  215. struct modInfo_t *McGetModuleInfo(void) // Export #42 XMCMAN only
  216. {
  217. #ifdef DEBUG
  218. DPRINTF("mcman: McGetModuleInfo\n");
  219. #endif
  220. return (struct modInfo_t *)&mcman_modInfo;
  221. }
  222. //--------------------------------------------------------------
  223. void McSetPS1CardFlag(int flag) // Export #40
  224. {
  225. #ifdef DEBUG
  226. DPRINTF("mcman: McSetPS1CardFlag flag %x\n", flag);
  227. #endif
  228. PS1CardFlag = flag;
  229. }
  230. //--------------------------------------------------------------
  231. int McGetFreeClusters(int port, int slot) // Export #38
  232. {
  233. register int r, mcfree;
  234. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  235. #ifdef DEBUG
  236. DPRINTF("mcman: McGetFreeClusters port%d slot%d\n", port, slot);
  237. #endif
  238. mcfree = 0;
  239. if (mcdi->cardform) {
  240. switch (mcdi->cardtype) {
  241. case sceMcTypePS2:
  242. mcfree = mcman_findfree2(port, slot, 0);
  243. break;
  244. case sceMcTypePS1:
  245. case sceMcTypePDA:
  246. mcfree = mcman_findfree1(port, slot, 0);
  247. break;
  248. case sceMcTypeNoCard:
  249. mcfree = 0;
  250. break;
  251. }
  252. if (mcfree == sceMcResFullDevice)
  253. mcfree = 0;
  254. r = mcfree;
  255. }
  256. else
  257. return 0;
  258. return r;
  259. }
  260. //--------------------------------------------------------------
  261. void mcman_wmemset(void *buf, int size, int value)
  262. {
  263. int *p = buf;
  264. size = (size >> 2) - 1;
  265. if (size > -1) {
  266. do {
  267. *p++ = value;
  268. } while (--size > -1);
  269. }
  270. }
  271. //--------------------------------------------------------------
  272. int mcman_calcEDC(void *buf, int size)
  273. {
  274. register u32 checksum;
  275. register int i;
  276. u8 *p = (u8 *)buf;
  277. checksum = 0;
  278. if (size > 0) {
  279. size--;
  280. i = 0;
  281. while (size-- != -1) {
  282. checksum ^= p[i];
  283. i++;
  284. }
  285. }
  286. return checksum & 0xff;
  287. }
  288. //--------------------------------------------------------------
  289. int mcman_checkpath(char *str) // check that a string do not contain special chars ( chr<32, ?, *)
  290. {
  291. register int i;
  292. u8 *p = (u8 *)str;
  293. i = 0;
  294. while (p[i]) {
  295. if (((p[i] & 0xff) == '?') || ((p[i] & 0xff) == '*'))
  296. return 0;
  297. if ((p[i] & 0xff) < 32)
  298. return 0;
  299. i++;
  300. }
  301. return 1;
  302. }
  303. //--------------------------------------------------------------
  304. int mcman_checkdirpath(char *str1, char *str2)
  305. {
  306. register int r, pos1, pos2, pos;
  307. u8 *p1 = (u8 *)str1;
  308. u8 *p2 = (u8 *)str2;
  309. do {
  310. pos1 = mcman_chrpos(p2, '?');
  311. pos2 = mcman_chrpos(p2, '*');
  312. if ((pos1 < 0) && (pos2 < 0)) {
  313. if (!strcmp(p2, p1))
  314. return 1;
  315. return 0;
  316. }
  317. pos = pos2;
  318. if (pos1 >= 0) {
  319. pos = pos1;
  320. if (pos2 >= 0) {
  321. pos = pos2;
  322. if (pos1 < pos2) {
  323. pos = pos1;
  324. }
  325. }
  326. }
  327. if (strncmp(p2, p1, pos) != 0)
  328. return 0;
  329. p2 += pos;
  330. p1 += pos;
  331. while (p2[0] == '?') {
  332. if (p1[0] == 0)
  333. return 1;
  334. p2++;
  335. p1++;
  336. }
  337. } while (p2[0] != '*');
  338. while((p2[0] == '*') || (p2[0] == '?'))
  339. p2++;
  340. if (p2[0] != 0) {
  341. do {
  342. pos = mcman_chrpos(p1, (u8)p2[0]);
  343. p1 += pos;
  344. if (pos < 0)
  345. return 0;
  346. r = mcman_checkdirpath(p1, p2);
  347. p1++;
  348. } while (r == 0);
  349. }
  350. return 1;
  351. }
  352. //--------------------------------------------------------------
  353. void mcman_invhandles(int port, int slot)
  354. {
  355. register int i = 0;
  356. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles;
  357. do {
  358. if ((fh->port == port) && (fh->slot == slot))
  359. fh->status = 0;
  360. fh++;
  361. } while (++i < MAX_FDHANDLES);
  362. }
  363. //--------------------------------------------------------------
  364. int McCloseAll(void) // Export #25 XMCMAN only
  365. {
  366. register int fd = 0, rv = 0;
  367. do {
  368. if (mcman_fdhandles[fd].status) {
  369. register int rc;
  370. rc = McClose(fd);
  371. if (rc < rv)
  372. rv = rc;
  373. }
  374. fd++;
  375. } while (fd < MAX_FDHANDLES);
  376. return rv;
  377. }
  378. //--------------------------------------------------------------
  379. int McDetectCard(int port, int slot) // Export #5
  380. {
  381. return mc_detectcard(port, slot);
  382. }
  383. //--------------------------------------------------------------
  384. int mcman_detectcard(int port, int slot)
  385. {
  386. register int r;
  387. register MCDevInfo *mcdi;
  388. #ifdef DEBUG
  389. DPRINTF("mcman: mcman_detectcard port%d slot%d\n", port, slot);
  390. #endif
  391. mcdi = (MCDevInfo *)&mcman_devinfos[port][slot];
  392. if ((mcdi->cardtype == sceMcTypeNoCard) || (mcdi->cardtype == sceMcTypePS2)) {
  393. r = mcman_probePS2Card2(port, slot);
  394. if (r < -9) {
  395. r = mcman_probePS1Card2(port, slot);
  396. if (!(r < -9)) {
  397. if (mcman_probePDACard(port, slot)) {
  398. mcdi->cardtype = sceMcTypePS1;
  399. return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
  400. }
  401. else {
  402. mcdi->cardtype = sceMcTypePDA;
  403. return r;
  404. }
  405. }
  406. }
  407. else {
  408. mcdi->cardtype = sceMcTypePS2;
  409. return r;
  410. }
  411. }
  412. else {
  413. r = mcman_probePS1Card2(port, slot);
  414. if (r) {
  415. if ((r < -9) || (r >= 0)) {
  416. r = mcman_probePS2Card2(port, slot);
  417. if (!(r < -9)) {
  418. mcdi->cardtype = sceMcTypePS2;
  419. return r;
  420. }
  421. }
  422. else {
  423. if (mcman_probePDACard(port, slot)) {
  424. mcdi->cardtype = sceMcTypePS1;
  425. return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
  426. }
  427. else {
  428. mcdi->cardtype = sceMcTypePDA;
  429. return r;
  430. }
  431. }
  432. }
  433. else {
  434. if (PS1CardFlag)
  435. return sceMcResSucceed;
  436. if (mcdi->cardtype == sceMcTypePS1)
  437. return sceMcResDeniedPS1Permit;
  438. return sceMcResSucceed;
  439. }
  440. }
  441. mcdi->cardtype = 0;
  442. mcdi->cardform = 0;
  443. mcman_invhandles(port, slot);
  444. mcman_clearcache(port, slot);
  445. return r;
  446. }
  447. //--------------------------------------------------------------
  448. int McDetectCard2(int port, int slot) // Export #21 XMCMAN only
  449. {
  450. register int r;
  451. register MCDevInfo *mcdi;
  452. #ifdef DEBUG
  453. DPRINTF("mcman: McDetectCard2 port%d slot%d\n", port, slot);
  454. #endif
  455. mcdi = (MCDevInfo *)&mcman_devinfos[port][slot];
  456. if ((mcdi->cardtype == sceMcTypeNoCard) || (mcdi->cardtype == sceMcTypePS2)) {
  457. r = mcman_probePS2Card(port, slot);
  458. if (r < -9) {
  459. r = mcman_probePS1Card(port, slot);
  460. if (!(r < -9)) {
  461. if (mcman_probePDACard(port, slot)) {
  462. mcdi->cardtype = sceMcTypePS1;
  463. return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
  464. }
  465. else {
  466. mcdi->cardtype = sceMcTypePDA;
  467. return r;
  468. }
  469. }
  470. }
  471. else {
  472. mcdi->cardtype = sceMcTypePS2;
  473. return r;
  474. }
  475. }
  476. else {
  477. r = mcman_probePS1Card(port, slot);
  478. if (r) {
  479. if ((r < -9) || (r >= 0)) {
  480. r = mcman_probePS2Card(port, slot);
  481. if (!(r < -9)) {
  482. mcdi->cardtype = sceMcTypePS2;
  483. return r;
  484. }
  485. }
  486. else {
  487. if (mcman_probePDACard(port, slot)) {
  488. mcdi->cardtype = sceMcTypePS1;
  489. return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
  490. }
  491. else {
  492. mcdi->cardtype = sceMcTypePDA;
  493. return r;
  494. }
  495. }
  496. }
  497. else {
  498. if (PS1CardFlag)
  499. return sceMcResSucceed;
  500. if (mcdi->cardtype == sceMcTypePS1)
  501. return sceMcResDeniedPS1Permit;
  502. return sceMcResSucceed;
  503. }
  504. }
  505. mcdi->cardtype = 0;
  506. mcdi->cardform = 0;
  507. mcman_invhandles(port, slot);
  508. mcman_clearcache(port, slot);
  509. return r;
  510. }
  511. //--------------------------------------------------------------
  512. int McOpen(int port, int slot, char *filename, int flag) // Export #6
  513. {
  514. register int r;
  515. r = McDetectCard(port, slot);
  516. if (r != sceMcResSucceed)
  517. return r;
  518. if (!PS1CardFlag)
  519. flag &= 0xFFFFDFFF; // disables FRCOM flag OR what is it
  520. if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
  521. r = mcman_open2(port, slot, filename, flag);
  522. else
  523. r = mcman_open1(port, slot, filename, flag);
  524. if (r < -9) {
  525. mcman_invhandles(port, slot);
  526. mcman_clearcache(port, slot);
  527. }
  528. return r;
  529. }
  530. //--------------------------------------------------------------
  531. int McClose(int fd) // Export #7
  532. {
  533. register MC_FHANDLE *fh;
  534. register MCDevInfo *mcdi;
  535. register int r;
  536. if (!((u32)fd < MAX_FDHANDLES))
  537. return sceMcResDeniedPermit;
  538. fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  539. if (!fh->status)
  540. return sceMcResDeniedPermit;
  541. fh->status = 0;
  542. r = McDetectCard(fh->port, fh->slot);
  543. if (r != sceMcResSucceed)
  544. return r;
  545. r = mcman_flushmccache(fh->port, fh->slot);
  546. if (r < -9) {
  547. mcman_invhandles(fh->port, fh->slot);
  548. mcman_clearcache(fh->port, fh->slot);
  549. }
  550. if (r != sceMcResSucceed)
  551. return r;
  552. if (fh->unknown2 != 0) {
  553. fh->unknown2 = 0;
  554. mcdi = (MCDevInfo *)&mcman_devinfos[fh->port][fh->slot];
  555. if (mcdi->cardtype == sceMcTypePS2)
  556. r = mcman_close2(fd);
  557. else
  558. r = mcman_close1(fd);
  559. if (r < -9) {
  560. mcman_invhandles(fh->port, fh->slot);
  561. mcman_clearcache(fh->port, fh->slot);
  562. }
  563. if (r != sceMcResSucceed)
  564. return r;
  565. }
  566. r = mcman_flushmccache(fh->port, fh->slot);
  567. if (r < -9) {
  568. mcman_invhandles(fh->port, fh->slot);
  569. mcman_clearcache(fh->port, fh->slot);
  570. }
  571. return r;
  572. }
  573. //--------------------------------------------------------------
  574. int McFlush(int fd) // Export #14
  575. {
  576. register int r;
  577. register MC_FHANDLE *fh;
  578. register MCDevInfo *mcdi;
  579. if (!((u32)fd < MAX_FDHANDLES))
  580. return sceMcResDeniedPermit;
  581. fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  582. if (!fh->status)
  583. return sceMcResDeniedPermit;
  584. r = McDetectCard(fh->port, fh->slot);
  585. if (r != sceMcResSucceed)
  586. return r;
  587. r = mcman_flushmccache(fh->port, fh->slot);
  588. if (r < -9) {
  589. mcman_invhandles(fh->port, fh->slot);
  590. mcman_clearcache(fh->port, fh->slot);
  591. }
  592. if (r != sceMcResSucceed) {
  593. fh->status = 0;
  594. return r;
  595. }
  596. if (fh->unknown2 != 0) {
  597. fh->unknown2 = 0;
  598. mcdi = (MCDevInfo *)&mcman_devinfos[fh->port][fh->slot];
  599. if (mcdi->cardtype == sceMcTypePS2)
  600. r = mcman_close2(fd);
  601. else
  602. r = mcman_close1(fd);
  603. if (r < -9) {
  604. mcman_invhandles(fh->port, fh->slot);
  605. mcman_clearcache(fh->port, fh->slot);
  606. }
  607. if (r != sceMcResSucceed) {
  608. fh->status = 0;
  609. return r;
  610. }
  611. }
  612. r = mcman_flushmccache(fh->port, fh->slot);
  613. if (r < 0)
  614. fh->status = 0;
  615. if (r < -9) {
  616. mcman_invhandles(fh->port, fh->slot);
  617. mcman_clearcache(fh->port, fh->slot);
  618. }
  619. return r;
  620. }
  621. //--------------------------------------------------------------
  622. int McSeek(int fd, int offset, int origin) // Export #10
  623. {
  624. register int r;
  625. register MC_FHANDLE *fh;
  626. #ifdef DEBUG
  627. DPRINTF("mcman: McSeek fd %d offset %d origin %d\n", fd, offset, origin);
  628. #endif
  629. if (!((u32)fd < MAX_FDHANDLES))
  630. return sceMcResDeniedPermit;
  631. fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  632. if (!fh->status)
  633. return sceMcResDeniedPermit;
  634. r = McDetectCard(fh->port, fh->slot);
  635. if (r != sceMcResSucceed)
  636. return r;
  637. switch (origin) {
  638. default:
  639. case SEEK_CUR:
  640. r = fh->position + offset;
  641. break;
  642. case SEEK_SET:
  643. r = offset;
  644. break;
  645. case SEEK_END:
  646. r = fh->filesize + offset;
  647. break;
  648. }
  649. return fh->position = (r < 0) ? 0 : r;
  650. }
  651. //--------------------------------------------------------------
  652. int McRead(int fd, void *buf, int length) // Export #8
  653. {
  654. register int r;
  655. register MC_FHANDLE *fh;
  656. if (!((u32)fd < MAX_FDHANDLES))
  657. return sceMcResDeniedPermit;
  658. fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  659. if (!fh->status)
  660. return sceMcResDeniedPermit;
  661. if (!fh->rdflag)
  662. return sceMcResDeniedPermit;
  663. r = McDetectCard(fh->port, fh->slot);
  664. if (r != sceMcResSucceed)
  665. return r;
  666. if (mcman_devinfos[fh->port][fh->slot].cardtype == sceMcTypePS2)
  667. r = mcman_read2(fd, buf, length);
  668. else
  669. r = mcman_read1(fd, buf, length);
  670. if (r < 0)
  671. fh->status = 0;
  672. if (r < -9) {
  673. mcman_invhandles(fh->port, fh->slot);
  674. mcman_clearcache(fh->port, fh->slot);
  675. }
  676. return r;
  677. }
  678. //--------------------------------------------------------------
  679. int McWrite(int fd, void *buf, int length) // Export #9
  680. {
  681. register int r;
  682. register MC_FHANDLE *fh;
  683. if (!((u32)fd < MAX_FDHANDLES))
  684. return sceMcResDeniedPermit;
  685. fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  686. if (!fh->status)
  687. return sceMcResDeniedPermit;
  688. if (!fh->wrflag)
  689. return sceMcResDeniedPermit;
  690. r = McDetectCard(fh->port, fh->slot);
  691. if (r != sceMcResSucceed)
  692. return r;
  693. if (mcman_devinfos[fh->port][fh->slot].cardtype == sceMcTypePS2)
  694. r = mcman_write2(fd, buf, length);
  695. else
  696. r = mcman_write1(fd, buf, length);
  697. if (r < 0)
  698. fh->status = 0;
  699. if (r < -9) {
  700. mcman_invhandles(fh->port, fh->slot);
  701. mcman_clearcache(fh->port, fh->slot);
  702. }
  703. return r;
  704. }
  705. //--------------------------------------------------------------
  706. int McGetEntSpace(int port, int slot, char *dirname) // Export #23 XMCMAN only
  707. {
  708. register int r;
  709. r = McDetectCard(port, slot);
  710. if (r != sceMcResSucceed)
  711. return r;
  712. if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2) {
  713. r = mcman_getentspace(port, slot, dirname);
  714. }
  715. if (r < -9) {
  716. mcman_invhandles(port, slot);
  717. mcman_clearcache(port, slot);
  718. }
  719. return r;
  720. }
  721. //--------------------------------------------------------------
  722. int McGetDir(int port, int slot, char *dirname, int flags, int maxent, sceMcTblGetDir *info) // Export #12
  723. {
  724. register int r;
  725. r = McDetectCard(port, slot);
  726. if (r != sceMcResSucceed)
  727. return r;
  728. if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
  729. r = mcman_getdir2(port, slot, dirname, flags & 0xFFFF, maxent, info);
  730. else
  731. r = mcman_getdir1(port, slot, dirname, flags & 0xFFFF, maxent, info);
  732. if (r < -9) {
  733. mcman_invhandles(port, slot);
  734. mcman_clearcache(port, slot);
  735. }
  736. return r;
  737. }
  738. //--------------------------------------------------------------
  739. int mcman_dread(int fd, fio_dirent_t *dirent)
  740. {
  741. register int r;
  742. register MC_FHANDLE *fh;
  743. if (!((u32)fd < MAX_FDHANDLES))
  744. return sceMcResDeniedPermit;
  745. fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  746. if (!fh->status)
  747. return sceMcResDeniedPermit;
  748. if (!fh->drdflag)
  749. return sceMcResDeniedPermit;
  750. r = McDetectCard(fh->port, fh->slot);
  751. if (r != sceMcResSucceed)
  752. return r;
  753. if (mcman_devinfos[fh->port][fh->slot].cardtype == sceMcTypePS2)
  754. r = mcman_dread2(fd, dirent);
  755. else
  756. r = mcman_dread1(fd, dirent);
  757. if (r < 0)
  758. fh->status = 0;
  759. if (r < -9) {
  760. mcman_invhandles(fh->port, fh->slot);
  761. mcman_clearcache(fh->port, fh->slot);
  762. }
  763. return r;
  764. }
  765. //--------------------------------------------------------------
  766. int mcman_getstat(int port, int slot, char *filename, fio_stat_t *stat)
  767. {
  768. register int r;
  769. r = McDetectCard(port, slot);
  770. if (r != sceMcResSucceed)
  771. return r;
  772. if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
  773. r = mcman_getstat2(port, slot, filename, stat);
  774. else
  775. r = mcman_getstat1(port, slot, filename, stat);
  776. if (r < -9) {
  777. mcman_invhandles(port, slot);
  778. mcman_clearcache(port, slot);
  779. }
  780. return r;
  781. }
  782. //--------------------------------------------------------------
  783. int McSetFileInfo(int port, int slot, char *filename, sceMcTblGetDir *info, int flags) // Export #16
  784. {
  785. register int r;
  786. r = McDetectCard(port, slot);
  787. if (r != sceMcResSucceed)
  788. return r;
  789. if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
  790. r = mcman_setinfo2(port, slot, filename, info, flags);
  791. else
  792. r = mcman_setinfo1(port, slot, filename, info, flags);
  793. if (r < -9) {
  794. mcman_invhandles(port, slot);
  795. mcman_clearcache(port, slot);
  796. }
  797. if (r == sceMcResSucceed) {
  798. r = mcman_flushmccache(port, slot);
  799. if (r < -9) {
  800. mcman_invhandles(port, slot);
  801. mcman_clearcache(port, slot);
  802. }
  803. }
  804. return r;
  805. }
  806. //--------------------------------------------------------------
  807. int McChDir(int port, int slot, char *newdir, char *currentdir) // Export #15
  808. {
  809. register int r;
  810. r = McDetectCard(port, slot);
  811. if (r != sceMcResSucceed)
  812. return r;
  813. if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
  814. r = mcman_chdir(port, slot, newdir, currentdir);
  815. else {
  816. currentdir[0] = 0;
  817. r = sceMcResSucceed;
  818. }
  819. if (r < -9) {
  820. mcman_invhandles(port, slot);
  821. mcman_clearcache(port, slot);
  822. }
  823. return r;
  824. }
  825. //--------------------------------------------------------------
  826. int McDelete(int port, int slot, char *filename, int flags) // Export #13
  827. {
  828. register int r;
  829. r = McDetectCard(port, slot);
  830. if (r != sceMcResSucceed)
  831. return r;
  832. if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
  833. r = mcman_delete2(port, slot, filename, flags);
  834. else
  835. r = mcman_delete1(port, slot, filename, flags);
  836. if (r < -9) {
  837. mcman_invhandles(port, slot);
  838. mcman_clearcache(port, slot);
  839. }
  840. return r;
  841. }
  842. //--------------------------------------------------------------
  843. int McFormat(int port, int slot) // Export #11
  844. {
  845. register int r;
  846. mcman_invhandles(port, slot);
  847. r = McDetectCard(port, slot);
  848. if (r < -2)
  849. return r;
  850. mcman_clearcache(port, slot);
  851. if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
  852. r = mcman_format2(port, slot);
  853. else
  854. r = mcman_format1(port, slot);
  855. if (r < -9) {
  856. mcman_invhandles(port, slot);
  857. mcman_clearcache(port, slot);
  858. }
  859. return r;
  860. }
  861. //--------------------------------------------------------------
  862. int McUnformat(int port, int slot) // Export #36
  863. {
  864. register int r;
  865. mcman_invhandles(port, slot);
  866. r = McDetectCard(port, slot);
  867. if (r < -2)
  868. return r;
  869. mcman_clearcache(port, slot);
  870. if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
  871. r = mcman_unformat2(port, slot);
  872. else
  873. r = mcman_unformat1(port, slot);
  874. mcman_devinfos[port][slot].cardform = 0;
  875. if (r < -9) {
  876. mcman_invhandles(port, slot);
  877. mcman_clearcache(port, slot);
  878. }
  879. return r;
  880. }
  881. //--------------------------------------------------------------
  882. int mcman_getmcrtime(sceMcStDateTime *time)
  883. {
  884. register int retries;
  885. cd_clock_t cdtime;
  886. retries = 64;
  887. do {
  888. if (sceCdRC(&cdtime))
  889. break;
  890. } while (--retries > 0);
  891. if (cdtime.stat & 128) {
  892. *((u16 *)&cdtime.month) = 0x7d0;
  893. cdtime.day = 3;
  894. cdtime.week = 4;
  895. cdtime.hour = 0;
  896. cdtime.minute = 0;
  897. cdtime.second = 0;
  898. cdtime.stat = 0;
  899. }
  900. time->Resv2 = 0;
  901. time->Sec = ((((cdtime.second >> 4) << 2) + (cdtime.second >> 4)) << 1) + (cdtime.second & 0xf);
  902. time->Min = ((((cdtime.minute >> 4) << 2) + (cdtime.minute >> 4)) << 1) + (cdtime.minute & 0xf);
  903. time->Hour = ((((cdtime.hour >> 4) << 2) + (cdtime.hour >> 4)) << 1) + (cdtime.hour & 0xf);
  904. time->Day = ((((cdtime.day >> 4) << 2) + (cdtime.day >> 4)) << 1) + (cdtime.day & 0xf);
  905. if ((cdtime.month & 0x10) != 0)
  906. time->Month = (cdtime.month & 0xf) + 0xa;
  907. else
  908. time->Month = cdtime.month & 0xf;
  909. time->Year = ((((cdtime.year >> 4) << 2) + (cdtime.year >> 4)) << 1) + ((cdtime.year & 0xf) | 0x7d0);
  910. return 0;
  911. }
  912. //--------------------------------------------------------------
  913. int McEraseBlock(int port, int block, void **pagebuf, void *eccbuf) // Export #17 in MCMAN
  914. {
  915. return mcman_eraseblock(port, 0, block, (void **)pagebuf, eccbuf);
  916. }
  917. //--------------------------------------------------------------
  918. int McEraseBlock2(int port, int slot, int block, void **pagebuf, void *eccbuf) // Export #17 in XMCMAN
  919. {
  920. return mcman_eraseblock(port, slot, block, (void **)pagebuf, eccbuf);
  921. }
  922. //--------------------------------------------------------------
  923. int McReadPage(int port, int slot, int page, void *buf) // Export #18
  924. {
  925. register int r, index, ecres, retries, count, erase_byte;
  926. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  927. u8 eccbuf[32];
  928. u8 *pdata, *peccb;
  929. count = (mcdi->pagesize + 127) >> 7;
  930. erase_byte = (mcdi->cardflags & CF_ERASE_ZEROES) ? 0x0 : 0xFF;
  931. retries = 0;
  932. ecres = sceMcResSucceed;
  933. do {
  934. if (!mcman_readpage(port, slot, page, buf, eccbuf)) {
  935. if (mcdi->cardflags & CF_USE_ECC) { // checking ECC from spare data block
  936. // check for erased page (last byte of spare data set to 0xFF or 0x0)/
  937. if (eccbuf[mcman_sparesize(port, slot) - 1] == erase_byte)
  938. break;
  939. index = 0;
  940. if (count > 0) {
  941. peccb = (u8 *)eccbuf;
  942. pdata = (u8 *)buf;
  943. do {
  944. r = mcman_correctdata(pdata, peccb);
  945. if (r < ecres)
  946. ecres = r;
  947. peccb += 3;
  948. pdata += 128;
  949. } while (++index < count);
  950. }
  951. if (ecres == sceMcResSucceed)
  952. break;
  953. if ((retries == 4) && (!(ecres < sceMcResNoFormat)))
  954. break;
  955. }
  956. }
  957. } while (++retries < 5);
  958. if (retries < 5)
  959. return sceMcResSucceed;
  960. return (ecres != sceMcResSucceed) ? sceMcResNoFormat : sceMcResChangedCard;
  961. }
  962. //--------------------------------------------------------------
  963. void McDataChecksum(void *buf, void *ecc) // Export #20
  964. {
  965. register u8 *p, *p_ecc;
  966. register int i, a2, a3, v, t0;
  967. p = buf;
  968. i = 0;
  969. a2 = 0;
  970. a3 = 0;
  971. t0 = 0;
  972. do {
  973. v = mcman_xortable[*p++];
  974. a2 ^= v;
  975. if (v & 0x80) {
  976. a3 ^= ~i;
  977. t0 ^= i;
  978. }
  979. } while (++i < 0x80);
  980. p_ecc = ecc;
  981. p_ecc[0] = ~a2 & 0x77;
  982. p_ecc[1] = ~a3 & 0x7F;
  983. p_ecc[2] = ~t0 & 0x7F;
  984. }
  985. //--------------------------------------------------------------
  986. int mcman_getcnum(int port, int slot)
  987. {
  988. return ((port & 1) << 3) + slot;
  989. }
  990. //--------------------------------------------------------------
  991. int mcman_correctdata(void *buf, void *ecc)
  992. {
  993. register int xor0, xor1, xor2, xor3, xor4;
  994. u8 eccbuf[12];
  995. u8 *p = (u8 *)ecc;
  996. McDataChecksum(buf, eccbuf);
  997. xor0 = p[0] ^ eccbuf[0];
  998. xor1 = p[1] ^ eccbuf[1];
  999. xor2 = p[2] ^ eccbuf[2];
  1000. xor3 = xor1 ^ xor2;
  1001. xor4 = (xor0 & 0xf) ^ (xor0 >> 4);
  1002. if (!xor0 && !xor1 && !xor2)
  1003. return 0;
  1004. if ((xor3 == 0x7f) && (xor4 == 0x7)) {
  1005. p[xor2] ^= 1 << (xor0 >> 4);
  1006. return -1;
  1007. }
  1008. xor0 = 0;
  1009. xor2 = 7;
  1010. do {
  1011. if ((xor3 & 1))
  1012. xor0++;
  1013. xor2--;
  1014. xor3 = xor3 >> 1;
  1015. } while (xor2 >= 0);
  1016. xor2 = 3;
  1017. do {
  1018. if ((xor4 & 1))
  1019. xor0++;
  1020. xor2--;
  1021. xor4 = xor4 >> 1;
  1022. } while (xor2 >= 0);
  1023. if (xor0 == 1)
  1024. return -2;
  1025. return -3;
  1026. }
  1027. //--------------------------------------------------------------
  1028. int mcman_sparesize(int port, int slot)
  1029. { // Get ps2 mc spare size by dividing pagesize / 32
  1030. return (mcman_devinfos[port][slot].pagesize + 0x1F) >> 5;
  1031. }
  1032. //--------------------------------------------------------------
  1033. int mcman_setdevspec(int port, int slot)
  1034. {
  1035. int cardsize;
  1036. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  1037. #ifdef DEBUG
  1038. DPRINTF("mcman: mcman_setdevspec port%d, slot%d\n", port, slot);
  1039. #endif
  1040. if (McGetCardSpec(port, slot, &mcdi->pagesize, &mcdi->blocksize, &cardsize, &mcdi->cardflags) != sceMcResSucceed)
  1041. return sceMcResFullDevice;
  1042. mcdi->pages_per_cluster = MCMAN_CLUSTERSIZE / mcdi->pagesize;
  1043. mcdi->cluster_size = MCMAN_CLUSTERSIZE;
  1044. mcdi->unknown1 = 0;
  1045. mcdi->unknown2 = 0;
  1046. mcdi->unused = 0xff00;
  1047. mcdi->FATentries_per_cluster = MCMAN_CLUSTERFATENTRIES;
  1048. mcdi->unknown5 = -1;
  1049. mcdi->rootdir_cluster2 = mcdi->rootdir_cluster;
  1050. mcdi->clusters_per_block = mcdi->blocksize / mcdi->pages_per_cluster;
  1051. mcdi->clusters_per_card = (cardsize / mcdi->blocksize) * (mcdi->blocksize / mcdi->pages_per_cluster);
  1052. return sceMcResSucceed;
  1053. }
  1054. //--------------------------------------------------------------
  1055. int mcman_setdevinfos(int port, int slot)
  1056. {
  1057. register int r, allocatable_clusters_per_card, iscluster_valid, current_allocatable_cluster, cluster_cnt;
  1058. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  1059. McFsEntry *pfse;
  1060. #ifdef DEBUG
  1061. DPRINTF("mcman: mcman_setdevinfos port%d slot%d\n", port, slot);
  1062. #endif
  1063. mcman_wmemset((void *)mcdi, sizeof(MCDevInfo), 0);
  1064. r = mcman_setdevspec(port, slot);
  1065. if (r != sceMcResSucceed)
  1066. return -49;
  1067. r = McReadPage(port, slot, 0, mcman_pagebuf);
  1068. if (r == sceMcResNoFormat)
  1069. return sceMcResNoFormat; // should rebuild a valid superblock here
  1070. if (r != sceMcResSucceed)
  1071. return -48;
  1072. if (strncmp(SUPERBLOCK_MAGIC, mcman_pagebuf, 28) != 0) {
  1073. #ifdef DEBUG
  1074. DPRINTF("mcman: mcman_setdevinfos No card format !!!\n");
  1075. #endif
  1076. return sceMcResNoFormat;
  1077. }
  1078. if (((mcman_pagebuf[28] - 48) == 1) && ((mcman_pagebuf[30] - 48) == 0)) // check ver major & minor
  1079. return sceMcResNoFormat;
  1080. u8 *p = (u8 *)mcdi;
  1081. for (r=0; r<0x150; r++)
  1082. p[r] = mcman_pagebuf[r];
  1083. mcdi->cardtype = sceMcTypePS2; // <--
  1084. r = mcman_checkBackupBlocks(port, slot);
  1085. if (r != sceMcResSucceed)
  1086. return -47;
  1087. r = mcman_readdirentry(port, slot, 0, 0, &pfse);
  1088. if (r != sceMcResSucceed)
  1089. return sceMcResNoFormat; // -46
  1090. if (strcmp(pfse->name, ".") != 0)
  1091. return sceMcResNoFormat;
  1092. if (mcman_readdirentry(port, slot, 0, 1, &pfse) != sceMcResSucceed)
  1093. return -45;
  1094. if (strcmp(pfse->name, "..") != 0)
  1095. return sceMcResNoFormat;
  1096. mcdi->cardform = 1;
  1097. // mcdi->cardtype = sceMcTypePS2;
  1098. if (((mcman_pagebuf[28] - 48) == 1) && ((mcman_pagebuf[30] - 48) == 1)) { // check ver major & minor
  1099. if ((mcdi->clusters_per_block * mcdi->backup_block2) == mcdi->alloc_end)
  1100. mcdi->alloc_end = (mcdi->clusters_per_block * mcdi->backup_block2) - mcdi->alloc_offset;
  1101. }
  1102. u32 hi, lo, temp;
  1103. long_multiply(mcdi->clusters_per_card, 0x10624dd3, &hi, &lo);
  1104. temp = (hi >> 6) - (mcdi->clusters_per_card >> 31);
  1105. allocatable_clusters_per_card = (((((temp << 5) - temp) << 2) + temp) << 3) + 1;
  1106. iscluster_valid = 0;
  1107. cluster_cnt = 0;
  1108. current_allocatable_cluster = mcdi->alloc_offset;
  1109. while (cluster_cnt < allocatable_clusters_per_card) {
  1110. if (current_allocatable_cluster >= mcdi->clusters_per_card)
  1111. break;
  1112. if (((current_allocatable_cluster % mcdi->clusters_per_block) == 0) \
  1113. || (mcdi->alloc_offset == current_allocatable_cluster)) {
  1114. iscluster_valid = 1;
  1115. for (r=0; r<16; r++) {
  1116. if ((current_allocatable_cluster / mcdi->clusters_per_block) == mcdi->bad_block_list[r])
  1117. iscluster_valid = 0;
  1118. }
  1119. }
  1120. if (iscluster_valid == 1)
  1121. cluster_cnt++;
  1122. current_allocatable_cluster++;
  1123. }
  1124. mcdi->max_allocatable_clusters = current_allocatable_cluster - mcdi->alloc_offset;
  1125. return sceMcResSucceed;
  1126. }
  1127. //--------------------------------------------------------------
  1128. int mcman_reportBadBlocks(int port, int slot)
  1129. {
  1130. register int r, i, block, bad_blocks, page, erase_byte, err_cnt, err_limit;
  1131. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  1132. u8 *p;
  1133. #ifdef DEBUG
  1134. DPRINTF("mcman: mcman_reportBadBlocks port%d, slot%d\n", port, slot);
  1135. #endif
  1136. mcman_wmemset((void *)mcdi->bad_block_list, 128, -1);
  1137. if ((mcdi->cardflags & CF_BAD_BLOCK) == 0)
  1138. return sceMcResSucceed;
  1139. err_limit = (((mcdi->pagesize << 16) >> 16) + ((mcdi->pagesize << 16) >> 31)) >> 1; //s7
  1140. erase_byte = 0;
  1141. if ((mcdi->cardflags & CF_ERASE_ZEROES) != 0)
  1142. erase_byte = 0xff;
  1143. bad_blocks = 0; // s2
  1144. if ((mcdi->clusters_per_card / mcdi->clusters_per_block) > 0) {
  1145. block = 0; // s1
  1146. do {
  1147. if (bad_blocks >= 16)
  1148. break;
  1149. err_cnt = 0; //s4
  1150. page = 0; //s3
  1151. do {
  1152. r = McReadPage(port, slot, (block * mcdi->blocksize) + page, mcman_pagebuf);
  1153. if (r == sceMcResNoFormat) {
  1154. mcdi->bad_block_list[bad_blocks] = block;
  1155. bad_blocks++;
  1156. break;
  1157. }
  1158. if (r != sceMcResSucceed)
  1159. return r;
  1160. if ((mcdi->cardflags & CF_USE_ECC) == 0) {
  1161. p = (u8 *)&mcman_pagebuf;
  1162. for (i = 0; i < mcdi->pagesize; i++) {
  1163. // check if the content of page is clean
  1164. if (*p++ != erase_byte)
  1165. err_cnt++;
  1166. if (err_cnt >= err_limit) {
  1167. mcdi->bad_block_list[bad_blocks] = block;
  1168. bad_blocks++;
  1169. break;
  1170. }
  1171. }
  1172. }
  1173. } while (++page < 2);
  1174. } while (++block < (mcdi->clusters_per_card / mcdi->clusters_per_block));
  1175. }
  1176. return sceMcResSucceed;
  1177. }
  1178. //--------------------------------------------------------------
  1179. int mcman_createDirentry(int port, int slot, int parent_cluster, int num_entries, int cluster, sceMcStDateTime *ctime)
  1180. {
  1181. register int r;
  1182. McCacheEntry *mce;
  1183. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  1184. McFsEntry *mfe, *mfe_next, *pfse;
  1185. #ifdef DEBUG
  1186. DPRINTF("mcman: mcman_createDirentry port%d slot%d parent_cluster %x num_entries %d cluster %x\n", port, slot, parent_cluster, num_entries, cluster);
  1187. #endif
  1188. r = mcman_readcluster(port, slot, mcdi->alloc_offset + cluster, &mce);
  1189. if (r != sceMcResSucceed)
  1190. return r;
  1191. mcman_wmemset(mce->cl_data, MCMAN_CLUSTERSIZE, 0);
  1192. mfe = (McFsEntry*)mce->cl_data;
  1193. mfe_next = (McFsEntry*)(mce->cl_data + sizeof (McFsEntry));
  1194. mfe->mode = sceMcFileAttrReadable | sceMcFileAttrWriteable | sceMcFileAttrExecutable \
  1195. | sceMcFileAttrSubdir | sceMcFile0400 | sceMcFileAttrExists; // 0x8427
  1196. if (ctime == NULL)
  1197. mcman_getmcrtime(&mfe->created);
  1198. else
  1199. mfe->created = *ctime;
  1200. mfe->modified = mfe->created;
  1201. mfe->length = 0;
  1202. mfe->dir_entry = num_entries;
  1203. mfe->cluster = parent_cluster;
  1204. *(u16 *)&mfe->name = *((u16 *)&DOT);
  1205. if ((parent_cluster == 0) && (num_entries == 0)) {
  1206. // entry is root directory
  1207. mfe_next->created = mfe->created;
  1208. mfe->length = 2;
  1209. mfe++;
  1210. mfe->mode = sceMcFileAttrWriteable | sceMcFileAttrExecutable | sceMcFileAttrSubdir \
  1211. | sceMcFile0400 | sceMcFileAttrExists | sceMcFileAttrHidden; // 0xa426
  1212. mfe->dir_entry = 0;
  1213. mfe->cluster = 0;
  1214. }
  1215. else {
  1216. // entry is normal "." / ".."
  1217. mcman_readdirentry(port, slot, parent_cluster, 0, &pfse);
  1218. mfe_next->created = pfse->created;
  1219. mfe++;
  1220. mfe->mode = sceMcFileAttrReadable | sceMcFileAttrWriteable | sceMcFileAttrExecutable \
  1221. | sceMcFileAttrSubdir | sceMcFile0400 | sceMcFileAttrExists; // 0x8427
  1222. mfe->dir_entry = pfse->dir_entry;
  1223. mfe->cluster = pfse->cluster;
  1224. }
  1225. mfe->modified = mfe->created;
  1226. mfe->length = 0;
  1227. *(u16 *)&mfe->name = *(u16 *)&DOTDOT;
  1228. *(u8 *)&mfe->name[2] = *((u8 *)&DOTDOT+2);
  1229. mce->wr_flag = 1;
  1230. return sceMcResSucceed;
  1231. }
  1232. //--------------------------------------------------------------
  1233. int mcman_fatRseek(int fd)
  1234. {
  1235. register int r, entries_to_read, fat_index;
  1236. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd]; //s1
  1237. register MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot]; //s2
  1238. int fat_entry;
  1239. entries_to_read = fh->position / mcdi->cluster_size; //s0
  1240. //s5 = 0
  1241. if (entries_to_read < fh->clust_offset) //v1 = fh->fh->clust_offset
  1242. fat_index = fh->freeclink;
  1243. else {
  1244. fat_index = fh->clink; // a2
  1245. entries_to_read -= fh->clust_offset;
  1246. }
  1247. if (entries_to_read == 0) {
  1248. if (fat_index >= 0)
  1249. return fat_index + mcdi->alloc_offset;
  1250. return sceMcResFullDevice;
  1251. }
  1252. do {
  1253. r = mcman_getFATentry(fh->port, fh->slot, fat_index, &fat_entry);
  1254. if (r != sceMcResSucceed)
  1255. return r;
  1256. fat_index = fat_entry;
  1257. if (fat_index >= -1)
  1258. return sceMcResFullDevice;
  1259. entries_to_read--;
  1260. fat_index &= 0x7fffffff;
  1261. fh->clink = fat_index;
  1262. fh->clust_offset = (fh->position / mcdi->cluster_size) - entries_to_read;
  1263. } while (entries_to_read > 0);
  1264. return fat_index + mcdi->alloc_offset;
  1265. }
  1266. //--------------------------------------------------------------
  1267. int mcman_fatWseek(int fd) // modify FAT to hold new content for a file
  1268. {
  1269. register int r, entries_to_write, fat_index;
  1270. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  1271. register MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
  1272. register McCacheEntry *mce;
  1273. int fat_entry;
  1274. entries_to_write = fh->position / mcdi->cluster_size;
  1275. if ((fh->clust_offset == 0) || (entries_to_write < fh->clust_offset)) {
  1276. fat_index = fh->freeclink;
  1277. if (fat_index < 0) {
  1278. fat_index = mcman_findfree2(fh->port, fh->slot, 1);
  1279. if (fat_index < 0)
  1280. return sceMcResFullDevice;
  1281. mce = (McCacheEntry *)mcman_get1stcacheEntp();
  1282. fh->freeclink = fat_index;
  1283. r = mcman_close2(fd);
  1284. if (r != sceMcResSucceed)
  1285. return r;
  1286. mcman_addcacheentry(mce);
  1287. mcman_flushmccache(fh->port, fh->slot);
  1288. }
  1289. }
  1290. else {
  1291. fat_index = fh->clink;
  1292. entries_to_write -= fh->clust_offset;
  1293. }
  1294. if (entries_to_write != 0) {
  1295. do {
  1296. r = mcman_getFATentry(fh->port, fh->slot, fat_index, &fat_entry);
  1297. if (r != sceMcResSucceed)
  1298. return r;
  1299. if (fat_entry >= 0xffffffff) {
  1300. r = mcman_findfree2(fh->port, fh->slot, 1);
  1301. if (r < 0)
  1302. return r;
  1303. fat_entry = r;
  1304. fat_entry |= 0x80000000;
  1305. mce = (McCacheEntry *)mcman_get1stcacheEntp();
  1306. r = mcman_setFATentry(fh->port, fh->slot, fat_index, fat_entry);
  1307. if (r != sceMcResSucceed)
  1308. return r;
  1309. mcman_addcacheentry(mce);
  1310. }
  1311. entries_to_write--;
  1312. fat_index = fat_entry & 0x7fffffff;
  1313. } while (entries_to_write > 0);
  1314. }
  1315. fh->clink = fat_index;
  1316. fh->clust_offset = fh->position / mcdi->cluster_size;
  1317. return sceMcResSucceed;
  1318. }
  1319. //--------------------------------------------------------------
  1320. int mcman_findfree2(int port, int slot, int reserve)
  1321. {
  1322. register int r, rfree, indirect_index, ifc_index, fat_offset, indirect_offset, fat_index, block;
  1323. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  1324. McCacheEntry *mce1, *mce2;
  1325. #ifdef DEBUG
  1326. DPRINTF("mcman: mcman_findfree2 port%d slot%d reserve%d\n", port, slot, reserve);
  1327. #endif
  1328. fat_index = mcdi->unknown2;
  1329. rfree = 0;
  1330. for (fat_index = mcdi->unknown2; fat_index < mcdi->max_allocatable_clusters; fat_index++) {
  1331. indirect_index = fat_index / mcdi->FATentries_per_cluster;
  1332. fat_offset = fat_index % mcdi->FATentries_per_cluster;
  1333. if ((fat_offset == 0) || (fat_index == mcdi->unknown2)) {
  1334. ifc_index = indirect_index / mcdi->FATentries_per_cluster;
  1335. r = mcman_readcluster(port, slot, mcdi->ifc_list[ifc_index], &mce1);
  1336. if (r != sceMcResSucceed)
  1337. return r;
  1338. //}
  1339. //if ((fat_offset == 0) || (fat_index == mcdi->unknown2)) {
  1340. indirect_offset = indirect_index % mcdi->FATentries_per_cluster;
  1341. McFatCluster *fc = (McFatCluster *)mce1->cl_data;
  1342. r = mcman_readcluster(port, slot, fc->entry[indirect_offset], &mce2);
  1343. if (r != sceMcResSucceed)
  1344. return r;
  1345. }
  1346. McFatCluster *fc = (McFatCluster *)mce2->cl_data;
  1347. if (fc->entry[fat_offset] >= 0) {
  1348. block = (mcdi->alloc_offset + fat_offset) / mcdi->clusters_per_block;
  1349. if (block != mcman_badblock) {
  1350. if (reserve) {
  1351. fc->entry[fat_offset] = 0xffffffff;
  1352. mce2->wr_flag = 1;
  1353. mcdi->unknown2 = fat_index;
  1354. return fat_index;
  1355. }
  1356. rfree++;
  1357. }
  1358. }
  1359. }
  1360. if (reserve)
  1361. return sceMcResFullDevice;
  1362. return (rfree) ? rfree : sceMcResFullDevice;
  1363. }
  1364. //--------------------------------------------------------------
  1365. int mcman_getentspace(int port, int slot, char *dirname)
  1366. {
  1367. register int r, i, entspace;
  1368. McCacheDir cacheDir;
  1369. McFsEntry *fse;
  1370. McFsEntry mfe;
  1371. u8 *pfsentry, *pmfe, *pfseend;
  1372. #ifdef DEBUG
  1373. DPRINTF("mcman: mcman_getentspace port%d slot%d dirname %s\n", port, slot, dirname);
  1374. #endif
  1375. r = mcman_cachedirentry(port, slot, dirname, &cacheDir, &fse, 1);
  1376. if (r > 0)
  1377. return sceMcResNoEntry;
  1378. if (r < 0)
  1379. return r;
  1380. pfsentry = (u8 *)fse;
  1381. pmfe = (u8 *)&mfe;
  1382. pfseend = (u8 *)(pfsentry + sizeof (McFsEntry));
  1383. do {
  1384. *((u32 *)pmfe ) = *((u32 *)pfsentry );
  1385. *((u32 *)pmfe+1) = *((u32 *)pfsentry+1);
  1386. *((u32 *)pmfe+2) = *((u32 *)pfsentry+2);
  1387. *((u32 *)pmfe+3) = *((u32 *)pfsentry+3);
  1388. pfsentry += 16;
  1389. pmfe += 16;
  1390. } while (pfsentry < pfseend);
  1391. entspace = mfe.length & 1;
  1392. for (i = 0; i < mfe.length; i++) {
  1393. r = mcman_readdirentry(port, slot, mfe.cluster, i, &fse);
  1394. if (r != sceMcResSucceed)
  1395. return r;
  1396. if ((fse->mode & sceMcFileAttrExists) == 0)
  1397. entspace++;
  1398. }
  1399. return entspace;
  1400. }
  1401. //--------------------------------------------------------------
  1402. int mcman_cachedirentry(int port, int slot, char *filename, McCacheDir *pcacheDir, McFsEntry **pfse, int unknown_flag)
  1403. {
  1404. register int r, fsindex, cluster, fmode;
  1405. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  1406. McFsEntry *fse;
  1407. McCacheDir cacheDir;
  1408. u8 *p, *pfsentry, *pcache, *pfseend;
  1409. #ifdef DEBUG
  1410. DPRINTF("mcman: mcman_cachedirentry port%d slot%d name %s\n", port, slot, filename);
  1411. #endif
  1412. if (pcacheDir == NULL) {
  1413. pcacheDir = &cacheDir;
  1414. pcacheDir->maxent = -1;
  1415. }
  1416. p = (u8 *)filename;
  1417. if (*p == '/') {
  1418. p++;
  1419. cluster = 0;
  1420. fsindex = 0;
  1421. }
  1422. else {
  1423. cluster = mcdi->rootdir_cluster2;
  1424. fsindex = mcdi->unknown1;
  1425. }
  1426. r = mcman_readdirentry(port, slot, cluster, fsindex, &fse);
  1427. if (r != sceMcResSucceed)
  1428. return r;
  1429. if (*p == 0) {
  1430. if (!(fse->mode & sceMcFileAttrExists))
  1431. return 2;
  1432. if (pcacheDir == NULL) {
  1433. *pfse = (McFsEntry *)fse;
  1434. return sceMcResSucceed;
  1435. }
  1436. pfsentry = (u8 *)fse;
  1437. pcache = (u8 *)&mcman_dircache[0];
  1438. pfseend = (u8 *)(pfsentry + sizeof (McFsEntry));
  1439. do {
  1440. *((u32 *)pcache ) = *((u32 *)pfsentry );
  1441. *((u32 *)pcache+1) = *((u32 *)pfsentry+1);
  1442. *((u32 *)pcache+2) = *((u32 *)pfsentry+2);
  1443. *((u32 *)pcache+3) = *((u32 *)pfsentry+3);
  1444. pfsentry += 16;
  1445. pcache += 16;
  1446. } while (pfsentry < pfseend);
  1447. r = mcman_getdirinfo(port, slot, (McFsEntry *)&mcman_dircache[0], ".", pcacheDir, unknown_flag);
  1448. mcman_readdirentry(port, slot, pcacheDir->cluster, pcacheDir->fsindex, pfse);
  1449. if (r > 0)
  1450. return 2;
  1451. return r;
  1452. } else {
  1453. do {
  1454. fmode = sceMcFileAttrReadable | sceMcFileAttrExecutable;
  1455. if ((fse->mode & fmode) != fmode)
  1456. return sceMcResDeniedPermit;
  1457. if (mcman_chrpos(p, '/') < 0)
  1458. strlen(p);
  1459. pfsentry = (u8 *)fse;
  1460. pcache = (u8 *)&mcman_dircache[0];
  1461. pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
  1462. do {
  1463. *((u32 *)pcache ) = *((u32 *)pfsentry );
  1464. *((u32 *)pcache+1) = *((u32 *)pfsentry+1);
  1465. *((u32 *)pcache+2) = *((u32 *)pfsentry+2);
  1466. *((u32 *)pcache+3) = *((u32 *)pfsentry+3);
  1467. pfsentry += 16;
  1468. pcache += 16;
  1469. } while (pfsentry < pfseend);
  1470. r = mcman_getdirinfo(port, slot, (McFsEntry *)&mcman_dircache[0], p, pcacheDir, unknown_flag);
  1471. if (r > 0) {
  1472. if (mcman_chrpos(p, '/') >= 0)
  1473. return 2;
  1474. pcacheDir->cluster = cluster;
  1475. pcacheDir->fsindex = fsindex;
  1476. return 1;
  1477. }
  1478. r = mcman_chrpos(p, '/');
  1479. if ((r >= 0) && (p[r + 1] != 0)) {
  1480. p += mcman_chrpos(p, '/') + 1;
  1481. cluster = pcacheDir->cluster;
  1482. fsindex = pcacheDir->fsindex;
  1483. mcman_readdirentry(port, slot, cluster, fsindex, &fse);
  1484. }
  1485. else {
  1486. mcman_readdirentry(port, slot, pcacheDir->cluster, pcacheDir->fsindex, pfse);
  1487. return sceMcResSucceed;
  1488. }
  1489. } while (*p != 0);
  1490. }
  1491. return sceMcResSucceed;
  1492. }
  1493. //--------------------------------------------------------------
  1494. int mcman_getdirinfo(int port, int slot, McFsEntry *pfse, char *filename, McCacheDir *pcd, int unknown_flag)
  1495. {
  1496. register int i, r, ret, len, pos;
  1497. McFsEntry *fse;
  1498. u8 *pfsentry, *pfsee, *pfseend;
  1499. #ifdef DEBUG
  1500. DPRINTF("mcman: mcman_getdirinfo port%d slot%d name %s\n", port, slot, filename);
  1501. #endif
  1502. pos = mcman_chrpos(filename, '/');
  1503. if (pos < 0)
  1504. pos = strlen(filename);
  1505. ret = 0;
  1506. if ((pos == 2) && (!strncmp(filename, "..", 2))) {
  1507. r = mcman_readdirentry(port, slot, pfse->cluster, 0, &fse);
  1508. if (r != sceMcResSucceed)
  1509. return r;
  1510. r = mcman_readdirentry(port, slot, fse->cluster, 0, &fse);
  1511. if (r != sceMcResSucceed)
  1512. return r;
  1513. if (pcd) {
  1514. pcd->cluster = fse->cluster;
  1515. pcd->fsindex = fse->dir_entry;
  1516. }
  1517. r = mcman_readdirentry(port, slot, fse->cluster, fse->dir_entry, &fse);
  1518. if (r != sceMcResSucceed)
  1519. return r;
  1520. pfsentry = (u8 *)fse;
  1521. pfsee = (u8 *)pfse;
  1522. pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
  1523. do {
  1524. *((u32 *)pfsee ) = *((u32 *)pfsentry );
  1525. *((u32 *)pfsee+1) = *((u32 *)pfsentry+1);
  1526. *((u32 *)pfsee+2) = *((u32 *)pfsentry+2);
  1527. *((u32 *)pfsee+3) = *((u32 *)pfsentry+3);
  1528. pfsentry += 16;
  1529. pfsee += 16;
  1530. } while (pfsentry < pfseend);
  1531. if ((fse->mode & sceMcFileAttrHidden) != 0) {
  1532. ret = 1;
  1533. if (!PS1CardFlag) {
  1534. ret = 2;
  1535. if ((pcd == NULL) || (pcd->maxent < 0))
  1536. return 3;
  1537. }
  1538. }
  1539. if ((pcd == NULL) || (pcd->maxent < 0))
  1540. return sceMcResSucceed;
  1541. }
  1542. else {
  1543. if ((pos == 1) && (!strncmp(filename, ".", 1))) {
  1544. r = mcman_readdirentry(port, slot, pfse->cluster, 0, &fse);
  1545. if (r != sceMcResSucceed)
  1546. return r;
  1547. if (pcd) {
  1548. pcd->cluster = fse->cluster;
  1549. pcd->fsindex = fse->dir_entry;
  1550. }
  1551. if ((fse->mode & sceMcFileAttrHidden) != 0) {
  1552. ret = 1;
  1553. if (!PS1CardFlag) {
  1554. ret = 2;
  1555. if ((pcd == NULL) || (pcd->maxent < 0))
  1556. return 3;
  1557. }
  1558. else {
  1559. if ((pcd == NULL) || (pcd->maxent < 0))
  1560. return sceMcResSucceed;
  1561. }
  1562. }
  1563. else {
  1564. ret = 1;
  1565. if ((pcd == NULL) || (pcd->maxent < 0))
  1566. return sceMcResSucceed;
  1567. }
  1568. }
  1569. }
  1570. if ((pcd) && (pcd->maxent >= 0))
  1571. pcd->maxent = pfse->length;
  1572. if (pfse->length > 0) {
  1573. i = 0;
  1574. do {
  1575. r = mcman_readdirentry(port, slot, pfse->cluster, i, &fse);
  1576. if (r != sceMcResSucceed)
  1577. return r;
  1578. if (((fse->mode & sceMcFileAttrExists) == 0) && (pcd) && (i < pcd->maxent))
  1579. pcd->maxent = i;
  1580. if (unknown_flag) {
  1581. if ((fse->mode & sceMcFileAttrExists) == 0)
  1582. continue;
  1583. }
  1584. else {
  1585. if ((fse->mode & sceMcFileAttrExists) != 0)
  1586. continue;
  1587. }
  1588. if (ret != 0)
  1589. continue;
  1590. if ((pos >= 11) && (!strncmp(&filename[10], &fse->name[10], pos-10))) {
  1591. len = pos;
  1592. if (strlen(fse->name) >= pos)
  1593. len = strlen(fse->name);
  1594. if (!strncmp(filename, fse->name, len))
  1595. goto continue_check;
  1596. }
  1597. if (strlen(fse->name) >= pos)
  1598. len = strlen(fse->name);
  1599. else
  1600. len = pos;
  1601. if (strncmp(filename, fse->name, len))
  1602. continue;
  1603. continue_check:
  1604. ret = 1;
  1605. if ((fse->mode & sceMcFileAttrHidden) != 0) {
  1606. if (!PS1CardFlag)
  1607. ret = 2;
  1608. }
  1609. if (pcd == NULL)
  1610. break;
  1611. pcd->fsindex = i;
  1612. pcd->cluster = pfse->cluster;
  1613. if (pcd->maxent < 0)
  1614. break;
  1615. } while (++i < pfse->length);
  1616. }
  1617. if (ret == 2)
  1618. return 2;
  1619. return ((ret < 1) ? 1 : 0);
  1620. }
  1621. //--------------------------------------------------------------
  1622. int mcman_writecluster(int port, int slot, int cluster, int flag)
  1623. {
  1624. register int r, i, j, page, block, pageword_cnt;
  1625. register u32 erase_value;
  1626. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  1627. block = cluster / mcdi->clusters_per_block;
  1628. if ((mcman_wr_port == port) && (mcman_wr_slot == slot) && (mcman_wr_block == block))
  1629. return mcman_wr_flag3;
  1630. mcman_wr_port = port;
  1631. mcman_wr_slot = slot;
  1632. mcman_wr_block = block;
  1633. mcman_wr_flag3 = -9;
  1634. for (i = 0; i < 16; i++) { // check only 16 bad blocks ?
  1635. if (mcdi->bad_block_list[i] < 0)
  1636. break;
  1637. if (mcdi->bad_block_list[i] == block) {
  1638. mcman_wr_flag3 = 0;
  1639. return sceMcResSucceed;
  1640. }
  1641. }
  1642. if (flag) {
  1643. for (i = 1; i < mcdi->blocksize; i++)
  1644. mcman_pagedata[i] = 0;
  1645. mcman_pagedata[0] = &mcman_pagebuf;
  1646. pageword_cnt = mcdi->pagesize >> 2;
  1647. page = block * mcdi->blocksize;
  1648. if (mcdi->cardflags & CF_ERASE_ZEROES)
  1649. erase_value = 0xffffffff;
  1650. else
  1651. erase_value = 0x00000000;
  1652. for (i = 0; i < pageword_cnt; i++)
  1653. *((u32 *)&mcman_pagebuf + i) = erase_value;
  1654. r = mcman_eraseblock(port, slot, block, (void **)mcman_pagedata, (void *)mcman_eccdata);
  1655. if (r == sceMcResFailReplace)
  1656. return sceMcResSucceed;
  1657. if (r != sceMcResSucceed)
  1658. return sceMcResChangedCard;
  1659. for (i = 1; i < mcdi->blocksize; i++) {
  1660. r = McWritePage(port, slot, page + i, mcman_pagebuf, mcman_eccdata);
  1661. if (r == sceMcResFailReplace)
  1662. return sceMcResSucceed;
  1663. if (r != sceMcResSucceed)
  1664. return sceMcResNoFormat;
  1665. }
  1666. for (i = 1; i < mcdi->blocksize; i++) {
  1667. r = McReadPage(port, slot, page + i, mcman_pagebuf);
  1668. if (r == sceMcResNoFormat)
  1669. return sceMcResSucceed;
  1670. if (r != sceMcResSucceed)
  1671. return sceMcResFullDevice;
  1672. for (j = 0; j < pageword_cnt; j++) {
  1673. if (*((u32 *)&mcman_pagebuf + j) != erase_value) {
  1674. mcman_wr_flag3 = 0;
  1675. return sceMcResSucceed;
  1676. }
  1677. }
  1678. }
  1679. r = mcman_eraseblock(port, slot, block, NULL, NULL);
  1680. if (r != sceMcResSucceed)
  1681. return sceMcResChangedCard;
  1682. r = McWritePage(port, slot, page, mcman_pagebuf, mcman_eccdata);
  1683. if (r == sceMcResFailReplace)
  1684. return sceMcResSucceed;
  1685. if (r != sceMcResSucceed)
  1686. return sceMcResNoFormat;
  1687. r = McReadPage

Large files files are truncated, but you can click here to view the full file