PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
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)
20IRX_ID(MODNAME, 2, 11);
21
22char SUPERBLOCK_MAGIC[] = "Sony PS2 Memory Card Format ";
23char SUPERBLOCK_VERSION[] = "1.2.0.0";
24
25int mcman_wr_port = -1;
26int mcman_wr_slot = -1;
27int mcman_wr_block = -1;
28int mcman_wr_flag3 = -10;
29int mcman_curdircluster = -1;
30
31#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
32int timer_ID;
33#endif
34int PS1CardFlag = 1;
35
38
39#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
40extern struct irx_export_table _exp_mcman;
41#elif defined(BUILDING_XFROMMAN)
42extern struct irx_export_table _exp_xfromman;
43#endif
44
45static u8 mcman_cachebuf[MAX_CACHEENTRY * MCMAN_CLUSTERSIZE];
46static McCacheEntry mcman_entrycache[MAX_CACHEENTRY];
47static McCacheEntry *mcman_mccache[MAX_CACHEENTRY];
48
49static McCacheEntry *pmcman_entrycache;
50static McCacheEntry **pmcman_mccache;
51
52static void *mcman_pagedata[32];
53static u8 mcman_backupbuf[16384];
54
55static int mcman_badblock_port;
56static int mcman_badblock_slot;
57static int mcman_badblock;
58static int mcman_replacementcluster[16];
59
60static McFatCache mcman_fatcache[2][MCMAN_MAXSLOT];
61McFsEntry mcman_dircache[MAX_CACHEDIRENTRY];
62
63MC_FHANDLE mcman_fdhandles[MAX_FDHANDLES];
64MCDevInfo mcman_devinfos[4][MCMAN_MAXSLOT];
65
66u8 mcman_eccdata[512]; // size for 32 ecc
67
68// mcman xor table
69// clang-format off
70static 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
107int sema_hakama_id = 0;
108#endif
109
110//--------------------------------------------------------------
111void 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//--------------------------------------------------------------
132int 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
151int MCMAN_ENTRYPOINT(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
152#else
153int 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
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//--------------------------------------------------------------
245int 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//--------------------------------------------------------------
252int 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//--------------------------------------------------------------
260struct irx_id *McGetModuleInfo(void) // Export #42 XMCMAN only
261{
262 DPRINTF("McGetModuleInfo\n");
263 return &_irx_id;
264}
265#endif
266
267//--------------------------------------------------------------
268void McSetPS1CardFlag(int flag) // Export #40
269{
270 DPRINTF("McSetPS1CardFlag flag %x\n", flag);
271 PS1CardFlag = flag;
272}
273
274//--------------------------------------------------------------
275int 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//--------------------------------------------------------------
308void 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//--------------------------------------------------------------
321int 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//--------------------------------------------------------------
342int 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//--------------------------------------------------------------
359int 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//--------------------------------------------------------------
417void 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//--------------------------------------------------------------
430int 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//--------------------------------------------------------------
450int 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//--------------------------------------------------------------
460int 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//--------------------------------------------------------------
535int 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//--------------------------------------------------------------
611int 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//--------------------------------------------------------------
636int 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//--------------------------------------------------------------
691int 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//--------------------------------------------------------------
752int 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//--------------------------------------------------------------
787int 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//--------------------------------------------------------------
823int 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//--------------------------------------------------------------
859int 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//--------------------------------------------------------------
880int 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//--------------------------------------------------------------
902int 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//--------------------------------------------------------------
938int 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//--------------------------------------------------------------
960int 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//--------------------------------------------------------------
990int 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//--------------------------------------------------------------
1014int 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//--------------------------------------------------------------
1036int 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//--------------------------------------------------------------
1062int 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//--------------------------------------------------------------
1090int 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//--------------------------------------------------------------
1150int 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//--------------------------------------------------------------
1156int 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//--------------------------------------------------------------
1162int 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//--------------------------------------------------------------
1221void 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//--------------------------------------------------------------
1250int mcman_getcnum(int port, int slot)
1251{
1252 return
1253#if !defined(BUILDING_DONGLEMAN)
1254 ((port & 1) << 3) + slot;
1255#else
1261 0xF;
1262#endif
1263}
1264
1265//--------------------------------------------------------------
1266int 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//--------------------------------------------------------------
1313int 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//--------------------------------------------------------------
1319int 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//--------------------------------------------------------------
1344int 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//--------------------------------------------------------------
1439int 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//--------------------------------------------------------------
1510int 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//--------------------------------------------------------------
1582int 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//--------------------------------------------------------------
1631int 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//--------------------------------------------------------------
1700int 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//--------------------------------------------------------------
1754int 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//--------------------------------------------------------------
1798int 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//--------------------------------------------------------------
1911int 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
2043continue_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//--------------------------------------------------------------
2070int 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//--------------------------------------------------------------
2193int 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//--------------------------------------------------------------
2265int 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
2334check_done:
2335 // Finally erase backup block2
2336 return mcman_eraseblock(port, slot, mcdi->backup_block2, NULL, NULL);
2337}
2338
2339//--------------------------------------------------------------
2340int 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
2485lbl_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//--------------------------------------------------------------
2514int 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//--------------------------------------------------------------
2573int 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//--------------------------------------------------------------
2609int 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 {
2643lbl0:
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
2692lbl1:
2693 r = McFlushCache(port, slot);
2694 if (r != sceMcResSucceed)
2695 return r;
2696
2697 return sceMcResSucceed;
2698}
2699
2700//--------------------------------------------------------------
2701int 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//--------------------------------------------------------------
2735int 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//--------------------------------------------------------------
2773int 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//--------------------------------------------------------------
2807int 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//--------------------------------------------------------------
2988int 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//--------------------------------------------------------------
3030int 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//--------------------------------------------------------------
3158int 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//--------------------------------------------------------------
3194void 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//--------------------------------------------------------------
3232int McRetOnly(int fd) // Export #37
3233{
3234 (void)fd;
3235
3236 DPRINTF("McRetOnly param %x\n", fd);
3237 return sceMcResSucceed;
3238}
3239
3240//--------------------------------------------------------------
3241int 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//--------------------------------------------------------------
3286McCacheEntry *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//--------------------------------------------------------------
3303void 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//--------------------------------------------------------------
3318int mcman_getFATindex(int port, int slot, int num)
3319{
3320 return mcman_fatcache[port][slot].entry[num];
3321}
3322
3323//--------------------------------------------------------------
3324void Mc1stCacheEntSetWrFlagOff(void)
3325{
3326 McCacheEntry *mce = (McCacheEntry *)*pmcman_mccache;
3327
3328 mce->wr_flag = -1;
3329}
3330
3331//--------------------------------------------------------------
3332McCacheEntry *mcman_get1stcacheEntp(void)
3333{
3334 return *pmcman_mccache;
3335}
3336
3337//--------------------------------------------------------------
3338void 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.
3359lbl1:
3360#endif
3361 do {
3362 pmce[i] = pmce[i-1];
3363 } while (--i != 0);
3364 }
3365
3366 pmce[0] = (McCacheEntry *)mce;
3367}
3368
3369//--------------------------------------------------------------
3370int 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//--------------------------------------------------------------
3399int 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) {
3433lbl0:
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
3553lbl1:
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) {
3557lbl2:
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
3696lbl3:
3697 r = mcman_replaceBackupBlock(mce->mc_port, mce->mc_slot, mcdi->backup_block2);
3698 mcdi->backup_block2 = r;
3699 goto lbl1;
3700
3701lbl_exit:
3702 return sceMcResSucceed;
3703}
3704
3705//--------------------------------------------------------------
3706int 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//--------------------------------------------------------------
3766int 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//--------------------------------------------------------------
3826int 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//--------------------------------------------------------------
3857int 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//--------------------------------------------------------------
3890int 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//--------------------------------------------------------------
3920int 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//--------------------------------------------------------------
3957int 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//--------------------------------------------------------------
3987int 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//--------------------------------------------------------------
4044int 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
4209lbl_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
4262lbl_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
4301lbl_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
4342lbl_e168:
4343 mcman_badblock = 0;
4344 return sceMcResFailReplace;
4345}
4346
4347//--------------------------------------------------------------
4348int 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//--------------------------------------------------------------
int CpuEnableIntr()
Definition intrman.c:250
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
Definition irx.h:27
u16 newflags
Definition loadcore.h:36
u32 count
start sector of fragmented bd/file