PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
ps1mc_fio.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright (c) 2009 jimmikaelkael
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <mcman.h>
12#include "mcman-internal.h"
13
14static int mcman_PS1curcluster;
15static char mcman_PS1curdir[64];
16
17//--------------------------------------------------------------
18int mcman_format1(int port, int slot)
19{
20 register int r, i;
21 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
22
23 DPRINTF("mcman_format1 port%d slot%d\n", port, slot);
24
25 mcman_invhandles(port, slot);
26
27 mcdi->cardform = -1;
28
29 for (i = 0; i < 56; i++) {
30 r = mcman_PS1pagetest(port, slot, i);
31 if (r == 0)
32 return sceMcResNoFormat;
33 if (r != 1)
34 return -41;
35 }
36
37 memset(&mcman_PS1PDApagebuf, 0, 128);
38
39 mcman_PS1PDApagebuf.word[0] = 0xa0;
40 mcman_PS1PDApagebuf.half[2] = 0xffff;
41
42 mcman_PS1PDApagebuf.byte[127] = mcman_calcEDC(&mcman_PS1PDApagebuf, 127);
43
44 for (i = 1; i < 15; i++) {
45 r = McWritePS1PDACard(port, slot, i, &mcman_PS1PDApagebuf);
46 if (r != sceMcResSucceed)
47 return -42;
48 }
49
50 memset(&mcman_PS1PDApagebuf, 0, 128);
51
52 mcman_PS1PDApagebuf.word[0] = 0xffffffff;
53
54 for (i = 0; i < 20; i++) {
55 mcman_PS1PDApagebuf.word[0] = mcdi->bad_block_list[i];
56 mcman_PS1PDApagebuf.byte[127] = mcman_calcEDC(&mcman_PS1PDApagebuf, 127);
57
58 r = McWritePS1PDACard(port, slot, i + 16, &mcman_PS1PDApagebuf);
59 if (r != sceMcResSucceed)
60 return -43;
61 }
62
63 mcman_wmemset(&mcman_PS1PDApagebuf, 128, 0);
64
65 mcman_PS1PDApagebuf.byte[0] = 0x4d;
66 mcman_PS1PDApagebuf.byte[1] = 0x43;
67 mcman_PS1PDApagebuf.byte[127] = 0x0e;
68
69 r = McWritePS1PDACard(port, slot, 0, &mcman_PS1PDApagebuf);
70 if (r != sceMcResSucceed)
71 return -44;
72
73 mcdi->cardform = 1;
74
75 return sceMcResSucceed;
76}
77
78//--------------------------------------------------------------
79int mcman_open1(int port, int slot, const char *filename, int flags)
80{
81 register int r, i, fd = 0, cluster, temp;
82 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
83 McFsEntryPS1 *fse; //sp18
84 McCacheEntry *mce;
85 const char *p = filename;
86
87 DPRINTF("mcman_open1 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
88
89 if ((flags & sceMcFileCreateFile) != 0)
90 flags |= sceMcFileAttrWriteable;
91
92 for (fd = 0; fd < MAX_FDHANDLES; fd++) {
93 fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
94 if (fh->status == 0)
95 break;
96 }
97
98 if (fd == MAX_FDHANDLES)
99 return -7;
100
101 mcman_wmemset((void *)fh, sizeof (MC_FHANDLE), 0);
102
103 fh->port = port;
104 fh->slot = slot;
105
106 if (*p == '/')
107 p++;
108
109 if ((*p == 0) || ((*p == '.') && (p[1] == 0))) {
110 fh->filesize = 15;
111 fh->drdflag = 1;
112 fh->status = 1;
113 return fd;
114 }
115
116 r = mcman_getPS1direntry(port, slot, p, &fse, 1);
117 if ((fse->mode & 0xf0) == 0xa0)
118 r = -4;
119
120 fh->freeclink = r;
121
122 if (r >= 0) {
123 if (fse->field_7d == 1)
124 fh->filesize = fse->field_38;
125 else
126 fh->filesize = fse->length;
127 }
128 else
129 fh->filesize = 0;
130
131 fh->rdflag = flags & sceMcFileAttrReadable;
132 fh->wrflag = flags & sceMcFileAttrWriteable;
133 fh->unknown1 = 0;
134
135 if ((flags & sceMcFileCreateFile) == 0) {
136 if (r < 0)
137 return sceMcResNoEntry;
138
139 fh->status = 1;
140 return fd;
141 }
142
143 for (i = 0; i < MAX_FDHANDLES; i++) {
144 if ((mcman_fdhandles[i].status != 0) && \
145 (mcman_fdhandles[i].port == port) && (mcman_fdhandles[i].slot == slot) && \
146 (mcman_fdhandles[i].freeclink == (u32)r) && (fh->wrflag != 0))
147 return sceMcResDeniedPermit;
148 }
149
150 if (r >= 0) {
151 r = mcman_clearPS1direntry(port, slot, r, 0);
152 if (r != sceMcResSucceed)
153 return r;
154 }
155
156 cluster = -1;
157 for (i = 0; i < 15; i++) {
158 r = mcman_readdirentryPS1(port, slot, i, &fse);
159 if (r != sceMcResSucceed)
160 return r;
161
162 if ((fse->mode & 0xf0) == 0xa0) {
163 if (cluster < 0)
164 cluster = i;
165
166 if (fse->mode != 0xa0) {
167
168 mcman_wmemset((void *)fse, sizeof(McFsEntryPS1), 0);
169 fse->mode = 0xa0;
170 fse->linked_block = -1;
171 fse->edc = mcman_calcEDC((void *)fse, 127);
172
173 mce = mcman_get1stcacheEntp();
174
175#if 0
176 // This condition is always false because "i" starts at 0 and increments.
177 if ((i + 1) < 0)
178 {
179 temp = i + 8;
180 }
181 else
182#endif
183 {
184 temp = i + 1;
185 }
186
187 temp &= ~0x00000007;
188 temp = (i + 1) - temp;
189#if 0
190 // This condition is always false due to the preceding set of assignments on "temp" variable.
191 if (temp < 0)
192 temp = 0;
193#endif
194
195 mce->wr_flag |= 1 << temp;
196 }
197 }
198 }
199
200 r = McFlushCache(port, slot);
201 if (r != sceMcResSucceed)
202 return r;
203
204 if (cluster < 0)
205 return sceMcResFullDevice;
206
207 r = mcman_readdirentryPS1(port, slot, cluster, &fse);
208 if (r != sceMcResSucceed)
209 return r;
210
211 mcman_wmemset((void *)fse, sizeof(McFsEntryPS1), 0);
212
213 fse->mode = 0x51;
214 fse->length = 0;
215 fse->linked_block = -1;
216
217 strncpy(fse->name, p, 20);
218
219 if ((flags & sceMcFileAttrPDAExec) != 0)
220 fse->field_7e = 1;
221
222 fse->edc = mcman_calcEDC((void *)fse, 127);
223 fh->freeclink = cluster;
224
225 mce = mcman_get1stcacheEntp();
226
227#if 0
228 // This condition is always false due to the preceding check on "cluster" variable.
229 if ((cluster + 1) < 0)
230 {
231 temp = cluster + 8;
232 }
233 else
234#endif
235 {
236 temp = cluster + 1;
237 }
238
239 temp &= ~0x00000007;
240 temp = (cluster + 1) - temp;
241 if (temp < 0)
242 temp = 0;
243
244 mce->wr_flag |= 1 << temp;
245
246 r = McFlushCache(port, slot);
247 if (r != sceMcResSucceed)
248 return r;
249
250 fh->unknown2 = 1;
251 fh->status = 1;
252
253 return fd;
254}
255
256//--------------------------------------------------------------
257int mcman_read1(int fd, void *buffer, int nbyte)
258{
259 register int rpos;
260 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
261 McCacheEntry *mce;
262 u8 *p = (u8 *)buffer;
263
264 if (fh->position >= fh->filesize)
265 return 0;
266
267 if ((u32)nbyte >= (fh->filesize - fh->position))
268 nbyte = fh->filesize - fh->position;
269
270 rpos = 0;
271 if (nbyte) {
272 do {
273 register int r, size, temp, offset, maxsize;
274
275 if ((int)(fh->position) < 0)
276 temp = fh->position + 0x3ff;
277 else
278 temp = fh->position;
279
280 offset = (fh->position - (temp & ~0x000003ff));
281 maxsize = MCMAN_CLUSTERSIZE - offset;
282 if (maxsize < nbyte)
283 size = maxsize;
284 else
285 size = nbyte;
286
287 r = mcman_fatRseekPS1(fd);
288 if (r < 0)
289 return r;
290
291 r = mcman_readclusterPS1(fh->port, fh->slot, r, &mce);
292 if (r != sceMcResSucceed)
293 return r;
294
295 memcpy(&p[rpos], (void *)(mce->cl_data + offset), size);
296
297 rpos += size;
298 nbyte -= size;
299 fh->position += size;
300
301 } while (nbyte);
302 }
303
304 return rpos;
305}
306
307//--------------------------------------------------------------
308int mcman_write1(int fd, void *buffer, int nbyte)
309{
310 register int r, wpos;
311 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
312 McCacheEntry *mce;
313 u8 *p = (u8 *)buffer;
314
315 if (nbyte) {
316 if (fh->unknown2 == 0) {
317 fh->unknown2 = 1;
318 r = mcman_close1(fd);
319 if (r != sceMcResSucceed)
320 return r;
321 r = McFlushCache(fh->port, fh->slot);
322 if (r != sceMcResSucceed)
323 return r;
324 }
325 }
326
327 wpos = 0;
328 if (nbyte) {
329
330 do {
331 register int size, temp, offset, maxsize;
332
333 r = mcman_fatRseekPS1(fd);
334
335 if (r == sceMcResFullDevice) {
336 r = mcman_fatWseekPS1(fd);
337 if (r == sceMcResFullDevice)
338 return r;
339 if (r!= sceMcResSucceed)
340 return r;
341
342 r = mcman_fatRseekPS1(fd);
343 }
344 else {
345 if (r < 0)
346 return r;
347 }
348
349 r = mcman_readclusterPS1(fh->port, fh->slot, r, &mce);
350 if (r != sceMcResSucceed)
351 return r;
352
353 if ((int)(fh->position) < 0)
354 temp = fh->position + 0x3ff;
355 else
356 temp = fh->position;
357
358 offset = fh->position - (temp & ~0x000003ff);
359 maxsize = MCMAN_CLUSTERSIZE - offset;
360 if (maxsize < nbyte)
361 size = maxsize;
362 else
363 size = nbyte;
364
365 memcpy((void *)(mce->cl_data + offset), &p[wpos], size);
366
367 mce->wr_flag = -1;
368 fh->position += size;
369 if (fh->position >= fh->filesize)
370 fh->filesize = fh->position;
371
372 nbyte -= size;
373 wpos += size;
374
375 } while (nbyte);
376
377 }
378
379 mcman_close1(fd);
380
381 return wpos;
382}
383
384//--------------------------------------------------------------
385int mcman_dread1(int fd, MC_IO_DRE_T *dirent)
386{
387 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
388 McFsEntryPS1 *fse;
389
390 if (fh->position < fh->filesize) {
391 do {
392 register int r;
393
394 r = mcman_readdirentryPS1(fh->port, fh->slot, fh->position, &fse);
395 if (r != sceMcResSucceed)
396 return r;
397
398 if (fse->mode == 0x51)
399 break;
400
401 } while (++fh->position < fh->filesize);
402 }
403
404 if (fh->position >= fh->filesize)
405 return 0;
406
407 fh->position++;
408 mcman_wmemset((void *)dirent, sizeof(MC_IO_DRE_T), 0);
409
410 strncpy(dirent->name, fse->name, 20);
411 dirent->name[20] = 0;
412
413 dirent->stat.mode = MC_IO_S_RD | MC_IO_S_WR | MC_IO_S_EX | MC_IO_S_FL;
414
415#if !MCMAN_ENABLE_EXTENDED_DEV_OPS
416 dirent->stat.mode |= sceMcFileAttrDupProhibit | sceMcFileAttrPS1;
417
418 if (fse->field_7e == 1)
419 dirent->stat.mode |= sceMcFileAttrPDAExec;
420#endif
421
422 if (fse->field_7d == 1) {
423 memcpy(dirent->stat.ctime, &fse->created, sizeof(sceMcStDateTime));
424 memcpy(dirent->stat.mtime, &fse->modified, sizeof(sceMcStDateTime));
425 dirent->stat.size = fse->field_38;
426 dirent->stat.attr = fse->field_28;
427 }
428 else {
429 dirent->stat.size = fse->length;
430 }
431
432 return 1;
433}
434
435//--------------------------------------------------------------
436int mcman_getstat1(int port, int slot, const char *filename, MC_IO_STA_T *stat)
437{
438 register int r;
439 McFsEntryPS1 *fse;
440
441 DPRINTF("mcman_getstat1 port%d slot%d filename %s\n", port, slot, filename);
442
443 r = mcman_getPS1direntry(port, slot, filename, &fse, 1);
444
445 if ((fse->mode & 0xf0) == 0xa0)
446 r = -4;
447
448 if (r < 0)
449 return sceMcResNoEntry;
450
451 mcman_wmemset(stat, sizeof(MC_IO_STA_T), 0);
452
453 stat->mode = MC_IO_S_RD | MC_IO_S_WR | MC_IO_S_EX | MC_IO_S_FL;
454
455#if !MCMAN_ENABLE_EXTENDED_DEV_OPS
456 stat->mode |= sceMcFileAttrDupProhibit;
457#endif
458
459 if (fse->field_7d == 1) {
460
461#if !MCMAN_ENABLE_EXTENDED_DEV_OPS
462 if ((fse->field_2c & sceMcFileAttrClosed) != 0)
463 stat->mode |= sceMcFileAttrClosed;
464#endif
465
466 memcpy(stat->ctime, &fse->created, sizeof(sceMcStDateTime));
467 memcpy(stat->mtime, &fse->modified, sizeof(sceMcStDateTime));
468
469 stat->size = fse->field_38;
470 stat->attr = fse->field_28;
471
472 return sceMcResSucceed;
473 }
474
475 stat->size = fse->length;
476
477 return sceMcResSucceed;
478}
479
480//--------------------------------------------------------------
481int mcman_setinfo1(int port, int slot, const char *filename, sceMcTblGetDir *info, int flags)
482{
483 register int r, temp, ret;
484#ifdef BUILDING_XMCMAN
485 McFsEntryPS1 *fse1;
486#endif
487 McFsEntryPS1 *fse2;
488 McCacheEntry *mce;
489
490 DPRINTF("mcman_setinfo1 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
491
492 ret = 0;
493#ifdef BUILDING_XMCMAN
494 if ((flags & sceMcFileAttrFile) != 0) {
495 r = mcman_getPS1direntry(port, slot, info->EntryName, &fse1, 1);
496 if (r < 0) {
497 if (r != sceMcResNoEntry) {
498 ret = r;
499 }
500 else {
501 if ((!strcmp(".", info->EntryName)) || (!strcmp("..", info->EntryName)) || (info->EntryName[0] == 0))
502 ret = sceMcResNoEntry;
503 }
504 }
505 }
506#endif
507
508 r = mcman_getPS1direntry(port, slot, filename, &fse2, 1);
509
510 if ((fse2->mode & 0xf0) == 0)
511 r = sceMcResNoEntry;
512
513 if (r < 0)
514 return r;
515
516 if (ret != sceMcResSucceed)
517 return sceMcResNoEntry;
518
519 mce = mcman_get1stcacheEntp();
520
521 temp = r + 1;
522#if 0
523 // This condition is always false due to the preceding check on "r" variable.
524 if ((r + 1) < 0)
525 temp = r + 8;
526#endif
527
528 temp &= ~0x00000007;
529 temp = (r + 1) - temp;
530 if (temp < 0)
531 temp = 0;
532
533 mce->wr_flag |= 1 << temp;
534
535#ifdef BUILDING_XMCMAN
536 fse2->field_7d = 0;
537 fse2->field_2c = 0;
538 flags &= -12;
539#else
540 if(fse2->field_7d != 1) {
541 fse2->field_7d = 1;
542 fse2->field_38 = fse2->length;
543 }
544#endif
545
546 if ((flags & sceMcFileAttrExecutable) != 0) {
547 if ((info->AttrFile & sceMcFileAttrPDAExec) != 0)
548 fse2->field_7e = 1;
549 else
550 fse2->field_7e = 0;
551 }
552
553 //Special fix clause for file managers (like uLaunchELF)
554 //This allows writing most entries that can be read by mcGetDir
555 //and without usual restrictions. This flags value should cause no conflict
556 //as Sony code never uses it, and the value is changed after its use here.
557 //This is primarily needed for PS2 MC backups, but must be implemented here
558 //too since the 'flags' argument may be used indiscriminately for both
559 if(flags == 0xFEED){
560 flags = sceMcFileAttrReadable|sceMcFileAttrWriteable;
561 //The changed flags value allows more entries to be copied below
562 }
563
564 if ((flags & sceMcFileAttrDupProhibit) != 0)
565 fse2->field_28 = info->Reserve2;
566
567 if ((flags & sceMcFileAttrReadable) != 0)
568 fse2->created = info->_Create;
569
570 if ((flags & sceMcFileAttrWriteable) != 0)
571 fse2->modified = info->_Modify;
572
573 if ((flags & sceMcFileAttrFile) != 0)
574 strncpy(fse2->name, info->EntryName, 20);
575
576 fse2->field_1e = 0;
577
578 r = McFlushCache(port, slot);
579
580 return r;
581}
582
583//--------------------------------------------------------------
584int mcman_getdir1(int port, int slot, const char *dirname, int flags, int maxent, sceMcTblGetDir *info)
585{
586 register int r, i;
587 McFsEntryPS1 *fse;
588
589 DPRINTF("mcman_getdir1 port%d slot%d dirname %s maxent %d flags %x\n", port, slot, dirname, maxent, flags);
590
591 flags &= 0xffff;
592
593 i = 0;
594
595 if (!flags) {
596 const char *p;
597
598 mcman_PS1curcluster = 0;
599 p = dirname;
600 do {
601 r = mcman_chrpos(p, '/');
602 if (r < 0)
603 break;
604 p += mcman_chrpos(p, '/') + 1;
605 } while (1);
606
607 strncpy(mcman_PS1curdir, p, 63);
608
609 }
610
611 if (maxent) {
612 do {
613 if (mcman_PS1curcluster >= 15)
614 break;
615
616 r = mcman_readdirentryPS1(port, slot, mcman_PS1curcluster, &fse);
617 if (r != sceMcResSucceed)
618 return r;
619
620 mcman_PS1curcluster++;
621
622 if (fse->mode != 0x51)
623 continue;
624
625 if (!mcman_checkdirpath(fse->name, mcman_PS1curdir))
626 continue;
627
628 memset((void *)info, 0, sizeof (sceMcTblGetDir));
629
630 info->AttrFile = 0x9417;
631
632 if (fse->field_7e == 1)
633 info->AttrFile = 0x9c17; //MC_ATTR_PDAEXEC set !!!
634
635 if (fse->field_7d == 1) {
636 if ((fse->field_2c & sceMcFileAttrClosed) != 0) {
637 info->AttrFile |= sceMcFileAttrClosed;
638 }
639 info->Reserve1 = fse->field_2e;
640 info->_Create = fse->created;
641 info->_Modify = fse->modified;
642 info->FileSizeByte = fse->field_38;
643 info->Reserve2 = fse->field_28;
644 }
645 else {
646 info->FileSizeByte = fse->length;
647 }
648
649 strncpy(info->EntryName, fse->name, 20);
650 info->EntryName[20] = 0;
651
652 i++;
653 info++;
654 maxent--;
655 } while (maxent);
656 }
657 return i;
658}
659
660//--------------------------------------------------------------
661int mcman_delete1(int port, int slot, const char *filename, int flags)
662{
663 register int r;
664 McFsEntryPS1 *fse;
665
666 DPRINTF("mcman_delete1 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
667
668 r = mcman_getPS1direntry(port, slot, filename, &fse, ((u32)flags < 1) ? 1 : 0);
669 if (r < 0)
670 return r;
671
672 r = mcman_clearPS1direntry(port, slot, r, flags);
673
674 return r;
675}
676
677//--------------------------------------------------------------
678int mcman_close1(int fd)
679{
680 register int r, temp;
681 MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
682 McFsEntryPS1 *fse;
683 McCacheEntry *mce;
684
685 DPRINTF("mcman_close1 fd %d\n", fd);
686
687 r = mcman_readdirentryPS1(fh->port, fh->slot, fh->freeclink, &fse);
688#ifdef BUILDING_XMCMAN
689 if (r != sceMcResSucceed)
690 return -31;
691#endif
692
693 mce = mcman_get1stcacheEntp();
694
695 if ((int)(fh->freeclink + 1) < 0)
696 temp = fh->freeclink + 8;
697 else
698 temp = fh->freeclink + 1;
699
700 temp &= ~0x00000007;
701 temp = (fh->freeclink + 1) - temp;
702 if (temp < 0)
703 temp = 0;
704
705 mce->wr_flag |= 1 << temp;
706
707 if (fh->filesize == 0) {
708 fse->length = 0x2000;
709 }
710 else {
711 if ((int)(fh->filesize - 1) < 0)
712 temp = (fh->filesize + 8190) >> 13;
713 else
714 temp = (fh->filesize - 1) >> 13;
715
716 temp++;
717 fse->length = temp << 13;
718 }
719
720#ifdef BUILDING_XMCMAN
721 fse->field_7d = 0; // <--- To preserve for XMCMAN
722 fse->field_2c = 0; //
723 fse->field_38 = 0; //
724 memset((void *)&fse->created, 0, 8); //
725 memset((void *)&fse->modified, 0, 8); //
726#else
727 // MCMAN does as following
728 fse->field_7d = 1;
729 fse->field_38 = fh->filesize;
730 mcman_getmcrtime(&fse->modified);
731#endif
732
733 fse->edc = mcman_calcEDC((void *)fse, 127);
734
735 r = McFlushCache(fh->port, fh->slot);
736 if (r != sceMcResSucceed)
737 return r;
738
739 return sceMcResSucceed;
740}
741
742//--------------------------------------------------------------
743int mcman_unformat1(int port, int slot)
744{
745 register int r, i;
746 u32 *p;
747
748 DPRINTF("mcman_unformat1 port%d slot%d\n", port, slot);
749
750 p = mcman_PS1PDApagebuf.word;
751 for (i = 0; i < 32; i++)
752 *p++ = 0;
753
754 for (i = 0; i < 1024; i++) {
755 r = McWritePS1PDACard(port, slot, i, &mcman_PS1PDApagebuf);
756 if (r != sceMcResSucceed)
757 return -41;
758 }
759
760 return r;
761}
762
763//--------------------------------------------------------------