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