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