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

/modules/vmc/mcman/ps2mc_io.c

https://bitbucket.org/ifcaro/open-ps2-loader/
C | 1436 lines | 1082 code | 307 blank | 47 comment | 425 complexity | 41215a3118a3f024031fcc9bf7e95ffb 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 char SUPERBLOCK_MAGIC[];
  8. extern char SUPERBLOCK_VERSION[];
  9. extern int mcman_wr_port;
  10. extern int mcman_wr_slot;
  11. extern int mcman_wr_block;
  12. extern int mcman_wr_flag3;
  13. extern int mcman_curdircluster;
  14. extern u32 DOT;
  15. extern u32 DOTDOT;
  16. extern int PS1CardFlag;
  17. //--------------------------------------------------------------
  18. int mcman_format2(int port, int slot)
  19. {
  20. register int r, i, size, ifc_index, indirect_offset, allocatable_clusters_per_card;
  21. register int ifc_length, fat_length, fat_entry, alloc_offset;
  22. register int j = 0, z = 0;
  23. MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  24. McCacheEntry *mce;
  25. #ifdef DEBUG
  26. DPRINTF("mcman: mcman_format2 port%d, slot%d cardform %d\n", port, slot, mcdi->cardform);
  27. #endif
  28. if (mcdi->cardform == sceMcResNoFormat) {
  29. for (i = 0; i < 32; i++)
  30. mcdi->bad_block_list[i] = -1;
  31. mcdi->rootdir_cluster = 0;
  32. mcdi->rootdir_cluster2 = 0;
  33. goto lbl1;
  34. }
  35. if (mcdi->cardform > 0) {
  36. if (((mcdi->version[0] - 48) >= 2) || ((mcdi->version[2] - 48) >= 2))
  37. goto lbl1;
  38. }
  39. r = mcman_reportBadBlocks(port, slot);
  40. if ((r != sceMcResSucceed) && (r != sceMcResNoFormat))
  41. return sceMcResChangedCard;
  42. lbl1:
  43. // set superblock magic & version
  44. memset((void *)&mcdi->magic, 0, sizeof (mcdi->magic) + sizeof (mcdi->version));
  45. *((u32 *)&mcdi->magic ) = *((u32 *)&SUPERBLOCK_MAGIC );
  46. *((u32 *)&mcdi->magic + 1) = *((u32 *)&SUPERBLOCK_MAGIC + 1);
  47. *((u32 *)&mcdi->magic + 2) = *((u32 *)&SUPERBLOCK_MAGIC + 2);
  48. *((u32 *)&mcdi->magic + 3) = *((u32 *)&SUPERBLOCK_MAGIC + 3);
  49. *((u32 *)&mcdi->magic + 4) = *((u32 *)&SUPERBLOCK_MAGIC + 4);
  50. *((u32 *)&mcdi->magic + 5) = *((u32 *)&SUPERBLOCK_MAGIC + 5);
  51. *((u32 *)&mcdi->magic + 6) = *((u32 *)&SUPERBLOCK_MAGIC + 6);
  52. *((u8 *)&mcdi->magic + 28) = *((u8 *)&SUPERBLOCK_MAGIC + 28);
  53. strcat((char *)&mcdi->magic, SUPERBLOCK_VERSION);
  54. //size = 8192 / mcdi->cluster_size; // get blocksize in cluster a better way must be found
  55. size = mcdi->blocksize;
  56. mcdi->cardform = -1;
  57. mcman_wr_port = -1;
  58. mcman_wr_slot = -1;
  59. mcman_wr_block = -1;
  60. mcman_wr_flag3 = -10;
  61. //if (size <= 0)
  62. // size = 1;
  63. if (mcdi->blocksize <= 0)
  64. size = 8;
  65. // clear first 8 clusters
  66. for (i = 0; i < size; i++) {
  67. r = mcman_writecluster(port, slot, i, 1);
  68. if (r == 0)
  69. return sceMcResNoFormat;
  70. if (r != 1)
  71. return -40;
  72. }
  73. fat_length = (((mcdi->clusters_per_card << 2) - 1) / mcdi->cluster_size) + 1; // get length of fat in clusters
  74. ifc_length = (((fat_length << 2) - 1) / mcdi->cluster_size) + 1; // get number of needed ifc clusters
  75. if (!(ifc_length <= 32)) {
  76. ifc_length = 32;
  77. fat_length = mcdi->FATentries_per_cluster << 5;
  78. }
  79. // clear ifc clusters
  80. if (ifc_length > 0) {
  81. j = 0;
  82. do {
  83. if (i >= mcdi->clusters_per_card)
  84. return sceMcResNoFormat;
  85. do {
  86. if (mcman_writecluster(port, slot, i, 1) != 0)
  87. break;
  88. i++;
  89. } while (i < mcdi->clusters_per_card);
  90. if (i >= mcdi->clusters_per_card)
  91. return sceMcResNoFormat;
  92. mcdi->ifc_list[j] = i;
  93. j++;
  94. i++;
  95. } while (j < ifc_length);
  96. }
  97. // read ifc clusters to mc cache and clear fat clusters
  98. if (fat_length > 0) {
  99. j = 0;
  100. do {
  101. ifc_index = j / mcdi->FATentries_per_cluster;
  102. indirect_offset = j % mcdi->FATentries_per_cluster;
  103. if (indirect_offset == 0) {
  104. if (mcman_readcluster(port, slot, mcdi->ifc_list[ifc_index], &mce) != sceMcResSucceed)
  105. return -42;
  106. mce->wr_flag = 1;
  107. }
  108. if (i >= mcdi->clusters_per_card)
  109. return sceMcResNoFormat;
  110. do {
  111. r = mcman_writecluster(port, slot, i, 1);
  112. if (r == 1)
  113. break;
  114. if (r < 0)
  115. return -43;
  116. i++;
  117. } while (i < mcdi->clusters_per_card);
  118. if (i >= mcdi->clusters_per_card)
  119. return sceMcResNoFormat;
  120. j++;
  121. McFatCluster *fc = (McFatCluster *)mce->cl_data;
  122. fc->entry[indirect_offset] = i;
  123. i++;
  124. } while (j < fat_length);
  125. }
  126. alloc_offset = i;
  127. mcdi->backup_block1 = 0;
  128. mcdi->backup_block2 = 0;
  129. // clear backup blocks
  130. for (i = (mcdi->clusters_per_card / mcdi->clusters_per_block) - 1; i > 0; i--) {
  131. r = mcman_writecluster(port, slot, mcdi->clusters_per_block * i, 1);
  132. if (r < 0)
  133. return -44;
  134. if ((r != 0) && (mcdi->backup_block1 == 0))
  135. mcdi->backup_block1 = i;
  136. else if ((r != 0) && (mcdi->backup_block2 == 0)) {
  137. mcdi->backup_block2 = i;
  138. break;
  139. }
  140. }
  141. // set backup block2 to erased state
  142. if (mcman_eraseblock(port, slot, mcdi->backup_block2, NULL, NULL) != sceMcResSucceed)
  143. return -45;
  144. u32 hi, lo, temp;
  145. long_multiply(mcdi->clusters_per_card, 0x10624dd3, &hi, &lo);
  146. temp = (hi >> 6) - (mcdi->clusters_per_card >> 31);
  147. allocatable_clusters_per_card = (((((temp << 5) - temp) << 2) + temp) << 3) + 1;
  148. j = alloc_offset;
  149. // checking for bad allocated clusters and building FAT
  150. if (j < i * mcdi->clusters_per_block) {
  151. z = 0;
  152. do { // quick check for bad clusters
  153. r = mcman_writecluster(port, slot, j, 0);
  154. if (r == 1) {
  155. if (z == 0) {
  156. mcdi->alloc_offset = j;
  157. mcdi->rootdir_cluster = 0;
  158. fat_entry = 0xffffffff; // marking rootdir end
  159. }
  160. else
  161. fat_entry = 0x7fffffff; // marking free cluster
  162. z++;
  163. if (z == allocatable_clusters_per_card)
  164. mcdi->max_allocatable_clusters = (j - mcdi->alloc_offset) + 1;
  165. }
  166. else {
  167. if (r != 0)
  168. return -45;
  169. fat_entry = 0xfffffffd; // marking bad cluster
  170. }
  171. if (mcman_setFATentry(port, slot, j - mcdi->alloc_offset, fat_entry) != sceMcResSucceed)
  172. return -46;
  173. j++;
  174. } while (j < (i * mcdi->clusters_per_block));
  175. }
  176. mcdi->alloc_end = (i * mcdi->clusters_per_block) - mcdi->alloc_offset;
  177. if (mcdi->max_allocatable_clusters == 0)
  178. mcdi->max_allocatable_clusters = i * mcdi->clusters_per_block;
  179. if (z < mcdi->clusters_per_block)
  180. return sceMcResNoFormat;
  181. // read superblock to mc cache
  182. for (i = 0; i < sizeof (MCDevInfo); i += MCMAN_CLUSTERSIZE) {
  183. if (i < 0)
  184. size = i + (MCMAN_CLUSTERSIZE - 1);
  185. else
  186. size = i;
  187. if (mcman_readcluster(port, slot, size >> 10, &mce) != sceMcResSucceed)
  188. return -48;
  189. size = MCMAN_CLUSTERSIZE;
  190. mce->wr_flag = 1;
  191. if ((sizeof (MCDevInfo) - i) <= 1024)
  192. size = sizeof (MCDevInfo) - i;
  193. memcpy((void *)mce->cl_data, (void *)(mcdi + i), size);
  194. }
  195. mcdi->unknown1 = 0;
  196. mcdi->unknown2 = 0;
  197. mcdi->unknown5 = -1;
  198. mcdi->rootdir_cluster2 = mcdi->rootdir_cluster;
  199. // Create root dir
  200. if (mcman_createDirentry(port, slot, 0, 0, 0, NULL) != sceMcResSucceed)
  201. return -49;
  202. // finally flush cache to memcard
  203. r = mcman_flushmccache(port, slot);
  204. if (r != sceMcResSucceed)
  205. return r;
  206. mcdi->cardform = 1;
  207. return sceMcResSucceed;
  208. }
  209. //--------------------------------------------------------------
  210. int mcman_dread2(int fd, fio_dirent_t *dirent)
  211. {
  212. register int r;
  213. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  214. McFsEntry *fse;
  215. #ifdef DEBUG
  216. DPRINTF("mcman: mcman_dread2 fd %d\n", fd);
  217. #endif
  218. if (fh->position >= fh->filesize)
  219. return sceMcResSucceed;
  220. do {
  221. r = mcman_readdirentry(fh->port, fh->slot, fh->freeclink, fh->position, &fse);
  222. if (r != sceMcResSucceed)
  223. return r;
  224. if (fse->mode & sceMcFileAttrExists)
  225. break;
  226. fh->position++;
  227. } while (fh->position < fh->filesize);
  228. if (fh->position >= fh->filesize)
  229. return sceMcResSucceed;
  230. fh->position++;
  231. mcman_wmemset((void *)dirent, sizeof (fio_dirent_t), 0);
  232. strcpy(dirent->name, fse->name);
  233. *(u8 *)&dirent->name[32] = 0;
  234. if (fse->mode & sceMcFileAttrReadable)
  235. dirent->stat.mode |= sceMcFileAttrReadable;
  236. if (fse->mode & sceMcFileAttrWriteable)
  237. dirent->stat.mode |= sceMcFileAttrWriteable;
  238. if (fse->mode & sceMcFileAttrExecutable)
  239. dirent->stat.mode |= sceMcFileAttrExecutable;
  240. if (fse->mode & sceMcFileAttrPS1)
  241. dirent->stat.mode |= sceMcFileAttrPS1;
  242. if (fse->mode & sceMcFileAttrPDAExec)
  243. dirent->stat.mode |= sceMcFileAttrPDAExec;
  244. if (fse->mode & sceMcFileAttrDupProhibit)
  245. dirent->stat.mode |= sceMcFileAttrDupProhibit;
  246. if (fse->mode & sceMcFileAttrSubdir)
  247. dirent->stat.mode |= sceMcFileAttrSubdir;
  248. else
  249. dirent->stat.mode |= sceMcFileAttrFile;
  250. dirent->stat.attr = fse->attr;
  251. dirent->stat.size = fse->length;
  252. *((u32 *)&dirent->stat.ctime ) = *((u32 *)&fse->created );
  253. *((u32 *)&dirent->stat.ctime+1) = *((u32 *)&fse->created+1);
  254. *((u32 *)&dirent->stat.mtime ) = *((u32 *)&fse->modified );
  255. *((u32 *)&dirent->stat.mtime+1) = *((u32 *)&fse->modified+1);
  256. return 1;
  257. }
  258. //--------------------------------------------------------------
  259. int mcman_getstat2(int port, int slot, char *filename, fio_stat_t *stat)
  260. {
  261. register int r;
  262. McFsEntry *fse;
  263. #ifdef DEBUG
  264. DPRINTF("mcman: mcman_getstat2 port%d slot%d filename %s\n", port, slot, filename);
  265. #endif
  266. r = mcman_cachedirentry(port, slot, filename, NULL, &fse, 1);
  267. if (r != sceMcResSucceed)
  268. return r;
  269. mcman_wmemset((void *)stat, sizeof (fio_stat_t), 0);
  270. if (fse->mode & sceMcFileAttrReadable)
  271. stat->mode |= sceMcFileAttrReadable;
  272. if (fse->mode & sceMcFileAttrWriteable)
  273. stat->mode |= sceMcFileAttrWriteable;
  274. if (fse->mode & sceMcFileAttrExecutable)
  275. stat->mode |= sceMcFileAttrExecutable;
  276. if (fse->mode & sceMcFileAttrPS1)
  277. stat->mode |= sceMcFileAttrPS1;
  278. if (fse->mode & sceMcFileAttrPDAExec)
  279. stat->mode |= sceMcFileAttrPDAExec;
  280. if (fse->mode & sceMcFileAttrDupProhibit)
  281. stat->mode |= sceMcFileAttrDupProhibit;
  282. if (fse->mode & sceMcFileAttrSubdir)
  283. stat->mode |= sceMcFileAttrSubdir;
  284. else
  285. stat->mode |= sceMcFileAttrFile;
  286. stat->attr = fse->attr;
  287. if (!(fse->mode & sceMcFileAttrSubdir))
  288. stat->size = fse->length;
  289. *((u32 *)&stat->ctime ) = *((u32 *)&fse->created );
  290. *((u32 *)&stat->ctime+1) = *((u32 *)&fse->created+1);
  291. *((u32 *)&stat->mtime ) = *((u32 *)&fse->modified );
  292. *((u32 *)&stat->mtime+1) = *((u32 *)&fse->modified+1);
  293. return sceMcResSucceed;
  294. }
  295. //--------------------------------------------------------------
  296. int mcman_setinfo2(int port, int slot, char *filename, sceMcTblGetDir *info, int flags)
  297. {
  298. register int r, fmode;
  299. McFsEntry *fse;
  300. McCacheDir dirInfo;
  301. McFsEntry mfe;
  302. u8 *pfsentry, *pfseend, *mfee;
  303. #ifdef DEBUG
  304. DPRINTF("mcman: mcman_setinfo2 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
  305. #endif
  306. r = mcman_cachedirentry(port, slot, filename, &dirInfo, &fse, 1); //dirInfo=sp218 fse=sp228
  307. if (r != sceMcResSucceed)
  308. return r;
  309. if ((flags & sceMcFileAttrFile) != 0) {
  310. if ((!strcmp(".", info->EntryName)) || (!strcmp("..", info->EntryName)))
  311. return sceMcResNoEntry;
  312. if (info->EntryName[0] == 0)
  313. return sceMcResNoEntry;
  314. r = mcman_chrpos(info->EntryName, '/');
  315. if (r >= 0)
  316. return sceMcResNoEntry;
  317. if (dirInfo.fsindex < 2)
  318. return sceMcResNoEntry;
  319. r = mcman_readdirentry(port, slot, dirInfo.cluster, 0, &fse);
  320. if (r != sceMcResSucceed)
  321. return r;
  322. r = mcman_readdirentry(port, slot, fse->cluster, fse->dir_entry, &fse);
  323. if (r != sceMcResSucceed)
  324. return r;
  325. pfsentry = (u8 *)fse;
  326. mfee = (u8 *)&mfe;
  327. pfseend = (u8 *)(pfsentry + sizeof (McFsEntry));
  328. do {
  329. *((u32 *)mfee ) = *((u32 *)pfsentry );
  330. *((u32 *)mfee+1) = *((u32 *)pfsentry+1);
  331. *((u32 *)mfee+2) = *((u32 *)pfsentry+2);
  332. *((u32 *)mfee+3) = *((u32 *)pfsentry+3);
  333. pfsentry += 16;
  334. mfee += 16;
  335. } while (pfsentry < pfseend);
  336. r = mcman_getdirinfo(port, slot, &mfe, info->EntryName, NULL, 1);
  337. if (r != 1) {
  338. if (r < 2) {
  339. if (r == 0)
  340. return sceMcResNoEntry;
  341. return r;
  342. }
  343. else {
  344. if (r != 2)
  345. return r;
  346. return sceMcResDeniedPermit;
  347. }
  348. }
  349. }
  350. r = mcman_readdirentry(port, slot, dirInfo.cluster, dirInfo.fsindex, &fse);
  351. if (r != sceMcResSucceed)
  352. return r;
  353. mcman_1stcacheEntsetwrflagoff();
  354. //Special fix clause for file managers (like uLaunchELF)
  355. //This allows writing most entries that can be read by mcGetDir
  356. //and without usual restrictions. This flags value should cause no conflict
  357. //as Sony code never uses it, and the value is changed after its use here.
  358. if(flags == 0xFEED){
  359. fse->mode = info->AttrFile;
  360. //fse->unused = info->Reserve1;
  361. //fse->length = info->FileSizeByte;
  362. flags = sceMcFileAttrReadable|sceMcFileAttrWriteable;
  363. //The changed flags value allows more entries to be copied below
  364. }
  365. if ((flags & sceMcFileAttrDupProhibit) != 0)
  366. fse->attr = info->Reserve2;
  367. if ((flags & sceMcFileAttrExecutable) != 0) {
  368. fmode = 0xffff7fcf;
  369. if (!PS1CardFlag)
  370. fmode = 0x180f;
  371. fse->mode = (fse->mode & ~fmode) | (info->AttrFile & fmode);
  372. }
  373. if ((flags & sceMcFileCreateFile) != 0) {
  374. fmode = 0x380f;
  375. if (!PS1CardFlag)
  376. fmode = 0x180f;
  377. fse->mode = (fse->mode & ~fmode) | (info->AttrFile & fmode);
  378. }
  379. if ((flags & sceMcFileAttrReadable) != 0)
  380. fse->created = info->_Create;
  381. if ((flags & sceMcFileAttrWriteable) != 0)
  382. fse->modified = info->_Modify;
  383. if ((flags & sceMcFileAttrFile) != 0) {
  384. strncpy(fse->name, info->EntryName, 32);
  385. fse->name[31] = 0;
  386. }
  387. return sceMcResSucceed;
  388. }
  389. //--------------------------------------------------------------
  390. int mcman_read2(int fd, void *buffer, int nbyte)
  391. {
  392. register int r, temp, rpos, size, offset;
  393. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  394. register MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
  395. McCacheEntry *mce;
  396. #ifdef DEBUG
  397. DPRINTF("mcman: mcman_read2 fd %d buf %x size %d\n", fd, (int)buffer, nbyte);
  398. #endif
  399. if (fh->position < fh->filesize) {
  400. temp = fh->filesize - fh->position;
  401. if (nbyte > temp)
  402. nbyte = temp;
  403. rpos = 0;
  404. if (nbyte > 0) {
  405. do {
  406. offset = fh->position % mcdi->cluster_size; // file pointer offset % cluster size
  407. temp = mcdi->cluster_size - offset;
  408. if (temp < nbyte)
  409. size = temp;
  410. else
  411. size = nbyte;
  412. r = mcman_fatRseek(fd);
  413. if (r <= 0)
  414. return r;
  415. r = mcman_readcluster(fh->port, fh->slot, r, &mce);
  416. if (r != sceMcResSucceed)
  417. return r;
  418. memcpy((void *)(buffer + rpos), (void *)(mce->cl_data + offset), size);
  419. rpos += size;
  420. mce->rd_flag = 1;
  421. nbyte -= size;
  422. fh->position += size;
  423. } while (nbyte);
  424. }
  425. return rpos;
  426. }
  427. return 0;
  428. }
  429. //--------------------------------------------------------------
  430. int mcman_write2(int fd, void *buffer, int nbyte)
  431. {
  432. register int r, r2, wpos, size, offset;
  433. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  434. register MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
  435. McCacheEntry *mce;
  436. if (nbyte) {
  437. if (fh->unknown2 == 0) {
  438. fh->unknown2 = 1;
  439. r = mcman_close2(fd);
  440. if (r != sceMcResSucceed)
  441. return r;
  442. r = mcman_flushmccache(fh->port, fh->slot);
  443. if (r != sceMcResSucceed)
  444. return r;
  445. }
  446. }
  447. wpos = 0;
  448. if (nbyte) {
  449. do {
  450. r = mcman_fatRseek(fd);
  451. if (r == sceMcResFullDevice) {
  452. r2 = mcman_fatWseek(fd);
  453. if (r2 == r)
  454. return sceMcResFullDevice;
  455. if (r2 != sceMcResSucceed)
  456. return r2;
  457. r = mcman_fatRseek(fd);
  458. }
  459. else {
  460. if (r < 0)
  461. return r;
  462. }
  463. r = mcman_readcluster(fh->port, fh->slot, r, &mce);
  464. if (r != sceMcResSucceed)
  465. return r;
  466. mce->rd_flag = 1;
  467. offset = fh->position % mcdi->cluster_size; // file pointer offset % cluster size
  468. r2 = mcdi->cluster_size - offset;
  469. if (r2 < nbyte)
  470. size = r2;
  471. else
  472. size = nbyte;
  473. memcpy((void *)(mce->cl_data + offset), (void *)(buffer + wpos), size);
  474. mce->wr_flag = 1;
  475. r = fh->position + size;
  476. fh->position += size;
  477. if (r < fh->filesize)
  478. r = fh->filesize ;
  479. fh->filesize = r;
  480. nbyte -= size;
  481. wpos += size;
  482. } while (nbyte);
  483. }
  484. r = mcman_close2(fd);
  485. if (r != sceMcResSucceed)
  486. return r;
  487. return wpos;
  488. }
  489. //--------------------------------------------------------------
  490. int mcman_close2(int fd)
  491. {
  492. register int r, fmode;
  493. register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  494. McFsEntry *fse1, *fse2;
  495. #ifdef DEBUG
  496. DPRINTF("mcman: mcman_close2 fd %d\n", fd);
  497. #endif
  498. r = mcman_readdirentry(fh->port, fh->slot, fh->field_20, fh->field_24, &fse1);
  499. if (r != sceMcResSucceed)
  500. return -31;
  501. if (fh->unknown2 == 0) {
  502. fmode = fse1->mode | sceMcFileAttrClosed;
  503. }
  504. else {
  505. fmode = fse1->mode & 0xff7f;
  506. }
  507. fse1->mode = fmode;
  508. mcman_getmcrtime(&fse1->modified);
  509. fse1->cluster = fh->freeclink;
  510. fse1->length = fh->filesize;
  511. mcman_1stcacheEntsetwrflagoff();
  512. mcman_fsmodtime = fse1->modified;
  513. r = mcman_readdirentry(fh->port, fh->slot, fh->field_28, fh->field_2C, &fse2);
  514. if (r != sceMcResSucceed)
  515. return r;
  516. fse2->modified = mcman_fsmodtime;
  517. mcman_1stcacheEntsetwrflagoff();
  518. return sceMcResSucceed;
  519. }
  520. //--------------------------------------------------------------
  521. int mcman_open2(int port, int slot, char *filename, int flags)
  522. {
  523. register int fd, i, r, fsindex, fsoffset, fat_index, rdflag, wrflag, pos, mcfree;
  524. register MC_FHANDLE *fh, *fh2;
  525. register MCDevInfo *mcdi;
  526. McCacheDir cacheDir;
  527. McFsEntry *fse1, *fse2;
  528. McCacheEntry *mce;
  529. u8 *p, *pfsentry, *pcache, *pfseend;
  530. int fat_entry;
  531. #ifdef DEBUG
  532. DPRINTF("mcman: mcman_open2 port%d slot%d name %s flags %x\n", port, slot, filename, flags);
  533. #endif
  534. if ((flags & sceMcFileCreateFile) != 0)
  535. flags |= sceMcFileAttrWriteable; // s5
  536. //if (!mcman_checkpath(filename))
  537. // return sceMcResNoEntry;
  538. if (filename[0] == 0)
  539. return sceMcResNoEntry;
  540. fd = 0;
  541. do {
  542. fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
  543. if (fh->status == 0)
  544. break;
  545. } while (++fd < MAX_FDHANDLES);
  546. if (fd == MAX_FDHANDLES)
  547. return sceMcResUpLimitHandle;
  548. fh = (MC_FHANDLE *)&mcman_fdhandles[fd]; // s2
  549. mcman_wmemset((void *)fh, sizeof (MC_FHANDLE), 0);
  550. mcdi = (MCDevInfo *)&mcman_devinfos[port][slot]; // s3
  551. if ((flags & (sceMcFileCreateFile | sceMcFileCreateDir)) == 0)
  552. cacheDir.maxent = -1; //sp20
  553. else
  554. cacheDir.maxent = 0; //sp20
  555. //fse1 = sp28
  556. //sp18 = cacheDir
  557. fse1 = NULL;
  558. r = mcman_cachedirentry(port, slot, filename, &cacheDir, &fse1, 1);
  559. if (r < 0)
  560. return r;
  561. if (fse1) {
  562. pfsentry = (u8 *)fse1;
  563. pcache = (u8 *)&mcman_dircache[1];
  564. pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
  565. do {
  566. *((u32 *)pcache ) = *((u32 *)pfsentry );
  567. *((u32 *)pcache+1) = *((u32 *)pfsentry+1);
  568. *((u32 *)pcache+2) = *((u32 *)pfsentry+2);
  569. *((u32 *)pcache+3) = *((u32 *)pfsentry+3);
  570. pfsentry += 16;
  571. pcache += 16;
  572. } while (pfsentry < pfseend);
  573. }
  574. if ((flags == 0) && ((fse1->mode & sceMcFileAttrExists) == 0))
  575. r = 1;
  576. if (r == 2)
  577. return sceMcResNoEntry;
  578. if (r == 3)
  579. return sceMcResDeniedPermit;
  580. if ((r == 0) && ((flags & sceMcFileCreateDir) != 0))
  581. return sceMcResNoEntry;
  582. if ((r == 1) && ((flags & (sceMcFileCreateFile | sceMcFileCreateDir)) == 0))
  583. return sceMcResNoEntry;
  584. rdflag = flags & sceMcFileAttrReadable;
  585. wrflag = flags & sceMcFileAttrWriteable;
  586. fh->freeclink = -1;
  587. fh->clink = -1;
  588. fh->clust_offset = 0;
  589. fh->filesize = 0;
  590. fh->position = 0;
  591. fh->port = port;
  592. fh->slot = slot;
  593. fh->unknown2 = 0;
  594. fh->rdflag = rdflag;
  595. fh->wrflag = wrflag;
  596. fh->unknown1 = 0;
  597. fh->field_20 = cacheDir.cluster;
  598. fh->field_24 = cacheDir.fsindex;
  599. // fse2 = sp2c
  600. if (r == 0) {
  601. if ((wrflag != 0) && ((mcman_dircache[1].mode & sceMcFileAttrWriteable) == 0))
  602. return sceMcResDeniedPermit;
  603. if (!PS1CardFlag) {
  604. if ((flags & sceMcFileAttrReadable) != 0) {
  605. if ((mcman_dircache[1].mode & sceMcFileAttrReadable) == 0)
  606. return sceMcResDeniedPermit;
  607. }
  608. }
  609. r = mcman_readdirentry(port, slot, cacheDir.cluster, 0, &fse2);
  610. if (r != sceMcResSucceed)
  611. return r;
  612. fh->field_28 = fse2->cluster;
  613. fh->field_2C = fse2->dir_entry;
  614. if ((mcman_dircache[1].mode & sceMcFileAttrSubdir) != 0) {
  615. if ((mcman_dircache[1].mode & sceMcFileAttrReadable) == 0)
  616. return sceMcResDeniedPermit;
  617. fh->freeclink = mcman_dircache[1].cluster;
  618. fh->rdflag = 0;
  619. fh->wrflag = 0;
  620. fh->unknown1 = 0;
  621. fh->drdflag = 1;
  622. fh->status = 1;
  623. fh->filesize = mcman_dircache[1].length;
  624. fh->clink = fh->freeclink;
  625. return fd;
  626. }
  627. if ((flags & sceMcFileAttrWriteable) != 0) {
  628. i = 0;
  629. do {
  630. fh2 = (MC_FHANDLE *)&mcman_fdhandles[i];
  631. if ((fh2->status == 0) || (fh2->port != port) || (fh2->slot != slot) \
  632. || (fh2->field_20 != cacheDir.cluster) || (fh2->field_24 != cacheDir.fsindex))
  633. continue;
  634. if (fh2->wrflag != 0)
  635. return sceMcResDeniedPermit;
  636. } while (++i < MAX_FDHANDLES);
  637. }
  638. if ((flags & sceMcFileCreateFile) != 0) {
  639. r = mcman_setdirentrystate(port, slot, cacheDir.cluster, cacheDir.fsindex, 0);
  640. mcman_flushmccache(port, slot);
  641. if (r != sceMcResSucceed)
  642. return -43;
  643. if (cacheDir.fsindex < cacheDir.maxent)
  644. cacheDir.maxent = cacheDir.fsindex;
  645. }
  646. else {
  647. fh->freeclink = mcman_dircache[1].cluster;
  648. fh->filesize = mcman_dircache[1].length;
  649. fh->clink = fh->freeclink;
  650. if (fh->rdflag != 0)
  651. fh->rdflag = (*((u8 *)&mcman_dircache[1].mode)) & sceMcFileAttrReadable;
  652. else
  653. fh->rdflag = 0;
  654. if (fh->wrflag != 0)
  655. fh->wrflag = (mcman_dircache[1].mode >> 1) & sceMcFileAttrReadable;
  656. else
  657. fh->wrflag = 0;
  658. fh->status = 1;
  659. return fd;
  660. }
  661. }
  662. else {
  663. fh->field_28 = cacheDir.cluster;
  664. fh->field_2C = cacheDir.fsindex;
  665. }
  666. r = mcman_readdirentry(port, slot, fh->field_28, fh->field_2C, &fse1);
  667. if (r != sceMcResSucceed)
  668. return r;
  669. pfsentry = (u8 *)fse1;
  670. pcache = (u8 *)&mcman_dircache[2];
  671. pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
  672. do {
  673. *((u32 *)pcache ) = *((u32 *)pfsentry );
  674. *((u32 *)pcache+1) = *((u32 *)pfsentry+1);
  675. *((u32 *)pcache+2) = *((u32 *)pfsentry+2);
  676. *((u32 *)pcache+3) = *((u32 *)pfsentry+3);
  677. pfsentry += 16;
  678. pcache += 16;
  679. } while (pfsentry < pfseend);
  680. i = -1;
  681. if (mcman_dircache[2].length == cacheDir.maxent) {
  682. fsindex = mcman_dircache[2].length / (mcdi->cluster_size >> 9); //v1
  683. fsoffset = mcman_dircache[2].length % (mcdi->cluster_size >> 9); //v0
  684. if (fsoffset == 0) {
  685. fat_index = mcman_dircache[2].cluster;
  686. i = fsindex;
  687. if ((mcman_dircache[2].cluster == 0) && (i >= 2)) {
  688. if (mcman_getFATindex(port, slot, i - 1) >= 0) {
  689. fat_index = mcman_getFATindex(port, slot, i - 1); // s3
  690. i = 1;
  691. }
  692. }
  693. i--;
  694. if (i != -1) {
  695. do {
  696. r = mcman_getFATentry(port, slot, fat_index, &fat_entry);
  697. if (r != sceMcResSucceed)
  698. return r;
  699. if (fat_entry >= -1) {
  700. r = mcman_findfree2(port, slot, 1);
  701. if (r < 0)
  702. return r;
  703. fat_entry = r;
  704. mce = mcman_get1stcacheEntp(); // s4
  705. fat_entry |= 0x80000000;
  706. r = mcman_setFATentry(port, slot, fat_index, fat_entry);
  707. if (r != sceMcResSucceed)
  708. return r;
  709. mcman_addcacheentry(mce);
  710. }
  711. i--;
  712. fat_index = fat_entry & 0x7fffffff;
  713. } while (i != -1);
  714. }
  715. }
  716. r = mcman_flushmccache(port, slot);
  717. if (r != sceMcResSucceed)
  718. return r;
  719. i = -1;
  720. mcman_dircache[2].length++;
  721. }
  722. do {
  723. p = (u8 *)(filename + i + 1);
  724. pos = i + 1;
  725. r = mcman_chrpos(p, '/');
  726. if (r < 0)
  727. break;
  728. i = pos + r;
  729. } while (1);
  730. p = (char *)(filename + pos);
  731. mcfree = 0;
  732. if ((flags & sceMcFileCreateDir) != 0) {
  733. r = mcman_findfree2(port, slot, 1); // r = s3
  734. if (r < 0)
  735. return r;
  736. mcfree = r;
  737. }
  738. mce = mcman_get1stcacheEntp(); // mce = s4
  739. mcman_getmcrtime(&mcman_dircache[2].modified);
  740. r = mcman_readdirentry(port, slot, mcman_dircache[2].cluster, cacheDir.maxent, &fse2);
  741. if (r != sceMcResSucceed)
  742. return r;
  743. mcman_wmemset((void *)fse2, sizeof (McFsEntry), 0);
  744. strncpy((void *)fse2->name, p, 32);
  745. fse2->created = mcman_dircache[2].modified;
  746. fse2->modified = mcman_dircache[2].modified;
  747. mcman_1stcacheEntsetwrflagoff();
  748. mcman_addcacheentry(mce);
  749. if (!PS1CardFlag)
  750. flags &= 0xffffdfff;
  751. if ((flags & sceMcFileCreateDir) != 0) {
  752. fse2->mode = ((flags & sceMcFileAttrHidden) | sceMcFileAttrReadable | sceMcFileAttrWriteable \
  753. | sceMcFileAttrExecutable | sceMcFileAttrSubdir | sceMcFile0400 | sceMcFileAttrExists) // 0x8427
  754. | (flags & (sceMcFileAttrPS1 | sceMcFileAttrPDAExec));
  755. fse2->length = 2;
  756. fse2->cluster = mcfree;
  757. r = mcman_createDirentry(port, slot, mcman_dircache[2].cluster, cacheDir.maxent, mcfree, (sceMcStDateTime *)&fse2->created);
  758. if (r != sceMcResSucceed)
  759. return -46;
  760. r = mcman_readdirentry(port, slot, fh->field_28, fh->field_2C, &fse1);
  761. if (r != sceMcResSucceed)
  762. return r;
  763. pfsentry = (u8 *)fse1;
  764. pcache = (u8 *)&mcman_dircache[2];
  765. pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
  766. do {
  767. *((u32 *)pfsentry ) = *((u32 *)pcache );
  768. *((u32 *)pfsentry+1) = *((u32 *)pcache+1);
  769. *((u32 *)pfsentry+2) = *((u32 *)pcache+2);
  770. *((u32 *)pfsentry+3) = *((u32 *)pcache+3);
  771. pfsentry += 16;
  772. pcache += 16;
  773. } while (pfsentry < pfseend);
  774. mcman_1stcacheEntsetwrflagoff();
  775. r = mcman_flushmccache(port, slot);
  776. if (r != sceMcResSucceed)
  777. return r;
  778. return sceMcResSucceed;
  779. }
  780. else {
  781. fse2->mode = ((flags & sceMcFileAttrHidden) | sceMcFileAttrReadable | sceMcFileAttrWriteable \
  782. | sceMcFileAttrExecutable | sceMcFileAttrFile | sceMcFile0400 | sceMcFileAttrExists) // 0x8417
  783. | (flags & (sceMcFileAttrPS1 | sceMcFileAttrPDAExec));
  784. fse2->cluster = -1;
  785. fh->field_20 = mcman_dircache[2].cluster;
  786. fh->status = 1;
  787. fh->field_24 = cacheDir.maxent;
  788. r = mcman_readdirentry(port, slot, fh->field_28, fh->field_2C, &fse1);
  789. if (r != sceMcResSucceed)
  790. return r;
  791. pfsentry = (u8 *)fse1;
  792. pcache = (u8 *)&mcman_dircache[2];
  793. pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
  794. do {
  795. *((u32 *)pfsentry ) = *((u32 *)pcache );
  796. *((u32 *)pfsentry+1) = *((u32 *)pcache+1);
  797. *((u32 *)pfsentry+2) = *((u32 *)pcache+2);
  798. *((u32 *)pfsentry+3) = *((u32 *)pcache+3);
  799. pfsentry += 16;
  800. pcache += 16;
  801. } while (pfsentry < pfseend);
  802. mcman_1stcacheEntsetwrflagoff();
  803. r = mcman_flushmccache(port, slot);
  804. if (r != sceMcResSucceed)
  805. return r;
  806. }
  807. return fd;
  808. }
  809. //--------------------------------------------------------------
  810. int mcman_chdir(int port, int slot, char *newdir, char *currentdir)
  811. {
  812. register int r, len, len2, cluster;
  813. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  814. McCacheDir cacheDir;
  815. McFsEntry *fse;
  816. #ifdef DEBUG
  817. DPRINTF("mcman: mcman_chdir port%d slot%d newdir %s\n", port, slot, newdir);
  818. #endif
  819. //if (!mcman_checkpath(newdir))
  820. // return sceMcResNoEntry;
  821. cacheDir.maxent = -1;
  822. r = mcman_cachedirentry(port, slot, newdir, &cacheDir, &fse, 1);
  823. if (r < 0)
  824. return r;
  825. if (((u32)(r - 1)) < 2)
  826. return sceMcResNoEntry;
  827. mcdi->rootdir_cluster2 = cacheDir.cluster;
  828. mcdi->unknown1 = cacheDir.fsindex;
  829. cluster = cacheDir.cluster;
  830. if (!strcmp(fse->name, "..")) {
  831. r = mcman_readdirentry(port, slot, cluster, 0, &fse);
  832. if (r != sceMcResSucceed)
  833. return r;
  834. }
  835. if (!strcmp(fse->name, ".")) {
  836. mcdi->rootdir_cluster2 = fse->cluster;
  837. mcdi->unknown1 = fse->dir_entry;
  838. cluster = fse->cluster;
  839. r = mcman_readdirentry(port, slot, cluster, fse->dir_entry, &fse);
  840. if (r != sceMcResSucceed)
  841. return r;
  842. }
  843. currentdir[0] = 0;
  844. lbl1:
  845. if (strcmp(fse->name, ".")) {
  846. if (strlen(fse->name) < 32)
  847. len = strlen(fse->name);
  848. else
  849. len = 32;
  850. if (strlen(currentdir)) {
  851. len2 = strlen(currentdir);
  852. if (len2 >= 0) {
  853. do {
  854. currentdir[1 + len2 + len] = currentdir[len2];
  855. } while (--len2 >= 0);
  856. }
  857. currentdir[len] = '/';
  858. strncpy(currentdir, fse->name, len);
  859. }
  860. else {
  861. strncpy(currentdir, fse->name, 32);
  862. currentdir[32] = 0;
  863. }
  864. r = mcman_readdirentry(port, slot, cluster, 0, &fse);
  865. if (r != sceMcResSucceed)
  866. return r;
  867. r = mcman_readdirentry(port, slot, fse->cluster, fse->dir_entry, &fse);
  868. if (r == sceMcResSucceed)
  869. goto lbl1;
  870. return r;
  871. }
  872. else {
  873. strlen(fse->name);
  874. len = strlen(currentdir);
  875. if (len >= 0) {
  876. do {
  877. currentdir[1 + len] = currentdir[len];
  878. } while (--len >= 0);
  879. }
  880. currentdir[0] = '/';
  881. r = sceMcResSucceed;
  882. }
  883. return sceMcResSucceed;
  884. }
  885. //--------------------------------------------------------------
  886. int mcman_getdir2(int port, int slot, char *dirname, int flags, int maxent, sceMcTblGetDir *info)
  887. {
  888. register int r, pos, nument;
  889. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  890. McFsEntry *fse;
  891. char *p;
  892. #ifdef DEBUG
  893. DPRINTF("mcman: mcman_getdir2 port%d slot%d dir=%s flags=%d maxent=%d\n", port, slot, dirname, flags, maxent);
  894. #endif
  895. nument = 0;
  896. flags &= 0xffff;
  897. if (!flags) {
  898. p = (char *)mcman_curdirpath;
  899. strncpy(p, dirname, 1023);
  900. mcman_curdirpath[1023] = 0;
  901. pos = -1; // s1
  902. p++; //s0
  903. do {
  904. r = mcman_chrpos((void *)&p[pos], '/');
  905. if (r < 0)
  906. break;
  907. pos += 1 + r;
  908. } while (1);
  909. if (pos <= 0) {
  910. if (pos == 0)
  911. *p = 0;
  912. else
  913. p[-1] = 0;
  914. }
  915. else {
  916. mcman_curdirpath[pos] = 0;
  917. }
  918. mcman_curdirname = &dirname[pos] + 1;
  919. r = mcman_cachedirentry(port, slot, mcman_curdirpath, NULL, &fse, 1);
  920. if (r > 0)
  921. return sceMcResNoEntry;
  922. if (r < 0)
  923. return r;
  924. if (!(fse->mode & sceMcFileAttrSubdir)) {
  925. mcman_curdircluster = -1;
  926. return sceMcResNoEntry;
  927. }
  928. mcman_curdircluster = fse->cluster;
  929. mcman_curdirlength = fse->length;
  930. if ((fse->cluster == mcdi->rootdir_cluster) && (fse->dir_entry == 0))
  931. mcman_curdirmaxent = 2;
  932. else
  933. mcman_curdirmaxent = 0;
  934. }
  935. else {
  936. if (mcman_curdircluster < 0)
  937. return sceMcResNoEntry;
  938. }
  939. if (maxent != 0) {
  940. do {
  941. if (mcman_curdirmaxent >= mcman_curdirlength)
  942. break;
  943. r = mcman_readdirentry(port, slot, mcman_curdircluster, mcman_curdirmaxent, &fse);
  944. if (r != sceMcResSucceed)
  945. return r;
  946. mcman_curdirmaxent++;
  947. if (!(fse->mode & sceMcFileAttrExists))
  948. continue;
  949. if ((fse->mode & sceMcFileAttrHidden) && (!PS1CardFlag))
  950. continue;
  951. if (!mcman_checkdirpath(fse->name, mcman_curdirname))
  952. continue;
  953. mcman_wmemset((void *)info, sizeof (sceMcTblGetDir), 0);
  954. if (mcman_curdirmaxent == 2) {
  955. r = mcman_readdirentry(port, slot, mcman_curdircluster, 0, &fse);
  956. if (r != sceMcResSucceed)
  957. return r;
  958. r = mcman_readdirentry(port, slot, fse->cluster, 0, &fse);
  959. if (r != sceMcResSucceed)
  960. return r;
  961. r = mcman_readdirentry(port, slot, fse->cluster, fse->dir_entry, &fse);
  962. if (r != sceMcResSucceed)
  963. return r;
  964. *(u16 *)&info->EntryName = *(u16 *)&DOTDOT;
  965. *(u8 *)&info->EntryName[2] = *((u8 *)&DOTDOT+2);
  966. }
  967. else if (mcman_curdirmaxent == 1) {
  968. r = mcman_readdirentry(port, slot, mcman_curdircluster, 0, &fse);
  969. if (r != sceMcResSucceed)
  970. return r;
  971. r = mcman_readdirentry(port, slot, fse->cluster, fse->dir_entry, &fse);
  972. if (r != sceMcResSucceed)
  973. return r;
  974. *(u16 *)&info->EntryName = *(u16 *)&DOT;
  975. }
  976. else {
  977. strncpy(info->EntryName, fse->name, 32);
  978. }
  979. info->AttrFile = fse->mode;
  980. info->Reserve1 = fse->unused;
  981. info->_Create = fse->created;
  982. info->_Modify = fse->modified;
  983. if (!(fse->mode & sceMcFileAttrSubdir))
  984. info->FileSizeByte = fse->length;
  985. nument++;
  986. maxent--;
  987. info++;
  988. } while (maxent);
  989. }
  990. return nument;
  991. }
  992. //--------------------------------------------------------------
  993. int mcman_delete2(int port, int slot, char *filename, int flags)
  994. {
  995. register int r, i;
  996. McCacheDir cacheDir;
  997. McFsEntry *fse1, *fse2;
  998. #ifdef DEBUG
  999. DPRINTF("mcman: mcman_delete2 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
  1000. #endif
  1001. //if (!mcman_checkpath(filename))
  1002. // return sceMcResNoEntry;
  1003. r = mcman_cachedirentry(port, slot, filename, &cacheDir, &fse1, ((u32)(flags < 1)) ? 1 : 0);
  1004. if (r > 0)
  1005. return sceMcResNoEntry;
  1006. if (r < 0)
  1007. return r;
  1008. if (!flags) {
  1009. if (!(fse1->mode & sceMcFileAttrExists))
  1010. return sceMcResNoEntry;
  1011. }
  1012. else {
  1013. if (fse1->mode & sceMcFileAttrExists)
  1014. return sceMcResNoEntry;
  1015. }
  1016. if ((!PS1CardFlag) && (!flags)) {
  1017. if (!(fse1->mode & sceMcFileAttrWriteable))
  1018. return sceMcResDeniedPermit;
  1019. }
  1020. if ((!fse1->cluster) && (!fse1->dir_entry))
  1021. return sceMcResNoEntry;
  1022. i = 2;
  1023. if ((!flags) && (fse1->mode & sceMcFileAttrSubdir) && (i < fse1->length)) {
  1024. do {
  1025. r = mcman_readdirentry(port, slot, fse1->cluster, i, &fse2);
  1026. if (r != sceMcResSucceed)
  1027. return r;
  1028. if (fse2->mode & sceMcFileAttrExists)
  1029. return sceMcResNotEmpty;
  1030. } while (++i < fse1->length);
  1031. }
  1032. r = mcman_setdirentrystate(port, slot, cacheDir.cluster, cacheDir.fsindex, flags);
  1033. if (r != sceMcResSucceed)
  1034. return r;
  1035. r = mcman_flushmccache(port, slot);
  1036. if (r != sceMcResSucceed)
  1037. return r;
  1038. return sceMcResSucceed;
  1039. }
  1040. //--------------------------------------------------------------
  1041. int mcman_unformat2(int port, int slot)
  1042. {
  1043. register int r, i, j, z, l, pageword_cnt, page, blocks_on_card, erase_byte, err_cnt;
  1044. register u32 erase_value;
  1045. register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
  1046. #ifdef DEBUG
  1047. DPRINTF("mcman: mcman_unformat2 port%d slot%d\n", port, slot);
  1048. #endif
  1049. pageword_cnt = mcdi->pagesize >> 2;
  1050. blocks_on_card = mcdi->clusters_per_card / mcdi->clusters_per_block; //sp18
  1051. erase_value = 0xffffffff; //s6
  1052. if (!(mcdi->cardflags & CF_ERASE_ZEROES))
  1053. erase_value = 0x00000000;
  1054. for (i = 0; i < pageword_cnt; i++)
  1055. *((u32 *)&mcman_pagebuf + i) = erase_value;
  1056. for (i = 0; i < 128; i++)
  1057. *((u32 *)&mcman_eccdata + i) = erase_value;
  1058. i = 1;
  1059. if (i < blocks_on_card) {
  1060. erase_byte = erase_value & 0xff; // sp20
  1061. do {
  1062. page = i * mcdi->blocksize;
  1063. if (mcdi->cardform > 0) {
  1064. j = 0;
  1065. for (j = 0; j < 16; j++) {
  1066. if (mcdi->bad_block_list[j] <= 0) {
  1067. j = 16;
  1068. goto lbl1;
  1069. }
  1070. if (mcdi->bad_block_list[j] == i)
  1071. goto lbl1;
  1072. }
  1073. }
  1074. else {
  1075. err_cnt = 0;
  1076. j = -1;
  1077. z = 0;
  1078. if (mcdi->blocksize > 0) {
  1079. do {
  1080. r = McReadPage(port, slot, page + z, mcman_pagebuf);
  1081. if (r == sceMcResNoFormat) {
  1082. j = -2;
  1083. break;
  1084. }
  1085. if (r != sceMcResSucceed)
  1086. return -42;
  1087. if ((mcdi->cardflags & CF_USE_ECC) == 0) {
  1088. for (l = 0; l < mcdi->pagesize; l++) {
  1089. if (mcman_pagebuf[l] != erase_byte)
  1090. err_cnt++;
  1091. if (err_cnt >= (mcdi->clusters_per_block << 6)) {
  1092. j = 16;
  1093. break;
  1094. }
  1095. }
  1096. if (j != -1)
  1097. break;
  1098. }
  1099. } while (++z < mcdi->blocksize);
  1100. }
  1101. }
  1102. if (((mcdi->cardflags & CF_USE_ECC) != 0) && (j == -1))
  1103. j = 16;
  1104. lbl1:
  1105. if (j == 16) {
  1106. r = mcman_eraseblock(port, slot, i, NULL, NULL);
  1107. if (r != sceMcResSucceed)
  1108. return -43;
  1109. }
  1110. else {
  1111. for (l = 0; l < pageword_cnt; l++)
  1112. *((u32 *)&mcman_pagebuf + l) = erase_value;
  1113. if (mcdi->blocksize > 0) {
  1114. z = 0;
  1115. do {
  1116. r = McWritePage(port, slot, page + z, mcman_pagebuf, mcman_eccdata);
  1117. if (r != sceMcResSucceed)
  1118. return -44;
  1119. } while (++z < mcdi->blocksize);
  1120. }
  1121. }
  1122. } while (++i < blocks_on_card);
  1123. }
  1124. r = mcman_eraseblock(port, slot, 0, NULL, NULL);
  1125. if (r != sceMcResSucceed)
  1126. return -45;
  1127. return sceMcResSucceed;
  1128. }
  1129. //--------------------------------------------------------------