PS2SDK
PS2 Homebrew Libraries
main.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 #define SIO2MAN_EXPORTS_IMPLEMENTATION
12 #include <mcman.h>
13 #include "mcman-internal.h"
14 
15 // TODO: last sdk 3.1.0 has MCMAN module version 0x2,0x30 with significant changes.
16 // Check what was changed, and maybe port changes.
17 // CRC32: EC5F33F9
18 // Note: currently is based on the last XMCMAN from BOOTROM:
19 // 0x02,0x0a (looks like mistake, cause last XMCMAN is 0x02,0x09)
20 IRX_ID(MODNAME, 2, 11);
21 
22 char SUPERBLOCK_MAGIC[] = "Sony PS2 Memory Card Format ";
23 char SUPERBLOCK_VERSION[] = "1.2.0.0";
24 
25 int mcman_wr_port = -1;
26 int mcman_wr_slot = -1;
27 int mcman_wr_block = -1;
28 int mcman_wr_flag3 = -10;
29 int mcman_curdircluster = -1;
30 
31 #if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
32 int timer_ID;
33 #endif
34 int PS1CardFlag = 1;
35 
38 
39 #if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
40 extern struct irx_export_table _exp_mcman;
41 #elif defined(BUILDING_XFROMMAN)
42 extern struct irx_export_table _exp_xfromman;
43 #endif
44 
45 static u8 mcman_cachebuf[MAX_CACHEENTRY * MCMAN_CLUSTERSIZE];
46 static McCacheEntry mcman_entrycache[MAX_CACHEENTRY];
47 static McCacheEntry *mcman_mccache[MAX_CACHEENTRY];
48 
49 static McCacheEntry *pmcman_entrycache;
50 static McCacheEntry **pmcman_mccache;
51 
52 static void *mcman_pagedata[32];
53 static u8 mcman_backupbuf[16384];
54 
55 static int mcman_badblock_port;
56 static int mcman_badblock_slot;
57 static int mcman_badblock;
58 static int mcman_replacementcluster[16];
59 
60 static McFatCache mcman_fatcache[2][MCMAN_MAXSLOT];
61 McFsEntry mcman_dircache[MAX_CACHEDIRENTRY];
62 
63 MC_FHANDLE mcman_fdhandles[MAX_FDHANDLES];
64 MCDevInfo mcman_devinfos[4][MCMAN_MAXSLOT];
65 
66 u8 mcman_eccdata[512]; // size for 32 ecc
67 
68 // mcman xor table
69 // clang-format off
70 static const u8 mcman_xortable[256] = {
71  0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4,
72  0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00,
73  0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77,
74  0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3,
75  0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66,
76  0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2,
77  0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5,
78  0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11,
79  0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55,
80  0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1,
81  0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96,
82  0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22,
83  0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87,
84  0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33,
85  0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44,
86  0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0,
87  0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44,
88  0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0,
89  0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87,
90  0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33,
91  0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96,
92  0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22,
93  0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55,
94  0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1,
95  0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5,
96  0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11,
97  0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66,
98  0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2,
99  0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77,
100  0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3,
101  0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4,
102  0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00
103 };
104 // clang-format on
105 
106 #ifdef BUILDING_DONGLEMAN
107 int sema_hakama_id = 0;
108 #endif
109 
110 //--------------------------------------------------------------
111 void long_multiply(u32 v1, u32 v2, u32 *HI, u32 *LO)
112 {
113  register long a, b, c, d;
114  register long x, y;
115 
116  a = (v1 >> 16) & 0xffff;
117  b = v1 & 0xffff;
118  c = (v2 >> 16) & 0xffff;
119  d = v2 & 0xffff;
120 
121  *LO = b * d;
122  x = a * d + c * b;
123  y = ((*LO >> 16) & 0xffff) + x;
124 
125  *LO = (*LO & 0xffff) | ((y & 0xffff) << 16);
126  *HI = (y >> 16) & 0xffff;
127 
128  *HI += a * c;
129 }
130 
131 //--------------------------------------------------------------
132 int mcman_chrpos(const char *str, int chr)
133 {
134  const char *p;
135 
136  p = str;
137  if (*str) {
138  do {
139  if (*p == (chr & 0xff))
140  break;
141  p++;
142  } while (*p);
143  }
144  if (*p != (chr & 0xff))
145  return -1;
146 
147  return p - str;
148 }
149 //--------------------------------------------------------------
150 #ifdef _IOP
151 int MCMAN_ENTRYPOINT(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
152 #else
153 int MCMAN_ENTRYPOINT(int argc, char *argv[])
154 #endif
155 {
156  struct irx_export_table *export_tbl;
157  (void)argc;
158  (void)argv;
159 
160 #ifdef SIO_DEBUG
161  sio_init(38400, 0, 0, 0, 0);
162 #endif
163  DPRINTF("_start...\n");
164 
165 #if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
166  export_tbl = &_exp_mcman;
167 #elif defined(BUILDING_XFROMMAN)
168  export_tbl = &_exp_xfromman;
169 #else
170  export_tbl = NULL;
171 #endif
172 
173 #ifdef _IOP
174  if (argc < 0)
175  {
176  int release_res;
177  int state;
178 
179  release_res = 0;
180  // cppcheck-suppress knownConditionTrueFalse
181  if (export_tbl != NULL)
182  {
183  CpuSuspendIntr(&state);
184  release_res = ReleaseLibraryEntries(export_tbl);
185  CpuResumeIntr(state);
186  }
187  if (release_res == 0 || release_res == -213)
188  {
189  mcman_deinitdev();
190  McCloseAll();
191  mcman_deinitPS2com();
192  mcman_deinitPS1PDAcom();
193  return MODULE_NO_RESIDENT_END;
194  }
195  return MODULE_REMOVABLE_END;
196  }
197 #endif
198 
199  DPRINTF("registering exports...\n");
200  // cppcheck-suppress knownConditionTrueFalse
201  if (export_tbl != NULL)
202  {
203  if (RegisterLibraryEntries(export_tbl) != 0)
204  return MODULE_NO_RESIDENT_END;
205  }
206 
207 #ifdef _IOP
208  CpuEnableIntr();
209 #endif
210 
211  DPRINTF("initPS2com...\n");
212  mcman_initPS2com();
213 
214  DPRINTF("initPS1PDAcom...\n");
215  mcman_initPS1PDAcom();
216 
217  DPRINTF("initcache...\n");
218  mcman_initcache();
219 
220  DPRINTF("initdev...\n");
221  mcman_initdev();
222 
223 #if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
224  timer_ID = ReferHardTimer(1, 32, 0, 0x6309);
225 
226  if (timer_ID != -150)
227  return MODULE_RESIDENT_END;
228 
229  timer_ID = AllocHardTimer(1, 32, 1);
230 
231  if (timer_ID > 0)
232  SetTimerMode(timer_ID, 0);
233 #endif
234 
235  DPRINTF("_start returns MODULE_RESIDENT_END...\n");
236 
237 #ifdef _IOP
238  if (mi && ((mi->newflags & 2) != 0))
239  mi->newflags |= 0x10;
240 #endif
241  return MODULE_RESIDENT_END;
242 }
243 
244 //--------------------------------------------------------------
245 int McGetFormat(int port, int slot) // Export #22 XMCMAN only
246 {
247  DPRINTF("McGetFormat port%d slot%d\n", port, slot);
248  return mcman_devinfos[port][slot].cardform;
249 }
250 
251 //--------------------------------------------------------------
252 int McGetMcType(int port, int slot) // Export #39
253 {
254  DPRINTF("McGetMcType port%d slot%d\n", port, slot);
255  return mcman_devinfos[port][slot].cardtype;
256 }
257 
258 #ifdef _IOP
259 //--------------------------------------------------------------
260 struct irx_id *McGetModuleInfo(void) // Export #42 XMCMAN only
261 {
262  DPRINTF("McGetModuleInfo\n");
263  return &_irx_id;
264 }
265 #endif
266 
267 //--------------------------------------------------------------
268 void McSetPS1CardFlag(int flag) // Export #40
269 {
270  DPRINTF("McSetPS1CardFlag flag %x\n", flag);
271  PS1CardFlag = flag;
272 }
273 
274 //--------------------------------------------------------------
275 int McGetFreeClusters(int port, int slot) // Export #38
276 {
277  register int r, mcfree;
278  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
279 
280  DPRINTF("McGetFreeClusters port%d slot%d\n", port, slot);
281 
282  mcfree = 0;
283  if (mcdi->cardform > 0) {
284  switch (mcdi->cardtype) {
285  case sceMcTypePS2:
286  mcfree = mcman_findfree2(port, slot, 0);
287  break;
288  case sceMcTypePS1:
289  case sceMcTypePDA:
290  mcfree = mcman_findfree1(port, slot, 0);
291  break;
292  case sceMcTypeNoCard:
293  mcfree = 0;
294  break;
295  }
296  if (mcfree == sceMcResFullDevice)
297  mcfree = 0;
298 
299  r = mcfree;
300  }
301  else
302  return 0;
303 
304  return r;
305 }
306 
307 //--------------------------------------------------------------
308 void mcman_wmemset(void *buf, int size, int value)
309 {
310  int *p = buf;
311  size = (size >> 2) - 1;
312 
313  if (size > -1) {
314  do {
315  *p++ = value;
316  } while (--size > -1);
317  }
318 }
319 
320 //--------------------------------------------------------------
321 int mcman_calcEDC(void *buf, int size)
322 {
323  register u32 checksum;
324  u8 *p = (u8 *)buf;
325 
326  checksum = 0;
327 
328  if (size > 0) {
329  register int i;
330 
331  size--;
332  i = 0;
333  while (size-- != -1) {
334  checksum ^= p[i];
335  i++;
336  }
337  }
338  return checksum & 0xff;
339 }
340 
341 //--------------------------------------------------------------
342 int mcman_checkpath(const char *str) // check that a string do not contain special chars ( chr<32, ?, *)
343 {
344  register int i;
345  u8 *p = (u8 *)str;
346 
347  i = 0;
348  while (p[i]) {
349  if (((p[i] & 0xff) == '?') || ((p[i] & 0xff) == '*'))
350  return 0;
351  if ((p[i] & 0xff) < 32)
352  return 0;
353  i++;
354  }
355  return 1;
356 }
357 
358 //--------------------------------------------------------------
359 int mcman_checkdirpath(const char *str1, const char *str2)
360 {
361  register int pos;
362  const char *p1 = str1;
363  const char *p2 = str2;
364 
365  do {
366  register int pos1, pos2;
367  pos1 = mcman_chrpos(p2, '?');
368  pos2 = mcman_chrpos(p2, '*');
369 
370  if ((pos1 < 0) && (pos2 < 0)) {
371  if (!strcmp(p2, p1))
372  return 1;
373  return 0;
374  }
375  pos = pos2;
376  if (pos1 >= 0) {
377  pos = pos1;
378  if (pos2 >= 0) {
379  pos = pos2;
380  if (pos1 < pos2) {
381  pos = pos1;
382  }
383  }
384  }
385  if (strncmp(p2, p1, pos) != 0)
386  return 0;
387 
388  p2 += pos;
389  p1 += pos;
390 
391  while (p2[0] == '?') {
392  if (p1[0] == 0)
393  return 1;
394  p2++;
395  p1++;
396  }
397  } while (p2[0] != '*');
398 
399  while((p2[0] == '*') || (p2[0] == '?'))
400  p2++;
401 
402  if (p2[0] != 0) {
403  register int r;
404  do {
405  pos = mcman_chrpos(p1, (u8)p2[0]);
406  p1 += pos;
407  if (pos < 0)
408  return 0;
409  r = mcman_checkdirpath(p1, p2);
410  p1++;
411  } while (r == 0);
412  }
413  return 1;
414 }
415 
416 //--------------------------------------------------------------
417 void mcman_invhandles(int port, int slot)
418 {
419  register int i = 0;
420  register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles;
421 
422  do {
423  if ((fh->port == port) && (fh->slot == slot))
424  fh->status = 0;
425  fh++;
426  } while (++i < MAX_FDHANDLES);
427 }
428 
429 //--------------------------------------------------------------
430 int McCloseAll(void) // Export #25 XMCMAN only
431 {
432  register int fd = 0, rv = 0;
433 
434  do {
435  if (mcman_fdhandles[fd].status) {
436  register int rc;
437 
438  rc = McClose(fd);
439  if (rc < rv)
440  rv = rc;
441  }
442  fd++;
443 
444  } while (fd < MAX_FDHANDLES);
445 
446  return rv;
447 }
448 
449 //--------------------------------------------------------------
450 int McDetectCard(int port, int slot) // Export #5
451 {
452 #ifdef BUILDING_XMCMAN
453  return mcman_detectcard(port, slot);
454 #else
455  return McDetectCard2(port, slot);
456 #endif
457 }
458 
459 //--------------------------------------------------------------
460 int mcman_detectcard(int port, int slot)
461 {
462  register int r;
463  register MCDevInfo *mcdi;
464 
465  DPRINTF("mcman_detectcard port%d slot%d\n", port, slot);
466  mcdi = (MCDevInfo *)&mcman_devinfos[port][slot];
467 
468 #if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
469  if ((mcdi->cardtype == sceMcTypeNoCard) || (mcdi->cardtype == sceMcTypePS2)) {
470  r = mcman_probePS2Card2(port, slot);
471  if (r < -9) {
472  r = mcman_probePS1Card2(port, slot);
473  if (!(r < -9)) {
474  if (mcman_probePDACard(port, slot)) {
475  mcdi->cardtype = sceMcTypePS1;
476  return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
477  }
478  else {
479  mcdi->cardtype = sceMcTypePDA;
480  return r;
481  }
482  }
483  }
484  else {
485  mcdi->cardtype = sceMcTypePS2;
486  return r;
487  }
488  }
489  else {
490  r = mcman_probePS1Card2(port, slot);
491  if (r) {
492  if ((r < -9) || (r >= 0)) {
493  r = mcman_probePS2Card2(port, slot);
494  if (!(r < -9)) {
495  mcdi->cardtype = sceMcTypePS2;
496  return r;
497  }
498  }
499  else {
500  if (mcman_probePDACard(port, slot)) {
501  mcdi->cardtype = sceMcTypePS1;
502  return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
503  }
504  else {
505  mcdi->cardtype = sceMcTypePDA;
506  return r;
507  }
508  }
509  }
510  else {
511  if (PS1CardFlag)
512  return sceMcResSucceed;
513  if (mcdi->cardtype == sceMcTypePS1)
514  return sceMcResDeniedPS1Permit;
515  return sceMcResSucceed;
516  }
517  }
518 #else
519  r = mcman_probePS2Card2(port, slot);
520  if (r >= -9) {
521  mcdi->cardtype = sceMcTypePS2;
522  return r;
523  }
524 #endif
525 
526  mcdi->cardtype = 0;
527  mcdi->cardform = 0;
528  mcman_invhandles(port, slot);
529  mcman_clearcache(port, slot);
530 
531  return r;
532 }
533 
534 //--------------------------------------------------------------
535 int McDetectCard2(int port, int slot) // Export #21 XMCMAN only
536 {
537  register int r;
538  register MCDevInfo *mcdi;
539 
540  DPRINTF("McDetectCard2 port%d slot%d\n", port, slot);
541 
542  mcdi = (MCDevInfo *)&mcman_devinfos[port][slot];
543 
544 #if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
545  if ((mcdi->cardtype == sceMcTypeNoCard) || (mcdi->cardtype == sceMcTypePS2)) {
546  r = mcman_probePS2Card(port, slot);
547  if (r < -9) {
548  r = mcman_probePS1Card(port, slot);
549  if (!(r < -9)) {
550  if (mcman_probePDACard(port, slot)) {
551  mcdi->cardtype = sceMcTypePS1;
552  return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
553  }
554  else {
555  mcdi->cardtype = sceMcTypePDA;
556  return r;
557  }
558  }
559  }
560  else {
561  mcdi->cardtype = sceMcTypePS2;
562  return r;
563  }
564  }
565  else {
566  r = mcman_probePS1Card(port, slot);
567  if (r) {
568  if ((r < -9) || (r >= 0)) {
569  r = mcman_probePS2Card(port, slot);
570  if (!(r < -9)) {
571  mcdi->cardtype = sceMcTypePS2;
572  return r;
573  }
574  }
575  else {
576  if (mcman_probePDACard(port, slot)) {
577  mcdi->cardtype = sceMcTypePS1;
578  return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
579  }
580  else {
581  mcdi->cardtype = sceMcTypePDA;
582  return r;
583  }
584  }
585  }
586  else {
587  if (PS1CardFlag)
588  return sceMcResSucceed;
589  if (mcdi->cardtype == sceMcTypePS1)
590  return sceMcResDeniedPS1Permit;
591  return sceMcResSucceed;
592  }
593  }
594 #else
595  r = mcman_probePS2Card(port, slot);
596  if (r >= -9) {
597  mcdi->cardtype = sceMcTypePS2;
598  return r;
599  }
600 #endif
601 
602  mcdi->cardtype = 0;
603  mcdi->cardform = 0;
604  mcman_invhandles(port, slot);
605  mcman_clearcache(port, slot);
606 
607  return r;
608 }
609 
610 //--------------------------------------------------------------
611 int McOpen(int port, int slot, const char *filename, int flag) // Export #6
612 {
613  register int r;
614 
615  r = McDetectCard(port, slot);
616  if (r != sceMcResSucceed)
617  return r;
618 
619  if (!PS1CardFlag)
620  flag &= ~0x00002000; // disables FRCOM flag OR what is it
621 
622  if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
623  r = mcman_open2(port, slot, filename, flag);
624  else
625  r = mcman_open1(port, slot, filename, flag);
626 
627  if (r < -9) {
628  mcman_invhandles(port, slot);
629  mcman_clearcache(port, slot);
630  }
631 
632  return r;
633 }
634 
635 //--------------------------------------------------------------
636 int McClose(int fd) // Export #7
637 {
638  register MC_FHANDLE *fh;
639  register int r;
640 
641  if (!((u32)fd < MAX_FDHANDLES))
642  return sceMcResDeniedPermit;
643 
644  fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
645  if (!fh->status)
646  return sceMcResDeniedPermit;
647 
648  fh->status = 0;
649  r = McDetectCard(fh->port, fh->slot);
650  if (r != sceMcResSucceed)
651  return r;
652 
653  r = McFlushCache(fh->port, fh->slot);
654  if (r < -9) {
655  mcman_invhandles(fh->port, fh->slot);
656  mcman_clearcache(fh->port, fh->slot);
657  }
658 
659  if (r != sceMcResSucceed)
660  return r;
661 
662  if (fh->unknown2 != 0) {
663  register MCDevInfo *mcdi;
664 
665  fh->unknown2 = 0;
666  mcdi = (MCDevInfo *)&mcman_devinfos[fh->port][fh->slot];
667  if (mcdi->cardtype == sceMcTypePS2)
668  r = mcman_close2(fd);
669  else
670  r = mcman_close1(fd);
671 
672  if (r < -9) {
673  mcman_invhandles(fh->port, fh->slot);
674  mcman_clearcache(fh->port, fh->slot);
675  }
676 
677  if (r != sceMcResSucceed)
678  return r;
679  }
680 
681  r = McFlushCache(fh->port, fh->slot);
682  if (r < -9) {
683  mcman_invhandles(fh->port, fh->slot);
684  mcman_clearcache(fh->port, fh->slot);
685  }
686 
687  return r;
688 }
689 
690 //--------------------------------------------------------------
691 int McFlush(int fd) // Export #14
692 {
693  register int r;
694  register MC_FHANDLE *fh;
695 
696  if (!((u32)fd < MAX_FDHANDLES))
697  return sceMcResDeniedPermit;
698 
699  fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
700  if (!fh->status)
701  return sceMcResDeniedPermit;
702 
703  r = McDetectCard(fh->port, fh->slot);
704  if (r != sceMcResSucceed)
705  return r;
706 
707  r = McFlushCache(fh->port, fh->slot);
708  if (r < -9) {
709  mcman_invhandles(fh->port, fh->slot);
710  mcman_clearcache(fh->port, fh->slot);
711  }
712 
713  if (r != sceMcResSucceed) {
714  fh->status = 0;
715  return r;
716  }
717 
718  if (fh->unknown2 != 0) {
719  register MCDevInfo *mcdi;
720 
721  fh->unknown2 = 0;
722  mcdi = (MCDevInfo *)&mcman_devinfos[fh->port][fh->slot];
723  if (mcdi->cardtype == sceMcTypePS2)
724  r = mcman_close2(fd);
725  else
726  r = mcman_close1(fd);
727 
728  if (r < -9) {
729  mcman_invhandles(fh->port, fh->slot);
730  mcman_clearcache(fh->port, fh->slot);
731  }
732 
733  if (r != sceMcResSucceed) {
734  fh->status = 0;
735  return r;
736  }
737  }
738 
739  r = McFlushCache(fh->port, fh->slot);
740  if (r < 0)
741  fh->status = 0;
742 
743  if (r < -9) {
744  mcman_invhandles(fh->port, fh->slot);
745  mcman_clearcache(fh->port, fh->slot);
746  }
747 
748  return r;
749 }
750 
751 //--------------------------------------------------------------
752 int McSeek(int fd, int offset, int origin) // Export #10
753 {
754  register int r;
755  register MC_FHANDLE *fh;
756 
757  DPRINTF("McSeek fd %d offset %d origin %d\n", fd, offset, origin);
758 
759  if (!((u32)fd < MAX_FDHANDLES))
760  return sceMcResDeniedPermit;
761 
762  fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
763  if (!fh->status)
764  return sceMcResDeniedPermit;
765 
766  r = McDetectCard(fh->port, fh->slot);
767  if (r != sceMcResSucceed)
768  return r;
769 
770  switch (origin) {
771  default:
772  case SEEK_CUR:
773  r = fh->position + offset;
774  break;
775  case SEEK_SET:
776  r = offset;
777  break;
778  case SEEK_END:
779  r = fh->filesize + offset;
780  break;
781  }
782 
783  return fh->position = (r < 0) ? 0 : r;
784 }
785 
786 //--------------------------------------------------------------
787 int McRead(int fd, void *buf, int length) // Export #8
788 {
789  register int r;
790  register MC_FHANDLE *fh;
791 
792  if (!((u32)fd < MAX_FDHANDLES))
793  return sceMcResDeniedPermit;
794 
795  fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
796  if (!fh->status)
797  return sceMcResDeniedPermit;
798 
799  if (!fh->rdflag)
800  return sceMcResDeniedPermit;
801 
802  r = McDetectCard(fh->port, fh->slot);
803  if (r != sceMcResSucceed)
804  return r;
805 
806  if (mcman_devinfos[fh->port][fh->slot].cardtype == sceMcTypePS2)
807  r = mcman_read2(fd, buf, length);
808  else
809  r = mcman_read1(fd, buf, length);
810 
811  if (r < 0)
812  fh->status = 0;
813 
814  if (r < -9) {
815  mcman_invhandles(fh->port, fh->slot);
816  mcman_clearcache(fh->port, fh->slot);
817  }
818 
819  return r;
820 }
821 
822 //--------------------------------------------------------------
823 int McWrite(int fd, void *buf, int length) // Export #9
824 {
825  register int r;
826  register MC_FHANDLE *fh;
827 
828  if (!((u32)fd < MAX_FDHANDLES))
829  return sceMcResDeniedPermit;
830 
831  fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
832  if (!fh->status)
833  return sceMcResDeniedPermit;
834 
835  if (!fh->wrflag)
836  return sceMcResDeniedPermit;
837 
838  r = McDetectCard(fh->port, fh->slot);
839  if (r != sceMcResSucceed)
840  return r;
841 
842  if (mcman_devinfos[fh->port][fh->slot].cardtype == sceMcTypePS2)
843  r = mcman_write2(fd, buf, length);
844  else
845  r = mcman_write1(fd, buf, length);
846 
847  if (r < 0)
848  fh->status = 0;
849 
850  if (r < -9) {
851  mcman_invhandles(fh->port, fh->slot);
852  mcman_clearcache(fh->port, fh->slot);
853  }
854 
855  return r;
856 }
857 
858 //--------------------------------------------------------------
859 int McGetEntSpace(int port, int slot, const char *dirname) // Export #23 XMCMAN only
860 {
861  register int r;
862 
863  r = McDetectCard(port, slot);
864  if (r != sceMcResSucceed)
865  return r;
866 
867  if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2) {
868  r = mcman_getentspace(port, slot, dirname);
869  }
870 
871  if (r < -9) {
872  mcman_invhandles(port, slot);
873  mcman_clearcache(port, slot);
874  }
875 
876  return r;
877 }
878 
879 //--------------------------------------------------------------
880 int McGetDir(int port, int slot, const char *dirname, int flags, int maxent, sceMcTblGetDir *info) // Export #12
881 {
882  register int r;
883 
884  r = McDetectCard(port, slot);
885  if (r != sceMcResSucceed)
886  return r;
887 
888  if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
889  r = mcman_getdir2(port, slot, dirname, flags & 0xFFFF, maxent, info);
890  else
891  r = mcman_getdir1(port, slot, dirname, flags & 0xFFFF, maxent, info);
892 
893  if (r < -9) {
894  mcman_invhandles(port, slot);
895  mcman_clearcache(port, slot);
896  }
897 
898  return r;
899 }
900 
901 //--------------------------------------------------------------
902 int mcman_dread(int fd, MC_IO_DRE_T *dirent)
903 {
904  register int r;
905  register MC_FHANDLE *fh;
906 
907  if (!((u32)fd < MAX_FDHANDLES))
908  return sceMcResDeniedPermit;
909 
910  fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
911  if (!fh->status)
912  return sceMcResDeniedPermit;
913 
914  if (!fh->drdflag)
915  return sceMcResDeniedPermit;
916 
917  r = McDetectCard(fh->port, fh->slot);
918  if (r != sceMcResSucceed)
919  return r;
920 
921  if (mcman_devinfos[fh->port][fh->slot].cardtype == sceMcTypePS2)
922  r = mcman_dread2(fd, dirent);
923  else
924  r = mcman_dread1(fd, dirent);
925 
926  if (r < 0)
927  fh->status = 0;
928 
929  if (r < -9) {
930  mcman_invhandles(fh->port, fh->slot);
931  mcman_clearcache(fh->port, fh->slot);
932  }
933 
934  return r;
935 }
936 
937 //--------------------------------------------------------------
938 int mcman_getstat(int port, int slot, const char *filename, MC_IO_STA_T *stat)
939 {
940  register int r;
941 
942  r = McDetectCard(port, slot);
943  if (r != sceMcResSucceed)
944  return r;
945 
946  if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
947  r = mcman_getstat2(port, slot, filename, stat);
948  else
949  r = mcman_getstat1(port, slot, filename, stat);
950 
951  if (r < -9) {
952  mcman_invhandles(port, slot);
953  mcman_clearcache(port, slot);
954  }
955 
956  return r;
957 }
958 
959 //--------------------------------------------------------------
960 int McSetFileInfo(int port, int slot, const char *filename, sceMcTblGetDir *info, int flags) // Export #16
961 {
962  register int r;
963 
964  r = McDetectCard(port, slot);
965  if (r != sceMcResSucceed)
966  return r;
967 
968  if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
969  r = mcman_setinfo2(port, slot, filename, info, flags);
970  else
971  r = mcman_setinfo1(port, slot, filename, info, flags);
972 
973  if (r < -9) {
974  mcman_invhandles(port, slot);
975  mcman_clearcache(port, slot);
976  }
977 
978  if (r == sceMcResSucceed) {
979  r = McFlushCache(port, slot);
980  if (r < -9) {
981  mcman_invhandles(port, slot);
982  mcman_clearcache(port, slot);
983  }
984  }
985 
986  return r;
987 }
988 
989 //--------------------------------------------------------------
990 int McChDir(int port, int slot, const char *newdir, char *currentdir) // Export #15
991 {
992  register int r;
993 
994  r = McDetectCard(port, slot);
995  if (r != sceMcResSucceed)
996  return r;
997 
998  if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
999  r = mcman_chdir(port, slot, newdir, currentdir);
1000  else {
1001  currentdir[0] = 0;
1002  r = sceMcResSucceed;
1003  }
1004 
1005  if (r < -9) {
1006  mcman_invhandles(port, slot);
1007  mcman_clearcache(port, slot);
1008  }
1009 
1010  return r;
1011 }
1012 
1013 //--------------------------------------------------------------
1014 int McDelete(int port, int slot, const char *filename, int flags) // Export #13
1015 {
1016  register int r;
1017 
1018  r = McDetectCard(port, slot);
1019  if (r != sceMcResSucceed)
1020  return r;
1021 
1022  if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
1023  r = mcman_delete2(port, slot, filename, flags);
1024  else
1025  r = mcman_delete1(port, slot, filename, flags);
1026 
1027  if (r < -9) {
1028  mcman_invhandles(port, slot);
1029  mcman_clearcache(port, slot);
1030  }
1031 
1032  return r;
1033 }
1034 
1035 //--------------------------------------------------------------
1036 int McFormat(int port, int slot) // Export #11
1037 {
1038  register int r;
1039 
1040  mcman_invhandles(port, slot);
1041 
1042  r = McDetectCard(port, slot);
1043  if (r < -2)
1044  return r;
1045 
1046  mcman_clearcache(port, slot);
1047 
1048  if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
1049  r = mcman_format2(port, slot);
1050  else
1051  r = mcman_format1(port, slot);
1052 
1053  if (r < -9) {
1054  mcman_invhandles(port, slot);
1055  mcman_clearcache(port, slot);
1056  }
1057 
1058  return r;
1059 }
1060 
1061 //--------------------------------------------------------------
1062 int McUnformat(int port, int slot) // Export #36
1063 {
1064  register int r;
1065 
1066  mcman_invhandles(port, slot);
1067 
1068  r = McDetectCard(port, slot);
1069  if (r < -2)
1070  return r;
1071 
1072  mcman_clearcache(port, slot);
1073 
1074  if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
1075  r = mcman_unformat2(port, slot);
1076  else
1077  r = mcman_unformat1(port, slot);
1078 
1079  mcman_devinfos[port][slot].cardform = 0;
1080 
1081  if (r < -9) {
1082  mcman_invhandles(port, slot);
1083  mcman_clearcache(port, slot);
1084  }
1085 
1086  return r;
1087 }
1088 
1089 //--------------------------------------------------------------
1090 int mcman_getmcrtime(sceMcStDateTime *tm)
1091 {
1092 #ifdef _IOP
1093  register int retries;
1094  sceCdCLOCK cdtime;
1095 
1096  retries = 64;
1097 
1098  do {
1099  if (sceCdRC(&cdtime))
1100  break;
1101  } while (--retries > 0);
1102 
1103  if (cdtime.stat & 0x80) {
1104  tm->Year = 2000;
1105  tm->Month = 3;
1106  tm->Day = 4;
1107  tm->Hour = 0;
1108  tm->Min = 0;
1109  tm->Sec = 0;
1110  tm->Resv2 = 0;
1111  }
1112  else {
1113  tm->Resv2 = 0;
1114  tm->Sec = btoi(cdtime.second);
1115  tm->Min = btoi(cdtime.minute);
1116  tm->Hour = btoi(cdtime.hour);
1117  tm->Day = btoi(cdtime.day);
1118 
1119  if ((cdtime.month & 0x10) != 0) //Keep only valid bits: 0x1f (for month values 1-12 in BCD)
1120  tm->Month = (cdtime.month & 0xf) + 0xa;
1121  else
1122  tm->Month = cdtime.month & 0xf;
1123 
1124  tm->Year = btoi(cdtime.year) + 2000;
1125  }
1126 #else
1127  time_t rawtime;
1128  struct tm timeinfo;
1129  time(&rawtime);
1130  // Convert to JST
1131  rawtime += (-9 * 60 * 60);
1132 #ifdef _WIN32
1133  gmtime_s(&timeinfo, &rawtime);
1134 #else
1135  gmtime_r(&rawtime, &timeinfo);
1136 #endif
1137 
1138  tm->Sec = timeinfo.tm_sec;
1139  tm->Min = timeinfo.tm_min;
1140  tm->Hour = timeinfo.tm_hour;
1141  tm->Day = timeinfo.tm_mday;
1142  tm->Month = timeinfo.tm_mon + 1;
1143  tm->Year = timeinfo.tm_year + 1900;
1144 #endif
1145 
1146  return 0;
1147 }
1148 
1149 //--------------------------------------------------------------
1150 int McEraseBlock(int port, int block, void **pagebuf, void *eccbuf) // Export #17 in MCMAN
1151 {
1152  return mcman_eraseblock(port, 0, block, (void **)pagebuf, eccbuf);
1153 }
1154 
1155 //--------------------------------------------------------------
1156 int McEraseBlock2(int port, int slot, int block, void **pagebuf, void *eccbuf) // Export #17 in XMCMAN
1157 {
1158  return mcman_eraseblock(port, slot, block, (void **)pagebuf, eccbuf);
1159 }
1160 
1161 //--------------------------------------------------------------
1162 int McReadPage(int port, int slot, int page, void *buf) // Export #18
1163 {
1164  register int r, index, ecres, retries, count, erase_byte;
1165  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1166  u8 eccbuf[32];
1167  u8 *pdata, *peccb;
1168 
1169  HAKAMA_WAITSEMA();
1170 
1171  count = (mcdi->pagesize + 127) >> 7;
1172  erase_byte = (mcdi->cardflags & CF_ERASE_ZEROES) ? 0x0 : 0xFF;
1173 
1174  retries = 0;
1175  ecres = sceMcResSucceed;
1176  do {
1177  if (!mcman_readpage(port, slot, page, buf, eccbuf)) {
1178  if (mcdi->cardflags & CF_USE_ECC) { // checking ECC from spare data block
1179  // check for erased page (last byte of spare data set to 0xFF or 0x0)/
1180  if (eccbuf[mcman_sparesize(port, slot) - 1] == erase_byte)
1181  break;
1182 
1183  index = 0;
1184 
1185  if (count > 0) {
1186  peccb = (u8 *)eccbuf;
1187  pdata = (u8 *)buf;
1188 
1189  do {
1190  r = mcman_correctdata(pdata, peccb);
1191  if (r < ecres)
1192  ecres = r;
1193 
1194  peccb += 3;
1195  pdata += 128;
1196  } while (++index < count);
1197  }
1198 
1199  if (ecres == sceMcResSucceed)
1200  break;
1201 
1202  if ((retries == 4) && (!(ecres < sceMcResNoFormat)))
1203  break;
1204  }
1205  else
1206  {
1207  break;
1208  }
1209  }
1210  } while (++retries < 5);
1211 
1212  HAKAMA_SIGNALSEMA();
1213 
1214  if (retries < 5)
1215  return sceMcResSucceed;
1216 
1217  return (ecres != sceMcResSucceed) ? sceMcResNoFormat : sceMcResChangedCard;
1218 }
1219 
1220 //--------------------------------------------------------------
1221 void McDataChecksum(void *buf, void *ecc) // Export #20
1222 {
1223  register u8 *p, *p_ecc;
1224  register int i, a2, a3, t0;
1225 
1226  p = buf;
1227  i = 0;
1228  a2 = 0;
1229  a3 = 0;
1230  t0 = 0;
1231 
1232  do {
1233  register int v;
1234 
1235  v = mcman_xortable[*p++];
1236  a2 ^= v;
1237  if (v & 0x80) {
1238  a3 ^= ~i;
1239  t0 ^= i;
1240  }
1241  } while (++i < 0x80);
1242 
1243  p_ecc = ecc;
1244  p_ecc[0] = ~a2 & 0x77;
1245  p_ecc[1] = ~a3 & 0x7F;
1246  p_ecc[2] = ~t0 & 0x7F;
1247 }
1248 
1249 //--------------------------------------------------------------
1250 int mcman_getcnum(int port, int slot)
1251 {
1252  return
1253 #if !defined(BUILDING_DONGLEMAN)
1254  ((port & 1) << 3) + slot;
1255 #else
1256 
1261  0xF;
1262 #endif
1263 }
1264 
1265 //--------------------------------------------------------------
1266 int mcman_correctdata(void *buf, void *ecc)
1267 {
1268  register int xor0, xor1, xor2, xor3, xor4;
1269  u8 eccbuf[12];
1270  u8 *p = (u8 *)ecc;
1271 
1272  McDataChecksum(buf, eccbuf);
1273 
1274  xor0 = p[0] ^ eccbuf[0];
1275  xor1 = p[1] ^ eccbuf[1];
1276  xor2 = p[2] ^ eccbuf[2];
1277 
1278  xor3 = xor1 ^ xor2;
1279  xor4 = (xor0 & 0xf) ^ (xor0 >> 4);
1280 
1281  if (!xor0 && !xor1 && !xor2)
1282  return 0;
1283 
1284  if ((xor3 == 0x7f) && (xor4 == 0x7)) {
1285  p[xor2] ^= 1 << (xor0 >> 4);
1286  return -1;
1287  }
1288 
1289  xor0 = 0;
1290  xor2 = 7;
1291  do {
1292  if ((xor3 & 1))
1293  xor0++;
1294  xor2--;
1295  xor3 = xor3 >> 1;
1296  } while (xor2 >= 0);
1297 
1298  xor2 = 3;
1299  do {
1300  if ((xor4 & 1))
1301  xor0++;
1302  xor2--;
1303  xor4 = xor4 >> 1;
1304  } while (xor2 >= 0);
1305 
1306  if (xor0 == 1)
1307  return -2;
1308 
1309  return -3;
1310 }
1311 
1312 //--------------------------------------------------------------
1313 int mcman_sparesize(int port, int slot)
1314 { // Get ps2 mc spare size by dividing pagesize / 32
1315  return (mcman_devinfos[port][slot].pagesize + 0x1F) >> 5;
1316 }
1317 
1318 //--------------------------------------------------------------
1319 int mcman_setdevspec(int port, int slot)
1320 {
1321  int cardsize;
1322  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1323 
1324  DPRINTF("mcman_setdevspec port%d, slot%d\n", port, slot);
1325 
1326  if (McGetCardSpec(port, slot, &mcdi->pagesize, &mcdi->blocksize, &cardsize, &mcdi->cardflags) != sceMcResSucceed)
1327  return sceMcResFullDevice;
1328 
1329  mcdi->pages_per_cluster = MCMAN_CLUSTERSIZE / mcdi->pagesize;
1330  mcdi->cluster_size = MCMAN_CLUSTERSIZE;
1331  mcdi->unknown1 = 0;
1332  mcdi->unknown2 = 0;
1333  mcdi->unused = 0xff00;
1334  mcdi->FATentries_per_cluster = MCMAN_CLUSTERFATENTRIES;
1335  mcdi->unknown5 = -1;
1336  mcdi->rootdir_cluster2 = mcdi->rootdir_cluster;
1337  mcdi->clusters_per_block = mcdi->blocksize / mcdi->pages_per_cluster;
1338  mcdi->clusters_per_card = (cardsize / mcdi->blocksize) * (mcdi->blocksize / mcdi->pages_per_cluster);
1339 
1340  return sceMcResSucceed;
1341 }
1342 
1343 //--------------------------------------------------------------
1344 int mcman_setdevinfos(int port, int slot)
1345 {
1346  register int r, allocatable_clusters_per_card, iscluster_valid, current_allocatable_cluster, cluster_cnt;
1347  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1348  McFsEntry *pfse;
1349 
1350  DPRINTF("mcman_setdevinfos port%d slot%d\n", port, slot);
1351 
1352  mcman_wmemset((void *)mcdi, sizeof(MCDevInfo), 0);
1353 
1354  mcdi->cardform = 0;
1355 
1356  r = mcman_setdevspec(port, slot);
1357  if (r != sceMcResSucceed)
1358  return -49;
1359 
1360  mcdi->cardform = -1;
1361 
1362  r = McReadPage(port, slot, 0, &mcman_pagebuf);
1363  if (r == sceMcResNoFormat)
1364  return sceMcResNoFormat; // should rebuild a valid superblock here
1365  if (r != sceMcResSucceed)
1366  return -48;
1367 
1368  if (strncmp(SUPERBLOCK_MAGIC, mcman_pagebuf.magic, 28) != 0) {
1369  DPRINTF("mcman_setdevinfos No card format !!!\n");
1370  return sceMcResNoFormat;
1371  }
1372 
1373  if (((mcman_pagebuf.byte[28] - 48) == 1) && ((mcman_pagebuf.byte[30] - 48) == 0)) // check ver major & minor
1374  return sceMcResNoFormat;
1375 
1376  u8 *p = (u8 *)mcdi;
1377  for (r=0; r<0x150; r++)
1378  p[r] = mcman_pagebuf.byte[r];
1379 
1380  mcdi->cardtype = sceMcTypePS2; // <--
1381 
1382  r = mcman_checkBackupBlocks(port, slot);
1383  if (r != sceMcResSucceed)
1384  return -47;
1385 
1386  r = McReadDirEntry(port, slot, 0, 0, &pfse);
1387  if (r != sceMcResSucceed)
1388  return sceMcResNoFormat; // -46
1389 
1390  if (strcmp(pfse->name, ".") != 0)
1391  return sceMcResNoFormat;
1392 
1393  if (McReadDirEntry(port, slot, 0, 1, &pfse) != sceMcResSucceed)
1394  return -45;
1395 
1396  if (strcmp(pfse->name, "..") != 0)
1397  return sceMcResNoFormat;
1398 
1399  mcdi->cardform = 1;
1400 // mcdi->cardtype = sceMcTypePS2;
1401 
1402  if (((mcman_pagebuf.byte[28] - 48) == 1) && ((mcman_pagebuf.byte[30] - 48) == 1)) { // check ver major & minor
1403  if ((mcdi->clusters_per_block * mcdi->backup_block2) == mcdi->alloc_end)
1404  mcdi->alloc_end = (mcdi->clusters_per_block * mcdi->backup_block2) - mcdi->alloc_offset;
1405  }
1406 
1407  u32 hi, lo, temp;
1408 
1409  long_multiply(mcdi->clusters_per_card, 0x10624dd3, &hi, &lo);
1410  temp = (hi >> 6) - (mcdi->clusters_per_card >> 31);
1411  allocatable_clusters_per_card = (((((temp << 5) - temp) << 2) + temp) << 3) + 1;
1412  iscluster_valid = 0;
1413  cluster_cnt = 0;
1414  current_allocatable_cluster = mcdi->alloc_offset;
1415 
1416  while (cluster_cnt < allocatable_clusters_per_card) {
1417  if ((u32)current_allocatable_cluster >= mcdi->clusters_per_card)
1418  break;
1419 
1420  if (((current_allocatable_cluster % mcdi->clusters_per_block) == 0) \
1421  || (mcdi->alloc_offset == (u32)current_allocatable_cluster)) {
1422  iscluster_valid = 1;
1423  for (r=0; r<16; r++) {
1424  if (current_allocatable_cluster / mcdi->clusters_per_block == (u32)(mcdi->bad_block_list[r]))
1425  iscluster_valid = 0;
1426  }
1427  }
1428  if (iscluster_valid == 1)
1429  cluster_cnt++;
1430  current_allocatable_cluster++;
1431  }
1432 
1433  mcdi->max_allocatable_clusters = current_allocatable_cluster - mcdi->alloc_offset;
1434 
1435  return sceMcResSucceed;
1436 }
1437 
1438 //--------------------------------------------------------------
1439 int mcman_reportBadBlocks(int port, int slot)
1440 {
1441  register int bad_blocks, erase_byte, err_limit;
1442  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1443 
1444  DPRINTF("mcman_reportBadBlocks port%d, slot%d\n", port, slot);
1445 
1446  mcman_wmemset((void *)mcdi->bad_block_list, 128, -1);
1447 
1448  if ((mcdi->cardflags & CF_BAD_BLOCK) == 0)
1449  return sceMcResSucceed;
1450 
1451  err_limit = ((mcdi->pagesize & 0xffff) + (mcdi->pagesize & 0x1)) >> 1; //s7
1452 
1453  erase_byte = 0;
1454  if ((mcdi->cardflags & CF_ERASE_ZEROES) != 0)
1455  erase_byte = 0xff;
1456 
1457  bad_blocks = 0; // s2
1458 
1459  if ((mcdi->clusters_per_card / mcdi->clusters_per_block) > 0) {
1460  register int block;
1461 
1462  block = 0; // s1
1463 
1464  do {
1465  register int page, err_cnt;
1466 
1467  if (bad_blocks >= 16)
1468  break;
1469 
1470  err_cnt = 0; //s4
1471  page = 0; //s3
1472  do {
1473  register int r;
1474 
1475  r = McReadPage(port, slot, (block * mcdi->blocksize) + page, &mcman_pagebuf);
1476  if (r == sceMcResNoFormat) {
1477  mcdi->bad_block_list[bad_blocks] = block;
1478  bad_blocks++;
1479  break;
1480  }
1481  if (r != sceMcResSucceed)
1482  return r;
1483 
1484  if ((mcdi->cardflags & CF_USE_ECC) == 0) {
1485  register int i;
1486  u8 *p;
1487 
1488  p = mcman_pagebuf.byte;
1489  for (i = 0; i < mcdi->pagesize; i++) {
1490  // check if the content of page is clean
1491  if (*p++ != erase_byte)
1492  err_cnt++;
1493 
1494  if (err_cnt >= err_limit) {
1495  mcdi->bad_block_list[bad_blocks] = block;
1496  bad_blocks++;
1497  break;
1498  }
1499  }
1500  }
1501  } while (++page < 2);
1502 
1503  } while ((u32)(++block) < (mcdi->clusters_per_card / mcdi->clusters_per_block));
1504  }
1505 
1506  return sceMcResSucceed;
1507 }
1508 
1509 //--------------------------------------------------------------
1510 int McCreateDirentry(int port, int slot, int parent_cluster, int num_entries, int cluster, const sceMcStDateTime *ctime)
1511 {
1512  register int r;
1513  McCacheEntry *mce;
1514  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1515  McFsEntry *mfe, *mfe_next, *pfse;
1516 
1517  DPRINTF("McCreateDirentry port%d slot%d parent_cluster %x num_entries %d cluster %x\n", port, slot, parent_cluster, num_entries, cluster);
1518 
1519  r = McReadCluster(port, slot, mcdi->alloc_offset + cluster, &mce);
1520  if (r != sceMcResSucceed)
1521  return r;
1522 
1523  mcman_wmemset(mce->cl_data, MCMAN_CLUSTERSIZE, 0);
1524 
1525  mfe = (McFsEntry*)mce->cl_data;
1526  mfe_next = (McFsEntry*)(mce->cl_data + sizeof (McFsEntry));
1527 
1528  mfe->mode = sceMcFileAttrReadable | sceMcFileAttrWriteable | sceMcFileAttrExecutable \
1529  | sceMcFileAttrSubdir | sceMcFile0400 | sceMcFileAttrExists; // 0x8427
1530 
1531  if (ctime == NULL)
1532  mcman_getmcrtime(&mfe->created);
1533  else
1534  mfe->created = *ctime;
1535 
1536  mfe->modified = mfe->created;
1537 
1538  mfe->length = 0;
1539  mfe->dir_entry = num_entries;
1540  mfe->cluster = parent_cluster;
1541  mfe->name[0] = '.';
1542  mfe->name[1] = '\0';
1543 
1544  if ((parent_cluster == 0) && (num_entries == 0)) {
1545  // entry is root directory
1546  mfe_next->created = mfe->created;
1547  mfe->length = 2;
1548  mfe++;
1549 
1550  mfe->mode = sceMcFileAttrWriteable | sceMcFileAttrExecutable | sceMcFileAttrSubdir \
1551  | sceMcFile0400 | sceMcFileAttrExists | sceMcFileAttrHidden; // 0xa426
1552  mfe->dir_entry = 0;
1553  mfe->cluster = 0;
1554  }
1555  else {
1556  // entry is normal "." / ".."
1557  McReadDirEntry(port, slot, parent_cluster, 0, &pfse);
1558 
1559  mfe_next->created = pfse->created;
1560  mfe++;
1561 
1562  mfe->mode = sceMcFileAttrReadable | sceMcFileAttrWriteable | sceMcFileAttrExecutable \
1563  | sceMcFileAttrSubdir | sceMcFile0400 | sceMcFileAttrExists; // 0x8427
1564  mfe->dir_entry = pfse->dir_entry;
1565 
1566  mfe->cluster = pfse->cluster;
1567  }
1568 
1569  mfe->modified = mfe->created;
1570  mfe->length = 0;
1571 
1572  mfe->name[0] = '.';
1573  mfe->name[1] = '.';
1574  mfe->name[2] = '\0';
1575 
1576  mce->wr_flag = 1;
1577 
1578  return sceMcResSucceed;
1579 }
1580 
1581 //--------------------------------------------------------------
1582 int mcman_fatRseek(int fd)
1583 {
1584  register int entries_to_read, fat_index;
1585  register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd]; //s1
1586  register MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot]; //s2
1587  int fat_entry;
1588 
1589  entries_to_read = fh->position / mcdi->cluster_size; //s0
1590 
1591  //s5 = 0
1592 
1593  if ((u32)entries_to_read < fh->clust_offset) //v1 = fh->fh->clust_offset
1594  fat_index = fh->freeclink;
1595  else {
1596  fat_index = fh->clink; // a2
1597  entries_to_read -= fh->clust_offset;
1598  }
1599 
1600  if (entries_to_read == 0) {
1601  if (fat_index >= 0)
1602  return fat_index + mcdi->alloc_offset;
1603 
1604  return sceMcResFullDevice;
1605  }
1606 
1607  do {
1608  register int r;
1609 
1610  r = McGetFATentry(fh->port, fh->slot, fat_index, &fat_entry);
1611  if (r != sceMcResSucceed)
1612  return r;
1613 
1614  fat_index = fat_entry;
1615 
1616  if (fat_index >= -1)
1617  return sceMcResFullDevice;
1618 
1619  entries_to_read--;
1620 
1621  fat_index &= ~0x80000000;
1622  fh->clink = fat_index;
1623  fh->clust_offset = (fh->position / mcdi->cluster_size) - entries_to_read;
1624 
1625  } while (entries_to_read > 0);
1626 
1627  return fat_index + mcdi->alloc_offset;
1628 }
1629 
1630 //--------------------------------------------------------------
1631 int mcman_fatWseek(int fd) // modify FAT to hold new content for a file
1632 {
1633  register int r, entries_to_write, fat_index;
1634  register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
1635  register MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
1636  register McCacheEntry *mce;
1637  int fat_entry;
1638 
1639  entries_to_write = fh->position / mcdi->cluster_size;
1640 
1641  if ((fh->clust_offset == 0) || ((u32)entries_to_write < fh->clust_offset)) {
1642  fat_index = fh->freeclink;
1643 
1644  if (fat_index < 0) {
1645  fat_index = mcman_findfree2(fh->port, fh->slot, 1);
1646 
1647  if (fat_index < 0)
1648  return sceMcResFullDevice;
1649 
1650  mce = (McCacheEntry *)mcman_get1stcacheEntp();
1651  fh->freeclink = fat_index;
1652 
1653  r = mcman_close2(fd);
1654  if (r != sceMcResSucceed)
1655  return r;
1656 
1657  mcman_addcacheentry(mce);
1658  McFlushCache(fh->port, fh->slot);
1659  }
1660  }
1661  else {
1662  fat_index = fh->clink;
1663  entries_to_write -= fh->clust_offset;
1664  }
1665 
1666  if (entries_to_write != 0) {
1667  do {
1668  r = McGetFATentry(fh->port, fh->slot, fat_index, &fat_entry);
1669  if (r != sceMcResSucceed)
1670  return r;
1671 
1672  if ((unsigned int)fat_entry >= 0xffffffff) {
1673  r = mcman_findfree2(fh->port, fh->slot, 1);
1674  if (r < 0)
1675  return r;
1676  fat_entry = r;
1677  fat_entry |= 0x80000000;
1678 
1679  mce = (McCacheEntry *)mcman_get1stcacheEntp();
1680 
1681  r = McSetFATentry(fh->port, fh->slot, fat_index, fat_entry);
1682  if (r != sceMcResSucceed)
1683  return r;
1684 
1685  mcman_addcacheentry(mce);
1686  }
1687 
1688  entries_to_write--;
1689  fat_index = fat_entry & ~0x80000000;
1690  } while (entries_to_write > 0);
1691  }
1692 
1693  fh->clink = fat_index;
1694  fh->clust_offset = fh->position / mcdi->cluster_size;
1695 
1696  return sceMcResSucceed;
1697 }
1698 
1699 //--------------------------------------------------------------
1700 int mcman_findfree2(int port, int slot, int reserve)
1701 {
1702  register int r, rfree, ifc_index, indirect_offset, fat_index, block;
1703  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1704  McCacheEntry *mce1, *mce2;
1705 
1706  DPRINTF("mcman_findfree2 port%d slot%d reserve%d\n", port, slot, reserve);
1707 
1708  rfree = 0;
1709 
1710  for (fat_index = mcdi->unknown2; (u32)fat_index < mcdi->max_allocatable_clusters; fat_index++) {
1711  register int indirect_index, fat_offset;
1712 
1713  indirect_index = fat_index / mcdi->FATentries_per_cluster;
1714  fat_offset = fat_index % mcdi->FATentries_per_cluster;
1715 
1716  if ((fat_offset == 0) || ((u32)fat_index == mcdi->unknown2)) {
1717 
1718  ifc_index = indirect_index / mcdi->FATentries_per_cluster;
1719  r = McReadCluster(port, slot, mcdi->ifc_list[ifc_index], &mce1);
1720  if (r != sceMcResSucceed)
1721  return r;
1722  //}
1723  //if ((fat_offset == 0) || (fat_index == mcdi->unknown2)) {
1724  indirect_offset = indirect_index % mcdi->FATentries_per_cluster;
1725  McFatCluster *fc = (McFatCluster *)mce1->cl_data;
1726  r = McReadCluster(port, slot, fc->entry[indirect_offset], &mce2);
1727  if (r != sceMcResSucceed)
1728  return r;
1729  }
1730 
1731  McFatCluster *fc = (McFatCluster *)mce2->cl_data;
1732 
1733  if (fc->entry[fat_offset] >= 0) {
1734  block = (mcdi->alloc_offset + fat_offset) / mcdi->clusters_per_block;
1735  if (block != mcman_badblock) {
1736  if (reserve) {
1737  fc->entry[fat_offset] = 0xffffffff;
1738  mce2->wr_flag = 1;
1739  mcdi->unknown2 = fat_index;
1740  return fat_index;
1741  }
1742  rfree++;
1743  }
1744  }
1745  }
1746 
1747  if (reserve)
1748  return sceMcResFullDevice;
1749 
1750  return (rfree) ? rfree : sceMcResFullDevice;
1751 }
1752 
1753 //--------------------------------------------------------------
1754 int mcman_getentspace(int port, int slot, const char *dirname)
1755 {
1756  register int r, i, entspace;
1757  McCacheDir cacheDir;
1758  McFsEntry *fse;
1759  McFsEntry mfe;
1760  u8 *pfsentry, *pmfe, *pfseend;
1761 
1762  DPRINTF("mcman_getentspace port%d slot%d dirname %s\n", port, slot, dirname);
1763 
1764  r = mcman_cachedirentry(port, slot, dirname, &cacheDir, &fse, 1);
1765  if (r > 0)
1766  return sceMcResNoEntry;
1767  if (r < 0)
1768  return r;
1769 
1770  pfsentry = (u8 *)fse;
1771  pmfe = (u8 *)&mfe;
1772  pfseend = (u8 *)(pfsentry + sizeof (McFsEntry));
1773 
1774  do {
1775  *((u32 *)pmfe ) = *((u32 *)pfsentry );
1776  *((u32 *)pmfe+1) = *((u32 *)pfsentry+1);
1777  *((u32 *)pmfe+2) = *((u32 *)pfsentry+2);
1778  *((u32 *)pmfe+3) = *((u32 *)pfsentry+3);
1779  pfsentry += 16;
1780  pmfe += 16;
1781  } while (pfsentry < pfseend);
1782 
1783  entspace = mfe.length & 1;
1784 
1785  for (i = 0; (u32)i < mfe.length; i++) {
1786 
1787  r = McReadDirEntry(port, slot, mfe.cluster, i, &fse);
1788  if (r != sceMcResSucceed)
1789  return r;
1790  if ((fse->mode & sceMcFileAttrExists) == 0)
1791  entspace++;
1792  }
1793 
1794  return entspace;
1795 }
1796 
1797 //--------------------------------------------------------------
1798 int mcman_cachedirentry(int port, int slot, const char *filename, McCacheDir *pcacheDir, McFsEntry **pfse, int unknown_flag)
1799 {
1800  register int r, fsindex, cluster, fmode;
1801  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1802  McFsEntry *fse;
1803  McCacheDir cacheDir;
1804  u8 *pfsentry, *pcache, *pfseend;
1805  const char *p;
1806 
1807  DPRINTF("mcman_cachedirentry port%d slot%d name %s\n", port, slot, filename);
1808 
1809  if (pcacheDir == NULL) {
1810  pcacheDir = &cacheDir;
1811  pcacheDir->maxent = -1;
1812  }
1813 
1814  p = filename;
1815  if (*p == '/') {
1816  p++;
1817  cluster = 0;
1818  fsindex = 0;
1819  }
1820  else {
1821  cluster = mcdi->rootdir_cluster2;
1822  fsindex = mcdi->unknown1;
1823  }
1824 
1825  r = McReadDirEntry(port, slot, cluster, fsindex, &fse);
1826  if (r != sceMcResSucceed)
1827  return r;
1828 
1829  if (*p == 0) {
1830  if (!(fse->mode & sceMcFileAttrExists))
1831  return 2;
1832 
1833  if (pcacheDir == NULL) {
1834  *pfse = (McFsEntry *)fse;
1835  return sceMcResSucceed;
1836  }
1837 
1838  pfsentry = (u8 *)fse;
1839  pcache = (u8 *)&mcman_dircache[0];
1840  pfseend = (u8 *)(pfsentry + sizeof (McFsEntry));
1841 
1842  do {
1843  *((u32 *)pcache ) = *((u32 *)pfsentry );
1844  *((u32 *)pcache+1) = *((u32 *)pfsentry+1);
1845  *((u32 *)pcache+2) = *((u32 *)pfsentry+2);
1846  *((u32 *)pcache+3) = *((u32 *)pfsentry+3);
1847  pfsentry += 16;
1848  pcache += 16;
1849  } while (pfsentry < pfseend);
1850 
1851  r = mcman_getdirinfo(port, slot, (McFsEntry *)&mcman_dircache[0], ".", pcacheDir, unknown_flag);
1852 
1853  McReadDirEntry(port, slot, pcacheDir->cluster, pcacheDir->fsindex, pfse);
1854 
1855  if (r > 0)
1856  return 2;
1857 
1858  return r;
1859 
1860  } else {
1861 
1862  do {
1863  fmode = sceMcFileAttrReadable | sceMcFileAttrExecutable;
1864  if ((fse->mode & fmode) != fmode)
1865  return sceMcResDeniedPermit;
1866 
1867  pfsentry = (u8 *)fse;
1868  pcache = (u8 *)&mcman_dircache[0];
1869  pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
1870 
1871  do {
1872  *((u32 *)pcache ) = *((u32 *)pfsentry );
1873  *((u32 *)pcache+1) = *((u32 *)pfsentry+1);
1874  *((u32 *)pcache+2) = *((u32 *)pfsentry+2);
1875  *((u32 *)pcache+3) = *((u32 *)pfsentry+3);
1876  pfsentry += 16;
1877  pcache += 16;
1878  } while (pfsentry < pfseend);
1879 
1880  r = mcman_getdirinfo(port, slot, (McFsEntry *)&mcman_dircache[0], p, pcacheDir, unknown_flag);
1881 
1882  if (r > 0) {
1883  if (mcman_chrpos(p, '/') >= 0)
1884  return 2;
1885 
1886  pcacheDir->cluster = cluster;
1887  pcacheDir->fsindex = fsindex;
1888 
1889  return 1;
1890  }
1891 
1892  r = mcman_chrpos(p, '/');
1893  if ((r >= 0) && (p[r + 1] != 0)) {
1894  p += mcman_chrpos(p, '/') + 1;
1895  cluster = pcacheDir->cluster;
1896  fsindex = pcacheDir->fsindex;
1897 
1898  McReadDirEntry(port, slot, cluster, fsindex, &fse);
1899  }
1900  else {
1901  McReadDirEntry(port, slot, pcacheDir->cluster, pcacheDir->fsindex, pfse);
1902 
1903  return sceMcResSucceed;
1904  }
1905  } while (*p != 0);
1906  }
1907  return sceMcResSucceed;
1908 }
1909 
1910 //--------------------------------------------------------------
1911 int mcman_getdirinfo(int port, int slot, McFsEntry *pfse, const char *filename, McCacheDir *pcd, int unknown_flag)
1912 {
1913  register int i, r, ret, len, pos;
1914  McFsEntry *fse;
1915  u8 *pfsentry, *pfsee, *pfseend;
1916 
1917  DPRINTF("mcman_getdirinfo port%d slot%d name %s\n", port, slot, filename);
1918 
1919  pos = mcman_chrpos(filename, '/');
1920  if (pos < 0)
1921  pos = strlen(filename);
1922 
1923  ret = 0;
1924  if ((pos == 2) && (!strncmp(filename, "..", 2))) {
1925 
1926  r = McReadDirEntry(port, slot, pfse->cluster, 0, &fse);
1927  if (r != sceMcResSucceed)
1928  return r;
1929 
1930  r = McReadDirEntry(port, slot, fse->cluster, 0, &fse);
1931  if (r != sceMcResSucceed)
1932  return r;
1933 
1934  if (pcd) {
1935  pcd->cluster = fse->cluster;
1936  pcd->fsindex = fse->dir_entry;
1937  }
1938 
1939  r = McReadDirEntry(port, slot, fse->cluster, fse->dir_entry, &fse);
1940  if (r != sceMcResSucceed)
1941  return r;
1942 
1943  pfsentry = (u8 *)fse;
1944  pfsee = (u8 *)pfse;
1945  pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
1946 
1947  do {
1948  *((u32 *)pfsee ) = *((u32 *)pfsentry );
1949  *((u32 *)pfsee+1) = *((u32 *)pfsentry+1);
1950  *((u32 *)pfsee+2) = *((u32 *)pfsentry+2);
1951  *((u32 *)pfsee+3) = *((u32 *)pfsentry+3);
1952  pfsentry += 16;
1953  pfsee += 16;
1954  } while (pfsentry < pfseend);
1955 
1956  if ((fse->mode & sceMcFileAttrHidden) != 0) {
1957  ret = 1;
1958  if (!PS1CardFlag) {
1959  ret = 2;
1960  if ((pcd == NULL) || (pcd->maxent < 0))
1961  return 3;
1962  }
1963  }
1964 
1965  if ((pcd == NULL) || (pcd->maxent < 0))
1966  return sceMcResSucceed;
1967  }
1968  else {
1969  if ((pos == 1) && (!strncmp(filename, ".", 1))) {
1970 
1971  r = McReadDirEntry(port, slot, pfse->cluster, 0, &fse);
1972  if (r != sceMcResSucceed)
1973  return r;
1974 
1975  if (pcd) {
1976  pcd->cluster = fse->cluster;
1977  pcd->fsindex = fse->dir_entry;
1978  }
1979 
1980  if ((fse->mode & sceMcFileAttrHidden) != 0) {
1981  ret = 1;
1982  if (!PS1CardFlag) {
1983  ret = 2;
1984  if ((pcd == NULL) || (pcd->maxent < 0))
1985  return 3;
1986  }
1987  else {
1988  if ((pcd == NULL) || (pcd->maxent < 0))
1989  return sceMcResSucceed;
1990  }
1991  }
1992  else {
1993  ret = 1;
1994  if ((pcd == NULL) || (pcd->maxent < 0))
1995  return sceMcResSucceed;
1996  }
1997  }
1998  }
1999 
2000  if ((pcd) && (pcd->maxent >= 0))
2001  pcd->maxent = pfse->length;
2002 
2003  if (pfse->length > 0) {
2004 
2005  i = 0;
2006  do {
2007  r = McReadDirEntry(port, slot, pfse->cluster, i, &fse);
2008  if (r != sceMcResSucceed)
2009  return r;
2010 
2011  if (((fse->mode & sceMcFileAttrExists) == 0) && (pcd) && (i < pcd->maxent))
2012  pcd->maxent = i;
2013 
2014  if (unknown_flag) {
2015  if ((fse->mode & sceMcFileAttrExists) == 0)
2016  continue;
2017  }
2018  else {
2019  if ((fse->mode & sceMcFileAttrExists) != 0)
2020  continue;
2021  }
2022 
2023  if (ret != 0)
2024  continue;
2025 
2026  if ((pos >= 11) && (!strncmp(&filename[10], &fse->name[10], pos-10))) {
2027  len = pos;
2028  if (strlen(fse->name) >= (unsigned int)pos)
2029  len = strlen(fse->name);
2030 
2031  if (!strncmp(filename, fse->name, len))
2032  goto continue_check;
2033  }
2034 
2035  if (strlen(fse->name) >= (unsigned int)pos)
2036  len = strlen(fse->name);
2037  else
2038  len = pos;
2039 
2040  if (strncmp(filename, fse->name, len))
2041  continue;
2042 
2043 continue_check:
2044  ret = 1;
2045 
2046  if ((fse->mode & sceMcFileAttrHidden) != 0) {
2047  if (!PS1CardFlag)
2048  ret = 2;
2049  }
2050 
2051  if (pcd == NULL)
2052  break;
2053 
2054  pcd->fsindex = i;
2055  pcd->cluster = pfse->cluster;
2056 
2057  if (pcd->maxent < 0)
2058  break;
2059 
2060  } while ((u32)(++i) < pfse->length);
2061  }
2062 
2063  if (ret == 2)
2064  return 2;
2065 
2066  return ((ret < 1) ? 1 : 0);
2067 }
2068 
2069 //--------------------------------------------------------------
2070 int mcman_writecluster(int port, int slot, int cluster, int flag)
2071 {
2072  register int i, block;
2073  register u32 erase_value;
2074  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2075 
2076  block = cluster / mcdi->clusters_per_block;
2077 
2078  if ((mcman_wr_port == port) && (mcman_wr_slot == slot) && (mcman_wr_block == block))
2079  return mcman_wr_flag3;
2080 
2081  mcman_wr_port = port;
2082  mcman_wr_slot = slot;
2083  mcman_wr_block = block;
2084  mcman_wr_flag3 = -9;
2085 
2086  for (i = 0; i < 16; i++) { // check only 16 bad blocks ?
2087  if (mcdi->bad_block_list[i] < 0)
2088  break;
2089  if (mcdi->bad_block_list[i] == block) {
2090  mcman_wr_flag3 = 0;
2091  return sceMcResSucceed;
2092  }
2093  }
2094 
2095  if (flag) {
2096  register int r, j, page, pageword_cnt;
2097 
2098  for (i = 1; i < mcdi->blocksize; i++)
2099  mcman_pagedata[i] = 0;
2100 
2101  mcman_pagedata[0] = mcman_pagebuf.byte;
2102 
2103  pageword_cnt = mcdi->pagesize >> 2;
2104  page = block * mcdi->blocksize;
2105 
2106  if (mcdi->cardflags & CF_ERASE_ZEROES)
2107  erase_value = 0xffffffff;
2108  else
2109  erase_value = 0x00000000;
2110 
2111  for (i = 0; i < pageword_cnt; i++)
2112  mcman_pagebuf.word[i] = erase_value;
2113 
2114  r = mcman_eraseblock(port, slot, block, (void **)mcman_pagedata, (void *)mcman_eccdata);
2115  if (r == sceMcResFailReplace)
2116  return sceMcResSucceed;
2117  if (r != sceMcResSucceed)
2118  return sceMcResChangedCard;
2119 
2120  for (i = 1; i < mcdi->blocksize; i++) {
2121  r = McWritePage(port, slot, page + i, &mcman_pagebuf, mcman_eccdata);
2122  if (r == sceMcResFailReplace)
2123  return sceMcResSucceed;
2124  if (r != sceMcResSucceed)
2125  return sceMcResNoFormat;
2126  }
2127 
2128  for (i = 1; i < mcdi->blocksize; i++) {
2129  r = McReadPage(port, slot, page + i, &mcman_pagebuf);
2130  if (r == sceMcResNoFormat)
2131  return sceMcResSucceed;
2132  if (r != sceMcResSucceed)
2133  return sceMcResFullDevice;
2134 
2135  for (j = 0; j < pageword_cnt; j++) {
2136  if (mcman_pagebuf.word[j] != erase_value) {
2137  mcman_wr_flag3 = 0;
2138  return sceMcResSucceed;
2139  }
2140  }
2141  }
2142 
2143  r = mcman_eraseblock(port, slot, block, NULL, NULL);
2144  if (r != sceMcResSucceed)
2145  return sceMcResChangedCard;
2146 
2147  r = McWritePage(port, slot, page, &mcman_pagebuf, mcman_eccdata);
2148  if (r == sceMcResFailReplace)
2149  return sceMcResSucceed;
2150  if (r != sceMcResSucceed)
2151  return sceMcResNoFormat;
2152 
2153  r = McReadPage(port, slot, page, &mcman_pagebuf);
2154  if (r == sceMcResNoFormat)
2155  return sceMcResSucceed;
2156  if (r != sceMcResSucceed)
2157  return sceMcResFullDevice;
2158 
2159  for (j = 0; j < pageword_cnt; j++) {
2160  if (mcman_pagebuf.word[j] != erase_value) {
2161  mcman_wr_flag3 = 0;
2162  return sceMcResSucceed;
2163  }
2164  }
2165 
2166  r = mcman_eraseblock(port, slot, block, NULL, NULL);
2167  if (r == sceMcResFailReplace)
2168  return sceMcResSucceed;
2169  if (r != sceMcResSucceed)
2170  return sceMcResFullDevice;
2171 
2172  erase_value = ~erase_value;
2173 
2174  for (i = 0; i < mcdi->blocksize; i++) {
2175  r = McReadPage(port, slot, page + i, &mcman_pagebuf);
2176  if (r != sceMcResSucceed)
2177  return sceMcResDeniedPermit;
2178 
2179  for (j = 0; j < pageword_cnt; j++) {
2180  if (mcman_pagebuf.word[j] != erase_value) {
2181  mcman_wr_flag3 = 0;
2182  return sceMcResSucceed;
2183  }
2184  }
2185  }
2186  }
2187  mcman_wr_flag3 = 1;
2188 
2189  return mcman_wr_flag3;
2190 }
2191 
2192 //--------------------------------------------------------------
2193 int McSetDirEntryState(int port, int slot, int cluster, int fsindex, int flags)
2194 {
2195  register int r, i, fat_index;
2196  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2197  McFsEntry *fse;
2198  int fat_entry;
2199 
2200  r = McReadDirEntry(port, slot, cluster, fsindex, &fse);
2201  if (r != sceMcResSucceed)
2202  return r;
2203 
2204  if (fse->name[0] == '.') {
2205  if ((fse->name[1] == 0) || (fse->name[1] == '.'))
2206  return sceMcResNoEntry;
2207  }
2208 
2209  i = 0;
2210  do {
2211  if (mcman_fdhandles[i].status == 0)
2212  continue;
2213 
2214  if ((mcman_fdhandles[i].port != port) || (mcman_fdhandles[i].slot != slot))
2215  continue;
2216 
2217  if (mcman_fdhandles[i].cluster != (u32)cluster)
2218  continue;
2219 
2220  if (mcman_fdhandles[i].fsindex == (u32)fsindex)
2221  return sceMcResDeniedPermit;
2222 
2223  } while (++i < MAX_FDHANDLES);
2224 
2225  if (flags == 0)
2226  fse->mode = fse->mode & (sceMcFileAttrExists - 1);
2227  else
2228  fse->mode = fse->mode | sceMcFileAttrExists;
2229 
2230  Mc1stCacheEntSetWrFlagOff();
2231 
2232  fat_index = fse->cluster;
2233 
2234  if (fat_index >= 0) {
2235  if ((u32)fat_index < mcdi->unknown2)
2236  mcdi->unknown2 = fat_index;
2237  mcdi->unknown5 = -1;
2238 
2239  do {
2240  r = McGetFATentry(port, slot, fat_index, &fat_entry);
2241  if (r != sceMcResSucceed)
2242  return r;
2243 
2244  if (flags == 0) {
2245  fat_entry &= ~0x80000000;
2246  if ((u32)fat_index < mcdi->unknown2)
2247  mcdi->unknown2 = fat_entry;
2248  }
2249  else
2250  fat_entry |= 0x80000000;
2251 
2252  r = McSetFATentry(port, slot, fat_index, fat_entry);
2253  if (r != sceMcResSucceed)
2254  return r;
2255 
2256  fat_index = fat_entry & ~0x80000000;
2257 
2258  } while (fat_index != ~0x80000000);
2259  }
2260 
2261  return sceMcResSucceed;
2262 }
2263 
2264 //--------------------------------------------------------------
2265 int mcman_checkBackupBlocks(int port, int slot)
2266 {
2267  register int r1, r2, r, eccsize;
2268  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2269  McCacheEntry *mce;
2270  u32 *pagebuf = mcman_pagebuf.word;
2271  u32 value1, value2;
2272 
2273  // First check backup block2 to see if it's in erased state
2274  r1 = McReadPage(port, slot, mcdi->backup_block2 * mcdi->blocksize, &mcman_pagebuf); //s1
2275 
2276  value1 = *pagebuf; //s3
2277  if (((mcdi->cardflags & CF_ERASE_ZEROES) != 0) && (value1 == 0))
2278  value1 = 0xffffffff;
2279  if (value1 != 0xffffffff)
2280  value1 = value1 & ~0x80000000;
2281 
2282  r2 = McReadPage(port, slot, (mcdi->backup_block2 * mcdi->blocksize) + 1, &mcman_pagebuf); //a0
2283 
2284  value2 = *pagebuf; //s0
2285  if (((mcdi->cardflags & CF_ERASE_ZEROES) != 0) && (value2 == 0))
2286  value2 = 0xffffffff;
2287  if (value2 != 0xffffffff)
2288  value2 = value2 & ~0x80000000;
2289 
2290  if ((value1 != 0xffffffff) && (value2 == 0xffffffff))
2291  goto check_done;
2292  if ((r1 < 0) || (r2 < 0))
2293  goto check_done;
2294 
2295  if ((value1 == 0xffffffff) && (value1 == value2))
2296  return sceMcResSucceed;
2297 
2298  // bachup block2 is not erased, so programming is assumed to have not been completed
2299  // reads content of backup block1
2300  for (r1 = 0; (u32)r1 < mcdi->clusters_per_block; r1++) {
2301 
2302  McReadCluster(port, slot, (mcdi->backup_block1 * mcdi->clusters_per_block) + r1, &mce);
2303  mce->rd_flag = 1;
2304 
2305  for (r2 = 0; r2 < mcdi->pages_per_cluster; r2++) {
2306  mcman_pagedata[(r1 * ((mcdi->pages_per_cluster << 16) >> 16)) + r2] = \
2307  (void *)(mce->cl_data + (r2 * mcdi->pagesize));
2308  }
2309  }
2310 
2311  // Erase the block where data must be written
2312  r = mcman_eraseblock(port, slot, value1, (void **)mcman_pagedata, (void *)mcman_eccdata);
2313  if (r != sceMcResSucceed)
2314  return r;
2315 
2316  // Write the block
2317  for (r1 = 0; r1 < mcdi->blocksize; r1++) {
2318 
2319  eccsize = mcdi->pagesize;
2320  if (eccsize < 0)
2321  eccsize += 0x1f;
2322  eccsize = eccsize >> 5;
2323 
2324  r = McWritePage(port, slot, (value1 * ((mcdi->blocksize << 16) >> 16)) + r1, \
2325  mcman_pagedata[r1], (void *)(mcman_eccdata + (eccsize * r1)));
2326 
2327  if (r != sceMcResSucceed)
2328  return r;
2329  }
2330 
2331  for (r1 = 0; (u32)r1 < mcdi->clusters_per_block; r1++)
2332  mcman_freecluster(port, slot, (mcdi->backup_block1 * mcdi->clusters_per_block) + r1);
2333 
2334 check_done:
2335  // Finally erase backup block2
2336  return mcman_eraseblock(port, slot, mcdi->backup_block2, NULL, NULL);
2337 }
2338 
2339 //--------------------------------------------------------------
2340 int McCheckBlock(int port, int slot, int block)
2341 {
2342  register int r, i, j, page, ecc_count, pageword_cnt, flag, erase_value;
2343  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2344  u8 *p_page, *p_ecc;
2345 
2346  DPRINTF("McCheckBlock port%d slot%d block 0x%x\n", port, slot, block);
2347 
2348  // sp50 = block;
2349  page = block * mcdi->blocksize; //sp18
2350  pageword_cnt = mcdi->pagesize >> 2; //s6
2351 
2352  ecc_count = mcdi->pagesize;
2353  if (mcdi->pagesize < 0)
2354  ecc_count += 127;
2355  ecc_count = ecc_count >> 7; // s7
2356 
2357  flag = 0; // s4
2358 
2359  if (mcdi->cardform > 0) {
2360  for (i = 0; i < 16; i++) {
2361  if (mcdi->bad_block_list[i] <= 0)
2362  break;
2363  if (mcdi->bad_block_list[i] == block)
2364  goto lbl_8764;
2365  }
2366  }
2367 
2368  flag = 16; // s4
2369 
2370  for (i = 0; i < mcdi->blocksize; i++) {
2371  r = mcman_readpage(port, slot, page + i, &mcman_pagebuf, mcman_eccdata);
2372  if (r != sceMcResSucceed)
2373  return -45;
2374 
2375  if ((mcdi->cardflags & CF_USE_ECC) != 0) {
2376  if (mcman_eccdata[mcman_sparesize(port, slot) - 1] != 0xff) {
2377  p_page = mcman_pagebuf.byte; //s1
2378  p_ecc = (void *)mcman_eccdata; //s2
2379 
2380  for (j = 0; j < ecc_count; j++) {
2381  r = mcman_correctdata(p_page, p_ecc);
2382  if (r != sceMcResSucceed) {
2383  flag = -1;
2384  goto lbl_8764;
2385  }
2386  p_ecc = (void *)((u8 *)p_ecc + 3);
2387  p_page = (void *)((u8 *)p_page + 128);
2388  }
2389  }
2390  }
2391  }
2392 
2393  for (j = 0; j < pageword_cnt; j++)
2394  mcman_pagebuf.word[j] = 0x5a5aa5a5;
2395 
2396  for (j = 0; j < 128; j++)
2397  *((u32 *)&mcman_eccdata + j) = 0x5a5aa5a5;
2398 
2399  r = mcman_eraseblock(port, slot, block, NULL, NULL);
2400  if (r != sceMcResSucceed) {
2401  r = mcman_probePS2Card2(port, slot);
2402  if (r != sceMcResSucceed)
2403  return -45;
2404  flag = -1;
2405  goto lbl_8764;
2406  }
2407 
2408  for (i = 0; i < mcdi->blocksize; i++) {
2409  r = McWritePage(port, slot, page + i, &mcman_pagebuf, mcman_eccdata);
2410  if (r != sceMcResSucceed) {
2411  r = mcman_probePS2Card2(port, slot);
2412  if (r != sceMcResSucceed)
2413  return -44;
2414  flag = -1;
2415  goto lbl_8764;
2416  }
2417  }
2418 
2419  for (i = 0; i < mcdi->blocksize; i++) {
2420  r = mcman_readpage(port, slot, page + i, &mcman_pagebuf, mcman_eccdata);
2421  if (r != sceMcResSucceed)
2422  return -45;
2423 
2424  for (j = 0; j < pageword_cnt; j++) {
2425  if (mcman_pagebuf.word[j] != 0x5a5aa5a5) {
2426  flag = -1;
2427  goto lbl_8764;
2428  }
2429  }
2430 
2431  for (j = 0; j < 128; j++) {
2432  if (*((u32 *)&mcman_eccdata + j) != 0x5a5aa5a5) {
2433  flag = -1;
2434  goto lbl_8764;
2435  }
2436  }
2437  }
2438 
2439  for (j = 0; j < pageword_cnt; j++)
2440  mcman_pagebuf.word[j] = 0x05a55a5a;
2441 
2442  for (j = 0; j < 128; j++)
2443  *((u32 *)&mcman_eccdata + j) = 0x05a55a5a;
2444 
2445  r = mcman_eraseblock(port, slot, block, NULL, NULL);
2446  if (r != sceMcResSucceed) {
2447  r = mcman_probePS2Card2(port, slot);
2448  if (r != sceMcResSucceed)
2449  return -42;
2450  flag = -1;
2451  goto lbl_8764;
2452  }
2453 
2454  for (i = 0; i < mcdi->blocksize; i++) {
2455  r = McWritePage(port, slot, page + i, &mcman_pagebuf, mcman_eccdata);
2456  if (r != sceMcResSucceed) {
2457  r = mcman_probePS2Card2(port, slot);
2458  if (r != sceMcResSucceed)
2459  return -46;
2460  flag = -1;
2461  goto lbl_8764;
2462  }
2463  }
2464 
2465  for (i = 0; i < mcdi->blocksize; i++) {
2466  r = mcman_readpage(port, slot, page + i, &mcman_pagebuf, mcman_eccdata);
2467  if (r != sceMcResSucceed)
2468  return -45;
2469 
2470  for (j = 0; j < pageword_cnt; j++) {
2471  if (mcman_pagebuf.word[j] != 0x05a55a5a) {
2472  flag = -1;
2473  goto lbl_8764;
2474  }
2475  }
2476 
2477  for (j = 0; j < 128; j++) {
2478  if (*((u32 *)&mcman_eccdata + j) != 0x05a55a5a) {
2479  flag = -1;
2480  goto lbl_8764;
2481  }
2482  }
2483  }
2484 
2485 lbl_8764:
2486  if (flag == 16) {
2487  mcman_eraseblock(port, slot, block, NULL, NULL);
2488  return sceMcResSucceed;
2489  }
2490 
2491  erase_value = 0x00000000;
2492  if ((mcdi->cardflags & CF_ERASE_ZEROES) != 0)
2493  erase_value = 0xffffffff;
2494 
2495  for (j = 0; j < pageword_cnt; j++)
2496  mcman_pagebuf.word[j] = erase_value;
2497 
2498  for (j = 0; j < 128; j++)
2499  *((u32 *)&mcman_eccdata + j) = erase_value;
2500 
2501  for (i = 0; i < mcdi->blocksize; i++) {
2502  r = McWritePage(port, slot, page + i, &mcman_pagebuf, mcman_eccdata);
2503  if (r != sceMcResSucceed) {
2504  r = mcman_probePS2Card2(port, slot);
2505  if (r != sceMcResSucceed)
2506  return -48;
2507  }
2508  }
2509 
2510  return 1;
2511 }
2512 
2513 //--------------------------------------------------------------
2514 int mcman_setPS1devinfos(int port, int slot)
2515 {
2516  register int r, i;
2517  MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2518 
2519  DPRINTF("mcman_setPS1devinfos port%d slot%d\n", port, slot);
2520 
2521  memset((void *)mcdi, 0, sizeof (MCDevInfo));
2522  memset((void *)&mcdi->bad_block_list[0], -1, 128);
2523 
2524  mcdi->pagesize = 128;
2525  mcdi->blocksize = 128;
2526  mcdi->pages_per_cluster = 64;
2527  mcdi->unused = 0xff00;
2528  mcdi->cluster_size = 8192;
2529  mcdi->FATentries_per_cluster = 2048;
2530  mcdi->clusters_per_card = 16;
2531  mcdi->clusters_per_block = 0;
2532  mcdi->cardform = 0;
2533  mcdi->cardtype = 1;
2534 
2535  r = McReadPS1PDACard(port, slot, 0, &mcman_PS1PDApagebuf);
2536  if (r < 0)
2537  return -14;
2538 
2539 #if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
2540  if (mcman_sio2outbufs_PS1PDA[1] != 0)
2541  return -15;
2542 #endif
2543 
2544  mcdi->cardform = -1;
2545 
2546  if (mcman_PS1PDApagebuf.byte[0] != 0x4d)
2547  return sceMcResNoFormat;
2548 
2549  if (mcman_PS1PDApagebuf.byte[1] != 0x43)
2550  return sceMcResNoFormat;
2551 
2552  for (i = 0; i < 20; i++) {
2553  r = McReadPS1PDACard(port, slot, i + 16, &mcman_PS1PDApagebuf);
2554  if (r != sceMcResSucceed)
2555  return -43;
2556 
2557  if (mcman_PS1PDApagebuf.byte[127] == (mcman_calcEDC(&mcman_PS1PDApagebuf, 127) & 0xff)) {
2558  mcdi->bad_block_list[i] = mcman_PS1PDApagebuf.word[0];
2559  }
2560  }
2561 
2562  r = mcman_cachePS1dirs(port, slot);
2563 
2564  if (r != sceMcResSucceed)
2565  return r;
2566 
2567  mcdi->cardform = 1;
2568 
2569  return sceMcResSucceed;
2570 }
2571 
2572 //--------------------------------------------------------------
2573 int mcman_getPS1direntry(int port, int slot, const char *filename, McFsEntryPS1 **pfse, int flag)
2574 {
2575  register int i;
2576  const char *p = filename;
2577 
2578  DPRINTF("mcman_getPS1direntry port%d slot%d file %s flag %x\n", port, slot, filename, flag);
2579 
2580  if (*p == '/')
2581  p++;
2582 
2583  i = 0;
2584  do {
2585  register int r;
2586 
2587  r = mcman_readdirentryPS1(port, slot, i, pfse);
2588  if (r != sceMcResSucceed)
2589  return r;
2590 
2591  if (flag != 0) {
2592  if (pfse[0]->mode != 0x51)
2593  continue;
2594  }
2595  else {
2596  if (pfse[0]->mode != 0xa1)
2597  continue;
2598  }
2599 
2600  if (!strcmp(p, pfse[0]->name))
2601  return i;
2602 
2603  } while (++i < 15);
2604 
2605  return sceMcResNoEntry;
2606 }
2607 
2608 //--------------------------------------------------------------
2609 int mcman_clearPS1direntry(int port, int slot, int cluster, int flags)
2610 {
2611  register int r, i, temp;
2612  McFsEntryPS1 *fse;
2613  MC_FHANDLE *fh;
2614  McCacheEntry *mce;
2615 
2616  DPRINTF("mcman_clearPS1direntry port%d slot%d cluster %x flags %x\n", port, slot, cluster, flags);
2617 
2618  r = mcman_readdirentryPS1(port, slot, cluster, &fse);
2619  if (r != sceMcResSucceed)
2620  return r;
2621 
2622  fh = (MC_FHANDLE *)&mcman_fdhandles[0];
2623 
2624  for (i = 0; i < MAX_FDHANDLES; i++) {
2625  if ((fh->status != 0) && (fh->port == port) && (fh->slot == slot)) {
2626  if (fh->freeclink == (u32)cluster)
2627  return sceMcResDeniedPermit;
2628 
2629  }
2630  fh++;
2631  }
2632 
2633  if (!flags) {
2634  if (fse->mode != 0x51)
2635  return sceMcResNoEntry;
2636  }
2637  else {
2638  if (fse->mode != 0xa1)
2639  return sceMcResNoEntry;
2640  }
2641 
2642  do {
2643 lbl0:
2644  mce = mcman_get1stcacheEntp();
2645 
2646  if (cluster + 1 < 0)
2647  temp = cluster + 8;
2648  else
2649  temp = cluster + 1;
2650 
2651  temp &= ~0x00000007;
2652  temp = (cluster + 1) - temp;
2653  if (temp < 0)
2654  temp = 0;
2655 
2656  mce->wr_flag |= 1 << temp;
2657 
2658  if (flags == 0)
2659  temp = (fse->mode & 0xf) | 0xa0;
2660  else
2661  temp = (fse->mode & 0xf) | 0x50;
2662 
2663  fse->mode = temp;
2664  fse->edc = mcman_calcEDC((void *)fse, 127);
2665 
2666  // Unofficial: upper bounds check linked_block
2667  if (fse->linked_block < 0 || fse->linked_block >= 15) {
2668  //cluster = 0;
2669  goto lbl1;
2670  }
2671 
2672  cluster = fse->linked_block;
2673 
2674  r = mcman_readdirentryPS1(port, slot, cluster, &fse);
2675  if (r != sceMcResSucceed)
2676  return r;
2677 
2678  if (flags == 0) {
2679  if ((fse->mode & 0xf0) != 0x50)
2680  break;
2681  goto lbl0;
2682  }
2683 
2684  } while ((fse->mode & 0xf0) == 0xa0);
2685 
2686  r = McFlushCache(port, slot);
2687  if (r != sceMcResSucceed)
2688  return r;
2689 
2690  return sceMcResNoEntry;
2691 
2692 lbl1:
2693  r = McFlushCache(port, slot);
2694  if (r != sceMcResSucceed)
2695  return r;
2696 
2697  return sceMcResSucceed;
2698 }
2699 
2700 //--------------------------------------------------------------
2701 int mcman_findfree1(int port, int slot, int reserve)
2702 {
2703  register int i, free;
2704  McFsEntryPS1 *fse;
2705 
2706  DPRINTF("mcman_findfree1 port%d slot%d reserve %d\n", port, slot, reserve);
2707 
2708  free = 0;
2709  i = 0;
2710 
2711  do {
2712  register int r;
2713 
2714  r = mcman_readdirentryPS1(port, slot, i, &fse);
2715  if (r != sceMcResSucceed)
2716  return -37;
2717 
2718  if ((fse->mode & 0xf0) == 0xa0) {
2719  if (reserve)
2720  return i;
2721  free++;
2722  }
2723  } while (++i < 15);
2724 
2725  if (reserve)
2726  return sceMcResFullDevice;
2727 
2728  if (free)
2729  return free;
2730 
2731  return sceMcResFullDevice;
2732 }
2733 
2734 //--------------------------------------------------------------
2735 int mcman_fatRseekPS1(int fd)
2736 {
2737  register int rpos, numclust, clust;
2738  MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
2739  MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
2740  McFsEntryPS1 *fse;
2741 
2742  numclust = fh->position / mcdi->cluster_size;
2743  numclust--;
2744  clust = fh->freeclink;
2745 
2746  if (numclust > -1) {
2747  do {
2748  register int r;
2749 
2750  if (clust < 0)
2751  return sceMcResFullDevice;
2752 
2753  r = mcman_readdirentryPS1(fh->port, fh->slot, clust, &fse);
2754  if (r != sceMcResSucceed)
2755  return r;
2756  clust = fse->linked_block;
2757 
2758  } while (--numclust > -1);
2759  }
2760 
2761  if (clust < 0)
2762  return sceMcResFullDevice;
2763 
2764  rpos = fh->position % mcdi->cluster_size;
2765 
2766  if (rpos < 0)
2767  rpos += 1023;
2768 
2769  return ((clust + 1) << 6) + ((rpos >> 10) * (1024 / mcdi->pagesize));
2770 }
2771 
2772 //--------------------------------------------------------------
2773 int mcman_fatWseekPS1(int fd)
2774 {
2775  register int r, numclust;
2776  MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
2777  MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
2778  McFsEntryPS1 *fse;
2779 
2780  numclust = fh->position / mcdi->cluster_size;
2781 
2782  if (numclust > 0) {
2783  register int clust;
2784 
2785  clust = fh->freeclink;
2786  do {
2787  r = mcman_readdirentryPS1(fh->port, fh->slot, clust, &fse);
2788  if (r != sceMcResSucceed)
2789  return r;
2790 
2791  clust = fse->linked_block;
2792 
2793  if (clust < 0) {
2794  r = mcman_FNC8ca4(fh->port, fh->slot, (MC_FHANDLE *)fh);
2795  if (r < 0)
2796  return r;
2797  clust = r;
2798  }
2799  } while (--numclust);
2800  }
2801  r = McFlushCache(fh->port, fh->slot);
2802 
2803  return r;
2804 }
2805 
2806 //--------------------------------------------------------------
2807 int mcman_FNC8ca4(int port, int slot, MC_FHANDLE *fh)
2808 {
2809  register int r, i, j, mcfree, cluster_size, pages_per_FATclust;
2810  register int temp;
2811  MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
2812  McFsEntryPS1 *fse1, *fse2, *fse3;
2813  McCacheEntry *mce;
2814 
2815  DPRINTF("mcman_FNC8ca4 port%d slot%d\n", port, slot);
2816 
2817  if ((int)(mcdi->cluster_size) < 0)
2818  cluster_size = mcdi->cluster_size + 1023;
2819  else
2820  cluster_size = mcdi->cluster_size;
2821 
2822  cluster_size = cluster_size >> 10;
2823 
2824  pages_per_FATclust = 1024 / mcdi->pagesize;
2825 
2826  r = mcman_findfree1(port, slot, 1);
2827  if (r < 0)
2828  return r;
2829 
2830  i = fh->freeclink;
2831  mcfree = r;
2832  j = -1;
2833 
2834  {
2835  // Unofficial: upper bounds check i
2836  while (i >= 0 && i < 15) {
2837  if (mcfree < i) {
2838  u8 *pfsentry, *pfsee, *pfseend;
2839 
2840  if (cluster_size > 0) {
2841  i = 0;
2842 
2843  do {
2844  mcman_freecluster(port, slot, ((mcfree * cluster_size) + i) * pages_per_FATclust);
2845 
2846  r = mcman_readclusterPS1(port, slot, ((i * cluster_size) + i) * pages_per_FATclust, &mce);
2847  if (r != sceMcResSucceed)
2848  return r;
2849 
2850  mce->wr_flag = -1;
2851  mce->cluster -= (i - mcfree) * cluster_size;
2852 
2853  } while (++i < cluster_size);
2854  }
2855 
2856  r = mcman_readdirentryPS1(port, slot, i, &fse1);
2857  if (r != sceMcResSucceed)
2858  return r;
2859 
2860  r = mcman_readdirentryPS1(port, slot, mcfree, &fse2);
2861  if (r != sceMcResSucceed)
2862  return r;
2863 
2864  mce = mcman_get1stcacheEntp();
2865 
2866  if (mcfree + 1 < 0)
2867  temp = mcfree + 8;
2868  else
2869  temp = mcfree + 1;
2870 
2871  temp &= ~0x00000007;
2872  temp = (mcfree + 1) - temp;
2873  if (temp < 0)
2874  temp = 0;
2875 
2876  mce->wr_flag |= 1 << temp;
2877 
2878  pfsentry = (u8 *)fse1;
2879  pfsee = (u8 *)fse2;
2880  pfseend = (u8 *)(pfsentry + sizeof(McFsEntryPS1));
2881 
2882  do {
2883  *((u32 *)pfsee ) = *((u32 *)pfsentry );
2884  *((u32 *)pfsee+1) = *((u32 *)pfsentry+1);
2885  *((u32 *)pfsee+2) = *((u32 *)pfsentry+2);
2886  *((u32 *)pfsee+3) = *((u32 *)pfsentry+3);
2887  pfsentry += 16;
2888  pfsee += 16;
2889  } while (pfsentry < pfseend);
2890 
2891  if (j >= 0) {
2892  r = mcman_readdirentryPS1(port, slot, j, &fse3);
2893  if (r != sceMcResSucceed)
2894  return r;
2895 
2896  mce = mcman_get1stcacheEntp();
2897 
2898 #if 0
2899  // This condition is always false due to the preceding check on "j" variable.
2900  if ((j + 1) < 0)
2901  {
2902  temp = j + 8;
2903  }
2904  else
2905 #endif
2906  {
2907  temp = j + 1;
2908  }
2909 
2910  temp &= ~0x00000007;
2911  temp = (j + 1) - temp;
2912  if (temp < 0)
2913  temp = 0;
2914 
2915  mce->wr_flag |= 1 << temp;
2916  fse3->linked_block = mcfree;
2917  fse3->edc = mcman_calcEDC((void *)fse3, 127);
2918  }
2919  else {
2920  fh->freeclink = mcfree;
2921  }
2922  j = mcfree;
2923  mcfree = i;
2924 
2925  }
2926  else {
2927  j = i;
2928  r = mcman_readdirentryPS1(port, slot, j, &fse1);
2929  if (r != sceMcResSucceed)
2930  return r;
2931  }
2932  i = fse1->linked_block;
2933  }
2934  }
2935 
2936  r = mcman_readdirentryPS1(port, slot, mcfree, &fse2);
2937  if (r != sceMcResSucceed)
2938  return r;
2939 
2940  mce = mcman_get1stcacheEntp();
2941 
2942  if (mcfree + 1 < 0)
2943  temp = mcfree + 8;
2944  else
2945  temp = mcfree + 1;
2946 
2947  temp &= ~0x00000007;
2948  temp = (mcfree + 1) - temp;
2949  if (temp < 0)
2950  temp = 0;
2951 
2952  mce->wr_flag |= 1 << temp;
2953 
2954  mcman_wmemset((void *)fse2, sizeof(McFsEntryPS1), 0);
2955 
2956  fse2->mode = 0x53;
2957  fse2->linked_block = -1;
2958  fse2->edc = mcman_calcEDC((void *)fse2, 127);
2959 
2960  r = mcman_readdirentryPS1(port, slot, j, &fse3);
2961  if (r != sceMcResSucceed)
2962  return r;
2963 
2964  mce = mcman_get1stcacheEntp();
2965 
2966  if ((j + 1) < 0)
2967  temp = j + 8;
2968  else
2969  temp = j + 1;
2970 
2971  temp &= ~0x00000007;
2972  temp = (j + 1) - temp;
2973  if (temp < 0)
2974  temp = 0;
2975 
2976  mce->wr_flag |= 1 << temp;
2977 
2978  if (fse3->mode == 0x53)
2979  fse3->mode = 0x52;
2980 
2981  fse3->linked_block = mcfree;
2982  fse3->edc = mcman_calcEDC((void *)fse3, 127);
2983 
2984  return mcfree;
2985 }
2986 
2987 //--------------------------------------------------------------
2988 int mcman_PS1pagetest(int port, int slot, int page)
2989 {
2990  register int r, i;
2991 
2992  for (i = 0; i < 32; i++)
2993  mcman_PS1PDApagebuf.word[i] = 0xffffffff;
2994 
2995  r = McWritePS1PDACard(port, slot, page, &mcman_PS1PDApagebuf);
2996  if (r != sceMcResSucceed)
2997  return sceMcResDeniedPermit;
2998 
2999  r = McReadPS1PDACard(port, slot, page, &mcman_PS1PDApagebuf);
3000  if (r != sceMcResSucceed)
3001  return sceMcResNotEmpty;
3002 
3003  for (i = 0; i < 32; i++) {
3004  if (mcman_PS1PDApagebuf.word[i] != 0xffffffff) {
3005  return 0;
3006  }
3007  }
3008 
3009  for (i = 0; i < 32; i++)
3010  mcman_PS1PDApagebuf.word[i] = 0;
3011 
3012  r = McWritePS1PDACard(port, slot, page, &mcman_PS1PDApagebuf);
3013  if (r != sceMcResSucceed)
3014  return sceMcResDeniedPermit;
3015 
3016  r = McReadPS1PDACard(port, slot, page, &mcman_PS1PDApagebuf);
3017  if (r != sceMcResSucceed)
3018  return sceMcResNotEmpty;
3019 
3020  for (i = 0; i < 32; i++) {
3021  if (mcman_PS1PDApagebuf.word[i] != 0) {
3022  return 0;
3023  }
3024  }
3025 
3026  return 1;
3027 }
3028 
3029 //--------------------------------------------------------------
3030 int mcman_cachePS1dirs(int port, int slot)
3031 {
3032  register int i, j, temp1, temp2, index, linked_block;
3033  McFsEntryPS1 *fs_t[15];
3034  McCacheEntry *mce[2];
3035  int cluster_t[15];
3036 
3037  DPRINTF("mcman_cachePS1dirs port%d slot%d\n", port, slot);
3038 
3039  i = 0;
3040  do {
3041  register int r;
3042 
3043  r = mcman_readdirentryPS1(port, slot, i, &fs_t[i]);
3044  if (r != sceMcResSucceed)
3045  return r;
3046 
3047  fs_t[i]->field_38 = fs_t[i]->length;
3048 
3049  if (i == 0) {
3050  mce[0] = mcman_get1stcacheEntp();
3051  }
3052  else {
3053  if (i == 7)
3054  mce[1] = mcman_get1stcacheEntp();
3055  }
3056  } while (++i < 15);
3057 
3058  memset((void *)cluster_t, -1, sizeof(cluster_t));
3059 
3060  i = 0;
3061  do {
3062  temp1 = fs_t[i]->mode & 0xf0;
3063 
3064  if ((fs_t[i]->mode & 0xf) != 1)
3065  continue;
3066 
3067  cluster_t[i] = i;
3068 
3069  linked_block = fs_t[i]->linked_block;
3070  // Unofficial: upper bounds check linked_block
3071  while (linked_block >= 0 && linked_block < 15) {
3072  if ((fs_t[linked_block]->mode & 0xf0) != temp1)
3073  temp1 = 0;
3074 
3075  if (fs_t[linked_block]->mode == 0xa0)
3076  break;
3077 
3078  if (cluster_t[linked_block] != -1)
3079  break;
3080 
3081  cluster_t[linked_block] = i;
3082  linked_block = fs_t[linked_block]->linked_block;
3083  }
3084 
3085  if ((linked_block < 0 || linked_block >= 15) && (temp1 != 0))
3086  continue;
3087 
3088  j = 0;
3089  do {
3090  if (cluster_t[j] != i)
3091  continue;
3092 
3093  memset((void *)fs_t[j], 0, sizeof (McFsEntryPS1));
3094 
3095  fs_t[j]->mode = 0xa0;
3096  fs_t[j]->linked_block = -1;
3097  fs_t[j]->edc = mcman_calcEDC((void *)fs_t[j], 127);
3098 
3099  temp2 = j + 1;
3100 
3101  if (j < 7)
3102  index = 0;
3103  else
3104  index = 1;
3105 
3106  if (temp2 < 0)
3107  temp1 = j + 8;
3108  else
3109  temp1 = temp2;
3110 
3111  temp1 &= ~0x00000007;
3112  temp1 = temp2 - temp1;
3113  if (temp1 < 0)
3114  temp1 = 0;
3115 
3116  mce[index]->wr_flag |= 1 << temp1;
3117 
3118  } while (++j < 15);
3119 
3120  } while (++i < 15);
3121 
3122  i = 0;
3123  do {
3124  if ((cluster_t[i] != -1) || (fs_t[i]->mode == 0xa0))
3125  continue;
3126 
3127  memset((void *)fs_t[i], 0, sizeof (McFsEntryPS1));
3128 
3129  fs_t[i]->mode = 0xa0;
3130  fs_t[i]->linked_block = cluster_t[i];
3131  fs_t[i]->edc = mcman_calcEDC((void *)fs_t[i], 127);
3132 
3133  temp2 = i + 1;
3134 
3135  if (i < 7)
3136  index = 0;
3137  else
3138  index = 1;
3139 
3140  if (temp2 < 0)
3141  temp1 = i + 8;
3142  else
3143  temp1 = temp2;
3144 
3145  temp1 &= ~0x00000007;
3146  temp1 = temp2 - temp1;
3147  if (temp1 < 0)
3148  temp1 = 0;
3149 
3150  mce[index]->wr_flag |= 1 << temp1;
3151 
3152  } while (++i < 15);
3153 
3154  return sceMcResSucceed;
3155 }
3156 
3157 //--------------------------------------------------------------
3158 int mcman_fillPS1backuparea(int port, int slot, int block)
3159 {
3160  register int r, i, curpage;
3161  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3162 
3163  memset(&mcman_PS1PDApagebuf, 0, 128);
3164 
3165  curpage = 16;
3166  i = 0;
3167  do {
3168  if (mcdi->bad_block_list[i] == block) {
3169  mcdi->bad_block_list[i] = block | 0x01000000;
3170  mcman_PS1PDApagebuf.word[0] = block | 0x01000000;
3171  mcman_PS1PDApagebuf.byte[127] = mcman_calcEDC(&mcman_PS1PDApagebuf, 127);
3172  r = McWritePS1PDACard(port, slot, curpage, &mcman_PS1PDApagebuf);
3173  if (r != sceMcResSucceed)
3174  return -43;
3175  }
3176  else {
3177  if (mcdi->bad_block_list[i] < 0) {
3178  mcman_PS1PDApagebuf.word[0] = block;
3179  mcman_PS1PDApagebuf.byte[127] = mcman_calcEDC(&mcman_PS1PDApagebuf, 127);
3180  r = McWritePS1PDACard(port, slot, curpage, &mcman_PS1PDApagebuf);
3181  if (r != sceMcResSucceed)
3182  return -43;
3183  mcdi->bad_block_list[i] = block;
3184  break;
3185  }
3186  }
3187  curpage++;
3188  } while (++i < 20);
3189 
3190  return sceMcResSucceed;
3191 }
3192 
3193 //--------------------------------------------------------------
3194 void mcman_initcache(void)
3195 {
3196  register int i, j;
3197  u8 *p;
3198 
3199  DPRINTF("mcman_initcache\n");
3200 
3201  j = MAX_CACHEENTRY - 1;
3202  p = (u8 *)mcman_cachebuf;
3203 
3204  for (i = 0; i < MAX_CACHEENTRY; i++) {
3205  mcman_entrycache[i].cl_data = (u8 *)p;
3206  mcman_mccache[i] = (McCacheEntry *)&mcman_entrycache[j - i];
3207  mcman_entrycache[i].cluster = -1;
3208  p += MCMAN_CLUSTERSIZE;
3209  }
3210 
3211  pmcman_entrycache = (McCacheEntry *)mcman_entrycache;
3212  pmcman_mccache = (McCacheEntry **)mcman_mccache;
3213 
3214  for (i = 0; i < MCMAN_MAXSLOT; i++) {
3215  mcman_devinfos[0][i].unknown3 = -1;
3216  mcman_devinfos[0][i].unknown4 = -1;
3217  mcman_devinfos[0][i].unknown5 = -1;
3218  mcman_devinfos[1][i].unknown3 = -1;
3219  mcman_devinfos[1][i].unknown4 = -1;
3220  mcman_devinfos[1][i].unknown5 = -1;
3221  }
3222 
3223  memset((void *)mcman_fatcache, -1, sizeof (mcman_fatcache));
3224 
3225  for (i = 0; i < MCMAN_MAXSLOT; i++) {
3226  mcman_fatcache[0][i].entry[0] = 0;
3227  mcman_fatcache[1][i].entry[0] = 0;
3228  }
3229 }
3230 
3231 //--------------------------------------------------------------
3232 int McRetOnly(int fd) // Export #37
3233 {
3234  (void)fd;
3235 
3236  DPRINTF("McRetOnly param %x\n", fd);
3237  return sceMcResSucceed;
3238 }
3239 
3240 //--------------------------------------------------------------
3241 int mcman_clearcache(int port, int slot)
3242 {
3243  register int i, j;
3244  McCacheEntry **pmce = (McCacheEntry **)pmcman_mccache;
3245  McCacheEntry *mce;
3246 
3247  DPRINTF("mcman_clearcache port%d, slot%d\n", port, slot);
3248 
3249  for (i = MAX_CACHEENTRY - 1; i >= 0; i--) {
3250  mce = (McCacheEntry *)pmce[i];
3251  if ((mce->mc_port == port) && (mce->mc_slot == slot) && (mce->cluster >= 0)) {
3252  mce->mc_port = -1;
3253  mce->mc_slot = -1;
3254  mce->wr_flag = 0;
3255  mce->cluster = -1;
3256  }
3257  }
3258 
3259  for (i = 0; i < (MAX_CACHEENTRY - 1); i++) {
3260  McCacheEntry *mce_save;
3261 
3262  mce = (McCacheEntry *)pmce[i];
3263  mce_save = (McCacheEntry *)pmce[i];
3264  if (mce->cluster < 0) {
3265  for (j = i+1; j < MAX_CACHEENTRY; j++) {
3266  mce = (McCacheEntry *)pmce[j];
3267  if (mce->cluster >= 0)
3268  break;
3269  }
3270  if (j == MAX_CACHEENTRY)
3271  break;
3272 
3273  pmce[i] = (McCacheEntry *)pmce[j];
3274  pmce[j] = (McCacheEntry *)mce_save;
3275  }
3276  }
3277 
3278  memset((void *)&mcman_fatcache[port][slot], -1, sizeof (McFatCache));
3279 
3280  mcman_fatcache[port][slot].entry[0] = 0;
3281 
3282  return sceMcResSucceed;
3283 }
3284 
3285 //--------------------------------------------------------------
3286 McCacheEntry *mcman_getcacheentry(int port, int slot, int cluster)
3287 {
3288  register int i;
3289  McCacheEntry *mce = (McCacheEntry *)pmcman_entrycache;
3290 
3291  //DPRINTF("mcman_getcacheentry port%d slot%d cluster %x\n", port, slot, cluster);
3292 
3293  for (i = 0; i < MAX_CACHEENTRY; i++) {
3294  if ((mce->mc_port == port) && (mce->mc_slot == slot) && (mce->cluster == cluster))
3295  return mce;
3296  mce++;
3297  }
3298 
3299  return NULL;
3300 }
3301 
3302 //--------------------------------------------------------------
3303 void mcman_freecluster(int port, int slot, int cluster) // release cluster from entrycache
3304 {
3305  register int i;
3306  McCacheEntry *mce = (McCacheEntry *)pmcman_entrycache;
3307 
3308  for (i = 0; i < MAX_CACHEENTRY; i++) {
3309  if ((mce->mc_port == port) && (mce->mc_slot == slot) && (mce->cluster == cluster)) {
3310  mce->cluster = -1;
3311  mce->wr_flag = 0;
3312  }
3313  mce++;
3314  }
3315 }
3316 
3317 //--------------------------------------------------------------
3318 int mcman_getFATindex(int port, int slot, int num)
3319 {
3320  return mcman_fatcache[port][slot].entry[num];
3321 }
3322 
3323 //--------------------------------------------------------------
3324 void Mc1stCacheEntSetWrFlagOff(void)
3325 {
3326  McCacheEntry *mce = (McCacheEntry *)*pmcman_mccache;
3327 
3328  mce->wr_flag = -1;
3329 }
3330 
3331 //--------------------------------------------------------------
3332 McCacheEntry *mcman_get1stcacheEntp(void)
3333 {
3334  return *pmcman_mccache;
3335 }
3336 
3337 //--------------------------------------------------------------
3338 void mcman_addcacheentry(McCacheEntry *mce)
3339 {
3340  register int i;
3341  McCacheEntry **pmce = (McCacheEntry **)pmcman_mccache;
3342 
3343  i = MAX_CACHEENTRY - 1;
3344 
3345 #if 0
3346  // This condition is always false because MAX_CACHEENTRY is always bigger than 0
3347  if (i < 0)
3348  goto lbl1;
3349 #endif
3350 
3351  do {
3352  if (pmce[i] == mce)
3353  break;
3354  } while (--i >= 0);
3355 
3356  if (i != 0) {
3357 #if 0
3358  // This label is not used.
3359 lbl1:
3360 #endif
3361  do {
3362  pmce[i] = pmce[i-1];
3363  } while (--i != 0);
3364  }
3365 
3366  pmce[0] = (McCacheEntry *)mce;
3367 }
3368 
3369 //--------------------------------------------------------------
3370 int McFlushCache(int port, int slot)
3371 {
3372  register int i;
3373  McCacheEntry **pmce = (McCacheEntry **)pmcman_mccache;
3374 
3375  DPRINTF("McFlushCache port%d slot%d\n", port, slot);
3376 
3377  i = MAX_CACHEENTRY - 1;
3378 
3379  {
3380  while (i >= 0) {
3381  McCacheEntry *mce;
3382 
3383  mce = (McCacheEntry *)pmce[i];
3384  if ((mce->mc_port == port) && (mce->mc_slot == slot) && (mce->wr_flag != 0)) {
3385  register int r;
3386 
3387  r = mcman_flushcacheentry((McCacheEntry *)mce);
3388  if (r != sceMcResSucceed)
3389  return r;
3390  }
3391  i--;
3392  }
3393  }
3394 
3395  return sceMcResSucceed;
3396 }
3397 
3398 //--------------------------------------------------------------
3399 int mcman_flushcacheentry(McCacheEntry *mce)
3400 {
3401  register int r, i, j, ecc_count;
3402  register int temp1, temp2, offset, pageindex;
3403  static int clusters_per_block, blocksize, cardtype, pagesize, sparesize, flag, cluster, block, pages_per_fatclust;
3404  McCacheEntry *pmce[16]; // sp18
3405  register MCDevInfo *mcdi;
3406  McCacheEntry *mcee;
3407  static u8 eccbuf[32];
3408  void *p_page, *p_ecc;
3409 
3410  DPRINTF("mcman_flushcacheentry mce %x cluster %x\n", (int)mce, (int)mce->cluster);
3411 
3412  if (mce->wr_flag == 0)
3413  return sceMcResSucceed;
3414 
3415  mcdi = (MCDevInfo *)&mcman_devinfos[mce->mc_port][mce->mc_slot];
3416 
3417  //mcdi->pagesize = sp84
3418  pagesize = mcdi->pagesize; //sp84
3419  cardtype = mcdi->cardtype;
3420 
3421  if (cardtype == 0) {
3422  mce->wr_flag = 0;
3423  return sceMcResSucceed;
3424  }
3425 
3426  if ((cardtype == sceMcTypePS1) || (cardtype == sceMcTypePDA)) {
3427  pages_per_fatclust = MCMAN_CLUSTERSIZE / pagesize;
3428  i = mce->cluster; //s0
3429  j = 0; //s1
3430  r = 0;
3431 
3432  if (pages_per_fatclust > 0) {
3433 lbl0:
3434 
3435  do {
3436  if (((mce->wr_flag >> j) & 1) != 0) {
3437  //DPRINTF("flushing ent %x cl_data %x to page %d offset %d\n", mce, mce->cl_data, i, (pagesize * j));
3438  r = McWritePS1PDACard(mce->mc_port, mce->mc_slot, i, (void *)(mce->cl_data + (pagesize * j)));
3439  if (r == sceMcResFailReplace)
3440  break;
3441  if (r != sceMcResSucceed)
3442  return -50;
3443 
3444  }
3445  i++;
3446  } while (++j < pages_per_fatclust);
3447  }
3448 
3449  if (j == pages_per_fatclust) {
3450  r = mcman_probePS1Card2(mce->mc_port, mce->mc_slot);
3451  if (r == -14)
3452  r = sceMcResFailReplace;
3453  }
3454  if (cardtype != sceMcTypePS1) {
3455  if (r == sceMcResFailReplace)
3456  return r;
3457 
3458  mce->wr_flag = 0;
3459  return sceMcResSucceed;
3460  }
3461  if (r != 8) {
3462  mce->wr_flag = 0;
3463  return sceMcResSucceed;
3464  }
3465 
3466  if ((mce->wr_flag & ~(((u32)(-1)) << j)) == 0) {
3467  mce->wr_flag = 0;
3468  return sceMcResSucceed;
3469  }
3470 
3471  if (j-- == 0) {
3472  mce->wr_flag = 0;
3473  return sceMcResSucceed;
3474  }
3475 
3476  i--;
3477 
3478  do {
3479  if (((mce->wr_flag >> j) & 1) != 0) {
3480  r = mcman_fillPS1backuparea(mce->mc_port, mce->mc_slot, i);
3481  if (r != sceMcResSucceed)
3482  return sceMcResFailReplace;
3483 
3484  goto lbl0;
3485  }
3486  } while (j++);
3487 
3488  mce->wr_flag = 0;
3489  return sceMcResSucceed;
3490  }
3491 
3492  clusters_per_block = mcdi->clusters_per_block; //sp7c
3493  block = mce->cluster / mcdi->clusters_per_block; //sp78
3494  blocksize = mcdi->blocksize; //sp80
3495  sparesize = mcman_sparesize(mce->mc_port, mce->mc_slot); //sp84
3496  flag = 0; //sp88
3497 
3498  memset((void *)pmce, 0, 64);
3499 
3500  i = 0; //s1
3501  if (MAX_CACHEENTRY > 0) {
3502  mcee = (McCacheEntry *)pmcman_entrycache;
3503  do {
3504  if ((mcee->mc_slot == mce->mc_slot) && (mcee->mc_port == mce->mc_port)) {
3505  temp1 = mcee->cluster / clusters_per_block;
3506  temp2 = mcee->cluster % clusters_per_block;
3507 
3508  if (temp1 == block) {
3509  pmce[temp2] = (McCacheEntry *)mcee;
3510  if (mcee->rd_flag == 0)
3511  flag = 1;
3512  }
3513  }
3514  mcee++;
3515  } while (++i < MAX_CACHEENTRY);
3516  }
3517 
3518  if (clusters_per_block > 0) {
3519  i = 0; //s1
3520  pageindex = 0; //s5
3521  cluster = block * clusters_per_block; // sp8c
3522 
3523  do {
3524  if (pmce[i] != 0) {
3525  j = 0; // s0
3526  offset = 0; //a0
3527  for (j = 0; j < mcdi->pages_per_cluster; j++) {
3528  mcman_pagedata[pageindex + j] = (void *)(pmce[i]->cl_data + offset);
3529  offset += pagesize;
3530  }
3531  }
3532  else {
3533  //s3 = s5
3534  // s2 = (cluster + i) * mcdi->pages_per_cluster
3535  j = 0; //s0
3536  do {
3537  offset = (pageindex + j) * pagesize; // t0
3538  mcman_pagedata[pageindex + j] = (void *)(mcman_backupbuf + offset);
3539 
3540  r = McReadPage(mce->mc_port, mce->mc_slot, \
3541  ((cluster + i) * mcdi->pages_per_cluster) + j, \
3542  mcman_backupbuf + offset);
3543  if (r != sceMcResSucceed)
3544  return -51;
3545 
3546  } while (++j < mcdi->pages_per_cluster);
3547  }
3548 
3549  pageindex += mcdi->pages_per_cluster;
3550  } while (++i < clusters_per_block);
3551  }
3552 
3553 lbl1:
3554  if ((flag != 0) && (mcman_badblock <= 0)) {
3555  r = mcman_eraseblock(mce->mc_port, mce->mc_slot, mcdi->backup_block1, (void**)mcman_pagedata, mcman_eccdata);
3556  if (r == sceMcResFailReplace) {
3557 lbl2:
3558  r = mcman_replaceBackupBlock(mce->mc_port, mce->mc_slot, mcdi->backup_block1);
3559  mcdi->backup_block1 = r;
3560  goto lbl1;
3561  }
3562  if (r != sceMcResSucceed)
3563  return -52;
3564 
3565  mcman_pagebuf.word[0] = block | 0x80000000;
3566  p_page = (void *)&mcman_pagebuf; //s0
3567  p_ecc = (void *)eccbuf; //s2 = sp58
3568 
3569  i = 0; //s1
3570  do {
3571  if (pagesize < 0)
3572  ecc_count = (pagesize + 0x7f) >> 7;
3573  else
3574  ecc_count = pagesize >> 7;
3575 
3576  if (i >= ecc_count)
3577  break;
3578 
3579  McDataChecksum(p_page, p_ecc);
3580 
3581  p_ecc = (void *)((u8 *)p_ecc + 3);
3582  p_page = (void *)((u8 *)p_page + 128);
3583  i++;
3584  } while (1);
3585 
3586 
3587  r = McWritePage(mce->mc_port, mce->mc_slot, mcdi->backup_block2 * blocksize, &mcman_pagebuf, eccbuf);
3588  if (r == sceMcResFailReplace)
3589  goto lbl3;
3590  if (r != sceMcResSucceed)
3591  return -53;
3592 
3593  if (r < mcdi->blocksize) {
3594  i = 0; //s0
3595  p_ecc = (void *)mcman_eccdata;
3596 
3597  do {
3598  r = McWritePage(mce->mc_port, mce->mc_slot, (mcdi->backup_block1 * blocksize) + i, mcman_pagedata[i], p_ecc);
3599  if (r == sceMcResFailReplace)
3600  goto lbl2;
3601  if (r != sceMcResSucceed)
3602  return -54;
3603  p_ecc = (void *)((u8 *)p_ecc + sparesize);
3604  } while (++i < mcdi->blocksize);
3605  }
3606 
3607  r = McWritePage(mce->mc_port, mce->mc_slot, (mcdi->backup_block2 * blocksize) + 1, &mcman_pagebuf, eccbuf);
3608  if (r == sceMcResFailReplace)
3609  goto lbl3;
3610  if (r != sceMcResSucceed)
3611  return -55;
3612  }
3613 
3614  r = mcman_eraseblock(mce->mc_port, mce->mc_slot, block, (void**)mcman_pagedata, mcman_eccdata);
3615  //if (block == 1) /////
3616  // r = sceMcResFailReplace; /////
3617  if (r == sceMcResFailReplace) {
3618  r = mcman_fillbackupblock1(mce->mc_port, mce->mc_slot, block, (void**)mcman_pagedata, mcman_eccdata);
3619  for (i = 0; i < clusters_per_block; i++) {
3620  if (pmce[i] != 0)
3621  pmce[i]->wr_flag = 0;
3622  }
3623  if (r == sceMcResFailReplace)
3624  return r;
3625  return -58;
3626  }
3627  if (r != sceMcResSucceed)
3628  return -57;
3629 
3630  if (mcdi->blocksize > 0) {
3631  i = 0; //s0
3632  p_ecc = (void *)mcman_eccdata;
3633 
3634  do {
3635  if (pmce[i / mcdi->pages_per_cluster] == 0) {
3636  r = McWritePage(mce->mc_port, mce->mc_slot, (block * blocksize) + i, mcman_pagedata[i], p_ecc);
3637  if (r == sceMcResFailReplace) {
3638  r = mcman_fillbackupblock1(mce->mc_port, mce->mc_slot, block, (void**)mcman_pagedata, mcman_eccdata);
3639  for (i = 0; i < clusters_per_block; i++) {
3640  if (pmce[i] != 0)
3641  pmce[i]->wr_flag = 0;
3642  }
3643  if (r == sceMcResFailReplace)
3644  return r;
3645  return -58;
3646  }
3647  if (r != sceMcResSucceed)
3648  return -57;
3649  }
3650  p_ecc = (void *)((u8 *)p_ecc + sparesize);
3651  } while (++i < mcdi->blocksize);
3652  }
3653 
3654  if (mcdi->blocksize > 0) {
3655  i = 0; //s0
3656  p_ecc = (void *)mcman_eccdata;
3657 
3658  do {
3659  if (pmce[i / mcdi->pages_per_cluster] != 0) {
3660  r = McWritePage(mce->mc_port, mce->mc_slot, (block * blocksize) + i, mcman_pagedata[i], p_ecc);
3661  if (r == sceMcResFailReplace) {
3662  r = mcman_fillbackupblock1(mce->mc_port, mce->mc_slot, block, (void**)mcman_pagedata, mcman_eccdata);
3663  for (i = 0; i < clusters_per_block; i++) {
3664  if (pmce[i] != 0)
3665  pmce[i]->wr_flag = 0;
3666  }
3667  if (r == sceMcResFailReplace)
3668  return r;
3669  return -58;
3670  }
3671  if (r != sceMcResSucceed)
3672  return -57;
3673  }
3674  p_ecc = (void *)((u8 *)p_ecc + sparesize);
3675  } while (++i < mcdi->blocksize);
3676  }
3677 
3678  if (clusters_per_block > 0) {
3679  i = 0;
3680  do {
3681  if (pmce[i] != 0)
3682  pmce[i]->wr_flag = 0;
3683  } while (++i < clusters_per_block);
3684  }
3685 
3686  if ((flag != 0) && (mcman_badblock <= 0)) {
3687  r = mcman_eraseblock(mce->mc_port, mce->mc_slot, mcdi->backup_block2, NULL, NULL);
3688  if (r == sceMcResFailReplace) {
3689  goto lbl3;
3690  }
3691  if (r != sceMcResSucceed)
3692  return -58;
3693  }
3694  goto lbl_exit;
3695 
3696 lbl3:
3697  r = mcman_replaceBackupBlock(mce->mc_port, mce->mc_slot, mcdi->backup_block2);
3698  mcdi->backup_block2 = r;
3699  goto lbl1;
3700 
3701 lbl_exit:
3702  return sceMcResSucceed;
3703 }
3704 
3705 //--------------------------------------------------------------
3706 int McReadCluster(int port, int slot, int cluster, McCacheEntry **pmce)
3707 {
3708  register int i;
3709  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3710  McCacheEntry *mce;
3711 
3712  if (mcman_badblock > 0) {
3713  register int block, block_offset;
3714 
3715  block = cluster / mcdi->clusters_per_block;
3716  block_offset = cluster % mcdi->clusters_per_block;
3717 
3718  if ((block == mcman_badblock) && (mcman_badblock_port == port) && (mcman_badblock_slot == slot)) {
3719  cluster = (mcdi->backup_block1 * mcdi->clusters_per_block) + block_offset;
3720  }
3721  else {
3722  {
3723  for (i = 0; (u32)i < mcdi->clusters_per_block; i++) {
3724  if ((mcman_replacementcluster[i] != 0) && (mcman_replacementcluster[i] == cluster)) {
3725  block_offset = i % mcdi->clusters_per_block;
3726  cluster = (mcdi->backup_block1 * mcdi->clusters_per_block) + block_offset;
3727  }
3728  }
3729  }
3730  }
3731  }
3732 
3733  mce = mcman_getcacheentry(port, slot, cluster);
3734  if (mce == NULL) {
3735  register int r;
3736 
3737  mce = pmcman_mccache[MAX_CACHEENTRY - 1];
3738 
3739  if (mce->wr_flag != 0) {
3740  r = mcman_flushcacheentry((McCacheEntry *)mce);
3741  if (r != sceMcResSucceed)
3742  return r;
3743  }
3744 
3745  mce->mc_port = port;
3746  mce->mc_slot = slot;
3747  mce->cluster = cluster;
3748  mce->rd_flag = 0;
3749  //s3 = (cluster * mcdi->pages_per_cluster);
3750 
3751  for (i = 0; i < mcdi->pages_per_cluster; i++) {
3752  r = McReadPage(port, slot, (cluster * mcdi->pages_per_cluster) + i, \
3753  (void *)(mce->cl_data + (i * mcdi->pagesize)));
3754  if (r != sceMcResSucceed)
3755  return -21;
3756 
3757  }
3758  }
3759  mcman_addcacheentry(mce);
3760  *pmce = (McCacheEntry *)mce;
3761 
3762  return sceMcResSucceed;
3763 }
3764 
3765 //--------------------------------------------------------------
3766 int McReadDirEntry(int port, int slot, int cluster, int fsindex, McFsEntry **pfse) // Export #47 XMCMAN only
3767 {
3768  register int r, i;
3769  static int maxent, index, clust;
3770  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3771  register McFatCache *fci = &mcman_fatcache[port][slot];
3772  McCacheEntry *mce;
3773 
3774  DPRINTF("McReadDirEntry port%d slot%d cluster %d fsindex %d\n", port, slot, cluster, fsindex);
3775 
3776  maxent = 0x402 / (mcdi->cluster_size >> 9); //a1
3777  index = fsindex / (mcdi->cluster_size >> 9);//s2
3778 
3779  clust = cluster;
3780  i = 0; // s0
3781  if ((cluster == 0) && (index != 0)) {
3782  if (index < maxent) {
3783  if ((fci->entry[index]) >= 0 )
3784  clust = fci->entry[index];
3785  }
3786  if (index > 0) {
3787  do {
3788  if (i >= maxent)
3789  break;
3790  if (fci->entry[i] < 0)
3791  break;
3792  clust = fci->entry[i];
3793  } while (++i < index);
3794  }
3795  i--;
3796  }
3797 
3798  if (i < index) {
3799  do {
3800  r = McGetFATentry(port, slot, clust, &clust);
3801  if (r != sceMcResSucceed)
3802  return -70;
3803 
3804  if ((unsigned int)clust == 0xffffffff)
3805  return sceMcResNoEntry;
3806  clust &= ~0x80000000;
3807 
3808  i++;
3809  if (cluster == 0) {
3810  if (i < maxent)
3811  fci->entry[i] = clust;
3812  }
3813  } while (i < index);
3814  }
3815 
3816  r = McReadCluster(port ,slot, mcdi->alloc_offset + clust, &mce);
3817  if (r != sceMcResSucceed)
3818  return -71;
3819 
3820  *pfse = (McFsEntry *)(mce->cl_data + ((fsindex % (mcdi->cluster_size >> 9)) << 9));
3821 
3822  return sceMcResSucceed;
3823 }
3824 
3825 //--------------------------------------------------------------
3826 int mcman_readdirentryPS1(int port, int slot, int cluster, McFsEntryPS1 **pfse)
3827 {
3828  register int r, offset, index, pages_per_fatclust;
3829  McCacheEntry *mce;
3830  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3831 
3832  // Unofficial: lower bounds check cluster
3833  if (cluster < 0 || cluster >= 15)
3834  return -73;
3835 
3836  pages_per_fatclust = MCMAN_CLUSTERSIZE / mcdi->pagesize;
3837 
3838  cluster++;
3839  index = cluster / pages_per_fatclust;
3840  offset = cluster % pages_per_fatclust;
3841 
3842  r = mcman_readclusterPS1(port, slot, index * pages_per_fatclust, &mce);
3843  if (r != sceMcResSucceed)
3844  return -74;
3845 
3846  *pfse = (void *)&mce->cl_data[offset << 7];
3847 
3848 #ifdef BUILDING_XMCMAN
3849  McFsEntryPS1 *fse = (McFsEntryPS1 *)*pfse; // <--- XMCMAN seems to work with this
3850  fse->field_7d = 0; //
3851 #endif
3852 
3853  return sceMcResSucceed;
3854 }
3855 
3856 //--------------------------------------------------------------
3857 int McSetFATentry(int port, int slot, int fat_index, int fat_entry) // Export #46 XMCMAN only
3858 {
3859  register int r, ifc_index, indirect_index, indirect_offset, fat_offset;
3860  McCacheEntry *mce;
3861  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3862 
3863  //DPRINTF("McSetFATentry port%d slot%d fat_index %x fat_entry %x\n", port, slot, fat_index, fat_entry);
3864 
3865  indirect_index = fat_index / mcdi->FATentries_per_cluster;
3866  fat_offset = fat_index % mcdi->FATentries_per_cluster;
3867 
3868  ifc_index = indirect_index / mcdi->FATentries_per_cluster;
3869  indirect_offset = indirect_index % mcdi->FATentries_per_cluster;
3870 
3871  r = McReadCluster(port, slot, mcdi->ifc_list[ifc_index], &mce);
3872  if (r != sceMcResSucceed)
3873  return -75;
3874 
3875  McFatCluster *fc = (McFatCluster *)mce->cl_data;
3876 
3877  r = McReadCluster(port, slot, fc->entry[indirect_offset], &mce);
3878  if (r != sceMcResSucceed)
3879  return -76;
3880 
3881  fc = (McFatCluster *)mce->cl_data;
3882 
3883  fc->entry[fat_offset] = fat_entry;
3884  mce->wr_flag = 1;
3885 
3886  return sceMcResSucceed;
3887 }
3888 
3889 //--------------------------------------------------------------
3890 int McGetFATentry(int port, int slot, int fat_index, int *fat_entry) // Export #44 XMCMAN only
3891 {
3892  register int r, ifc_index, indirect_index, indirect_offset, fat_offset;
3893  McCacheEntry *mce;
3894  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3895 
3896  indirect_index = fat_index / mcdi->FATentries_per_cluster;
3897  fat_offset = fat_index % mcdi->FATentries_per_cluster;
3898 
3899  ifc_index = indirect_index / mcdi->FATentries_per_cluster;
3900  indirect_offset = indirect_index % mcdi->FATentries_per_cluster;
3901 
3902  r = McReadCluster(port, slot, mcdi->ifc_list[ifc_index], &mce);
3903  if (r != sceMcResSucceed)
3904  return -78;
3905 
3906  McFatCluster *fc = (McFatCluster *)mce->cl_data;
3907 
3908  r = McReadCluster(port, slot, fc->entry[indirect_offset], &mce);
3909  if (r != sceMcResSucceed)
3910  return -79;
3911 
3912  fc = (McFatCluster *)mce->cl_data;
3913 
3914  *fat_entry = fc->entry[fat_offset];
3915 
3916  return sceMcResSucceed;
3917 }
3918 
3919 //--------------------------------------------------------------
3920 int mcman_readclusterPS1(int port, int slot, int cluster, McCacheEntry **pmce)
3921 {
3922  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3923  McCacheEntry *mce;
3924 
3925  mce = mcman_getcacheentry(port, slot, cluster);
3926  if (mce == NULL) {
3927  register int r, i, pages_per_fatclust;
3928 
3929  mce = pmcman_mccache[MAX_CACHEENTRY - 1];
3930 
3931  if (mce->wr_flag != 0) {
3932  r = mcman_flushcacheentry((McCacheEntry *)mce);
3933  if (r != sceMcResSucceed)
3934  return r;
3935  }
3936 
3937  mce->mc_port = port;
3938  mce->mc_slot = slot;
3939  mce->cluster = cluster;
3940 
3941  pages_per_fatclust = MCMAN_CLUSTERSIZE / mcdi->pagesize;
3942 
3943  for (i = 0; i < pages_per_fatclust; i++) {
3944  r = McReadPS1PDACard(port, slot, cluster + i, (void *)(mce->cl_data + (i * mcdi->pagesize)));
3945  if (r != sceMcResSucceed)
3946  return -21;
3947  }
3948  }
3949 
3950  mcman_addcacheentry(mce);
3951  *pmce = (McCacheEntry *)mce;
3952 
3953  return sceMcResSucceed;
3954 }
3955 
3956 //--------------------------------------------------------------
3957 int mcman_replaceBackupBlock(int port, int slot, int block)
3958 {
3959  register int i;
3960  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3961 
3962  if (mcman_badblock > 0)
3963  return sceMcResFailReplace;
3964 
3965  for (i = 0; i < 16; i++) {
3966  if (mcdi->bad_block_list[i] == -1)
3967  break;
3968  }
3969 
3970  if (i < 16) {
3971  if ((mcdi->alloc_end - mcdi->max_allocatable_clusters) < 8)
3972  return sceMcResFullDevice;
3973 
3974  mcdi->alloc_end -= 8;
3975  mcdi->bad_block_list[i] = block;
3976  mcman_badblock_port = port;
3977  mcman_badblock_slot = slot;
3978  mcman_badblock = -1;
3979 
3980  return (mcdi->alloc_offset + mcdi->alloc_end) / mcdi->clusters_per_block;
3981  }
3982 
3983  return sceMcResFullDevice;
3984 }
3985 
3986 //--------------------------------------------------------------
3987 int mcman_fillbackupblock1(int port, int slot, int block, void **pagedata, void *eccdata)
3988 {
3989  register int r, i, sparesize, page_offset;
3990  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3991  register u8 *p_ecc;
3992 
3993  DPRINTF("mcman_fillbackupblock1 port%d slot%d block %x mcman_badblock %x\n", port, slot, block, mcman_badblock);
3994 
3995  sparesize = mcman_sparesize(port, slot);
3996 
3997  if (mcman_badblock != 0) {
3998  if ((mcman_badblock != block) || (mcman_badblock_port != port) || (mcman_badblock_slot != slot))
3999  return sceMcResFailReplace;
4000  }
4001 
4002  if ((mcdi->alloc_offset / mcdi->clusters_per_block) == (u32)block) // Appparently this refuse to take care of a bad rootdir cluster
4003  return sceMcResFailReplace;
4004 
4005  r = mcman_eraseblock(port, slot, mcdi->backup_block2, NULL, NULL);
4006  if (r != sceMcResSucceed)
4007  return r;
4008 
4009  r = mcman_eraseblock(port, slot, mcdi->backup_block1, NULL, NULL);
4010  if (r != sceMcResSucceed)
4011  return r;
4012 
4013  for (i = 0; i < 16; i++) {
4014  if (mcdi->bad_block_list[i] == -1)
4015  break;
4016  }
4017 
4018  if (i >= 16)
4019  return sceMcResFailReplace;
4020 
4021  page_offset = mcdi->backup_block1 * mcdi->blocksize;
4022  p_ecc = (u8 *)eccdata;
4023 
4024  for (i = 0; i < mcdi->blocksize; i++) {
4025  r = McWritePage(port, slot, page_offset + i, pagedata[i], p_ecc);
4026  if (r != sceMcResSucceed)
4027  return r;
4028  p_ecc += sparesize;
4029  }
4030 
4031  mcman_badblock_port = port;
4032  mcman_badblock_slot = slot;
4033  mcman_badblock = block;
4034 
4035  i = 15;
4036  do {
4037  mcman_replacementcluster[i] = 0;
4038  } while (--i >= 0);
4039 
4040  return sceMcResSucceed;
4041 }
4042 
4043 //--------------------------------------------------------------
4044 int McReplaceBadBlock(void)
4045 {
4046  register int r, i, curentry, clust, index, offset, numifc, fat_length, temp, length;
4047  register int value, value2, cluster, index2, offset2, s3;
4048  register MCDevInfo *mcdi = &mcman_devinfos[mcman_badblock_port][mcman_badblock_slot];
4049  int fat_entry[16];
4050  int fat_entry2;
4051  McCacheEntry *mce;
4052  McFsEntry *fse;
4053 
4054  DPRINTF("McReplaceBadBlock mcman_badblock_port%d mcman_badblock_slot%d mcman_badblock %x\n", mcman_badblock_port, mcman_badblock_slot, mcman_badblock);
4055 
4056  if (mcman_badblock == 0)
4057  return sceMcResSucceed;
4058 
4059  if (mcman_badblock >= 0) {
4060  McFlushCache(mcman_badblock_port, mcman_badblock_slot);
4061  mcman_clearcache(mcman_badblock_port, mcman_badblock_slot);
4062 
4063  for (i = 0; i <16; i++) {
4064  if (mcdi->bad_block_list[i] == -1)
4065  break;
4066  }
4067  if (i >= 16)
4068  goto lbl_e168;
4069 
4070  if (mcdi->alloc_end >= (mcdi->max_allocatable_clusters + 8)) {
4071  mcdi->max_allocatable_clusters += 8;
4072  mcdi->bad_block_list[i] = mcman_badblock;
4073  }
4074 
4075  fat_length = (((mcdi->clusters_per_card << 2) - 1) / mcdi->cluster_size) + 1;
4076  numifc = (((fat_length << 2) - 1) / mcdi->cluster_size) + 1;
4077 
4078  if (numifc > 32) {
4079  numifc = 32;
4080  fat_length = mcdi->FATentries_per_cluster << 5;
4081  }
4082 
4083  i = 0; //sp5c
4084  value = ~(((u32)(-1)) << mcdi->clusters_per_block);
4085  do {
4086  clust = (mcman_badblock * mcdi->clusters_per_block) + i;
4087  if ((u32)clust < mcdi->alloc_offset) {
4088  fat_entry[i] = 0;
4089  }
4090  else {
4091  r = McGetFATentry(mcman_badblock_port, mcman_badblock_slot, clust - mcdi->alloc_offset, &fat_entry[i]);
4092  if (r != sceMcResSucceed)
4093  goto lbl_e168;
4094 
4095  if (((fat_entry[i] & 0x80000000) == 0) || ((fat_entry[i] < -1) && (fat_entry[i] >= -9)))
4096  value &= ~(1 << i);
4097  }
4098  } while ((u32)(++i) < mcdi->clusters_per_block);
4099 
4100  if (mcdi->clusters_per_block > 0) {
4101  i = 0;
4102  do {
4103  if ((value & (1 << i)) != 0) {
4104  r = mcman_findfree2(mcman_badblock_port, mcman_badblock_slot, 1);
4105  if (r < 0) {
4106  mcman_replacementcluster[i] = r;
4107  goto lbl_e168;
4108  }
4109  r += mcdi->alloc_offset;
4110  mcman_replacementcluster[i] = r;
4111  }
4112  } while ((u32)(++i) < mcdi->clusters_per_block);
4113  }
4114 
4115  if (mcdi->clusters_per_block > 0) {
4116  i = 0;
4117  do {
4118  if ((value & (1 << i)) != 0) {
4119  if (fat_entry[i] != 0) {
4120  index = ((fat_entry[i] & ~0x80000000) + mcdi->alloc_offset) / mcdi->clusters_per_block;
4121  offset = ((fat_entry[i] & ~0x80000000) + mcdi->alloc_offset) % mcdi->clusters_per_block;
4122  if (index == mcman_badblock) {
4123  fat_entry[i] = (mcman_replacementcluster[offset] - mcdi->alloc_offset) | 0x80000000;
4124  }
4125  }
4126  }
4127  } while ((u32)(++i) < mcdi->clusters_per_block);
4128  }
4129 
4130  if (mcdi->clusters_per_block > 0) {
4131  i = 0;
4132  do {
4133  if ((mcman_replacementcluster[i] != 0) && (fat_entry[i] != 0)) {
4134  r = McSetFATentry(mcman_badblock_port, mcman_badblock_slot, mcman_replacementcluster[i] + mcdi->alloc_offset, fat_entry[i]);
4135  if (r != sceMcResSucceed)
4136  goto lbl_e168;
4137  }
4138  } while ((u32)(++i) < mcdi->clusters_per_block);
4139  }
4140 
4141  for (i = 0; i < numifc; i++) {
4142  index = mcdi->ifc_list[i] / mcdi->clusters_per_block;
4143  offset = mcdi->ifc_list[i] % mcdi->clusters_per_block;
4144 
4145  if (index == mcman_badblock) {
4146  value &= ~(1 << offset);
4147  mcdi->ifc_list[i] = mcman_replacementcluster[i];
4148  }
4149  }
4150 
4151  if (value == 0)
4152  goto lbl_e030;
4153 
4154  for (i = 0; i < fat_length; i++) {
4155  index = i / mcdi->FATentries_per_cluster;
4156  offset = i % mcdi->FATentries_per_cluster;
4157 
4158  if (offset == 0) {
4159  r = McReadCluster(mcman_badblock_port, mcman_badblock_slot, mcdi->ifc_list[index], &mce);
4160  if (r != sceMcResSucceed)
4161  goto lbl_e168;
4162  }
4163  offset = i % mcdi->FATentries_per_cluster;
4164  index2 = *((u32 *)&mce->cl_data[offset]) / mcdi->clusters_per_block;
4165  offset2 = *((u32 *)&mce->cl_data[offset]) % mcdi->clusters_per_block;
4166 
4167  if (index2 == mcman_badblock) {
4168  value &= ~(1 << offset2);
4169  *((u32 *)&mce->cl_data[offset]) = mcman_replacementcluster[offset2];
4170  mce->wr_flag = 1;
4171  }
4172  }
4173 
4174  McFlushCache(mcman_badblock_port, mcman_badblock_slot);
4175  mcman_clearcache(mcman_badblock_port, mcman_badblock_slot);
4176 
4177  if (value == 0)
4178  goto lbl_e030;
4179 
4180  value2 = value;
4181 
4182  for (i = 0; (u32)i < mcdi->alloc_end; i++) {
4183  r = McGetFATentry(mcman_badblock_port, mcman_badblock_slot, i, &fat_entry2);
4184  if (r != sceMcResSucceed)
4185  goto lbl_e168;
4186 
4187  index = (u32)(((fat_entry2 & ~0x80000000) + mcdi->alloc_offset) / mcdi->clusters_per_block);
4188  offset = (u32)(((fat_entry2 & ~0x80000000) + mcdi->alloc_offset) % mcdi->clusters_per_block);
4189 
4190  if (index == mcman_badblock) {
4191  value &= ~(1 << offset);
4192  r = McSetFATentry(mcman_badblock_port, mcman_badblock_slot, i, (mcman_replacementcluster[offset] - mcdi->alloc_offset) | 0x80000000);
4193  if (r != sceMcResSucceed)
4194  goto lbl_e168;
4195  }
4196  }
4197 
4198  if (value2 != value)
4199  McFlushCache(mcman_badblock_port, mcman_badblock_slot);
4200 
4201  r = McReadDirEntry(mcman_badblock_port, mcman_badblock_slot, 0, 0, &fse);
4202  if (r != sceMcResSucceed)
4203  goto lbl_e168;
4204 
4205  curentry = 2;
4206  s3 = 0;
4207  length = fse->length;
4208 
4209 lbl_dd8c:
4210  if (curentry >= length)
4211  goto lbl_ded0;
4212 
4213  r = McReadDirEntry(mcman_badblock_port, mcman_badblock_slot, s3, curentry, &fse);
4214  if (r != sceMcResSucceed)
4215  goto lbl_e168;
4216 
4217  cluster = fse->cluster;
4218  index = (fse->cluster + mcdi->alloc_offset) / mcdi->clusters_per_block;
4219  offset = (fse->cluster + mcdi->alloc_offset) % mcdi->clusters_per_block;
4220 
4221  temp = fse->length;
4222 
4223  if (index == mcman_badblock) {
4224  fse->cluster = mcman_replacementcluster[offset] - mcdi->alloc_offset;
4225  Mc1stCacheEntSetWrFlagOff();
4226  }
4227 
4228  if ((fse->mode & sceMcFileAttrSubdir) == 0) {
4229  curentry++;
4230  goto lbl_dd8c;
4231  }
4232 
4233  r = McReadDirEntry(mcman_badblock_port, mcman_badblock_slot, cluster, 0, &fse);
4234  if (r != sceMcResSucceed)
4235  goto lbl_e168;
4236 
4237  if ((fse->mode & sceMcFileAttrSubdir) == 0) {
4238  curentry++;
4239  goto lbl_dd8c;
4240  }
4241 
4242  if (fse->cluster != 0) {
4243  curentry++;
4244  goto lbl_dd8c;
4245  }
4246 
4247  if ((int)(fse->dir_entry) != curentry) {
4248  curentry++;
4249  goto lbl_dd8c;
4250  }
4251 
4252  curentry++;
4253 
4254  if (strcmp(fse->name, "."))
4255  goto lbl_dd8c;
4256 
4257  s3 = cluster;
4258  curentry = 2;
4259  length = temp;
4260  goto lbl_dd8c;
4261 
4262 lbl_ded0:
4263  r = McReadDirEntry(mcman_badblock_port, mcman_badblock_slot, s3, 1, &fse);
4264  if (r != sceMcResSucceed)
4265  goto lbl_e168;
4266 
4267  index = (fse->cluster + mcdi->alloc_offset) / mcdi->clusters_per_block;
4268  offset = (fse->cluster + mcdi->alloc_offset) % mcdi->clusters_per_block;
4269 
4270  if (index == mcman_badblock) {
4271  fse->cluster = mcman_replacementcluster[offset] - mcdi->alloc_offset;
4272  Mc1stCacheEntSetWrFlagOff();
4273  }
4274 
4275  r = McReadDirEntry(mcman_badblock_port, mcman_badblock_slot, fse->cluster, fse->dir_entry, &fse);
4276  if (r != sceMcResSucceed)
4277  goto lbl_e168;
4278 
4279  length = fse->length;
4280 
4281  r = McReadDirEntry(mcman_badblock_port, mcman_badblock_slot, s3, 0, &fse);
4282  if (r != sceMcResSucceed)
4283  goto lbl_e168;
4284 
4285  s3 = fse->cluster;
4286  index = (fse->cluster + mcdi->alloc_offset) / mcdi->clusters_per_block;
4287  offset = (fse->cluster + mcdi->alloc_offset) % mcdi->clusters_per_block;
4288  curentry = fse->dir_entry + 1;
4289 
4290  if (index == mcman_badblock) {
4291  fse->cluster = mcman_replacementcluster[offset] - mcdi->alloc_offset;
4292  Mc1stCacheEntSetWrFlagOff();
4293  }
4294 
4295  if (s3 != 0)
4296  goto lbl_dd8c;
4297 
4298  if (curentry != 1)
4299  goto lbl_dd8c;
4300 
4301 lbl_e030:
4302  if (mcdi->clusters_per_block > 0) {
4303  i = 0;
4304  do {
4305  clust = (mcman_badblock * mcdi->clusters_per_block) + i;
4306  if ((u32)clust >= mcdi->alloc_offset) {
4307  r = McSetFATentry(mcman_badblock_port, mcman_badblock_slot, clust - mcdi->alloc_offset, 0xfffffffd);
4308  if (r != sceMcResSucceed)
4309  goto lbl_e168;
4310  }
4311  } while ((u32)(++i) < mcdi->clusters_per_block);
4312  }
4313 
4314  McFlushCache(mcman_badblock_port, mcman_badblock_slot);
4315  mcman_clearcache(mcman_badblock_port, mcman_badblock_slot);
4316 
4317  mcman_badblock = 0;
4318 
4319  if (mcdi->clusters_per_block > 0) {
4320  i = 0;
4321  do {
4322  if (mcman_replacementcluster[i] != 0) {
4323  r = McReadCluster(mcman_badblock_port, mcman_badblock_slot, (mcdi->backup_block1 * mcdi->clusters_per_block) + i, &mce);
4324  if (r != sceMcResSucceed)
4325  goto lbl_e168;
4326 
4327  mce->cluster = mcman_replacementcluster[i];
4328  mce->wr_flag = 1;
4329  }
4330  } while ((u32)(++i) < mcdi->clusters_per_block);
4331  }
4332 
4333  McFlushCache(mcman_badblock_port, mcman_badblock_slot);
4334  }
4335  else {
4336  mcman_badblock = 0;
4337  }
4338 
4339  r = mcman_clearsuperblock(mcman_badblock_port, mcman_badblock_slot);
4340  return r;
4341 
4342 lbl_e168:
4343  mcman_badblock = 0;
4344  return sceMcResFailReplace;
4345 }
4346 
4347 //--------------------------------------------------------------
4348 int mcman_clearsuperblock(int port, int slot)
4349 {
4350  register int r, i;
4351  register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
4352  McCacheEntry *mce;
4353 
4354  // set superblock magic & version
4355  memset((void *)mcdi->magic, 0, sizeof (mcdi->magic) + sizeof (mcdi->version));
4356  strcpy(mcdi->magic, SUPERBLOCK_MAGIC);
4357  strcat(mcdi->magic, SUPERBLOCK_VERSION);
4358 
4359  for (i = 0; (u32)((unsigned int)i < sizeof(MCDevInfo)); i += 1024) {
4360  register int size, temp;
4361 
4362  temp = i;
4363  if (i < 0)
4364  temp = i + 1023;
4365  r = McReadCluster(port, slot, temp >> 10, &mce);
4366  if (r != sceMcResSucceed)
4367  return -48;
4368  mce->wr_flag = 1;
4369  size = 1024;
4370  temp = sizeof(MCDevInfo) - i;
4371 
4372  if (temp <= 1024)
4373  size = temp;
4374 
4375  memcpy((void *)mce->cl_data, (void *)mcdi, size);
4376  }
4377 
4378  r = McFlushCache(port, slot);
4379 
4380  return r;
4381 }
4382 
4383 //--------------------------------------------------------------
_ModuleInfo::newflags
u16 newflags
Definition: loadcore.h:36
_MCCacheDir
Definition: mcman-internal.h:93
sceCdCLOCK::year
u8 year
Definition: libcdvd-common.h:205
CpuEnableIntr
int CpuEnableIntr()
Definition: intrman.c:240
McFsEntryPS1
Definition: libmc-common.h:34
s_info
Definition: xprintf.c:78
sceCdCLOCK
Definition: libcdvd-common.h:188
mcman_pagebuf
Definition: mcman-internal.h:327
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
sceCdCLOCK::hour
u8 hour
Definition: libcdvd-common.h:197
irx_id
Definition: irx.h:27
sceCdCLOCK::month
u8 month
Definition: libcdvd-common.h:203
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
_sceMcTblGetDir
Definition: libmc.h:139
_MCCacheEntry
Definition: libmc-common.h:69
irx_export_table
Definition: irx.h:90
_McFatCluster
Definition: mcman-internal.h:113
sceCdCLOCK::stat
u8 stat
Definition: libcdvd-common.h:191
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
McFatCache
Definition: mcman-internal.h:119
sceCdCLOCK::day
u8 day
Definition: libcdvd-common.h:201
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
sceCdCLOCK::minute
u8 minute
Definition: libcdvd-common.h:195
_ModuleInfo
Definition: loadcore.h:31
sceCdCLOCK::second
u8 second
Definition: libcdvd-common.h:193
mcman.h
McFsEntry
Definition: libmc-common.h:54