PS2SDK
PS2 Homebrew Libraries
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 
14 static int mcman_PS1curcluster;
15 static char mcman_PS1curdir[64];
16 
17 //--------------------------------------------------------------
18 int 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 //--------------------------------------------------------------
79 int 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 //--------------------------------------------------------------
257 int 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 //--------------------------------------------------------------
308 int 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 //--------------------------------------------------------------
385 int 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 //--------------------------------------------------------------
436 int 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 //--------------------------------------------------------------
481 int 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 //--------------------------------------------------------------
584 int 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 //--------------------------------------------------------------
661 int 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 //--------------------------------------------------------------
678 int 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 //--------------------------------------------------------------
743 int 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 //--------------------------------------------------------------
McFsEntryPS1
Definition: libmc-common.h:34
s_info
Definition: xprintf.c:78
_sceMcTblGetDir
Definition: libmc.h:139
_MCCacheEntry
Definition: libmc-common.h:69
MC_FHANDLE
Definition: mcman-internal.h:125
mcman_PS1PDApagebuf
Definition: mcman-internal.h:333
_sceMcStDateTime
Definition: libmc-common.h:22
MCDevInfo
Definition: mcman-internal.h:295
mcman.h