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 int sio2man_type
;
11 //--------------------------------------------------------------
12 int mcman_format1(int port
, int slot
)
15 register MCDevInfo
*mcdi
= &mcman_devinfos
[port
][slot
];
18 DPRINTF("mcman: mcman_format1 port%d slot%d\n", port
, slot
);
21 mcman_invhandles(port
, slot
);
23 for (i
= 0; i
< 56; i
++) {
24 r
= mcman_PS1pagetest(port
, slot
, i
);
26 return sceMcResNoFormat
;
31 memset(mcman_PS1PDApagebuf
, 0, 128);
33 *((u32
*)&mcman_PS1PDApagebuf
) = 0xa0;
34 *((u16
*)&mcman_PS1PDApagebuf
+4) = 0xffff;
36 mcman_PS1PDApagebuf
[127] = mcman_calcEDC(mcman_PS1PDApagebuf
, 127);
38 for (i
= 1; i
< 15; i
++) {
39 r
= McWritePS1PDACard(port
, slot
, i
, mcman_PS1PDApagebuf
);
40 if (r
!= sceMcResSucceed
)
44 memset(mcman_PS1PDApagebuf
, 0, 128);
46 *((u32
*)&mcman_PS1PDApagebuf
) = 0xffffffff;
48 for (i
= 0; i
< 20; i
++) {
49 *((u32
*)&mcman_PS1PDApagebuf
) = mcdi
->bad_block_list
[i
];
50 mcman_PS1PDApagebuf
[127] = mcman_calcEDC(mcman_PS1PDApagebuf
, 127);
52 r
= McWritePS1PDACard(port
, slot
, i
+ 16, mcman_PS1PDApagebuf
);
53 if (r
!= sceMcResSucceed
)
57 mcman_wmemset(mcman_PS1PDApagebuf
, 128, 0);
59 mcman_PS1PDApagebuf
[0] = 0x4d;
60 mcman_PS1PDApagebuf
[1] = 0x43;
61 mcman_PS1PDApagebuf
[127] = 0x0e;
63 r
= McWritePS1PDACard(port
, slot
, 0, mcman_PS1PDApagebuf
);
64 if (r
!= sceMcResSucceed
)
69 return sceMcResSucceed
;
72 //--------------------------------------------------------------
73 int mcman_open1(int port
, int slot
, char *filename
, int flags
)
75 register int r
, i
, fd
, cluster
, temp
;
76 register MC_FHANDLE
*fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
77 McFsEntryPS1
*fse
; //sp18
79 char *p
= (char *)filename
;
82 DPRINTF("mcman: mcman_open1 port%d slot%d filename %s flags %x\n", port
, slot
, filename
, flags
);
85 if ((flags
& sceMcFileCreateFile
) != 0)
86 flags
|= sceMcFileAttrWriteable
;
88 for (fd
= 0; fd
< MAX_FDHANDLES
; fd
++) {
89 fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
94 if (fd
== MAX_FDHANDLES
)
97 mcman_wmemset((void *)fh
, sizeof (MC_FHANDLE
), 0);
105 if ((*p
== 0) || ((*p
== '.') && (p
[1] == 0))) {
112 r
= mcman_getPS1direntry(port
, slot
, p
, &fse
, 1);
113 if ((fse
->mode
& 0xf0) == 0xa0)
119 if (fse
->field_7d
== 1)
120 fh
->filesize
= fse
->field_38
;
122 fh
->filesize
= fse
->length
;
127 fh
->rdflag
= flags
& sceMcFileAttrReadable
;
128 fh
->wrflag
= flags
& sceMcFileAttrWriteable
;
131 if ((flags
& sceMcFileCreateFile
) == 0) {
133 return sceMcResNoEntry
;
139 for (i
= 0; i
< MAX_FDHANDLES
; i
++) {
140 if ((mcman_fdhandles
[i
].status
!= 0) && \
141 (mcman_fdhandles
[i
].port
== port
) && (mcman_fdhandles
[i
].slot
== slot
) && \
142 (mcman_fdhandles
[i
].freeclink
== r
) && (fh
->wrflag
!= 0))
143 return sceMcResDeniedPermit
;
147 r
= mcman_clearPS1direntry(port
, slot
, r
, 0);
148 if (r
!= sceMcResSucceed
)
153 for (i
= 0; i
< 15; i
++) {
154 r
= mcman_readdirentryPS1(port
, slot
, i
, &fse
);
155 if (r
!= sceMcResSucceed
)
158 if ((fse
->mode
& 0xf0) == 0xa0) {
162 if (fse
->mode
!= 0xa0) {
164 mcman_wmemset((void *)fse
, sizeof(McFsEntryPS1
), 0);
166 fse
->linked_block
= -1;
167 fse
->edc
= mcman_calcEDC((void *)fse
, 127);
169 mce
= mcman_get1stcacheEntp();
176 mce
->wr_flag
|= 1 << ((i
+ 1) - ((temp
>> 3) << 3));
181 r
= mcman_flushmccache(port
, slot
);
182 if (r
!= sceMcResSucceed
)
186 return sceMcResFullDevice
;
188 r
= mcman_readdirentryPS1(port
, slot
, cluster
, &fse
);
189 if (r
!= sceMcResSucceed
)
192 mcman_wmemset((void *)fse
, sizeof(McFsEntryPS1
), 0);
196 fse
->linked_block
= -1;
198 strncpy(fse
->name
, p
, 20);
200 if ((flags
& sceMcFileAttrPDAExec
) != 0)
203 fse
->edc
= mcman_calcEDC((void *)fse
, 127);
204 fh
->freeclink
= cluster
;
206 mce
= mcman_get1stcacheEntp();
208 if ((cluster
+ 1) < 0)
213 mce
->wr_flag
|= 1 << ((cluster
+ 1) - ((temp
>> 3) << 3));
215 r
= mcman_flushmccache(port
, slot
);
216 if (r
!= sceMcResSucceed
)
225 //--------------------------------------------------------------
226 int mcman_read1(int fd
, void *buffer
, int nbyte
)
228 register int r
, size
, temp
, rpos
, offset
, maxsize
;
229 register MC_FHANDLE
*fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
231 u8
*p
= (u8
*)buffer
;
233 if (fh
->position
>= fh
->filesize
)
236 if (nbyte
>= (fh
->filesize
- fh
->position
))
237 nbyte
= fh
->filesize
- fh
->position
;
242 if (fh
->position
< 0)
243 temp
= fh
->position
+ 0x3ff;
247 offset
= (fh
->position
- ((temp
>> 10) << 10));
248 maxsize
= MCMAN_CLUSTERSIZE
- offset
;
254 r
= mcman_fatRseekPS1(fd
);
258 r
= mcman_readclusterPS1(fh
->port
, fh
->slot
, r
, &mce
);
259 if (r
!= sceMcResSucceed
)
262 memcpy(&p
[rpos
], (void *)(mce
->cl_data
+ offset
), size
);
266 fh
->position
+= size
;
274 //--------------------------------------------------------------
275 int mcman_write1(int fd
, void *buffer
, int nbyte
)
277 register int r
, size
, temp
, wpos
, offset
, maxsize
;
278 register MC_FHANDLE
*fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
280 u8
*p
= (u8
*)buffer
;
283 if (fh
->unknown2
== 0) {
285 r
= mcman_close1(fd
);
286 if (r
!= sceMcResSucceed
)
288 r
= mcman_flushmccache(fh
->port
, fh
->slot
);
289 if (r
!= sceMcResSucceed
)
298 r
= mcman_fatRseekPS1(fd
);
300 if (r
== sceMcResFullDevice
) {
301 r
= mcman_fatWseekPS1(fd
);
302 if (r
== sceMcResFullDevice
)
304 if (r
!= sceMcResSucceed
)
307 r
= mcman_fatRseekPS1(fd
);
314 r
= mcman_readclusterPS1(fh
->port
, fh
->slot
, r
, &mce
);
315 if (r
!= sceMcResSucceed
)
318 if (fh
->position
< 0)
319 temp
= fh
->position
+ 0x3ff;
323 offset
= fh
->position
- ((temp
>> 10) << 10);
324 maxsize
= MCMAN_CLUSTERSIZE
- offset
;
330 memcpy((void *)(mce
->cl_data
+ offset
), &p
[wpos
], size
);
333 fh
->position
+= size
;
334 if (fh
->position
>= fh
->filesize
)
335 fh
->filesize
= fh
->position
;
349 //--------------------------------------------------------------
350 int mcman_dread1(int fd
, fio_dirent_t
*dirent
)
353 register MC_FHANDLE
*fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
356 if (fh
->position
< fh
->filesize
) {
358 r
= mcman_readdirentryPS1(fh
->port
, fh
->slot
, fh
->position
, &fse
);
359 if (r
!= sceMcResSucceed
)
362 if (fse
->mode
== 0x51)
365 } while (++fh
->position
< fh
->filesize
);
368 if (fh
->position
>= fh
->filesize
)
372 mcman_wmemset((void *)dirent
, sizeof(fio_dirent_t
), 0);
374 strncpy(dirent
->name
, fse
->name
, 20);
375 dirent
->name
[20] = 0;
377 dirent
->stat
.mode
= 0x101f;
379 if (fse
->field_7e
== 1)
380 dirent
->stat
.mode
= 0x181f;
382 if (fse
->field_7d
== 1) {
383 *((u32
*)&dirent
->stat
.ctime
) = *((u32
*)&fse
->created
);
384 *((u32
*)&dirent
->stat
.ctime
+ 1) = *((u32
*)&fse
->created
+ 1);
385 *((u32
*)&dirent
->stat
.mtime
) = *((u32
*)&fse
->modified
);
386 *((u32
*)&dirent
->stat
.mtime
+ 1) = *((u32
*)&fse
->modified
+ 1);
387 dirent
->stat
.size
= fse
->field_38
;
388 dirent
->stat
.attr
= fse
->field_28
;
391 dirent
->stat
.size
= fse
->length
;
397 //--------------------------------------------------------------
398 int mcman_getstat1(int port
, int slot
, char *filename
, fio_stat_t
*stat
)
404 DPRINTF("mcman: mcman_getstat1 port%d slot%d filename %s\n", port
, slot
, filename
);
407 r
= mcman_getPS1direntry(port
, slot
, filename
, &fse
, 1);
409 if ((fse
->mode
& 0xf0) == 0xa0)
413 return sceMcResNoEntry
;
415 mcman_wmemset(stat
, sizeof(fio_stat_t
), 0);
419 if (fse
->field_7d
== 1) {
421 if ((fse
->field_2c
& sceMcFileAttrClosed
) != 0)
424 *((u32
*)&stat
->ctime
) = *((u32
*)&fse
->created
);
425 *((u32
*)&stat
->ctime
+1) = *((u32
*)&fse
->created
+1);
426 *((u32
*)&stat
->mtime
) = *((u32
*)&fse
->modified
);
427 *((u32
*)&stat
->mtime
+1) = *((u32
*)&fse
->modified
+1);
429 stat
->size
= fse
->field_38
;
430 stat
->attr
= fse
->field_28
;
432 return sceMcResSucceed
;
435 stat
->size
= fse
->length
;
437 return sceMcResSucceed
;
440 //--------------------------------------------------------------
441 int mcman_setinfo1(int port
, int slot
, char *filename
, sceMcTblGetDir
*info
, int flags
)
443 register int r
, temp
, ret
;
444 McFsEntryPS1
*fse1
, *fse2
;
448 DPRINTF("mcman: mcman_setinfo1 port%d slot%d filename %s flags %x\n", port
, slot
, filename
, flags
);
452 if (sio2man_type
== XSIO2MAN
) {
453 if ((flags
& sceMcFileAttrFile
) != 0) {
454 r
= mcman_getPS1direntry(port
, slot
, info
->EntryName
, &fse1
, 1);
456 if (r
!= sceMcResNoEntry
) {
460 if ((!strcmp(".", info
->EntryName
)) || (!strcmp("..", info
->EntryName
)) || (info
->EntryName
[0] == 0))
461 ret
= sceMcResNoEntry
;
467 r
= mcman_getPS1direntry(port
, slot
, filename
, &fse2
, 1);
469 if ((fse2
->mode
& 0xf0) == 0)
475 if (sio2man_type
== XSIO2MAN
) {
476 if (ret
!= sceMcResSucceed
)
477 return sceMcResNoEntry
;
480 mce
= mcman_get1stcacheEntp();
486 mce
->wr_flag
|= 1 << ((r
+ 1) - ((temp
>> 3) << 3));
488 if (sio2man_type
== XSIO2MAN
) {
494 if(fse2
->field_7d
!= 1) {
496 fse2
->field_38
= fse2
->length
;
500 if ((flags
& sceMcFileAttrExecutable
) != 0) {
501 if ((info
->AttrFile
& sceMcFileAttrPDAExec
) != 0)
507 //Special fix clause for file managers (like uLaunchELF)
508 //This allows writing most entries that can be read by mcGetDir
509 //and without usual restrictions. This flags value should cause no conflict
510 //as Sony code never uses it, and the value is changed after its use here.
511 //This is primarily needed for PS2 MC backups, but must be implemented here
512 //too since the 'flags' argument may be used indiscriminately for both
514 flags
= sceMcFileAttrReadable
|sceMcFileAttrWriteable
;
515 //The changed flags value allows more entries to be copied below
518 if ((flags
& sceMcFileAttrDupProhibit
) != 0)
519 fse2
->field_28
= info
->Reserve2
;
521 if ((flags
& sceMcFileAttrReadable
) != 0)
522 fse2
->created
= info
->_Create
;
524 if ((flags
& sceMcFileAttrWriteable
) != 0)
525 fse2
->modified
= info
->_Modify
;
527 if ((flags
& sceMcFileAttrFile
) != 0)
528 strncpy(fse2
->name
, info
->EntryName
, 20);
532 r
= mcman_flushmccache(port
, slot
);
537 //--------------------------------------------------------------
538 int mcman_getdir1(int port
, int slot
, char *dirname
, int flags
, int maxent
, sceMcTblGetDir
*info
)
545 DPRINTF("mcman: mcman_getdir1 port%d slot%d dirname %s maxent %d flags %x\n", port
, slot
, dirname
, maxent
, flags
);
553 mcman_PS1curcluster
= 0;
556 r
= mcman_chrpos(p
, '/');
559 p
+= mcman_chrpos(p
, '/') + 1;
562 strncpy(mcman_PS1curdir
, p
, 63);
568 if (mcman_PS1curcluster
>= 15)
571 r
= mcman_readdirentryPS1(port
, slot
, mcman_PS1curcluster
, &fse
);
572 if (r
!= sceMcResSucceed
)
575 mcman_PS1curcluster
++;
577 if (fse
->mode
!= 0x51)
580 if (!mcman_checkdirpath(fse
->name
, mcman_PS1curdir
))
583 memset((void *)info
, 0, sizeof (sceMcTblGetDir
));
585 info
->AttrFile
= 0x9417;
587 if (fse
->field_7e
== 1)
588 info
->AttrFile
= 0x9c17; //MC_ATTR_PDAEXEC set !!!
590 if (fse
->field_7d
== 1) {
591 if ((fse
->field_2c
& sceMcFileAttrClosed
) != 0) {
592 info
->AttrFile
|= sceMcFileAttrClosed
;
594 info
->Reserve1
= fse
->field_2e
;
595 info
->_Create
= fse
->created
;
596 info
->_Modify
= fse
->modified
;
597 info
->FileSizeByte
= fse
->field_38
;
598 info
->Reserve2
= fse
->field_28
;
601 info
->FileSizeByte
= fse
->length
;
604 strncpy(info
->EntryName
, fse
->name
, 20);
605 info
->EntryName
[20] = 0;
615 //--------------------------------------------------------------
616 int mcman_delete1(int port
, int slot
, char *filename
, int flags
)
622 DPRINTF("mcman: mcman_delete1 port%d slot%d filename %s flags %x\n", port
, slot
, filename
, flags
);
625 r
= mcman_getPS1direntry(port
, slot
, filename
, &fse
, ((u32
)flags
< 1) ? 1 : 0);
629 r
= mcman_clearPS1direntry(port
, slot
, r
, flags
);
634 //--------------------------------------------------------------
635 int mcman_close1(int fd
)
637 register int r
, temp
;
638 MC_FHANDLE
*fh
= (MC_FHANDLE
*)&mcman_fdhandles
[fd
];
643 DPRINTF("mcman: mcman_close1 fd %d\n", fd
);
646 r
= mcman_readdirentryPS1(fh
->port
, fh
->slot
, fh
->freeclink
, &fse
);
647 if (r
!= sceMcResSucceed
)
650 mce
= mcman_get1stcacheEntp();
652 if (fh
->freeclink
+ 1 < 0)
653 temp
= fh
->freeclink
+ 8;
655 temp
= fh
->freeclink
+ 1;
657 mce
->wr_flag
|= 1 << ((fh
->freeclink
+ 1) - ((temp
>> 3) << 3));
659 if (fh
->filesize
== 0) {
660 fse
->length
= 0x2000;
663 if ((fh
->filesize
- 1) < 0)
664 temp
= (fh
->filesize
+ 8190) >> 13;
666 temp
= (fh
->filesize
- 1) >> 13;
669 fse
->length
= temp
<< 13;
672 if (sio2man_type
== XSIO2MAN
) {
673 fse
->field_7d
= 0; // <--- To preserve for XMCMAN
674 fse
->field_2c
= 0; //
675 fse
->field_38
= 0; //
676 memset((void *)&fse
->created
, 0, 8); //
677 memset((void *)&fse
->modified
, 0, 8); //
679 else { // MCMAN does as following
681 fse
->field_38
= fh
->filesize
;
682 mcman_getmcrtime(&fse
->modified
);
685 fse
->edc
= mcman_calcEDC((void *)fse
, 127);
687 r
= mcman_flushmccache(fh
->port
, fh
->slot
);
688 if (r
!= sceMcResSucceed
)
691 return sceMcResSucceed
;
694 //--------------------------------------------------------------
695 int mcman_unformat1(int port
, int slot
)
701 DPRINTF("mcman: mcman_unformat1 port%d slot%d\n", port
, slot
);
704 p
= (u32
*)&mcman_PS1PDApagebuf
;
705 for (i
= 0; i
< 32; i
++)
708 for (i
= 0; i
< 1024; i
++) {
709 r
= McWritePS1PDACard(port
, slot
, i
, mcman_PS1PDApagebuf
);
710 if (r
!= sceMcResSucceed
)
717 //--------------------------------------------------------------