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.
9 extern char SUPERBLOCK_MAGIC
[];
10 extern char SUPERBLOCK_VERSION
[];
12 extern int mcman_wr_port
;
13 extern int mcman_wr_slot
;
14 extern int mcman_wr_block
;
15 extern int mcman_wr_flag3
;
16 extern int mcman_curdircluster
;
21 extern int PS1CardFlag
;
23 //--------------------------------------------------------------
24 int mcman_format2(int port
, int slot
)
26 register int r
, i
, size
, ifc_index
, indirect_offset
, allocatable_clusters_per_card
;
27 register int ifc_length
, fat_length
, fat_entry
, alloc_offset
;
28 register int j
= 0, z
= 0;
29 MCDevInfo
*mcdi
= &mcman_devinfos
[port
][slot
];
33 DPRINTF("mcman: mcman_format2 port%d, slot%d cardform %d\n", port
, slot
, mcdi
->cardform
);
36 if (mcdi
->cardform
== sceMcResNoFormat
) {
37 for (i
= 0; i
< 32; i
++)
38 mcdi
->bad_block_list
[i
] = -1;
39 mcdi
->rootdir_cluster
= 0;
40 mcdi
->rootdir_cluster2
= 0;
44 if (mcdi
->cardform
> 0) {
45 if (((mcdi
->version
[0] - 48) >= 2) || ((mcdi
->version
[2] - 48) >= 2))
49 r
= mcman_reportBadBlocks(port
, slot
);
50 if ((r
!= sceMcResSucceed
) && (r
!= sceMcResNoFormat
))
51 return sceMcResChangedCard
;
54 // set superblock magic & version
55 memset((void *)&mcdi
->magic
, 0, sizeof (mcdi
->magic
) + sizeof (mcdi
->version
));
56 *((u32
*)&mcdi
->magic
) = *((u32
*)&SUPERBLOCK_MAGIC
);
57 *((u32
*)&mcdi
->magic
+ 1) = *((u32
*)&SUPERBLOCK_MAGIC
+ 1);
58 *((u32
*)&mcdi
->magic
+ 2) = *((u32
*)&SUPERBLOCK_MAGIC
+ 2);
59 *((u32
*)&mcdi
->magic
+ 3) = *((u32
*)&SUPERBLOCK_MAGIC
+ 3);
60 *((u32
*)&mcdi
->magic
+ 4) = *((u32
*)&SUPERBLOCK_MAGIC
+ 4);
61 *((u32
*)&mcdi
->magic
+ 5) = *((u32
*)&SUPERBLOCK_MAGIC
+ 5);
62 *((u32
*)&mcdi
->magic
+ 6) = *((u32
*)&SUPERBLOCK_MAGIC
+ 6);
63 *((u8
*)&mcdi
->magic
+ 28) = *((u8
*)&SUPERBLOCK_MAGIC
+ 28);
65 strcat((char *)&mcdi
->magic
, SUPERBLOCK_VERSION
);
67 //size = 8192 / mcdi->cluster_size; // get blocksize in cluster a better way must be found
68 size
= mcdi
->blocksize
;
78 if (mcdi
->blocksize
<= 0)
81 // clear first 8 clusters
82 for (i
= 0; i
< size
; i
++) {
83 r
= mcman_writecluster(port
, slot
, i
, 1);
85 return sceMcResNoFormat
;
91 fat_length
= (((mcdi
->clusters_per_card
<< 2) - 1) / mcdi
->cluster_size
) + 1; // get length of fat in clusters
92 ifc_length
= (((fat_length
<< 2) - 1) / mcdi
->cluster_size
) + 1; // get number of needed ifc clusters
94 if (!(ifc_length
<= 32)) {
96 fat_length
= mcdi
->FATentries_per_cluster
<< 5;
100 if (ifc_length
> 0) {
103 if (i
>= mcdi
->clusters_per_card
)
104 return sceMcResNoFormat
;
107 if (mcman_writecluster(port
, slot
, i
, 1) != 0)
111 } while (i
< mcdi
->clusters_per_card
);
113 if (i
>= mcdi
->clusters_per_card
)
114 return sceMcResNoFormat
;
116 mcdi
->ifc_list
[j
] = i
;
119 } while (j
< ifc_length
);
122 // read ifc clusters to mc cache and clear fat clusters
123 if (fat_length
> 0) {
127 ifc_index
= j
/ mcdi
->FATentries_per_cluster
;
128 indirect_offset
= j
% mcdi
->FATentries_per_cluster
;
130 if (indirect_offset
== 0) {
131 if (mcman_readcluster(port
, slot
, mcdi
->ifc_list
[ifc_index
], &mce
) != sceMcResSucceed
)
136 if (i
>= mcdi
->clusters_per_card
)
137 return sceMcResNoFormat
;
140 r
= mcman_writecluster(port
, slot
, i
, 1);
148 } while (i
< mcdi
->clusters_per_card
);
150 if (i
>= mcdi
->clusters_per_card
)
151 return sceMcResNoFormat
;
154 McFatCluster
*fc
= (McFatCluster
*)mce
->cl_data
;
155 fc
->entry
[indirect_offset
] = i
;
158 } while (j
< fat_length
);
162 mcdi
->backup_block1
= 0;
163 mcdi
->backup_block2
= 0;
165 // clear backup blocks
166 for (i
= (mcdi
->clusters_per_card
/ mcdi
->clusters_per_block
) - 1; i
> 0; i
--) {
168 r
= mcman_writecluster(port
, slot
, mcdi
->clusters_per_block
* i
, 1);
172 if ((r
!= 0) && (mcdi
->backup_block1
== 0))
173 mcdi
->backup_block1
= i
;
174 else if ((r
!= 0) && (mcdi
->backup_block2
== 0)) {
175 mcdi
->backup_block2
= i
;
180 // set backup block2 to erased state
181 if (mcman_eraseblock(port
, slot
, mcdi
->backup_block2
, NULL
, NULL
) != sceMcResSucceed
)
186 long_multiply(mcdi
->clusters_per_card
, 0x10624dd3, &hi
, &lo
);
187 temp
= (hi
>> 6) - (mcdi
->clusters_per_card
>> 31);
188 allocatable_clusters_per_card
= (((((temp
<< 5) - temp
) << 2) + temp
) << 3) + 1;
191 // checking for bad allocated clusters and building FAT
192 if (j
< i
* mcdi
->clusters_per_block
) {
194 do { // quick check for bad clusters
195 r
= mcman_writecluster(port
, slot
, j
, 0);
198 mcdi
->alloc_offset
= j
;
199 mcdi
->rootdir_cluster
= 0;
200 fat_entry
= 0xffffffff; // marking rootdir end
203 fat_entry
= 0x7fffffff; // marking free cluster
205 if (z
== allocatable_clusters_per_card
)
206 mcdi
->max_allocatable_clusters
= (j
- mcdi
->alloc_offset
) + 1;
211 fat_entry
= 0xfffffffd; // marking bad cluster
214 if (mcman_setFATentry(port
, slot
, j
- mcdi
->alloc_offset
, fat_entry
) != sceMcResSucceed
)
218 } while (j
< (i
* mcdi
->clusters_per_block
));
221 mcdi
->alloc_end
= (i
* mcdi
->clusters_per_block
) - mcdi
->alloc_offset
;
223 if (mcdi
->max_allocatable_clusters
== 0)
224 mcdi
->max_allocatable_clusters
= i
* mcdi
->clusters_per_block
;
226 if (z
< mcdi
->clusters_per_block
)
227 return sceMcResNoFormat
;
229 // read superblock to mc cache
230 for (i
= 0; i
< sizeof (MCDevInfo
); i
+= MCMAN_CLUSTERSIZE
) {
232 size
= i
+ (MCMAN_CLUSTERSIZE
- 1);
236 if (mcman_readcluster(port
, slot
, size
>> 10, &mce
) != sceMcResSucceed
)
239 size
= MCMAN_CLUSTERSIZE
;
242 if ((sizeof (MCDevInfo
) - i
) <= 1024)
243 size
= sizeof (MCDevInfo
) - i
;
245 memcpy((void *)mce
->cl_data
, (void *)(mcdi
+ i
), size
);
251 mcdi
->rootdir_cluster2
= mcdi
->rootdir_cluster
;
254 if (mcman_createDirentry(port
, slot
, 0, 0, 0, NULL
) != sceMcResSucceed
)
257 // finally flush cache to memcard
258 r
= mcman_flushmccache(port
, slot
);
259 if (r
!= sceMcResSucceed
)
264 return sceMcResSucceed
;
267 //--------------------------------------------------------------
268 int mcman_dread2(int fd
, fio_dirent_t
*dirent
)
271 register MC_FHANDLE
*fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
275 DPRINTF("mcman: mcman_dread2 fd %d\n", fd
);
278 if (fh
->position
>= fh
->filesize
)
279 return sceMcResSucceed
;
282 r
= mcman_readdirentry(fh
->port
, fh
->slot
, fh
->freeclink
, fh
->position
, &fse
);
283 if (r
!= sceMcResSucceed
)
286 if (fse
->mode
& sceMcFileAttrExists
)
290 } while (fh
->position
< fh
->filesize
);
292 if (fh
->position
>= fh
->filesize
)
293 return sceMcResSucceed
;
296 mcman_wmemset((void *)dirent
, sizeof (fio_dirent_t
), 0);
297 strcpy(dirent
->name
, fse
->name
);
298 *(u8
*)&dirent
->name
[32] = 0;
300 if (fse
->mode
& sceMcFileAttrReadable
)
301 dirent
->stat
.mode
|= sceMcFileAttrReadable
;
302 if (fse
->mode
& sceMcFileAttrWriteable
)
303 dirent
->stat
.mode
|= sceMcFileAttrWriteable
;
304 if (fse
->mode
& sceMcFileAttrExecutable
)
305 dirent
->stat
.mode
|= sceMcFileAttrExecutable
;
306 if (fse
->mode
& sceMcFileAttrPS1
)
307 dirent
->stat
.mode
|= sceMcFileAttrPS1
;
308 if (fse
->mode
& sceMcFileAttrPDAExec
)
309 dirent
->stat
.mode
|= sceMcFileAttrPDAExec
;
310 if (fse
->mode
& sceMcFileAttrDupProhibit
)
311 dirent
->stat
.mode
|= sceMcFileAttrDupProhibit
;
312 if (fse
->mode
& sceMcFileAttrSubdir
)
313 dirent
->stat
.mode
|= sceMcFileAttrSubdir
;
315 dirent
->stat
.mode
|= sceMcFileAttrFile
;
317 dirent
->stat
.attr
= fse
->attr
;
318 dirent
->stat
.size
= fse
->length
;
319 *((u32
*)&dirent
->stat
.ctime
) = *((u32
*)&fse
->created
);
320 *((u32
*)&dirent
->stat
.ctime
+1) = *((u32
*)&fse
->created
+1);
321 *((u32
*)&dirent
->stat
.mtime
) = *((u32
*)&fse
->modified
);
322 *((u32
*)&dirent
->stat
.mtime
+1) = *((u32
*)&fse
->modified
+1);
327 //--------------------------------------------------------------
328 int mcman_getstat2(int port
, int slot
, char *filename
, fio_stat_t
*stat
)
334 DPRINTF("mcman: mcman_getstat2 port%d slot%d filename %s\n", port
, slot
, filename
);
337 r
= mcman_cachedirentry(port
, slot
, filename
, NULL
, &fse
, 1);
338 if (r
!= sceMcResSucceed
)
341 mcman_wmemset((void *)stat
, sizeof (fio_stat_t
), 0);
343 if (fse
->mode
& sceMcFileAttrReadable
)
344 stat
->mode
|= sceMcFileAttrReadable
;
345 if (fse
->mode
& sceMcFileAttrWriteable
)
346 stat
->mode
|= sceMcFileAttrWriteable
;
347 if (fse
->mode
& sceMcFileAttrExecutable
)
348 stat
->mode
|= sceMcFileAttrExecutable
;
349 if (fse
->mode
& sceMcFileAttrPS1
)
350 stat
->mode
|= sceMcFileAttrPS1
;
351 if (fse
->mode
& sceMcFileAttrPDAExec
)
352 stat
->mode
|= sceMcFileAttrPDAExec
;
353 if (fse
->mode
& sceMcFileAttrDupProhibit
)
354 stat
->mode
|= sceMcFileAttrDupProhibit
;
355 if (fse
->mode
& sceMcFileAttrSubdir
)
356 stat
->mode
|= sceMcFileAttrSubdir
;
358 stat
->mode
|= sceMcFileAttrFile
;
360 stat
->attr
= fse
->attr
;
362 if (!(fse
->mode
& sceMcFileAttrSubdir
))
363 stat
->size
= fse
->length
;
365 *((u32
*)&stat
->ctime
) = *((u32
*)&fse
->created
);
366 *((u32
*)&stat
->ctime
+1) = *((u32
*)&fse
->created
+1);
367 *((u32
*)&stat
->mtime
) = *((u32
*)&fse
->modified
);
368 *((u32
*)&stat
->mtime
+1) = *((u32
*)&fse
->modified
+1);
370 return sceMcResSucceed
;
373 //--------------------------------------------------------------
374 int mcman_setinfo2(int port
, int slot
, char *filename
, sceMcTblGetDir
*info
, int flags
)
376 register int r
, fmode
;
380 u8
*pfsentry
, *pfseend
, *mfee
;
383 DPRINTF("mcman: mcman_setinfo2 port%d slot%d filename %s flags %x\n", port
, slot
, filename
, flags
);
386 r
= mcman_cachedirentry(port
, slot
, filename
, &dirInfo
, &fse
, 1); //dirInfo=sp218 fse=sp228
387 if (r
!= sceMcResSucceed
)
390 if ((flags
& sceMcFileAttrFile
) != 0) {
391 if ((!strcmp(".", info
->EntryName
)) || (!strcmp("..", info
->EntryName
)))
392 return sceMcResNoEntry
;
394 if (info
->EntryName
[0] == 0)
395 return sceMcResNoEntry
;
397 r
= mcman_chrpos(info
->EntryName
, '/');
399 return sceMcResNoEntry
;
401 if (dirInfo
.fsindex
< 2)
402 return sceMcResNoEntry
;
404 r
= mcman_readdirentry(port
, slot
, dirInfo
.cluster
, 0, &fse
);
405 if (r
!= sceMcResSucceed
)
408 r
= mcman_readdirentry(port
, slot
, fse
->cluster
, fse
->dir_entry
, &fse
);
409 if (r
!= sceMcResSucceed
)
412 pfsentry
= (u8
*)fse
;
414 pfseend
= (u8
*)(pfsentry
+ sizeof (McFsEntry
));
417 *((u32
*)mfee
) = *((u32
*)pfsentry
);
418 *((u32
*)mfee
+1) = *((u32
*)pfsentry
+1);
419 *((u32
*)mfee
+2) = *((u32
*)pfsentry
+2);
420 *((u32
*)mfee
+3) = *((u32
*)pfsentry
+3);
423 } while (pfsentry
< pfseend
);
425 r
= mcman_getdirinfo(port
, slot
, &mfe
, info
->EntryName
, NULL
, 1);
429 return sceMcResNoEntry
;
435 return sceMcResDeniedPermit
;
440 r
= mcman_readdirentry(port
, slot
, dirInfo
.cluster
, dirInfo
.fsindex
, &fse
);
441 if (r
!= sceMcResSucceed
)
444 mcman_1stcacheEntsetwrflagoff();
446 //Special fix clause for file managers (like uLaunchELF)
447 //This allows writing most entries that can be read by mcGetDir
448 //and without usual restrictions. This flags value should cause no conflict
449 //as Sony code never uses it, and the value is changed after its use here.
451 fse
->mode
= info
->AttrFile
;
452 //fse->unused = info->Reserve1;
453 //fse->length = info->FileSizeByte;
454 flags
= sceMcFileAttrReadable
|sceMcFileAttrWriteable
;
455 //The changed flags value allows more entries to be copied below
458 if ((flags
& sceMcFileAttrDupProhibit
) != 0)
459 fse
->attr
= info
->Reserve2
;
461 if ((flags
& sceMcFileAttrExecutable
) != 0) {
465 fse
->mode
= (fse
->mode
& ~fmode
) | (info
->AttrFile
& fmode
);
468 if ((flags
& sceMcFileCreateFile
) != 0) {
472 fse
->mode
= (fse
->mode
& ~fmode
) | (info
->AttrFile
& fmode
);
475 if ((flags
& sceMcFileAttrReadable
) != 0)
476 fse
->created
= info
->_Create
;
478 if ((flags
& sceMcFileAttrWriteable
) != 0)
479 fse
->modified
= info
->_Modify
;
481 if ((flags
& sceMcFileAttrFile
) != 0) {
482 strncpy(fse
->name
, info
->EntryName
, 32);
486 return sceMcResSucceed
;
489 //--------------------------------------------------------------
490 int mcman_read2(int fd
, void *buffer
, int nbyte
)
492 register int r
, temp
, rpos
, size
, offset
;
493 register MC_FHANDLE
*fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
494 register MCDevInfo
*mcdi
= &mcman_devinfos
[fh
->port
][fh
->slot
];
498 DPRINTF("mcman: mcman_read2 fd %d buf %x size %d\n", fd
, (int)buffer
, nbyte
);
501 if (fh
->position
< fh
->filesize
) {
503 temp
= fh
->filesize
- fh
->position
;
511 offset
= fh
->position
% mcdi
->cluster_size
; // file pointer offset % cluster size
512 temp
= mcdi
->cluster_size
- offset
;
518 r
= mcman_fatRseek(fd
);
523 r
= mcman_readcluster(fh
->port
, fh
->slot
, r
, &mce
);
524 if (r
!= sceMcResSucceed
)
527 memcpy((void *)(buffer
+ rpos
), (void *)(mce
->cl_data
+ offset
), size
);
532 fh
->position
+= size
;
542 //--------------------------------------------------------------
543 int mcman_write2(int fd
, void *buffer
, int nbyte
)
545 register int r
, r2
, wpos
, size
, offset
;
546 register MC_FHANDLE
*fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
547 register MCDevInfo
*mcdi
= &mcman_devinfos
[fh
->port
][fh
->slot
];
551 if (fh
->unknown2
== 0) {
553 r
= mcman_close2(fd
);
554 if (r
!= sceMcResSucceed
)
556 r
= mcman_flushmccache(fh
->port
, fh
->slot
);
557 if (r
!= sceMcResSucceed
)
565 r
= mcman_fatRseek(fd
);
566 if (r
== sceMcResFullDevice
) {
568 r2
= mcman_fatWseek(fd
);
570 return sceMcResFullDevice
;
572 if (r2
!= sceMcResSucceed
)
575 r
= mcman_fatRseek(fd
);
582 r
= mcman_readcluster(fh
->port
, fh
->slot
, r
, &mce
);
583 if (r
!= sceMcResSucceed
)
588 offset
= fh
->position
% mcdi
->cluster_size
; // file pointer offset % cluster size
589 r2
= mcdi
->cluster_size
- offset
;
595 memcpy((void *)(mce
->cl_data
+ offset
), (void *)(buffer
+ wpos
), size
);
599 r
= fh
->position
+ size
;
600 fh
->position
+= size
;
602 if (r
< fh
->filesize
)
613 r
= mcman_close2(fd
);
614 if (r
!= sceMcResSucceed
)
620 //--------------------------------------------------------------
621 int mcman_close2(int fd
)
623 register int r
, fmode
;
624 register MC_FHANDLE
*fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
625 McFsEntry
*fse1
, *fse2
;
628 DPRINTF("mcman: mcman_close2 fd %d\n", fd
);
631 r
= mcman_readdirentry(fh
->port
, fh
->slot
, fh
->field_20
, fh
->field_24
, &fse1
);
632 if (r
!= sceMcResSucceed
)
635 if (fh
->unknown2
== 0) {
636 fmode
= fse1
->mode
| sceMcFileAttrClosed
;
639 fmode
= fse1
->mode
& 0xff7f;
643 mcman_getmcrtime(&fse1
->modified
);
645 fse1
->cluster
= fh
->freeclink
;
646 fse1
->length
= fh
->filesize
;
648 mcman_1stcacheEntsetwrflagoff();
650 mcman_fsmodtime
= fse1
->modified
;
652 r
= mcman_readdirentry(fh
->port
, fh
->slot
, fh
->field_28
, fh
->field_2C
, &fse2
);
653 if (r
!= sceMcResSucceed
)
656 fse2
->modified
= mcman_fsmodtime
;
658 mcman_1stcacheEntsetwrflagoff();
660 return sceMcResSucceed
;
663 //--------------------------------------------------------------
664 int mcman_open2(int port
, int slot
, char *filename
, int flags
)
666 register int fd
, i
, r
, fsindex
, fsoffset
, fat_index
, rdflag
, wrflag
, pos
, mcfree
;
667 register MC_FHANDLE
*fh
, *fh2
;
668 register MCDevInfo
*mcdi
;
670 McFsEntry
*fse1
, *fse2
;
672 u8
*p
, *pfsentry
, *pcache
, *pfseend
;
676 DPRINTF("mcman: mcman_open2 port%d slot%d name %s flags %x\n", port
, slot
, filename
, flags
);
679 if ((flags
& sceMcFileCreateFile
) != 0)
680 flags
|= sceMcFileAttrWriteable
; // s5
682 //if (!mcman_checkpath(filename))
683 // return sceMcResNoEntry;
684 if (filename
[0] == 0)
685 return sceMcResNoEntry
;
689 fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
692 } while (++fd
< MAX_FDHANDLES
);
694 if (fd
== MAX_FDHANDLES
)
695 return sceMcResUpLimitHandle
;
697 fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
]; // s2
699 mcman_wmemset((void *)fh
, sizeof (MC_FHANDLE
), 0);
701 mcdi
= (MCDevInfo
*)&mcman_devinfos
[port
][slot
]; // s3
703 if ((flags
& (sceMcFileCreateFile
| sceMcFileCreateDir
)) == 0)
704 cacheDir
.maxent
= -1; //sp20
706 cacheDir
.maxent
= 0; //sp20
712 r
= mcman_cachedirentry(port
, slot
, filename
, &cacheDir
, &fse1
, 1);
717 pfsentry
= (u8
*)fse1
;
718 pcache
= (u8
*)&mcman_dircache
[1];
719 pfseend
= (u8
*)(pfsentry
+ sizeof(McFsEntry
));
722 *((u32
*)pcache
) = *((u32
*)pfsentry
);
723 *((u32
*)pcache
+1) = *((u32
*)pfsentry
+1);
724 *((u32
*)pcache
+2) = *((u32
*)pfsentry
+2);
725 *((u32
*)pcache
+3) = *((u32
*)pfsentry
+3);
728 } while (pfsentry
< pfseend
);
731 if ((flags
== 0) && ((fse1
->mode
& sceMcFileAttrExists
) == 0))
735 return sceMcResNoEntry
;
738 return sceMcResDeniedPermit
;
740 if ((r
== 0) && ((flags
& sceMcFileCreateDir
) != 0))
741 return sceMcResNoEntry
;
743 if ((r
== 1) && ((flags
& (sceMcFileCreateFile
| sceMcFileCreateDir
)) == 0))
744 return sceMcResNoEntry
;
746 rdflag
= flags
& sceMcFileAttrReadable
;
747 wrflag
= flags
& sceMcFileAttrWriteable
;
750 fh
->clust_offset
= 0;
759 fh
->field_20
= cacheDir
.cluster
;
760 fh
->field_24
= cacheDir
.fsindex
;
766 if ((wrflag
!= 0) && ((mcman_dircache
[1].mode
& sceMcFileAttrWriteable
) == 0))
767 return sceMcResDeniedPermit
;
770 if ((flags
& sceMcFileAttrReadable
) != 0) {
771 if ((mcman_dircache
[1].mode
& sceMcFileAttrReadable
) == 0)
772 return sceMcResDeniedPermit
;
775 r
= mcman_readdirentry(port
, slot
, cacheDir
.cluster
, 0, &fse2
);
776 if (r
!= sceMcResSucceed
)
779 fh
->field_28
= fse2
->cluster
;
780 fh
->field_2C
= fse2
->dir_entry
;
782 if ((mcman_dircache
[1].mode
& sceMcFileAttrSubdir
) != 0) {
783 if ((mcman_dircache
[1].mode
& sceMcFileAttrReadable
) == 0)
784 return sceMcResDeniedPermit
;
786 fh
->freeclink
= mcman_dircache
[1].cluster
;
792 fh
->filesize
= mcman_dircache
[1].length
;
793 fh
->clink
= fh
->freeclink
;
798 if ((flags
& sceMcFileAttrWriteable
) != 0) {
801 fh2
= (MC_FHANDLE
*)&mcman_fdhandles
[i
];
803 if ((fh2
->status
== 0) || (fh2
->port
!= port
) || (fh2
->slot
!= slot
) \
804 || (fh2
->field_20
!= cacheDir
.cluster
) || (fh2
->field_24
!= cacheDir
.fsindex
))
807 if (fh2
->wrflag
!= 0)
808 return sceMcResDeniedPermit
;
810 } while (++i
< MAX_FDHANDLES
);
813 if ((flags
& sceMcFileCreateFile
) != 0) {
814 r
= mcman_setdirentrystate(port
, slot
, cacheDir
.cluster
, cacheDir
.fsindex
, 0);
815 mcman_flushmccache(port
, slot
);
817 if (r
!= sceMcResSucceed
)
820 if (cacheDir
.fsindex
< cacheDir
.maxent
)
821 cacheDir
.maxent
= cacheDir
.fsindex
;
824 fh
->freeclink
= mcman_dircache
[1].cluster
;
825 fh
->filesize
= mcman_dircache
[1].length
;
826 fh
->clink
= fh
->freeclink
;
829 fh
->rdflag
= (*((u8
*)&mcman_dircache
[1].mode
)) & sceMcFileAttrReadable
;
834 fh
->wrflag
= (mcman_dircache
[1].mode
>> 1) & sceMcFileAttrReadable
;
844 fh
->field_28
= cacheDir
.cluster
;
845 fh
->field_2C
= cacheDir
.fsindex
;
848 r
= mcman_readdirentry(port
, slot
, fh
->field_28
, fh
->field_2C
, &fse1
);
849 if (r
!= sceMcResSucceed
)
852 pfsentry
= (u8
*)fse1
;
853 pcache
= (u8
*)&mcman_dircache
[2];
854 pfseend
= (u8
*)(pfsentry
+ sizeof(McFsEntry
));
857 *((u32
*)pcache
) = *((u32
*)pfsentry
);
858 *((u32
*)pcache
+1) = *((u32
*)pfsentry
+1);
859 *((u32
*)pcache
+2) = *((u32
*)pfsentry
+2);
860 *((u32
*)pcache
+3) = *((u32
*)pfsentry
+3);
863 } while (pfsentry
< pfseend
);
866 if (mcman_dircache
[2].length
== cacheDir
.maxent
) {
868 fsindex
= mcman_dircache
[2].length
/ (mcdi
->cluster_size
>> 9); //v1
869 fsoffset
= mcman_dircache
[2].length
% (mcdi
->cluster_size
>> 9); //v0
872 fat_index
= mcman_dircache
[2].cluster
;
875 if ((mcman_dircache
[2].cluster
== 0) && (i
>= 2)) {
876 if (mcman_getFATindex(port
, slot
, i
- 1) >= 0) {
877 fat_index
= mcman_getFATindex(port
, slot
, i
- 1); // s3
886 r
= mcman_getFATentry(port
, slot
, fat_index
, &fat_entry
);
887 if (r
!= sceMcResSucceed
)
890 if (fat_entry
>= -1) {
891 r
= mcman_findfree2(port
, slot
, 1);
896 mce
= mcman_get1stcacheEntp(); // s4
898 fat_entry
|= 0x80000000;
900 r
= mcman_setFATentry(port
, slot
, fat_index
, fat_entry
);
901 if (r
!= sceMcResSucceed
)
904 mcman_addcacheentry(mce
);
907 fat_index
= fat_entry
& 0x7fffffff;
913 r
= mcman_flushmccache(port
, slot
);
914 if (r
!= sceMcResSucceed
)
919 mcman_dircache
[2].length
++;
923 p
= (u8
*)(filename
+ i
+ 1);
925 r
= mcman_chrpos(p
, '/');
931 p
= (char *)(filename
+ pos
);
935 if ((flags
& sceMcFileCreateDir
) != 0) {
936 r
= mcman_findfree2(port
, slot
, 1); // r = s3
942 mce
= mcman_get1stcacheEntp(); // mce = s4
944 mcman_getmcrtime(&mcman_dircache
[2].modified
);
946 r
= mcman_readdirentry(port
, slot
, mcman_dircache
[2].cluster
, cacheDir
.maxent
, &fse2
);
947 if (r
!= sceMcResSucceed
)
950 mcman_wmemset((void *)fse2
, sizeof (McFsEntry
), 0);
952 strncpy((void *)fse2
->name
, p
, 32);
954 fse2
->created
= mcman_dircache
[2].modified
;
955 fse2
->modified
= mcman_dircache
[2].modified
;
957 mcman_1stcacheEntsetwrflagoff();
959 mcman_addcacheentry(mce
);
964 if ((flags
& sceMcFileCreateDir
) != 0) {
966 fse2
->mode
= ((flags
& sceMcFileAttrHidden
) | sceMcFileAttrReadable
| sceMcFileAttrWriteable \
967 | sceMcFileAttrExecutable
| sceMcFileAttrSubdir
| sceMcFile0400
| sceMcFileAttrExists
) // 0x8427
968 | (flags
& (sceMcFileAttrPS1
| sceMcFileAttrPDAExec
));
970 fse2
->cluster
= mcfree
;
972 r
= mcman_createDirentry(port
, slot
, mcman_dircache
[2].cluster
, cacheDir
.maxent
, mcfree
, (sceMcStDateTime
*)&fse2
->created
);
973 if (r
!= sceMcResSucceed
)
976 r
= mcman_readdirentry(port
, slot
, fh
->field_28
, fh
->field_2C
, &fse1
);
977 if (r
!= sceMcResSucceed
)
980 pfsentry
= (u8
*)fse1
;
981 pcache
= (u8
*)&mcman_dircache
[2];
982 pfseend
= (u8
*)(pfsentry
+ sizeof(McFsEntry
));
985 *((u32
*)pfsentry
) = *((u32
*)pcache
);
986 *((u32
*)pfsentry
+1) = *((u32
*)pcache
+1);
987 *((u32
*)pfsentry
+2) = *((u32
*)pcache
+2);
988 *((u32
*)pfsentry
+3) = *((u32
*)pcache
+3);
991 } while (pfsentry
< pfseend
);
993 mcman_1stcacheEntsetwrflagoff();
995 r
= mcman_flushmccache(port
, slot
);
996 if (r
!= sceMcResSucceed
)
999 return sceMcResSucceed
;
1002 fse2
->mode
= ((flags
& sceMcFileAttrHidden
) | sceMcFileAttrReadable
| sceMcFileAttrWriteable \
1003 | sceMcFileAttrExecutable
| sceMcFileAttrFile
| sceMcFile0400
| sceMcFileAttrExists
) // 0x8417
1004 | (flags
& (sceMcFileAttrPS1
| sceMcFileAttrPDAExec
));
1007 fh
->field_20
= mcman_dircache
[2].cluster
;
1009 fh
->field_24
= cacheDir
.maxent
;
1011 r
= mcman_readdirentry(port
, slot
, fh
->field_28
, fh
->field_2C
, &fse1
);
1012 if (r
!= sceMcResSucceed
)
1015 pfsentry
= (u8
*)fse1
;
1016 pcache
= (u8
*)&mcman_dircache
[2];
1017 pfseend
= (u8
*)(pfsentry
+ sizeof(McFsEntry
));
1020 *((u32
*)pfsentry
) = *((u32
*)pcache
);
1021 *((u32
*)pfsentry
+1) = *((u32
*)pcache
+1);
1022 *((u32
*)pfsentry
+2) = *((u32
*)pcache
+2);
1023 *((u32
*)pfsentry
+3) = *((u32
*)pcache
+3);
1026 } while (pfsentry
< pfseend
);
1028 mcman_1stcacheEntsetwrflagoff();
1030 r
= mcman_flushmccache(port
, slot
);
1031 if (r
!= sceMcResSucceed
)
1038 //--------------------------------------------------------------
1039 int mcman_chdir(int port
, int slot
, char *newdir
, char *currentdir
)
1041 register int r
, len
, len2
, cluster
;
1042 register MCDevInfo
*mcdi
= &mcman_devinfos
[port
][slot
];
1043 McCacheDir cacheDir
;
1047 DPRINTF("mcman: mcman_chdir port%d slot%d newdir %s\n", port
, slot
, newdir
);
1050 //if (!mcman_checkpath(newdir))
1051 // return sceMcResNoEntry;
1053 cacheDir
.maxent
= -1;
1055 r
= mcman_cachedirentry(port
, slot
, newdir
, &cacheDir
, &fse
, 1);
1059 if (((u32
)(r
- 1)) < 2)
1060 return sceMcResNoEntry
;
1062 mcdi
->rootdir_cluster2
= cacheDir
.cluster
;
1063 mcdi
->unknown1
= cacheDir
.fsindex
;
1065 cluster
= cacheDir
.cluster
;
1066 if (!strcmp(fse
->name
, "..")) {
1067 r
= mcman_readdirentry(port
, slot
, cluster
, 0, &fse
);
1068 if (r
!= sceMcResSucceed
)
1072 if (!strcmp(fse
->name
, ".")) {
1073 mcdi
->rootdir_cluster2
= fse
->cluster
;
1074 mcdi
->unknown1
= fse
->dir_entry
;
1076 cluster
= fse
->cluster
;
1077 r
= mcman_readdirentry(port
, slot
, cluster
, fse
->dir_entry
, &fse
);
1078 if (r
!= sceMcResSucceed
)
1085 if (strcmp(fse
->name
, ".")) {
1087 if (strlen(fse
->name
) < 32)
1088 len
= strlen(fse
->name
);
1092 if (strlen(currentdir
)) {
1093 len2
= strlen(currentdir
);
1096 currentdir
[1 + len2
+ len
] = currentdir
[len2
];
1097 } while (--len2
>= 0);
1099 currentdir
[len
] = '/';
1100 strncpy(currentdir
, fse
->name
, len
);
1103 strncpy(currentdir
, fse
->name
, 32);
1107 r
= mcman_readdirentry(port
, slot
, cluster
, 0, &fse
);
1108 if (r
!= sceMcResSucceed
)
1111 r
= mcman_readdirentry(port
, slot
, fse
->cluster
, fse
->dir_entry
, &fse
);
1113 if (r
== sceMcResSucceed
)
1120 len
= strlen(currentdir
);
1124 currentdir
[1 + len
] = currentdir
[len
];
1125 } while (--len
>= 0);
1127 currentdir
[0] = '/';
1129 r
= sceMcResSucceed
;
1132 return sceMcResSucceed
;
1135 //--------------------------------------------------------------
1136 int mcman_getdir2(int port
, int slot
, char *dirname
, int flags
, int maxent
, sceMcTblGetDir
*info
)
1138 register int r
, pos
, nument
;
1139 register MCDevInfo
*mcdi
= &mcman_devinfos
[port
][slot
];
1144 DPRINTF("mcman: mcman_getdir2 port%d slot%d dir=%s flags=%d maxent=%d\n", port
, slot
, dirname
, flags
, maxent
);
1152 p
= (char *)mcman_curdirpath
;
1153 strncpy(p
, dirname
, 1023);
1154 mcman_curdirpath
[1023] = 0;
1159 r
= mcman_chrpos((void *)&p
[pos
], '/');
1172 mcman_curdirpath
[pos
] = 0;
1175 mcman_curdirname
= &dirname
[pos
] + 1;
1177 r
= mcman_cachedirentry(port
, slot
, mcman_curdirpath
, NULL
, &fse
, 1);
1179 return sceMcResNoEntry
;
1183 if (!(fse
->mode
& sceMcFileAttrSubdir
)) {
1184 mcman_curdircluster
= -1;
1185 return sceMcResNoEntry
;
1188 mcman_curdircluster
= fse
->cluster
;
1189 mcman_curdirlength
= fse
->length
;
1191 if ((fse
->cluster
== mcdi
->rootdir_cluster
) && (fse
->dir_entry
== 0))
1192 mcman_curdirmaxent
= 2;
1194 mcman_curdirmaxent
= 0;
1197 if (mcman_curdircluster
< 0)
1198 return sceMcResNoEntry
;
1203 if (mcman_curdirmaxent
>= mcman_curdirlength
)
1206 r
= mcman_readdirentry(port
, slot
, mcman_curdircluster
, mcman_curdirmaxent
, &fse
);
1207 if (r
!= sceMcResSucceed
)
1210 mcman_curdirmaxent
++;
1212 if (!(fse
->mode
& sceMcFileAttrExists
))
1214 if ((fse
->mode
& sceMcFileAttrHidden
) && (!PS1CardFlag
))
1216 if (!mcman_checkdirpath(fse
->name
, mcman_curdirname
))
1219 mcman_wmemset((void *)info
, sizeof (sceMcTblGetDir
), 0);
1221 if (mcman_curdirmaxent
== 2) {
1223 r
= mcman_readdirentry(port
, slot
, mcman_curdircluster
, 0, &fse
);
1224 if (r
!= sceMcResSucceed
)
1227 r
= mcman_readdirentry(port
, slot
, fse
->cluster
, 0, &fse
);
1228 if (r
!= sceMcResSucceed
)
1231 r
= mcman_readdirentry(port
, slot
, fse
->cluster
, fse
->dir_entry
, &fse
);
1232 if (r
!= sceMcResSucceed
)
1235 *(u16
*)&info
->EntryName
= *(u16
*)&DOTDOT
;
1236 *(u8
*)&info
->EntryName
[2] = *((u8
*)&DOTDOT
+2);
1238 else if (mcman_curdirmaxent
== 1) {
1240 r
= mcman_readdirentry(port
, slot
, mcman_curdircluster
, 0, &fse
);
1241 if (r
!= sceMcResSucceed
)
1244 r
= mcman_readdirentry(port
, slot
, fse
->cluster
, fse
->dir_entry
, &fse
);
1245 if (r
!= sceMcResSucceed
)
1248 *(u16
*)&info
->EntryName
= *(u16
*)&DOT
;
1251 strncpy(info
->EntryName
, fse
->name
, 32);
1254 info
->AttrFile
= fse
->mode
;
1255 info
->Reserve1
= fse
->unused
;
1257 info
->_Create
= fse
->created
;
1258 info
->_Modify
= fse
->modified
;
1260 if (!(fse
->mode
& sceMcFileAttrSubdir
))
1261 info
->FileSizeByte
= fse
->length
;
1273 //--------------------------------------------------------------
1274 int mcman_delete2(int port
, int slot
, char *filename
, int flags
)
1277 McCacheDir cacheDir
;
1278 McFsEntry
*fse1
, *fse2
;
1281 DPRINTF("mcman: mcman_delete2 port%d slot%d filename %s flags %x\n", port
, slot
, filename
, flags
);
1284 //if (!mcman_checkpath(filename))
1285 // return sceMcResNoEntry;
1287 r
= mcman_cachedirentry(port
, slot
, filename
, &cacheDir
, &fse1
, ((u32
)(flags
< 1)) ? 1 : 0);
1289 return sceMcResNoEntry
;
1294 if (!(fse1
->mode
& sceMcFileAttrExists
))
1295 return sceMcResNoEntry
;
1298 if (fse1
->mode
& sceMcFileAttrExists
)
1299 return sceMcResNoEntry
;
1302 if ((!PS1CardFlag
) && (!flags
)) {
1303 if (!(fse1
->mode
& sceMcFileAttrWriteable
))
1304 return sceMcResDeniedPermit
;
1307 if ((!fse1
->cluster
) && (!fse1
->dir_entry
))
1308 return sceMcResNoEntry
;
1311 if ((!flags
) && (fse1
->mode
& sceMcFileAttrSubdir
) && (i
< fse1
->length
)) {
1314 r
= mcman_readdirentry(port
, slot
, fse1
->cluster
, i
, &fse2
);
1315 if (r
!= sceMcResSucceed
)
1318 if (fse2
->mode
& sceMcFileAttrExists
)
1319 return sceMcResNotEmpty
;
1321 } while (++i
< fse1
->length
);
1324 r
= mcman_setdirentrystate(port
, slot
, cacheDir
.cluster
, cacheDir
.fsindex
, flags
);
1325 if (r
!= sceMcResSucceed
)
1328 r
= mcman_flushmccache(port
, slot
);
1329 if (r
!= sceMcResSucceed
)
1332 return sceMcResSucceed
;
1335 //--------------------------------------------------------------
1336 int mcman_unformat2(int port
, int slot
)
1338 register int r
, i
, j
, z
, l
, pageword_cnt
, page
, blocks_on_card
, erase_byte
, err_cnt
;
1339 register u32 erase_value
;
1340 register MCDevInfo
*mcdi
= &mcman_devinfos
[port
][slot
];
1343 DPRINTF("mcman: mcman_unformat2 port%d slot%d\n", port
, slot
);
1346 pageword_cnt
= mcdi
->pagesize
>> 2;
1347 blocks_on_card
= mcdi
->clusters_per_card
/ mcdi
->clusters_per_block
; //sp18
1349 erase_value
= 0xffffffff; //s6
1350 if (!(mcdi
->cardflags
& CF_ERASE_ZEROES
))
1351 erase_value
= 0x00000000;
1353 for (i
= 0; i
< pageword_cnt
; i
++)
1354 *((u32
*)&mcman_pagebuf
+ i
) = erase_value
;
1356 for (i
= 0; i
< 128; i
++)
1357 *((u32
*)&mcman_eccdata
+ i
) = erase_value
;
1360 if (i
< blocks_on_card
) {
1361 erase_byte
= erase_value
& 0xff; // sp20
1363 page
= i
* mcdi
->blocksize
;
1364 if (mcdi
->cardform
> 0) {
1366 for (j
= 0; j
< 16; j
++) {
1367 if (mcdi
->bad_block_list
[j
] <= 0) {
1371 if (mcdi
->bad_block_list
[j
] == i
)
1379 if (mcdi
->blocksize
> 0) {
1381 r
= McReadPage(port
, slot
, page
+ z
, mcman_pagebuf
);
1382 if (r
== sceMcResNoFormat
) {
1386 if (r
!= sceMcResSucceed
)
1389 if ((mcdi
->cardflags
& CF_USE_ECC
) == 0) {
1390 for (l
= 0; l
< mcdi
->pagesize
; l
++) {
1391 if (mcman_pagebuf
[l
] != erase_byte
)
1393 if (err_cnt
>= (mcdi
->clusters_per_block
<< 6)) {
1401 } while (++z
< mcdi
->blocksize
);
1405 if (((mcdi
->cardflags
& CF_USE_ECC
) != 0) && (j
== -1))
1409 r
= mcman_eraseblock(port
, slot
, i
, NULL
, NULL
);
1410 if (r
!= sceMcResSucceed
)
1414 for (l
= 0; l
< pageword_cnt
; l
++)
1415 *((u32
*)&mcman_pagebuf
+ l
) = erase_value
;
1417 if (mcdi
->blocksize
> 0) {
1420 r
= McWritePage(port
, slot
, page
+ z
, mcman_pagebuf
, mcman_eccdata
);
1421 if (r
!= sceMcResSucceed
)
1423 } while (++z
< mcdi
->blocksize
);
1426 } while (++i
< blocks_on_card
);
1429 r
= mcman_eraseblock(port
, slot
, 0, NULL
, NULL
);
1430 if (r
!= sceMcResSucceed
)
1433 return sceMcResSucceed
;
1436 //--------------------------------------------------------------