Disabling auto-refresh of game list by default, as it is causing bugs sometimes
[open-ps2-loader/simon.git] / modules / vmc / mcman / main.c
bloba28062da969eea18f2df617c082e2842091ad455
1 /*
2 Copyright 2009-2010, jimmikaelkael
3 Licenced under Academic Free License version 3.0
4 Review Open PS2 Loader README & LICENSE files for further details.
5 */
7 #include "mcman.h"
9 IRX_ID(MODNAME, 1, 1);
11 struct modInfo_t mcman_modInfo = { "mcman_cex", 0x20b };
13 char sio2man_modname[8] = "sio2man\0";
14 int sio2man_type = SIO2MAN;
16 char SUPERBLOCK_MAGIC[] = "Sony PS2 Memory Card Format ";
17 char SUPERBLOCK_VERSION[] = "1.2.0.0";
19 int mcman_wr_port = -1;
20 int mcman_wr_slot = -1;
21 int mcman_wr_block = -1;
22 int mcman_wr_flag3 = -10;
23 int mcman_curdircluster = -1;
25 u32 DOT = 0x0000002e;
26 u32 DOTDOT = 0x00002e2e;
28 int timer_ID;
29 int PS1CardFlag = 1;
32 // mcman xor table
33 u8 mcman_xortable[256] = {
34 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4,
35 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00,
36 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77,
37 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3,
38 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66,
39 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2,
40 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5,
41 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11,
42 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55,
43 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1,
44 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96,
45 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22,
46 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87,
47 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33,
48 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44,
49 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0,
50 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44,
51 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0,
52 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87,
53 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33,
54 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96,
55 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22,
56 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55,
57 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1,
58 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5,
59 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11,
60 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66,
61 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2,
62 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77,
63 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3,
64 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4,
65 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00
68 //--------------------------------------------------------------
69 void long_multiply(u32 v1, u32 v2, u32 *HI, u32 *LO)
71 register long a, b, c, d;
72 register long x, y;
74 a = (v1 >> 16) & 0xffff;
75 b = v1 & 0xffff;
76 c = (v2 >> 16) & 0xffff;
77 d = v2 & 0xffff;
79 *LO = b * d;
80 x = a * d + c * b;
81 y = ((*LO >> 16) & 0xffff) + x;
83 *LO = (*LO & 0xffff) | ((y & 0xffff) << 16);
84 *HI = (y >> 16) & 0xffff;
86 *HI += a * c;
89 //--------------------------------------------------------------
90 int mcman_chrpos(char *str, int chr)
92 char *p;
94 p = str;
95 if (*str) {
96 do {
97 if (*p == (chr & 0xff))
98 break;
99 p++;
100 } while (*p);
102 if (*p != (chr & 0xff))
103 return -1;
105 return p - str;
107 //--------------------------------------------------------------
108 int _start(int argc, const char **argv)
110 iop_library_table_t *libtable;
111 iop_library_t *libptr;
112 register int i, sio2man_loaded;
113 void **export_tab;
115 #ifdef SIO_DEBUG
116 sio_init(38400, 0, 0, 0, 0);
117 #endif
118 #ifdef DEBUG
119 DPRINTF("mcman: _start...\n");
120 #endif
122 // Get sio2man lib ptr
123 sio2man_loaded = 0;
124 libtable = GetLibraryEntryTable();
125 libptr = libtable->tail;
126 while (libptr != 0) {
127 for (i=0; i<8; i++) {
128 if (libptr->name[i] != sio2man_modname[i])
129 break;
131 if (i == 8) {
132 sio2man_loaded = 1;
133 break;
135 libptr = libptr->prev;
138 if (!sio2man_loaded) {
139 #ifdef DEBUG
140 DPRINTF("mcman: sio2man module is not loaded...\n");
141 #endif
142 return MODULE_NO_RESIDENT_END;
145 #ifdef DEBUG
146 DPRINTF("mcman: sio2man version=0x%03x\n", libptr->version);
147 #endif
148 if (libptr->version > 0x101)
149 sio2man_type = XSIO2MAN;
151 // Get sio2man export table
152 export_tab = (void **)(((struct irx_export_table *)libptr)->fptrs);
154 // Set functions pointers to match SIO2MAN exports
155 sio2_mc_transfer_init = export_tab[24];
156 sio2_transfer = export_tab[25];
157 // set internals function pointers for MCMAN
158 mcman_sio2transfer = (void *)mcsio2_transfer;
159 mc_detectcard = (void *)McDetectCard2;
161 if (sio2man_type == XSIO2MAN) {
162 // Set functions pointers to match XSIO2MAN exports
163 sio2_transfer_reset = export_tab[26];
164 sio2_func1 = export_tab[55];
166 // set internals function pointers for XMCMAN
167 mcman_sio2transfer = (void *)mcsio2_transfer2;
168 mc_detectcard = (void *)mcman_detectcard;
170 // Modify mcman export ver
171 _exp_mcman.version = 0x203;
172 // Get mcman export table
173 export_tab = (void **)(struct irx_export_table *)&_exp_mcman.fptrs;
174 export_tab[17] = (void *)McEraseBlock2;
175 export_tab[21] = (void *)McDetectCard2;
176 export_tab[22] = (void *)McGetFormat;
177 export_tab[23] = (void *)McGetEntSpace;
178 export_tab[24] = (void *)mcman_replacebadblock;
179 export_tab[25] = (void *)McCloseAll;
180 export_tab[42] = (void *)McGetModuleInfo;
181 export_tab[43] = (void *)McGetCardSpec;
182 export_tab[44] = (void *)mcman_getFATentry;
183 export_tab[45] = (void *)McCheckBlock;
184 export_tab[46] = (void *)mcman_setFATentry;
185 export_tab[47] = (void *)mcman_readdirentry;
186 export_tab[48] = (void *)mcman_1stcacheEntsetwrflagoff;
187 export_tab[49] = (void *)mcman_createDirentry;
188 export_tab[50] = (void *)mcman_readcluster;
189 export_tab[51] = (void *)mcman_flushmccache;
190 export_tab[52] = (void *)mcman_setdirentrystate;
193 #ifdef DEBUG
194 DPRINTF("mcman: registering exports...\n");
195 #endif
196 if (RegisterLibraryEntries(&_exp_mcman) != 0)
197 return MODULE_NO_RESIDENT_END;
199 CpuEnableIntr();
201 #ifdef DEBUG
202 DPRINTF("mcman: initPS2com...\n");
203 #endif
204 mcman_initPS2com();
206 #ifdef DEBUG
207 DPRINTF("mcman: initPS1PDAcom...\n");
208 #endif
209 mcman_initPS1PDAcom();
211 #ifdef DEBUG
212 DPRINTF("mcman: initcache...\n");
213 #endif
214 mcman_initcache();
216 #ifdef DEBUG
217 DPRINTF("mcman: initdev...\n");
218 #endif
219 mcman_initdev();
221 timer_ID = ReferHardTimer(1, 32, 0, 0x6309);
223 if (timer_ID != -150)
224 return MODULE_RESIDENT_END;
226 timer_ID = AllocHardTimer(1, 32, 1);
228 if (timer_ID > 0)
229 SetTimerMode(timer_ID, 0);
231 #ifdef DEBUG
232 DPRINTF("mcman: _start returns MODULE_RESIDENT_END...\n");
233 #endif
235 return MODULE_RESIDENT_END;
238 //--------------------------------------------------------------
239 int McGetFormat(int port, int slot) // Export #22 XMCMAN only
241 #ifdef DEBUG
242 DPRINTF("mcman: McGetFormat port%d slot%d\n", port, slot);
243 #endif
244 return mcman_devinfos[port][slot].cardform;
247 //--------------------------------------------------------------
248 int McGetMcType(int port, int slot) // Export #39
250 #ifdef DEBUG
251 DPRINTF("mcman: McGetMcType port%d slot%d\n", port, slot);
252 #endif
253 return mcman_devinfos[port][slot].cardtype;
256 //--------------------------------------------------------------
257 struct modInfo_t *McGetModuleInfo(void) // Export #42 XMCMAN only
259 #ifdef DEBUG
260 DPRINTF("mcman: McGetModuleInfo\n");
261 #endif
262 return (struct modInfo_t *)&mcman_modInfo;
265 //--------------------------------------------------------------
266 void McSetPS1CardFlag(int flag) // Export #40
268 #ifdef DEBUG
269 DPRINTF("mcman: McSetPS1CardFlag flag %x\n", flag);
270 #endif
271 PS1CardFlag = flag;
274 //--------------------------------------------------------------
275 int McGetFreeClusters(int port, int slot) // Export #38
277 register int r, mcfree;
278 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
280 #ifdef DEBUG
281 DPRINTF("mcman: McGetFreeClusters port%d slot%d\n", port, slot);
282 #endif
284 mcfree = 0;
285 if (mcdi->cardform) {
286 switch (mcdi->cardtype) {
287 case sceMcTypePS2:
288 mcfree = mcman_findfree2(port, slot, 0);
289 break;
290 case sceMcTypePS1:
291 case sceMcTypePDA:
292 mcfree = mcman_findfree1(port, slot, 0);
293 break;
294 case sceMcTypeNoCard:
295 mcfree = 0;
296 break;
298 if (mcfree == sceMcResFullDevice)
299 mcfree = 0;
301 r = mcfree;
303 else
304 return 0;
306 return r;
309 //--------------------------------------------------------------
310 void mcman_wmemset(void *buf, int size, int value)
312 int *p = buf;
313 size = (size >> 2) - 1;
315 if (size > -1) {
316 do {
317 *p++ = value;
318 } while (--size > -1);
322 //--------------------------------------------------------------
323 int mcman_calcEDC(void *buf, int size)
325 register u32 checksum;
326 register int i;
327 u8 *p = (u8 *)buf;
329 checksum = 0;
331 if (size > 0) {
332 size--;
333 i = 0;
334 while (size-- != -1) {
335 checksum ^= p[i];
336 i++;
339 return checksum & 0xff;
342 //--------------------------------------------------------------
343 int mcman_checkpath(char *str) // check that a string do not contain special chars ( chr<32, ?, *)
345 register int i;
346 u8 *p = (u8 *)str;
348 i = 0;
349 while (p[i]) {
350 if (((p[i] & 0xff) == '?') || ((p[i] & 0xff) == '*'))
351 return 0;
352 if ((p[i] & 0xff) < 32)
353 return 0;
354 i++;
356 return 1;
359 //--------------------------------------------------------------
360 int mcman_checkdirpath(char *str1, char *str2)
362 register int r, pos1, pos2, pos;
363 u8 *p1 = (u8 *)str1;
364 u8 *p2 = (u8 *)str2;
366 do {
367 pos1 = mcman_chrpos(p2, '?');
368 pos2 = mcman_chrpos(p2, '*');
370 if ((pos1 < 0) && (pos2 < 0)) {
371 if (!strcmp(p2, p1))
372 return 1;
373 return 0;
375 pos = pos2;
376 if (pos1 >= 0) {
377 pos = pos1;
378 if (pos2 >= 0) {
379 pos = pos2;
380 if (pos1 < pos2) {
381 pos = pos1;
385 if (strncmp(p2, p1, pos) != 0)
386 return 0;
388 p2 += pos;
389 p1 += pos;
391 while (p2[0] == '?') {
392 if (p1[0] == 0)
393 return 1;
394 p2++;
395 p1++;
397 } while (p2[0] != '*');
399 while((p2[0] == '*') || (p2[0] == '?'))
400 p2++;
402 if (p2[0] != 0) {
403 do {
404 pos = mcman_chrpos(p1, (u8)p2[0]);
405 p1 += pos;
406 if (pos < 0)
407 return 0;
408 r = mcman_checkdirpath(p1, p2);
409 p1++;
410 } while (r == 0);
412 return 1;
415 //--------------------------------------------------------------
416 void mcman_invhandles(int port, int slot)
418 register int i = 0;
419 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles;
421 do {
422 if ((fh->port == port) && (fh->slot == slot))
423 fh->status = 0;
424 fh++;
425 } while (++i < MAX_FDHANDLES);
428 //--------------------------------------------------------------
429 int McCloseAll(void) // Export #25 XMCMAN only
431 register int fd = 0, rv = 0;
433 do {
434 if (mcman_fdhandles[fd].status) {
435 register int rc;
437 rc = McClose(fd);
438 if (rc < rv)
439 rv = rc;
441 fd++;
443 } while (fd < MAX_FDHANDLES);
445 return rv;
448 //--------------------------------------------------------------
449 int McDetectCard(int port, int slot) // Export #5
451 return mc_detectcard(port, slot);
454 //--------------------------------------------------------------
455 int mcman_detectcard(int port, int slot)
457 register int r;
458 register MCDevInfo *mcdi;
460 #ifdef DEBUG
461 DPRINTF("mcman: mcman_detectcard port%d slot%d\n", port, slot);
462 #endif
463 mcdi = (MCDevInfo *)&mcman_devinfos[port][slot];
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;
474 else {
475 mcdi->cardtype = sceMcTypePDA;
476 return r;
480 else {
481 mcdi->cardtype = sceMcTypePS2;
482 return r;
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;
495 else {
496 if (mcman_probePDACard(port, slot)) {
497 mcdi->cardtype = sceMcTypePS1;
498 return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
500 else {
501 mcdi->cardtype = sceMcTypePDA;
502 return r;
506 else {
507 if (PS1CardFlag)
508 return sceMcResSucceed;
509 if (mcdi->cardtype == sceMcTypePS1)
510 return sceMcResDeniedPS1Permit;
511 return sceMcResSucceed;
515 mcdi->cardtype = 0;
516 mcdi->cardform = 0;
517 mcman_invhandles(port, slot);
518 mcman_clearcache(port, slot);
520 return r;
523 //--------------------------------------------------------------
524 int McDetectCard2(int port, int slot) // Export #21 XMCMAN only
526 register int r;
527 register MCDevInfo *mcdi;
529 #ifdef DEBUG
530 DPRINTF("mcman: McDetectCard2 port%d slot%d\n", port, slot);
531 #endif
533 mcdi = (MCDevInfo *)&mcman_devinfos[port][slot];
535 if ((mcdi->cardtype == sceMcTypeNoCard) || (mcdi->cardtype == sceMcTypePS2)) {
536 r = mcman_probePS2Card(port, slot);
537 if (r < -9) {
538 r = mcman_probePS1Card(port, slot);
539 if (!(r < -9)) {
540 if (mcman_probePDACard(port, slot)) {
541 mcdi->cardtype = sceMcTypePS1;
542 return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
544 else {
545 mcdi->cardtype = sceMcTypePDA;
546 return r;
550 else {
551 mcdi->cardtype = sceMcTypePS2;
552 return r;
555 else {
556 r = mcman_probePS1Card(port, slot);
557 if (r) {
558 if ((r < -9) || (r >= 0)) {
559 r = mcman_probePS2Card(port, slot);
560 if (!(r < -9)) {
561 mcdi->cardtype = sceMcTypePS2;
562 return r;
565 else {
566 if (mcman_probePDACard(port, slot)) {
567 mcdi->cardtype = sceMcTypePS1;
568 return (!PS1CardFlag) ? sceMcResDeniedPS1Permit : r;
570 else {
571 mcdi->cardtype = sceMcTypePDA;
572 return r;
576 else {
577 if (PS1CardFlag)
578 return sceMcResSucceed;
579 if (mcdi->cardtype == sceMcTypePS1)
580 return sceMcResDeniedPS1Permit;
581 return sceMcResSucceed;
585 mcdi->cardtype = 0;
586 mcdi->cardform = 0;
587 mcman_invhandles(port, slot);
588 mcman_clearcache(port, slot);
590 return r;
593 //--------------------------------------------------------------
594 int McOpen(int port, int slot, char *filename, int flag) // Export #6
596 register int r;
598 r = McDetectCard(port, slot);
599 if (r != sceMcResSucceed)
600 return r;
602 if (!PS1CardFlag)
603 flag &= 0xFFFFDFFF; // disables FRCOM flag OR what is it
605 if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
606 r = mcman_open2(port, slot, filename, flag);
607 else
608 r = mcman_open1(port, slot, filename, flag);
610 if (r < -9) {
611 mcman_invhandles(port, slot);
612 mcman_clearcache(port, slot);
615 return r;
618 //--------------------------------------------------------------
619 int McClose(int fd) // Export #7
621 register MC_FHANDLE *fh;
622 register MCDevInfo *mcdi;
623 register int r;
625 if (!((u32)fd < MAX_FDHANDLES))
626 return sceMcResDeniedPermit;
628 fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
629 if (!fh->status)
630 return sceMcResDeniedPermit;
632 fh->status = 0;
633 r = McDetectCard(fh->port, fh->slot);
634 if (r != sceMcResSucceed)
635 return r;
637 r = mcman_flushmccache(fh->port, fh->slot);
638 if (r < -9) {
639 mcman_invhandles(fh->port, fh->slot);
640 mcman_clearcache(fh->port, fh->slot);
643 if (r != sceMcResSucceed)
644 return r;
646 if (fh->unknown2 != 0) {
647 fh->unknown2 = 0;
648 mcdi = (MCDevInfo *)&mcman_devinfos[fh->port][fh->slot];
649 if (mcdi->cardtype == sceMcTypePS2)
650 r = mcman_close2(fd);
651 else
652 r = mcman_close1(fd);
654 if (r < -9) {
655 mcman_invhandles(fh->port, fh->slot);
656 mcman_clearcache(fh->port, fh->slot);
659 if (r != sceMcResSucceed)
660 return r;
663 r = mcman_flushmccache(fh->port, fh->slot);
664 if (r < -9) {
665 mcman_invhandles(fh->port, fh->slot);
666 mcman_clearcache(fh->port, fh->slot);
669 return r;
672 //--------------------------------------------------------------
673 int McFlush(int fd) // Export #14
675 register int r;
676 register MC_FHANDLE *fh;
677 register MCDevInfo *mcdi;
679 if (!((u32)fd < MAX_FDHANDLES))
680 return sceMcResDeniedPermit;
682 fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
683 if (!fh->status)
684 return sceMcResDeniedPermit;
686 r = McDetectCard(fh->port, fh->slot);
687 if (r != sceMcResSucceed)
688 return r;
690 r = mcman_flushmccache(fh->port, fh->slot);
691 if (r < -9) {
692 mcman_invhandles(fh->port, fh->slot);
693 mcman_clearcache(fh->port, fh->slot);
696 if (r != sceMcResSucceed) {
697 fh->status = 0;
698 return r;
701 if (fh->unknown2 != 0) {
702 fh->unknown2 = 0;
703 mcdi = (MCDevInfo *)&mcman_devinfos[fh->port][fh->slot];
704 if (mcdi->cardtype == sceMcTypePS2)
705 r = mcman_close2(fd);
706 else
707 r = mcman_close1(fd);
709 if (r < -9) {
710 mcman_invhandles(fh->port, fh->slot);
711 mcman_clearcache(fh->port, fh->slot);
714 if (r != sceMcResSucceed) {
715 fh->status = 0;
716 return r;
720 r = mcman_flushmccache(fh->port, fh->slot);
721 if (r < 0)
722 fh->status = 0;
724 if (r < -9) {
725 mcman_invhandles(fh->port, fh->slot);
726 mcman_clearcache(fh->port, fh->slot);
729 return r;
732 //--------------------------------------------------------------
733 int McSeek(int fd, int offset, int origin) // Export #10
735 register int r;
736 register MC_FHANDLE *fh;
738 #ifdef DEBUG
739 DPRINTF("mcman: McSeek fd %d offset %d origin %d\n", fd, offset, origin);
740 #endif
742 if (!((u32)fd < MAX_FDHANDLES))
743 return sceMcResDeniedPermit;
745 fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
746 if (!fh->status)
747 return sceMcResDeniedPermit;
749 r = McDetectCard(fh->port, fh->slot);
750 if (r != sceMcResSucceed)
751 return r;
753 switch (origin) {
754 default:
755 case SEEK_CUR:
756 r = fh->position + offset;
757 break;
758 case SEEK_SET:
759 r = offset;
760 break;
761 case SEEK_END:
762 r = fh->filesize + offset;
763 break;
766 return fh->position = (r < 0) ? 0 : r;
769 //--------------------------------------------------------------
770 int McRead(int fd, void *buf, int length) // Export #8
772 register int r;
773 register MC_FHANDLE *fh;
775 if (!((u32)fd < MAX_FDHANDLES))
776 return sceMcResDeniedPermit;
778 fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
779 if (!fh->status)
780 return sceMcResDeniedPermit;
782 if (!fh->rdflag)
783 return sceMcResDeniedPermit;
785 r = McDetectCard(fh->port, fh->slot);
786 if (r != sceMcResSucceed)
787 return r;
789 if (mcman_devinfos[fh->port][fh->slot].cardtype == sceMcTypePS2)
790 r = mcman_read2(fd, buf, length);
791 else
792 r = mcman_read1(fd, buf, length);
794 if (r < 0)
795 fh->status = 0;
797 if (r < -9) {
798 mcman_invhandles(fh->port, fh->slot);
799 mcman_clearcache(fh->port, fh->slot);
802 return r;
805 //--------------------------------------------------------------
806 int McWrite(int fd, void *buf, int length) // Export #9
808 register int r;
809 register MC_FHANDLE *fh;
811 if (!((u32)fd < MAX_FDHANDLES))
812 return sceMcResDeniedPermit;
814 fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
815 if (!fh->status)
816 return sceMcResDeniedPermit;
818 if (!fh->wrflag)
819 return sceMcResDeniedPermit;
821 r = McDetectCard(fh->port, fh->slot);
822 if (r != sceMcResSucceed)
823 return r;
825 if (mcman_devinfos[fh->port][fh->slot].cardtype == sceMcTypePS2)
826 r = mcman_write2(fd, buf, length);
827 else
828 r = mcman_write1(fd, buf, length);
830 if (r < 0)
831 fh->status = 0;
833 if (r < -9) {
834 mcman_invhandles(fh->port, fh->slot);
835 mcman_clearcache(fh->port, fh->slot);
838 return r;
841 //--------------------------------------------------------------
842 int McGetEntSpace(int port, int slot, char *dirname) // Export #23 XMCMAN only
844 register int r;
846 r = McDetectCard(port, slot);
847 if (r != sceMcResSucceed)
848 return r;
850 if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2) {
851 r = mcman_getentspace(port, slot, dirname);
854 if (r < -9) {
855 mcman_invhandles(port, slot);
856 mcman_clearcache(port, slot);
859 return r;
862 //--------------------------------------------------------------
863 int McGetDir(int port, int slot, char *dirname, int flags, int maxent, sceMcTblGetDir *info) // Export #12
865 register int r;
867 r = McDetectCard(port, slot);
868 if (r != sceMcResSucceed)
869 return r;
871 if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
872 r = mcman_getdir2(port, slot, dirname, flags & 0xFFFF, maxent, info);
873 else
874 r = mcman_getdir1(port, slot, dirname, flags & 0xFFFF, maxent, info);
876 if (r < -9) {
877 mcman_invhandles(port, slot);
878 mcman_clearcache(port, slot);
881 return r;
884 //--------------------------------------------------------------
885 int mcman_dread(int fd, fio_dirent_t *dirent)
887 register int r;
888 register MC_FHANDLE *fh;
890 if (!((u32)fd < MAX_FDHANDLES))
891 return sceMcResDeniedPermit;
893 fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
894 if (!fh->status)
895 return sceMcResDeniedPermit;
897 if (!fh->drdflag)
898 return sceMcResDeniedPermit;
900 r = McDetectCard(fh->port, fh->slot);
901 if (r != sceMcResSucceed)
902 return r;
904 if (mcman_devinfos[fh->port][fh->slot].cardtype == sceMcTypePS2)
905 r = mcman_dread2(fd, dirent);
906 else
907 r = mcman_dread1(fd, dirent);
909 if (r < 0)
910 fh->status = 0;
912 if (r < -9) {
913 mcman_invhandles(fh->port, fh->slot);
914 mcman_clearcache(fh->port, fh->slot);
917 return r;
920 //--------------------------------------------------------------
921 int mcman_getstat(int port, int slot, char *filename, fio_stat_t *stat)
923 register int r;
925 r = McDetectCard(port, slot);
926 if (r != sceMcResSucceed)
927 return r;
929 if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
930 r = mcman_getstat2(port, slot, filename, stat);
931 else
932 r = mcman_getstat1(port, slot, filename, stat);
934 if (r < -9) {
935 mcman_invhandles(port, slot);
936 mcman_clearcache(port, slot);
939 return r;
942 //--------------------------------------------------------------
943 int McSetFileInfo(int port, int slot, char *filename, sceMcTblGetDir *info, int flags) // Export #16
945 register int r;
947 r = McDetectCard(port, slot);
948 if (r != sceMcResSucceed)
949 return r;
951 if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
952 r = mcman_setinfo2(port, slot, filename, info, flags);
953 else
954 r = mcman_setinfo1(port, slot, filename, info, flags);
956 if (r < -9) {
957 mcman_invhandles(port, slot);
958 mcman_clearcache(port, slot);
961 if (r == sceMcResSucceed) {
962 r = mcman_flushmccache(port, slot);
963 if (r < -9) {
964 mcman_invhandles(port, slot);
965 mcman_clearcache(port, slot);
969 return r;
972 //--------------------------------------------------------------
973 int McChDir(int port, int slot, char *newdir, char *currentdir) // Export #15
975 register int r;
977 r = McDetectCard(port, slot);
978 if (r != sceMcResSucceed)
979 return r;
981 if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
982 r = mcman_chdir(port, slot, newdir, currentdir);
983 else {
984 currentdir[0] = 0;
985 r = sceMcResSucceed;
988 if (r < -9) {
989 mcman_invhandles(port, slot);
990 mcman_clearcache(port, slot);
993 return r;
996 //--------------------------------------------------------------
997 int McDelete(int port, int slot, char *filename, int flags) // Export #13
999 register int r;
1001 r = McDetectCard(port, slot);
1002 if (r != sceMcResSucceed)
1003 return r;
1005 if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
1006 r = mcman_delete2(port, slot, filename, flags);
1007 else
1008 r = mcman_delete1(port, slot, filename, flags);
1010 if (r < -9) {
1011 mcman_invhandles(port, slot);
1012 mcman_clearcache(port, slot);
1015 return r;
1018 //--------------------------------------------------------------
1019 int McFormat(int port, int slot) // Export #11
1021 register int r;
1023 mcman_invhandles(port, slot);
1025 r = McDetectCard(port, slot);
1026 if (r < -2)
1027 return r;
1029 mcman_clearcache(port, slot);
1031 if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
1032 r = mcman_format2(port, slot);
1033 else
1034 r = mcman_format1(port, slot);
1036 if (r < -9) {
1037 mcman_invhandles(port, slot);
1038 mcman_clearcache(port, slot);
1041 return r;
1044 //--------------------------------------------------------------
1045 int McUnformat(int port, int slot) // Export #36
1047 register int r;
1049 mcman_invhandles(port, slot);
1051 r = McDetectCard(port, slot);
1052 if (r < -2)
1053 return r;
1055 mcman_clearcache(port, slot);
1057 if (mcman_devinfos[port][slot].cardtype == sceMcTypePS2)
1058 r = mcman_unformat2(port, slot);
1059 else
1060 r = mcman_unformat1(port, slot);
1062 mcman_devinfos[port][slot].cardform = 0;
1064 if (r < -9) {
1065 mcman_invhandles(port, slot);
1066 mcman_clearcache(port, slot);
1069 return r;
1072 //--------------------------------------------------------------
1073 int mcman_getmcrtime(sceMcStDateTime *time)
1075 register int retries;
1076 cd_clock_t cdtime;
1078 retries = 64;
1080 do {
1081 if (sceCdRC(&cdtime))
1082 break;
1083 } while (--retries > 0);
1085 if (cdtime.stat & 128) {
1086 *((u16 *)&cdtime.month) = 0x7d0;
1087 cdtime.day = 3;
1088 cdtime.week = 4;
1089 cdtime.hour = 0;
1090 cdtime.minute = 0;
1091 cdtime.second = 0;
1092 cdtime.stat = 0;
1095 time->Resv2 = 0;
1096 time->Sec = ((((cdtime.second >> 4) << 2) + (cdtime.second >> 4)) << 1) + (cdtime.second & 0xf);
1097 time->Min = ((((cdtime.minute >> 4) << 2) + (cdtime.minute >> 4)) << 1) + (cdtime.minute & 0xf);
1098 time->Hour = ((((cdtime.hour >> 4) << 2) + (cdtime.hour >> 4)) << 1) + (cdtime.hour & 0xf);
1099 time->Day = ((((cdtime.day >> 4) << 2) + (cdtime.day >> 4)) << 1) + (cdtime.day & 0xf);
1101 if ((cdtime.month & 0x10) != 0)
1102 time->Month = (cdtime.month & 0xf) + 0xa;
1103 else
1104 time->Month = cdtime.month & 0xf;
1106 time->Year = ((((cdtime.year >> 4) << 2) + (cdtime.year >> 4)) << 1) + ((cdtime.year & 0xf) | 0x7d0);
1108 return 0;
1111 //--------------------------------------------------------------
1112 int McEraseBlock(int port, int block, void **pagebuf, void *eccbuf) // Export #17 in MCMAN
1114 return mcman_eraseblock(port, 0, block, (void **)pagebuf, eccbuf);
1117 //--------------------------------------------------------------
1118 int McEraseBlock2(int port, int slot, int block, void **pagebuf, void *eccbuf) // Export #17 in XMCMAN
1120 return mcman_eraseblock(port, slot, block, (void **)pagebuf, eccbuf);
1123 //--------------------------------------------------------------
1124 int McReadPage(int port, int slot, int page, void *buf) // Export #18
1126 register int r, index, ecres, retries, count, erase_byte;
1127 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1128 u8 eccbuf[32];
1129 u8 *pdata, *peccb;
1131 count = (mcdi->pagesize + 127) >> 7;
1132 erase_byte = (mcdi->cardflags & CF_ERASE_ZEROES) ? 0x0 : 0xFF;
1134 retries = 0;
1135 ecres = sceMcResSucceed;
1136 do {
1137 if (!mcman_readpage(port, slot, page, buf, eccbuf)) {
1138 if (mcdi->cardflags & CF_USE_ECC) { // checking ECC from spare data block
1139 // check for erased page (last byte of spare data set to 0xFF or 0x0)/
1140 if (eccbuf[mcman_sparesize(port, slot) - 1] == erase_byte)
1141 break;
1143 index = 0;
1145 if (count > 0) {
1146 peccb = (u8 *)eccbuf;
1147 pdata = (u8 *)buf;
1149 do {
1150 r = mcman_correctdata(pdata, peccb);
1151 if (r < ecres)
1152 ecres = r;
1154 peccb += 3;
1155 pdata += 128;
1156 } while (++index < count);
1159 if (ecres == sceMcResSucceed)
1160 break;
1162 if ((retries == 4) && (!(ecres < sceMcResNoFormat)))
1163 break;
1166 } while (++retries < 5);
1168 if (retries < 5)
1169 return sceMcResSucceed;
1171 return (ecres != sceMcResSucceed) ? sceMcResNoFormat : sceMcResChangedCard;
1174 //--------------------------------------------------------------
1175 void McDataChecksum(void *buf, void *ecc) // Export #20
1177 register u8 *p, *p_ecc;
1178 register int i, a2, a3, v, t0;
1180 p = buf;
1181 i = 0;
1182 a2 = 0;
1183 a3 = 0;
1184 t0 = 0;
1186 do {
1187 v = mcman_xortable[*p++];
1188 a2 ^= v;
1189 if (v & 0x80) {
1190 a3 ^= ~i;
1191 t0 ^= i;
1193 } while (++i < 0x80);
1195 p_ecc = ecc;
1196 p_ecc[0] = ~a2 & 0x77;
1197 p_ecc[1] = ~a3 & 0x7F;
1198 p_ecc[2] = ~t0 & 0x7F;
1201 //--------------------------------------------------------------
1202 int mcman_getcnum(int port, int slot)
1204 return ((port & 1) << 3) + slot;
1207 //--------------------------------------------------------------
1208 int mcman_correctdata(void *buf, void *ecc)
1210 register int xor0, xor1, xor2, xor3, xor4;
1211 u8 eccbuf[12];
1212 u8 *p = (u8 *)ecc;
1214 McDataChecksum(buf, eccbuf);
1216 xor0 = p[0] ^ eccbuf[0];
1217 xor1 = p[1] ^ eccbuf[1];
1218 xor2 = p[2] ^ eccbuf[2];
1220 xor3 = xor1 ^ xor2;
1221 xor4 = (xor0 & 0xf) ^ (xor0 >> 4);
1223 if (!xor0 && !xor1 && !xor2)
1224 return 0;
1226 if ((xor3 == 0x7f) && (xor4 == 0x7)) {
1227 p[xor2] ^= 1 << (xor0 >> 4);
1228 return -1;
1231 xor0 = 0;
1232 xor2 = 7;
1233 do {
1234 if ((xor3 & 1))
1235 xor0++;
1236 xor2--;
1237 xor3 = xor3 >> 1;
1238 } while (xor2 >= 0);
1240 xor2 = 3;
1241 do {
1242 if ((xor4 & 1))
1243 xor0++;
1244 xor2--;
1245 xor4 = xor4 >> 1;
1246 } while (xor2 >= 0);
1248 if (xor0 == 1)
1249 return -2;
1251 return -3;
1254 //--------------------------------------------------------------
1255 int mcman_sparesize(int port, int slot)
1256 { // Get ps2 mc spare size by dividing pagesize / 32
1257 return (mcman_devinfos[port][slot].pagesize + 0x1F) >> 5;
1260 //--------------------------------------------------------------
1261 int mcman_setdevspec(int port, int slot)
1263 int cardsize;
1264 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1266 #ifdef DEBUG
1267 DPRINTF("mcman: mcman_setdevspec port%d, slot%d\n", port, slot);
1268 #endif
1270 if (McGetCardSpec(port, slot, &mcdi->pagesize, &mcdi->blocksize, &cardsize, &mcdi->cardflags) != sceMcResSucceed)
1271 return sceMcResFullDevice;
1273 mcdi->pages_per_cluster = MCMAN_CLUSTERSIZE / mcdi->pagesize;
1274 mcdi->cluster_size = MCMAN_CLUSTERSIZE;
1275 mcdi->unknown1 = 0;
1276 mcdi->unknown2 = 0;
1277 mcdi->unused = 0xff00;
1278 mcdi->FATentries_per_cluster = MCMAN_CLUSTERFATENTRIES;
1279 mcdi->unknown5 = -1;
1280 mcdi->rootdir_cluster2 = mcdi->rootdir_cluster;
1281 mcdi->clusters_per_block = mcdi->blocksize / mcdi->pages_per_cluster;
1282 mcdi->clusters_per_card = (cardsize / mcdi->blocksize) * (mcdi->blocksize / mcdi->pages_per_cluster);
1284 return sceMcResSucceed;
1287 //--------------------------------------------------------------
1288 int mcman_setdevinfos(int port, int slot)
1290 register int r, allocatable_clusters_per_card, iscluster_valid, current_allocatable_cluster, cluster_cnt;
1291 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1292 McFsEntry *pfse;
1294 #ifdef DEBUG
1295 DPRINTF("mcman: mcman_setdevinfos port%d slot%d\n", port, slot);
1296 #endif
1298 mcman_wmemset((void *)mcdi, sizeof(MCDevInfo), 0);
1300 r = mcman_setdevspec(port, slot);
1301 if (r != sceMcResSucceed)
1302 return -49;
1304 r = McReadPage(port, slot, 0, mcman_pagebuf);
1305 if (r == sceMcResNoFormat)
1306 return sceMcResNoFormat; // should rebuild a valid superblock here
1307 if (r != sceMcResSucceed)
1308 return -48;
1310 if (strncmp(SUPERBLOCK_MAGIC, mcman_pagebuf, 28) != 0) {
1311 #ifdef DEBUG
1312 DPRINTF("mcman: mcman_setdevinfos No card format !!!\n");
1313 #endif
1314 return sceMcResNoFormat;
1317 if (((mcman_pagebuf[28] - 48) == 1) && ((mcman_pagebuf[30] - 48) == 0)) // check ver major & minor
1318 return sceMcResNoFormat;
1320 u8 *p = (u8 *)mcdi;
1321 for (r=0; r<0x150; r++)
1322 p[r] = mcman_pagebuf[r];
1324 mcdi->cardtype = sceMcTypePS2; // <--
1326 r = mcman_checkBackupBlocks(port, slot);
1327 if (r != sceMcResSucceed)
1328 return -47;
1330 r = mcman_readdirentry(port, slot, 0, 0, &pfse);
1331 if (r != sceMcResSucceed)
1332 return sceMcResNoFormat; // -46
1334 if (strcmp(pfse->name, ".") != 0)
1335 return sceMcResNoFormat;
1337 if (mcman_readdirentry(port, slot, 0, 1, &pfse) != sceMcResSucceed)
1338 return -45;
1340 if (strcmp(pfse->name, "..") != 0)
1341 return sceMcResNoFormat;
1343 mcdi->cardform = 1;
1344 // mcdi->cardtype = sceMcTypePS2;
1346 if (((mcman_pagebuf[28] - 48) == 1) && ((mcman_pagebuf[30] - 48) == 1)) { // check ver major & minor
1347 if ((mcdi->clusters_per_block * mcdi->backup_block2) == mcdi->alloc_end)
1348 mcdi->alloc_end = (mcdi->clusters_per_block * mcdi->backup_block2) - mcdi->alloc_offset;
1351 u32 hi, lo, temp;
1353 long_multiply(mcdi->clusters_per_card, 0x10624dd3, &hi, &lo);
1354 temp = (hi >> 6) - (mcdi->clusters_per_card >> 31);
1355 allocatable_clusters_per_card = (((((temp << 5) - temp) << 2) + temp) << 3) + 1;
1356 iscluster_valid = 0;
1357 cluster_cnt = 0;
1358 current_allocatable_cluster = mcdi->alloc_offset;
1360 while (cluster_cnt < allocatable_clusters_per_card) {
1361 if (current_allocatable_cluster >= mcdi->clusters_per_card)
1362 break;
1364 if (((current_allocatable_cluster % mcdi->clusters_per_block) == 0) \
1365 || (mcdi->alloc_offset == current_allocatable_cluster)) {
1366 iscluster_valid = 1;
1367 for (r=0; r<16; r++) {
1368 if ((current_allocatable_cluster / mcdi->clusters_per_block) == mcdi->bad_block_list[r])
1369 iscluster_valid = 0;
1372 if (iscluster_valid == 1)
1373 cluster_cnt++;
1374 current_allocatable_cluster++;
1377 mcdi->max_allocatable_clusters = current_allocatable_cluster - mcdi->alloc_offset;
1379 return sceMcResSucceed;
1382 //--------------------------------------------------------------
1383 int mcman_reportBadBlocks(int port, int slot)
1385 register int r, i, block, bad_blocks, page, erase_byte, err_cnt, err_limit;
1386 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1387 u8 *p;
1389 #ifdef DEBUG
1390 DPRINTF("mcman: mcman_reportBadBlocks port%d, slot%d\n", port, slot);
1391 #endif
1393 mcman_wmemset((void *)mcdi->bad_block_list, 128, -1);
1395 if ((mcdi->cardflags & CF_BAD_BLOCK) == 0)
1396 return sceMcResSucceed;
1398 err_limit = (((mcdi->pagesize << 16) >> 16) + ((mcdi->pagesize << 16) >> 31)) >> 1; //s7
1400 erase_byte = 0;
1401 if ((mcdi->cardflags & CF_ERASE_ZEROES) != 0)
1402 erase_byte = 0xff;
1404 bad_blocks = 0; // s2
1406 if ((mcdi->clusters_per_card / mcdi->clusters_per_block) > 0) {
1408 block = 0; // s1
1410 do {
1411 if (bad_blocks >= 16)
1412 break;
1414 err_cnt = 0; //s4
1415 page = 0; //s3
1416 do {
1418 r = McReadPage(port, slot, (block * mcdi->blocksize) + page, mcman_pagebuf);
1419 if (r == sceMcResNoFormat) {
1420 mcdi->bad_block_list[bad_blocks] = block;
1421 bad_blocks++;
1422 break;
1424 if (r != sceMcResSucceed)
1425 return r;
1427 if ((mcdi->cardflags & CF_USE_ECC) == 0) {
1428 p = (u8 *)&mcman_pagebuf;
1429 for (i = 0; i < mcdi->pagesize; i++) {
1430 // check if the content of page is clean
1431 if (*p++ != erase_byte)
1432 err_cnt++;
1434 if (err_cnt >= err_limit) {
1435 mcdi->bad_block_list[bad_blocks] = block;
1436 bad_blocks++;
1437 break;
1441 } while (++page < 2);
1443 } while (++block < (mcdi->clusters_per_card / mcdi->clusters_per_block));
1446 return sceMcResSucceed;
1449 //--------------------------------------------------------------
1450 int mcman_createDirentry(int port, int slot, int parent_cluster, int num_entries, int cluster, sceMcStDateTime *ctime)
1452 register int r;
1453 McCacheEntry *mce;
1454 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1455 McFsEntry *mfe, *mfe_next, *pfse;
1457 #ifdef DEBUG
1458 DPRINTF("mcman: mcman_createDirentry port%d slot%d parent_cluster %x num_entries %d cluster %x\n", port, slot, parent_cluster, num_entries, cluster);
1459 #endif
1461 r = mcman_readcluster(port, slot, mcdi->alloc_offset + cluster, &mce);
1462 if (r != sceMcResSucceed)
1463 return r;
1465 mcman_wmemset(mce->cl_data, MCMAN_CLUSTERSIZE, 0);
1467 mfe = (McFsEntry*)mce->cl_data;
1468 mfe_next = (McFsEntry*)(mce->cl_data + sizeof (McFsEntry));
1470 mfe->mode = sceMcFileAttrReadable | sceMcFileAttrWriteable | sceMcFileAttrExecutable \
1471 | sceMcFileAttrSubdir | sceMcFile0400 | sceMcFileAttrExists; // 0x8427
1473 if (ctime == NULL)
1474 mcman_getmcrtime(&mfe->created);
1475 else
1476 mfe->created = *ctime;
1478 mfe->modified = mfe->created;
1480 mfe->length = 0;
1481 mfe->dir_entry = num_entries;
1482 mfe->cluster = parent_cluster;
1483 *(u16 *)&mfe->name = *((u16 *)&DOT);
1485 if ((parent_cluster == 0) && (num_entries == 0)) {
1486 // entry is root directory
1487 mfe_next->created = mfe->created;
1488 mfe->length = 2;
1489 mfe++;
1491 mfe->mode = sceMcFileAttrWriteable | sceMcFileAttrExecutable | sceMcFileAttrSubdir \
1492 | sceMcFile0400 | sceMcFileAttrExists | sceMcFileAttrHidden; // 0xa426
1493 mfe->dir_entry = 0;
1494 mfe->cluster = 0;
1496 else {
1497 // entry is normal "." / ".."
1498 mcman_readdirentry(port, slot, parent_cluster, 0, &pfse);
1500 mfe_next->created = pfse->created;
1501 mfe++;
1503 mfe->mode = sceMcFileAttrReadable | sceMcFileAttrWriteable | sceMcFileAttrExecutable \
1504 | sceMcFileAttrSubdir | sceMcFile0400 | sceMcFileAttrExists; // 0x8427
1505 mfe->dir_entry = pfse->dir_entry;
1507 mfe->cluster = pfse->cluster;
1510 mfe->modified = mfe->created;
1511 mfe->length = 0;
1513 *(u16 *)&mfe->name = *(u16 *)&DOTDOT;
1514 *(u8 *)&mfe->name[2] = *((u8 *)&DOTDOT+2);
1516 mce->wr_flag = 1;
1518 return sceMcResSucceed;
1521 //--------------------------------------------------------------
1522 int mcman_fatRseek(int fd)
1524 register int r, entries_to_read, fat_index;
1525 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd]; //s1
1526 register MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot]; //s2
1527 int fat_entry;
1529 entries_to_read = fh->position / mcdi->cluster_size; //s0
1531 //s5 = 0
1533 if (entries_to_read < fh->clust_offset) //v1 = fh->fh->clust_offset
1534 fat_index = fh->freeclink;
1535 else {
1536 fat_index = fh->clink; // a2
1537 entries_to_read -= fh->clust_offset;
1540 if (entries_to_read == 0) {
1541 if (fat_index >= 0)
1542 return fat_index + mcdi->alloc_offset;
1544 return sceMcResFullDevice;
1547 do {
1548 r = mcman_getFATentry(fh->port, fh->slot, fat_index, &fat_entry);
1549 if (r != sceMcResSucceed)
1550 return r;
1552 fat_index = fat_entry;
1554 if (fat_index >= -1)
1555 return sceMcResFullDevice;
1557 entries_to_read--;
1559 fat_index &= 0x7fffffff;
1560 fh->clink = fat_index;
1561 fh->clust_offset = (fh->position / mcdi->cluster_size) - entries_to_read;
1563 } while (entries_to_read > 0);
1565 return fat_index + mcdi->alloc_offset;
1568 //--------------------------------------------------------------
1569 int mcman_fatWseek(int fd) // modify FAT to hold new content for a file
1571 register int r, entries_to_write, fat_index;
1572 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
1573 register MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
1574 register McCacheEntry *mce;
1575 int fat_entry;
1577 entries_to_write = fh->position / mcdi->cluster_size;
1579 if ((fh->clust_offset == 0) || (entries_to_write < fh->clust_offset)) {
1580 fat_index = fh->freeclink;
1582 if (fat_index < 0) {
1583 fat_index = mcman_findfree2(fh->port, fh->slot, 1);
1585 if (fat_index < 0)
1586 return sceMcResFullDevice;
1588 mce = (McCacheEntry *)mcman_get1stcacheEntp();
1589 fh->freeclink = fat_index;
1591 r = mcman_close2(fd);
1592 if (r != sceMcResSucceed)
1593 return r;
1595 mcman_addcacheentry(mce);
1596 mcman_flushmccache(fh->port, fh->slot);
1599 else {
1600 fat_index = fh->clink;
1601 entries_to_write -= fh->clust_offset;
1604 if (entries_to_write != 0) {
1605 do {
1606 r = mcman_getFATentry(fh->port, fh->slot, fat_index, &fat_entry);
1607 if (r != sceMcResSucceed)
1608 return r;
1610 if (fat_entry >= 0xffffffff) {
1611 r = mcman_findfree2(fh->port, fh->slot, 1);
1612 if (r < 0)
1613 return r;
1614 fat_entry = r;
1615 fat_entry |= 0x80000000;
1617 mce = (McCacheEntry *)mcman_get1stcacheEntp();
1619 r = mcman_setFATentry(fh->port, fh->slot, fat_index, fat_entry);
1620 if (r != sceMcResSucceed)
1621 return r;
1623 mcman_addcacheentry(mce);
1626 entries_to_write--;
1627 fat_index = fat_entry & 0x7fffffff;
1628 } while (entries_to_write > 0);
1631 fh->clink = fat_index;
1632 fh->clust_offset = fh->position / mcdi->cluster_size;
1634 return sceMcResSucceed;
1637 //--------------------------------------------------------------
1638 int mcman_findfree2(int port, int slot, int reserve)
1640 register int r, rfree, indirect_index, ifc_index, fat_offset, indirect_offset, fat_index, block;
1641 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1642 McCacheEntry *mce1, *mce2;
1644 #ifdef DEBUG
1645 DPRINTF("mcman: mcman_findfree2 port%d slot%d reserve%d\n", port, slot, reserve);
1646 #endif
1648 fat_index = mcdi->unknown2;
1649 rfree = 0;
1651 for (fat_index = mcdi->unknown2; fat_index < mcdi->max_allocatable_clusters; fat_index++) {
1653 indirect_index = fat_index / mcdi->FATentries_per_cluster;
1654 fat_offset = fat_index % mcdi->FATentries_per_cluster;
1656 if ((fat_offset == 0) || (fat_index == mcdi->unknown2)) {
1658 ifc_index = indirect_index / mcdi->FATentries_per_cluster;
1659 r = mcman_readcluster(port, slot, mcdi->ifc_list[ifc_index], &mce1);
1660 if (r != sceMcResSucceed)
1661 return r;
1663 //if ((fat_offset == 0) || (fat_index == mcdi->unknown2)) {
1664 indirect_offset = indirect_index % mcdi->FATentries_per_cluster;
1665 McFatCluster *fc = (McFatCluster *)mce1->cl_data;
1666 r = mcman_readcluster(port, slot, fc->entry[indirect_offset], &mce2);
1667 if (r != sceMcResSucceed)
1668 return r;
1671 McFatCluster *fc = (McFatCluster *)mce2->cl_data;
1673 if (fc->entry[fat_offset] >= 0) {
1674 block = (mcdi->alloc_offset + fat_offset) / mcdi->clusters_per_block;
1675 if (block != mcman_badblock) {
1676 if (reserve) {
1677 fc->entry[fat_offset] = 0xffffffff;
1678 mce2->wr_flag = 1;
1679 mcdi->unknown2 = fat_index;
1680 return fat_index;
1682 rfree++;
1687 if (reserve)
1688 return sceMcResFullDevice;
1690 return (rfree) ? rfree : sceMcResFullDevice;
1693 //--------------------------------------------------------------
1694 int mcman_getentspace(int port, int slot, char *dirname)
1696 register int r, i, entspace;
1697 McCacheDir cacheDir;
1698 McFsEntry *fse;
1699 McFsEntry mfe;
1700 u8 *pfsentry, *pmfe, *pfseend;
1702 #ifdef DEBUG
1703 DPRINTF("mcman: mcman_getentspace port%d slot%d dirname %s\n", port, slot, dirname);
1704 #endif
1706 r = mcman_cachedirentry(port, slot, dirname, &cacheDir, &fse, 1);
1707 if (r > 0)
1708 return sceMcResNoEntry;
1709 if (r < 0)
1710 return r;
1712 pfsentry = (u8 *)fse;
1713 pmfe = (u8 *)&mfe;
1714 pfseend = (u8 *)(pfsentry + sizeof (McFsEntry));
1716 do {
1717 *((u32 *)pmfe ) = *((u32 *)pfsentry );
1718 *((u32 *)pmfe+1) = *((u32 *)pfsentry+1);
1719 *((u32 *)pmfe+2) = *((u32 *)pfsentry+2);
1720 *((u32 *)pmfe+3) = *((u32 *)pfsentry+3);
1721 pfsentry += 16;
1722 pmfe += 16;
1723 } while (pfsentry < pfseend);
1725 entspace = mfe.length & 1;
1727 for (i = 0; i < mfe.length; i++) {
1729 r = mcman_readdirentry(port, slot, mfe.cluster, i, &fse);
1730 if (r != sceMcResSucceed)
1731 return r;
1732 if ((fse->mode & sceMcFileAttrExists) == 0)
1733 entspace++;
1736 return entspace;
1739 //--------------------------------------------------------------
1740 int mcman_cachedirentry(int port, int slot, char *filename, McCacheDir *pcacheDir, McFsEntry **pfse, int unknown_flag)
1742 register int r, fsindex, cluster, fmode;
1743 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1744 McFsEntry *fse;
1745 McCacheDir cacheDir;
1746 u8 *p, *pfsentry, *pcache, *pfseend;
1748 #ifdef DEBUG
1749 DPRINTF("mcman: mcman_cachedirentry port%d slot%d name %s\n", port, slot, filename);
1750 #endif
1752 if (pcacheDir == NULL) {
1753 pcacheDir = &cacheDir;
1754 pcacheDir->maxent = -1;
1757 p = (u8 *)filename;
1758 if (*p == '/') {
1759 p++;
1760 cluster = 0;
1761 fsindex = 0;
1763 else {
1764 cluster = mcdi->rootdir_cluster2;
1765 fsindex = mcdi->unknown1;
1768 r = mcman_readdirentry(port, slot, cluster, fsindex, &fse);
1769 if (r != sceMcResSucceed)
1770 return r;
1772 if (*p == 0) {
1773 if (!(fse->mode & sceMcFileAttrExists))
1774 return 2;
1776 if (pcacheDir == NULL) {
1777 *pfse = (McFsEntry *)fse;
1778 return sceMcResSucceed;
1781 pfsentry = (u8 *)fse;
1782 pcache = (u8 *)&mcman_dircache[0];
1783 pfseend = (u8 *)(pfsentry + sizeof (McFsEntry));
1785 do {
1786 *((u32 *)pcache ) = *((u32 *)pfsentry );
1787 *((u32 *)pcache+1) = *((u32 *)pfsentry+1);
1788 *((u32 *)pcache+2) = *((u32 *)pfsentry+2);
1789 *((u32 *)pcache+3) = *((u32 *)pfsentry+3);
1790 pfsentry += 16;
1791 pcache += 16;
1792 } while (pfsentry < pfseend);
1794 r = mcman_getdirinfo(port, slot, (McFsEntry *)&mcman_dircache[0], ".", pcacheDir, unknown_flag);
1796 mcman_readdirentry(port, slot, pcacheDir->cluster, pcacheDir->fsindex, pfse);
1798 if (r > 0)
1799 return 2;
1801 return r;
1803 } else {
1805 do {
1806 fmode = sceMcFileAttrReadable | sceMcFileAttrExecutable;
1807 if ((fse->mode & fmode) != fmode)
1808 return sceMcResDeniedPermit;
1810 if (mcman_chrpos(p, '/') < 0)
1811 strlen(p);
1813 pfsentry = (u8 *)fse;
1814 pcache = (u8 *)&mcman_dircache[0];
1815 pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
1817 do {
1818 *((u32 *)pcache ) = *((u32 *)pfsentry );
1819 *((u32 *)pcache+1) = *((u32 *)pfsentry+1);
1820 *((u32 *)pcache+2) = *((u32 *)pfsentry+2);
1821 *((u32 *)pcache+3) = *((u32 *)pfsentry+3);
1822 pfsentry += 16;
1823 pcache += 16;
1824 } while (pfsentry < pfseend);
1826 r = mcman_getdirinfo(port, slot, (McFsEntry *)&mcman_dircache[0], p, pcacheDir, unknown_flag);
1828 if (r > 0) {
1829 if (mcman_chrpos(p, '/') >= 0)
1830 return 2;
1832 pcacheDir->cluster = cluster;
1833 pcacheDir->fsindex = fsindex;
1835 return 1;
1838 r = mcman_chrpos(p, '/');
1839 if ((r >= 0) && (p[r + 1] != 0)) {
1840 p += mcman_chrpos(p, '/') + 1;
1841 cluster = pcacheDir->cluster;
1842 fsindex = pcacheDir->fsindex;
1844 mcman_readdirentry(port, slot, cluster, fsindex, &fse);
1846 else {
1847 mcman_readdirentry(port, slot, pcacheDir->cluster, pcacheDir->fsindex, pfse);
1849 return sceMcResSucceed;
1851 } while (*p != 0);
1853 return sceMcResSucceed;
1856 //--------------------------------------------------------------
1857 int mcman_getdirinfo(int port, int slot, McFsEntry *pfse, char *filename, McCacheDir *pcd, int unknown_flag)
1859 register int i, r, ret, len, pos;
1860 McFsEntry *fse;
1861 u8 *pfsentry, *pfsee, *pfseend;
1863 #ifdef DEBUG
1864 DPRINTF("mcman: mcman_getdirinfo port%d slot%d name %s\n", port, slot, filename);
1865 #endif
1867 pos = mcman_chrpos(filename, '/');
1868 if (pos < 0)
1869 pos = strlen(filename);
1871 ret = 0;
1872 if ((pos == 2) && (!strncmp(filename, "..", 2))) {
1874 r = mcman_readdirentry(port, slot, pfse->cluster, 0, &fse);
1875 if (r != sceMcResSucceed)
1876 return r;
1878 r = mcman_readdirentry(port, slot, fse->cluster, 0, &fse);
1879 if (r != sceMcResSucceed)
1880 return r;
1882 if (pcd) {
1883 pcd->cluster = fse->cluster;
1884 pcd->fsindex = fse->dir_entry;
1887 r = mcman_readdirentry(port, slot, fse->cluster, fse->dir_entry, &fse);
1888 if (r != sceMcResSucceed)
1889 return r;
1891 pfsentry = (u8 *)fse;
1892 pfsee = (u8 *)pfse;
1893 pfseend = (u8 *)(pfsentry + sizeof(McFsEntry));
1895 do {
1896 *((u32 *)pfsee ) = *((u32 *)pfsentry );
1897 *((u32 *)pfsee+1) = *((u32 *)pfsentry+1);
1898 *((u32 *)pfsee+2) = *((u32 *)pfsentry+2);
1899 *((u32 *)pfsee+3) = *((u32 *)pfsentry+3);
1900 pfsentry += 16;
1901 pfsee += 16;
1902 } while (pfsentry < pfseend);
1904 if ((fse->mode & sceMcFileAttrHidden) != 0) {
1905 ret = 1;
1906 if (!PS1CardFlag) {
1907 ret = 2;
1908 if ((pcd == NULL) || (pcd->maxent < 0))
1909 return 3;
1913 if ((pcd == NULL) || (pcd->maxent < 0))
1914 return sceMcResSucceed;
1916 else {
1917 if ((pos == 1) && (!strncmp(filename, ".", 1))) {
1919 r = mcman_readdirentry(port, slot, pfse->cluster, 0, &fse);
1920 if (r != sceMcResSucceed)
1921 return r;
1923 if (pcd) {
1924 pcd->cluster = fse->cluster;
1925 pcd->fsindex = fse->dir_entry;
1928 if ((fse->mode & sceMcFileAttrHidden) != 0) {
1929 ret = 1;
1930 if (!PS1CardFlag) {
1931 ret = 2;
1932 if ((pcd == NULL) || (pcd->maxent < 0))
1933 return 3;
1935 else {
1936 if ((pcd == NULL) || (pcd->maxent < 0))
1937 return sceMcResSucceed;
1940 else {
1941 ret = 1;
1942 if ((pcd == NULL) || (pcd->maxent < 0))
1943 return sceMcResSucceed;
1948 if ((pcd) && (pcd->maxent >= 0))
1949 pcd->maxent = pfse->length;
1951 if (pfse->length > 0) {
1953 i = 0;
1954 do {
1955 r = mcman_readdirentry(port, slot, pfse->cluster, i, &fse);
1956 if (r != sceMcResSucceed)
1957 return r;
1959 if (((fse->mode & sceMcFileAttrExists) == 0) && (pcd) && (i < pcd->maxent))
1960 pcd->maxent = i;
1962 if (unknown_flag) {
1963 if ((fse->mode & sceMcFileAttrExists) == 0)
1964 continue;
1966 else {
1967 if ((fse->mode & sceMcFileAttrExists) != 0)
1968 continue;
1971 if (ret != 0)
1972 continue;
1974 if ((pos >= 11) && (!strncmp(&filename[10], &fse->name[10], pos-10))) {
1975 len = pos;
1976 if (strlen(fse->name) >= pos)
1977 len = strlen(fse->name);
1979 if (!strncmp(filename, fse->name, len))
1980 goto continue_check;
1983 if (strlen(fse->name) >= pos)
1984 len = strlen(fse->name);
1985 else
1986 len = pos;
1988 if (strncmp(filename, fse->name, len))
1989 continue;
1991 continue_check:
1992 ret = 1;
1994 if ((fse->mode & sceMcFileAttrHidden) != 0) {
1995 if (!PS1CardFlag)
1996 ret = 2;
1999 if (pcd == NULL)
2000 break;
2002 pcd->fsindex = i;
2003 pcd->cluster = pfse->cluster;
2005 if (pcd->maxent < 0)
2006 break;
2008 } while (++i < pfse->length);
2011 if (ret == 2)
2012 return 2;
2014 return ((ret < 1) ? 1 : 0);
2017 //--------------------------------------------------------------
2018 int mcman_writecluster(int port, int slot, int cluster, int flag)
2020 register int r, i, j, page, block, pageword_cnt;
2021 register u32 erase_value;
2022 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2024 block = cluster / mcdi->clusters_per_block;
2026 if ((mcman_wr_port == port) && (mcman_wr_slot == slot) && (mcman_wr_block == block))
2027 return mcman_wr_flag3;
2029 mcman_wr_port = port;
2030 mcman_wr_slot = slot;
2031 mcman_wr_block = block;
2032 mcman_wr_flag3 = -9;
2034 for (i = 0; i < 16; i++) { // check only 16 bad blocks ?
2035 if (mcdi->bad_block_list[i] < 0)
2036 break;
2037 if (mcdi->bad_block_list[i] == block) {
2038 mcman_wr_flag3 = 0;
2039 return sceMcResSucceed;
2043 if (flag) {
2044 for (i = 1; i < mcdi->blocksize; i++)
2045 mcman_pagedata[i] = 0;
2047 mcman_pagedata[0] = &mcman_pagebuf;
2049 pageword_cnt = mcdi->pagesize >> 2;
2050 page = block * mcdi->blocksize;
2052 if (mcdi->cardflags & CF_ERASE_ZEROES)
2053 erase_value = 0xffffffff;
2054 else
2055 erase_value = 0x00000000;
2057 for (i = 0; i < pageword_cnt; i++)
2058 *((u32 *)&mcman_pagebuf + i) = erase_value;
2060 r = mcman_eraseblock(port, slot, block, (void **)mcman_pagedata, (void *)mcman_eccdata);
2061 if (r == sceMcResFailReplace)
2062 return sceMcResSucceed;
2063 if (r != sceMcResSucceed)
2064 return sceMcResChangedCard;
2066 for (i = 1; i < mcdi->blocksize; i++) {
2067 r = McWritePage(port, slot, page + i, mcman_pagebuf, mcman_eccdata);
2068 if (r == sceMcResFailReplace)
2069 return sceMcResSucceed;
2070 if (r != sceMcResSucceed)
2071 return sceMcResNoFormat;
2074 for (i = 1; i < mcdi->blocksize; i++) {
2075 r = McReadPage(port, slot, page + i, mcman_pagebuf);
2076 if (r == sceMcResNoFormat)
2077 return sceMcResSucceed;
2078 if (r != sceMcResSucceed)
2079 return sceMcResFullDevice;
2081 for (j = 0; j < pageword_cnt; j++) {
2082 if (*((u32 *)&mcman_pagebuf + j) != erase_value) {
2083 mcman_wr_flag3 = 0;
2084 return sceMcResSucceed;
2089 r = mcman_eraseblock(port, slot, block, NULL, NULL);
2090 if (r != sceMcResSucceed)
2091 return sceMcResChangedCard;
2093 r = McWritePage(port, slot, page, mcman_pagebuf, mcman_eccdata);
2094 if (r == sceMcResFailReplace)
2095 return sceMcResSucceed;
2096 if (r != sceMcResSucceed)
2097 return sceMcResNoFormat;
2099 r = McReadPage(port, slot, page, mcman_pagebuf);
2100 if (r == sceMcResNoFormat)
2101 return sceMcResSucceed;
2102 if (r != sceMcResSucceed)
2103 return sceMcResFullDevice;
2105 for (j = 0; j < pageword_cnt; j++) {
2106 if (*((u32 *)&mcman_pagebuf + j) != erase_value) {
2107 mcman_wr_flag3 = 0;
2108 return sceMcResSucceed;
2112 r = mcman_eraseblock(port, slot, block, NULL, NULL);
2113 if (r == sceMcResFailReplace)
2114 return sceMcResSucceed;
2115 if (r != sceMcResSucceed)
2116 return sceMcResFullDevice;
2118 erase_value = ~erase_value;
2120 for (i = 0; i < mcdi->blocksize; i++) {
2121 r = McReadPage(port, slot, page + i, mcman_pagebuf);
2122 if (r != sceMcResSucceed)
2123 return sceMcResDeniedPermit;
2125 for (j = 0; j < pageword_cnt; j++) {
2126 if (*((u32 *)&mcman_pagebuf + j) != erase_value) {
2127 mcman_wr_flag3 = 0;
2128 return sceMcResSucceed;
2133 mcman_wr_flag3 = 1;
2135 return mcman_wr_flag3;
2138 //--------------------------------------------------------------
2139 int mcman_setdirentrystate(int port, int slot, int cluster, int fsindex, int flags)
2141 register int r, i, fat_index;
2142 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2143 McFsEntry *fse;
2144 int fat_entry;
2146 r = mcman_readdirentry(port, slot, cluster, fsindex, &fse);
2147 if (r != sceMcResSucceed)
2148 return r;
2150 if (fse->name[0] == '.') {
2151 if ((fse->name[1] == 0) || (fse->name[1] == '.'))
2152 return sceMcResNoEntry;
2155 i = 0;
2156 do {
2157 if (mcman_fdhandles[i].status == 0)
2158 continue;
2160 if ((mcman_fdhandles[i].port != port) || (mcman_fdhandles[i].slot != slot))
2161 continue;
2163 if (mcman_fdhandles[i].field_20 != cluster)
2164 continue;
2166 if (mcman_fdhandles[i].field_24 == fsindex)
2167 return sceMcResDeniedPermit;
2169 } while (++i < MAX_FDHANDLES);
2171 if (flags == 0)
2172 fse->mode = fse->mode & (sceMcFileAttrExists - 1);
2173 else
2174 fse->mode = fse->mode | sceMcFileAttrExists;
2176 mcman_1stcacheEntsetwrflagoff();
2178 fat_index = fse->cluster;
2180 if (fat_index >= 0) {
2181 if (fat_index < mcdi->unknown2)
2182 mcdi->unknown2 = fat_index;
2183 mcdi->unknown5 = -1;
2185 do {
2186 r = mcman_getFATentry(port, slot, fat_index, &fat_entry);
2187 if (r != sceMcResSucceed)
2188 return r;
2190 if (flags == 0) {
2191 fat_entry &= 0x7fffffff;
2192 if (fat_index < mcdi->unknown2)
2193 mcdi->unknown2 = fat_entry;
2195 else
2196 fat_entry |= 0x80000000;
2198 r = mcman_setFATentry(port, slot, fat_index, fat_entry);
2199 if (r != sceMcResSucceed)
2200 return r;
2202 fat_index = fat_entry & 0x7fffffff;
2204 } while (fat_index != 0x7fffffff);
2207 return sceMcResSucceed;
2210 //--------------------------------------------------------------
2211 int mcman_checkBackupBlocks(int port, int slot)
2213 register int r1, r2, r, value1, value2, eccsize;
2214 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2215 McCacheEntry *mce;
2216 int *pagebuf = (int *)&mcman_pagebuf;
2218 // First check backup block2 to see if it's in erased state
2219 r1 = McReadPage(port, slot, mcdi->backup_block2 * mcdi->blocksize, mcman_pagebuf); //s1
2221 value1 = *pagebuf; //s3
2222 if (((mcdi->cardflags & CF_ERASE_ZEROES) != 0) && (value1 == 0))
2223 value1 = -1;
2224 if (value1 != -1)
2225 value1 = value1 & 0x7fffffff;
2227 r2 = McReadPage(port, slot, (mcdi->backup_block2 * mcdi->blocksize) + 1, mcman_pagebuf); //a0
2229 value2 = *pagebuf; //s0
2230 if (((mcdi->cardflags & CF_ERASE_ZEROES) != 0) && (value2 == 0))
2231 value2 = -1;
2232 if (value2 != -1)
2233 value2 = value2 & 0x7fffffff;
2235 if ((value1 != -1) && (value2 == -1))
2236 goto check_done;
2237 if ((r1 < 0) || (r2 < 0))
2238 goto check_done;
2240 if ((value1 == -1) && (value1 == value2))
2241 return sceMcResSucceed;
2243 // bachup block2 is not erased, so programming is assumed to have not been completed
2244 // reads content of backup block1
2245 for (r1 = 0; r1 < mcdi->clusters_per_block; r1++) {
2247 mcman_readcluster(port, slot, (mcdi->backup_block1 * mcdi->clusters_per_block) + r1, &mce);
2248 mce->rd_flag = 1;
2250 for (r2 = 0; r2 < mcdi->pages_per_cluster; r2++) {
2251 mcman_pagedata[(r1 * ((mcdi->pages_per_cluster << 16) >> 16)) + r2] = \
2252 (void *)(mce->cl_data + (r2 * mcdi->pagesize));
2256 // Erase the block where data must be written
2257 r = mcman_eraseblock(port, slot, value1, (void **)mcman_pagedata, (void *)mcman_eccdata);
2258 if (r != sceMcResSucceed)
2259 return r;
2261 // Write the block
2262 for (r1 = 0; r1 < mcdi->blocksize; r1++) {
2264 eccsize = mcdi->pagesize;
2265 if (eccsize < 0)
2266 eccsize += 0x1f;
2267 eccsize = eccsize >> 5;
2269 r = McWritePage(port, slot, (value1 * ((mcdi->blocksize << 16) >> 16)) + r1, \
2270 mcman_pagedata[r1], (void *)(mcman_eccdata + (eccsize * r1)));
2272 if (r != sceMcResSucceed)
2273 return r;
2276 for (r1 = 0; r1 < mcdi->clusters_per_block; r1++)
2277 mcman_freecluster(port, slot, (mcdi->backup_block1 * mcdi->clusters_per_block) + r1);
2279 check_done:
2280 // Finally erase backup block2
2281 return mcman_eraseblock(port, slot, mcdi->backup_block2, NULL, NULL);
2284 //--------------------------------------------------------------
2285 int McCheckBlock(int port, int slot, int block)
2287 register int r, i, j, page, ecc_count, pageword_cnt, flag, erase_value;
2288 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2289 u8 *p_page, *p_ecc;
2291 #ifdef DEBUG
2292 DPRINTF("mcman: McCheckBlock port%d slot%d block 0x%x\n", port, slot, block);
2293 #endif
2295 // sp50 = block;
2296 page = block * mcdi->blocksize; //sp18
2297 pageword_cnt = mcdi->pagesize >> 2; //s6
2299 ecc_count = mcdi->pagesize;
2300 if (mcdi->pagesize < 0)
2301 ecc_count += 127;
2302 ecc_count = ecc_count >> 7; // s7
2304 flag = 0; // s4
2306 if (mcdi->cardform > 0) {
2307 for (i = 0; i < 16; i++) {
2308 if (mcdi->bad_block_list[i] <= 0)
2309 break;
2310 if (mcdi->bad_block_list[i] == block)
2311 goto lbl_8764;
2315 flag = 16; // s4
2317 for (i = 0; i < mcdi->blocksize; i++) {
2318 r = mcman_readpage(port, slot, page + i, mcman_pagebuf, mcman_eccdata);
2319 if (r != sceMcResSucceed)
2320 return -45;
2322 if ((mcdi->cardflags & CF_USE_ECC) != 0) {
2323 if (mcman_eccdata[mcman_sparesize(port, slot) - 1] != 0xff) {
2324 p_page = (void *)mcman_pagebuf; //s1
2325 p_ecc = (void *)mcman_eccdata; //s2
2327 for (j = 0; j < ecc_count; j++) {
2328 r = mcman_correctdata(p_page, p_ecc);
2329 if (r != sceMcResSucceed) {
2330 flag = -1;
2331 goto lbl_8764;
2333 p_ecc += 3;
2334 p_page += 128;
2340 for (j = 0; j < pageword_cnt; j++)
2341 *((u32 *)&mcman_pagebuf + j) = 0x5a5aa5a5;
2343 for (j = 0; j < 128; j++)
2344 *((u32 *)&mcman_eccdata + j) = 0x5a5aa5a5;
2346 r = mcman_eraseblock(port, slot, block, NULL, NULL);
2347 if (r != sceMcResSucceed) {
2348 r = mcman_probePS2Card2(port, slot);
2349 if (r != sceMcResSucceed)
2350 return -45;
2351 flag = -1;
2352 goto lbl_8764;
2355 for (i = 0; i < mcdi->blocksize; i++) {
2356 r = McWritePage(port, slot, page + i, mcman_pagebuf, mcman_eccdata);
2357 if (r != sceMcResSucceed) {
2358 r = mcman_probePS2Card2(port, slot);
2359 if (r != sceMcResSucceed)
2360 return -44;
2361 flag = -1;
2362 goto lbl_8764;
2366 for (i = 0; i < mcdi->blocksize; i++) {
2367 r = mcman_readpage(port, slot, page + i, mcman_pagebuf, mcman_eccdata);
2368 if (r != sceMcResSucceed)
2369 return -45;
2371 for (j = 0; j < pageword_cnt; j++) {
2372 if (*((u32 *)&mcman_pagebuf + j) != 0x5a5aa5a5) {
2373 flag = -1;
2374 goto lbl_8764;
2378 for (j = 0; j < 128; j++) {
2379 if (*((u32 *)&mcman_eccdata + j) != 0x5a5aa5a5) {
2380 flag = -1;
2381 goto lbl_8764;
2386 for (j = 0; j < pageword_cnt; j++)
2387 *((u32 *)&mcman_pagebuf + j) = 0x05a55a5a;
2389 for (j = 0; j < 128; j++)
2390 *((u32 *)&mcman_eccdata + j) = 0x05a55a5a;
2392 r = mcman_eraseblock(port, slot, block, NULL, NULL);
2393 if (r != sceMcResSucceed) {
2394 r = mcman_probePS2Card2(port, slot);
2395 if (r != sceMcResSucceed)
2396 return -42;
2397 flag = -1;
2398 goto lbl_8764;
2401 for (i = 0; i < mcdi->blocksize; i++) {
2402 r = McWritePage(port, slot, page + i, mcman_pagebuf, mcman_eccdata);
2403 if (r != sceMcResSucceed) {
2404 r = mcman_probePS2Card2(port, slot);
2405 if (r != sceMcResSucceed)
2406 return -46;
2407 flag = -1;
2408 goto lbl_8764;
2412 for (i = 0; i < mcdi->blocksize; i++) {
2413 r = mcman_readpage(port, slot, page + i, mcman_pagebuf, mcman_eccdata);
2414 if (r != sceMcResSucceed)
2415 return -45;
2417 for (j = 0; j < pageword_cnt; j++) {
2418 if (*((u32 *)&mcman_pagebuf + j) != 0x05a55a5a) {
2419 flag = -1;
2420 goto lbl_8764;
2424 for (j = 0; j < 128; j++) {
2425 if (*((u32 *)&mcman_eccdata + j) != 0x05a55a5a) {
2426 flag = -1;
2427 goto lbl_8764;
2432 lbl_8764:
2433 if (flag == 16) {
2434 mcman_eraseblock(port, slot, block, NULL, NULL);
2435 return sceMcResSucceed;
2438 erase_value = 0x00000000;
2439 if ((mcdi->cardflags & CF_ERASE_ZEROES) != 0)
2440 erase_value = 0xffffffff;
2442 for (j = 0; j < pageword_cnt; j++)
2443 *((u32 *)&mcman_pagebuf + j) = erase_value;
2445 for (j = 0; j < 128; j++)
2446 *((u32 *)&mcman_eccdata + j) = erase_value;
2448 for (i = 0; i < mcdi->blocksize; i++) {
2449 r = McWritePage(port, slot, page + i, mcman_pagebuf, mcman_eccdata);
2450 if (r != sceMcResSucceed) {
2451 r = mcman_probePS2Card2(port, slot);
2452 if (r != sceMcResSucceed)
2453 return -48;
2457 return 1;
2460 //--------------------------------------------------------------
2461 int mcman_setPS1devinfos(int port, int slot)
2463 register int r, i;
2464 MCDevInfo *mcdi = &mcman_devinfos[port][slot];
2466 #ifdef DEBUG
2467 DPRINTF("mcman: mcman_setPS1devinfos port%d slot%d\n", port, slot);
2468 #endif
2470 memset((void *)mcdi, 0, sizeof (MCDevInfo));
2471 memset((void *)&mcdi->bad_block_list[0], -1, 128);
2473 mcdi->pagesize = 128;
2474 mcdi->blocksize = 128;
2475 mcdi->pages_per_cluster = 64;
2476 mcdi->unused = 0xff00;
2477 mcdi->cluster_size = 8192;
2478 mcdi->FATentries_per_cluster = 2048;
2479 mcdi->clusters_per_card = 16;
2480 mcdi->clusters_per_block = 0;
2481 mcdi->cardform = 0;
2482 mcdi->cardtype = 1;
2484 r = McReadPS1PDACard(port, slot, 0, mcman_PS1PDApagebuf);
2485 if (r < 0)
2486 return -14;
2488 if (mcman_sio2outbufs_PS1PDA[1] != 0)
2489 return -15;
2491 if (mcman_PS1PDApagebuf[0] != 0x4d)
2492 return sceMcResNoFormat;
2494 if (mcman_PS1PDApagebuf[1] != 0x43)
2495 return sceMcResNoFormat;
2497 for (i = 0; i < 20; i++) {
2498 r = McReadPS1PDACard(port, slot, i + 16, mcman_PS1PDApagebuf);
2499 if (r != sceMcResSucceed)
2500 return -43;
2502 if (mcman_PS1PDApagebuf[127] == (mcman_calcEDC(mcman_PS1PDApagebuf, 127) & 0xff)) {
2503 mcdi->bad_block_list[i] = *((u32 *)mcman_PS1PDApagebuf);
2507 r = mcman_cachePS1dirs(port, slot);
2509 if (r != sceMcResSucceed)
2510 return r;
2512 mcdi->cardform = 1;
2514 return sceMcResSucceed;
2517 //--------------------------------------------------------------
2518 int mcman_getPS1direntry(int port, int slot, char *filename, McFsEntryPS1 **pfse, int flag)
2520 register int r, i;
2521 char *p = filename;
2523 #ifdef DEBUG
2524 DPRINTF("mcman: mcman_getPS1direntry port%d slot%d file %s flag %x\n", port, slot, filename, flag);
2525 #endif
2527 if (*p == '/')
2528 p++;
2530 i = 0;
2531 do {
2532 r = mcman_readdirentryPS1(port, slot, i, pfse);
2533 if (r != sceMcResSucceed)
2534 return r;
2536 if (flag != 0) {
2537 if (pfse[0]->mode != 0x51)
2538 continue;
2540 else {
2541 if (pfse[0]->mode != 0xa1)
2542 continue;
2545 if (!strcmp(p, pfse[0]->name))
2546 return i;
2548 } while (++i < 15);
2550 return sceMcResNoEntry;
2553 //--------------------------------------------------------------
2554 int mcman_clearPS1direntry(int port, int slot, int cluster, int flags)
2556 register int r, i, temp;
2557 McFsEntryPS1 *fse;
2558 MC_FHANDLE *fh;
2559 McCacheEntry *mce;
2561 #ifdef DEBUG
2562 DPRINTF("mcman: mcman_clearPS1direntry port%d slot%d cluster %x flags %x\n", port, slot, cluster, flags);
2563 #endif
2565 r = mcman_readdirentryPS1(port, slot, cluster, &fse);
2566 if (r != sceMcResSucceed)
2567 return r;
2569 fh = (MC_FHANDLE *)&mcman_fdhandles[0];
2571 for (i = 0; i < MAX_FDHANDLES; i++) {
2572 if ((fh->status != 0) && (fh->port == port) && (fh->slot == slot)) {
2573 if (fh->freeclink == cluster)
2574 return sceMcResDeniedPermit;
2577 fh++;
2580 if (!flags) {
2581 if (fse->mode != 0x51)
2582 return sceMcResNoEntry;
2584 else {
2585 if (fse->mode != 0xa1)
2586 return sceMcResNoEntry;
2589 do {
2590 lbl0:
2591 mce = mcman_get1stcacheEntp();
2593 if (cluster + 1 < 0)
2594 temp = cluster + 8;
2595 else
2596 temp = cluster + 1;
2598 mce->wr_flag |= 1 << ((cluster + 1) - ((temp >> 3) << 3));
2600 if (flags == 0)
2601 temp = (fse->mode & 0xf) | 0xa0;
2602 else
2603 temp = (fse->mode & 0xf) | 0x50;
2605 fse->mode = temp;
2606 fse->edc = mcman_calcEDC((void *)fse, 127);
2608 if (fse->linked_block < 0) {
2609 //cluster = 0;
2610 goto lbl1;
2613 cluster = fse->linked_block;
2615 r = mcman_readdirentryPS1(port, slot, cluster, &fse);
2616 if (r != sceMcResSucceed)
2617 return r;
2619 if (flags == 0) {
2620 if ((fse->mode & 0xf0) != 0x50)
2621 break;
2622 goto lbl0;
2625 } while ((fse->mode & 0xf0) == 0xa0);
2627 r = mcman_flushmccache(port, slot);
2628 if (r != sceMcResSucceed)
2629 return r;
2631 return sceMcResNoEntry;
2633 lbl1:
2634 r = mcman_flushmccache(port, slot);
2635 if (r != sceMcResSucceed)
2636 return r;
2638 return sceMcResSucceed;
2641 //--------------------------------------------------------------
2642 int mcman_findfree1(int port, int slot, int reserve)
2644 register int r, i, free;
2645 McFsEntryPS1 *fse;
2647 #ifdef DEBUG
2648 DPRINTF("mcman: mcman_findfree1 port%d slot%d reserve %d\n", port, slot, reserve);
2649 #endif
2651 free = 0;
2652 i = 0;
2654 do {
2655 r = mcman_readdirentryPS1(port, slot, i, &fse);
2656 if (r != sceMcResSucceed)
2657 return -37;
2659 if ((fse->mode & 0xf0) == 0xa0) {
2660 if (reserve)
2661 return i;
2662 free++;
2664 } while (++i < 15);
2666 if (reserve)
2667 return sceMcResFullDevice;
2669 if (free)
2670 return free;
2672 return sceMcResFullDevice;
2675 //--------------------------------------------------------------
2676 int mcman_fatRseekPS1(int fd)
2678 register int r, rpos, numclust, clust;
2679 MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
2680 MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
2681 McFsEntryPS1 *fse;
2683 numclust = fh->position / mcdi->cluster_size;
2684 numclust--;
2685 clust = fh->freeclink;
2687 if (numclust > -1) {
2688 do {
2689 if (clust < 0)
2690 return sceMcResFullDevice;
2692 r = mcman_readdirentryPS1(fh->port, fh->slot, clust, &fse);
2693 if (r != sceMcResSucceed)
2694 return r;
2695 clust = fse->linked_block;
2697 } while (--numclust > -1);
2700 if (clust < 0)
2701 return sceMcResFullDevice;
2703 rpos = fh->position % mcdi->cluster_size;
2705 if (rpos < 0)
2706 rpos += 1023;
2708 return ((clust + 1) << 6) + ((rpos >> 10) * (1024 / mcdi->pagesize));
2711 //--------------------------------------------------------------
2712 int mcman_fatWseekPS1(int fd)
2714 register int r, numclust, clust;
2715 MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
2716 MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
2717 McFsEntryPS1 *fse;
2719 numclust = fh->position / mcdi->cluster_size;
2721 if (numclust > 0) {
2722 clust = fh->freeclink;
2723 do {
2724 r = mcman_readdirentryPS1(fh->port, fh->slot, clust, &fse);
2725 if (r != sceMcResSucceed)
2726 return r;
2728 clust = fse->linked_block;
2730 if (clust < 0) {
2731 r = mcman_FNC8ca4(fh->port, fh->slot, (MC_FHANDLE *)fh);
2732 if (r < 0)
2733 return r;
2734 clust = r;
2736 } while (--numclust);
2738 r = mcman_flushmccache(fh->port, fh->slot);
2740 return r;
2743 //--------------------------------------------------------------
2744 int mcman_FNC8ca4(int port, int slot, MC_FHANDLE *fh)
2746 register int r, i, j, mcfree, cluster_size, pages_per_FATclust;
2747 register int temp;
2748 MCDevInfo *mcdi = &mcman_devinfos[fh->port][fh->slot];
2749 McFsEntryPS1 *fse1, *fse2, *fse3;
2750 McCacheEntry *mce;
2751 u8 *pfsentry, *pfsee, *pfseend;
2753 #ifdef DEBUG
2754 DPRINTF("mcman: mcman_FNC8ca4 port%d slot%d\n", port, slot);
2755 #endif
2757 if (mcdi->cluster_size < 0)
2758 cluster_size = mcdi->cluster_size + 1023;
2759 else
2760 cluster_size = mcdi->cluster_size;
2762 cluster_size = cluster_size >> 10;
2764 pages_per_FATclust = 1024 / mcdi->pagesize;
2766 r = mcman_findfree1(port, slot, 1);
2767 if (r < 0)
2768 return r;
2770 i = fh->freeclink;
2771 mcfree = r;
2772 j = -1;
2774 if (i >= 0) {
2775 do {
2776 if (mcfree < i) {
2777 if (cluster_size > 0) {
2778 i = 0;
2780 do {
2781 mcman_freecluster(port, slot, ((mcfree * cluster_size) + i) * pages_per_FATclust);
2783 r = mcman_readclusterPS1(port, slot, ((i * cluster_size) + i) * pages_per_FATclust, &mce);
2784 if (r != sceMcResSucceed)
2785 return r;
2787 mce->wr_flag = -1;
2788 mce->cluster -= (i - mcfree) * cluster_size;
2790 } while (++i < cluster_size);
2793 r = mcman_readdirentryPS1(port, slot, i, &fse1);
2794 if (r != sceMcResSucceed)
2795 return r;
2797 r = mcman_readdirentryPS1(port, slot, mcfree, &fse2);
2798 if (r != sceMcResSucceed)
2799 return r;
2801 mce = mcman_get1stcacheEntp();
2803 if (mcfree + 1 < 0)
2804 temp = mcfree + 8;
2805 else
2806 temp = mcfree + 1;
2808 mce->wr_flag |= 1 << ((mcfree + 1) - ((temp >> 3) << 3));
2810 pfsentry = (u8 *)fse1;
2811 pfsee = (u8 *)fse2;
2812 pfseend = (u8 *)(pfsentry + sizeof(McFsEntryPS1));
2814 do {
2815 *((u32 *)pfsee ) = *((u32 *)pfsentry );
2816 *((u32 *)pfsee+1) = *((u32 *)pfsentry+1);
2817 *((u32 *)pfsee+2) = *((u32 *)pfsentry+2);
2818 *((u32 *)pfsee+3) = *((u32 *)pfsentry+3);
2819 pfsentry += 16;
2820 pfsee += 16;
2821 } while (pfsentry < pfseend);
2823 if (j >= 0) {
2824 r = mcman_readdirentryPS1(port, slot, j, &fse3);
2825 if (r != sceMcResSucceed)
2826 return r;
2828 mce = mcman_get1stcacheEntp();
2830 if ((j + 1) < 0)
2831 temp = j + 8;
2832 else
2833 temp = j + 1;
2835 mce->wr_flag |= 1 << ((j + 1) - ((temp >> 3) << 3));
2836 fse3->linked_block = mcfree;
2837 fse3->edc = mcman_calcEDC((void *)fse3, 127);
2839 else {
2840 fh->freeclink = mcfree;
2842 j = mcfree;
2843 mcfree = i;
2846 else {
2847 j = i;
2848 r = mcman_readdirentryPS1(port, slot, j, &fse1);
2849 if (r != sceMcResSucceed)
2850 return r;
2852 i = fse1->linked_block;
2853 } while (i >= 0);
2856 r = mcman_readdirentryPS1(port, slot, mcfree, &fse2);
2857 if (r != sceMcResSucceed)
2858 return r;
2860 mce = mcman_get1stcacheEntp();
2862 if (mcfree + 1 < 0)
2863 temp = mcfree + 8;
2864 else
2865 temp = mcfree + 1;
2867 mce->wr_flag |= 1 << ((mcfree + 1) - ((temp >> 3) << 3));
2869 mcman_wmemset((void *)fse2, sizeof(McFsEntryPS1), 0);
2871 fse2->mode = 0x53;
2872 fse2->linked_block = -1;
2873 fse2->edc = mcman_calcEDC((void *)fse2, 127);
2875 r = mcman_readdirentryPS1(port, slot, j, &fse3);
2876 if (r != sceMcResSucceed)
2877 return r;
2879 mce = mcman_get1stcacheEntp();
2881 if ((j + 1) < 0)
2882 temp = j + 8;
2883 else
2884 temp = j + 1;
2886 mce->wr_flag |= 1 << ((j + 1) - ((temp >> 3) << 3));
2888 if (fse3->mode == 0x53)
2889 fse3->mode = 0x52;
2891 fse3->linked_block = mcfree;
2892 fse3->edc = mcman_calcEDC((void *)fse3, 127);
2894 return mcfree;
2897 //--------------------------------------------------------------
2898 int mcman_PS1pagetest(int port, int slot, int page)
2900 register int r, i;
2902 for (i = 0; i < 32; i++)
2903 *((u32 *)&mcman_PS1PDApagebuf+i) = 0xffffffff;
2905 r = McWritePS1PDACard(port, slot, page, mcman_PS1PDApagebuf);
2906 if (r != sceMcResSucceed)
2907 return sceMcResDeniedPermit;
2909 r = McReadPS1PDACard(port, slot, page, mcman_PS1PDApagebuf);
2910 if (r != sceMcResSucceed)
2911 return sceMcResNotEmpty;
2913 for (i = 0; i < 32; i++) {
2914 if (*((u32 *)&mcman_PS1PDApagebuf + i) != 0xffffffff) {
2915 return 0;
2919 for (i = 0; i < 32; i++)
2920 *((u32 *)&mcman_PS1PDApagebuf + i) = 0;
2922 r = McWritePS1PDACard(port, slot, page, mcman_PS1PDApagebuf);
2923 if (r != sceMcResSucceed)
2924 return sceMcResDeniedPermit;
2926 r = McReadPS1PDACard(port, slot, page, mcman_PS1PDApagebuf);
2927 if (r != sceMcResSucceed)
2928 return sceMcResNotEmpty;
2930 for (i = 0; i < 32; i++) {
2931 if (*((u32 *)&mcman_PS1PDApagebuf + i) != 0) {
2932 return 0;
2936 return 1;
2939 //--------------------------------------------------------------
2940 int mcman_cachePS1dirs(int port, int slot)
2942 register int r, i, j, temp1, temp2, index, linked_block;
2943 McFsEntryPS1 *fs_t[15];
2944 McCacheEntry *mce[2];
2945 int cluster_t[15];
2947 #ifdef DEBUG
2948 DPRINTF("mcman: mcman_cachePS1dirs port%d slot%d\n", port, slot);
2949 #endif
2951 i = 0;
2952 do {
2953 r = mcman_readdirentryPS1(port, slot, i, &fs_t[i]);
2954 if (r != sceMcResSucceed)
2955 return r;
2957 fs_t[i]->field_38 = fs_t[i]->length; /// <-- Special fix for saves from a real PS1
2959 if (i == 0) {
2960 mce[0] = mcman_get1stcacheEntp();
2962 else {
2963 if (i == 7)
2964 mce[1] = mcman_get1stcacheEntp();
2966 } while (++i < 15);
2968 memset((void *)cluster_t, -1, sizeof(cluster_t));
2970 i = 0;
2971 do {
2972 temp1 = fs_t[i]->mode & 0xf0;
2974 if ((fs_t[i]->mode & 0xf) != 1)
2975 continue;
2977 cluster_t[i] = i;
2979 linked_block = fs_t[i]->linked_block;
2980 if (linked_block >= 0) {
2981 do {
2982 if ((fs_t[linked_block]->mode & 0xf0) != temp1)
2983 temp1 = 0;
2985 if (fs_t[linked_block]->mode == 0xa0)
2986 break;
2988 if (cluster_t[linked_block] != -1)
2989 break;
2991 cluster_t[linked_block] = i;
2992 linked_block = fs_t[linked_block]->linked_block;
2994 } while (linked_block >= 0);
2996 if ((linked_block < 0) && (temp1 != 0))
2997 continue;
2999 else {
3000 if (temp1 != 0)
3001 continue;
3004 j = 0;
3005 do {
3006 if (cluster_t[j] != i)
3007 continue;
3009 memset((void *)fs_t[j], 0, sizeof (McFsEntryPS1));
3011 fs_t[j]->mode = 0xa0;
3012 fs_t[j]->linked_block = -1;
3013 fs_t[j]->edc = mcman_calcEDC((void *)fs_t[j], 127);
3015 temp2 = j + 1;
3017 if (j < 7)
3018 index = 0;
3019 else
3020 index = 1;
3022 if (temp2 < 0)
3023 temp1 = j + 8;
3024 else
3025 temp1 = temp2;
3027 mce[index]->wr_flag |= (1 << (temp2 - ((temp1 >> 3) << 3)));
3029 } while (++j < 15);
3031 } while (++i < 15);
3033 i = 0;
3034 do {
3035 if ((cluster_t[i] != -1) || (fs_t[i]->mode == 0xa0))
3036 continue;
3038 memset((void *)fs_t[i], 0, sizeof (McFsEntryPS1));
3040 fs_t[i]->mode = 0xa0;
3041 fs_t[i]->linked_block = cluster_t[i];
3042 fs_t[i]->edc = mcman_calcEDC((void *)fs_t[i], 127);
3044 temp2 = i + 1;
3046 if (i < 7)
3047 index = 0;
3048 else
3049 index = 1;
3051 if (temp2 < 0)
3052 temp1 = i + 8;
3053 else
3054 temp1 = temp2;
3056 mce[index]->wr_flag |= (1 << (temp2 - ((temp1 >> 3) << 3)));
3058 } while (++i < 15);
3060 return sceMcResSucceed;
3063 //--------------------------------------------------------------
3064 int mcman_fillPS1backuparea(int port, int slot, int block)
3066 register int r, i, curpage;
3067 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3069 memset(mcman_PS1PDApagebuf, 0, 128);
3071 curpage = 16;
3072 i = 0;
3073 do {
3074 if (mcdi->bad_block_list[i] == block) {
3075 mcdi->bad_block_list[i] = block | 0x01000000;
3076 *((u32 *)&mcman_PS1PDApagebuf) = block | 0x01000000;
3077 mcman_PS1PDApagebuf[127] = mcman_calcEDC(mcman_PS1PDApagebuf, 127);
3078 r = McWritePS1PDACard(port, slot, curpage, mcman_PS1PDApagebuf);
3079 if (r != sceMcResSucceed)
3080 return -43;
3082 else {
3083 if (mcdi->bad_block_list[i] < 0) {
3084 *((u32 *)&mcman_PS1PDApagebuf) = block;
3085 mcman_PS1PDApagebuf[127] = mcman_calcEDC(mcman_PS1PDApagebuf, 127);
3086 r = McWritePS1PDACard(port, slot, curpage, mcman_PS1PDApagebuf);
3087 if (r != sceMcResSucceed)
3088 return -43;
3089 mcdi->bad_block_list[i] = block;
3090 break;
3093 curpage++;
3094 } while (++i < 20);
3096 return sceMcResSucceed;
3099 //--------------------------------------------------------------
3100 void mcman_initcache(void)
3102 register int i, j;
3103 u8 *p;
3105 #ifdef DEBUG
3106 DPRINTF("mcman: mcman_initcache\n");
3107 #endif
3109 j = MAX_CACHEENTRY - 1;
3110 p = (u8 *)mcman_cachebuf;
3112 for (i = 0; i < MAX_CACHEENTRY; i++) {
3113 mcman_entrycache[i].cl_data = (u8 *)p;
3114 mcman_mccache[i] = (McCacheEntry *)&mcman_entrycache[j - i];
3115 mcman_entrycache[i].cluster = -1;
3116 p += MCMAN_CLUSTERSIZE;
3119 pmcman_entrycache = (McCacheEntry *)mcman_entrycache;
3120 pmcman_mccache = (McCacheEntry **)mcman_mccache;
3122 for (i = 0; i < MCMAN_MAXSLOT; i++) {
3123 mcman_devinfos[0][i].unknown3 = -1;
3124 mcman_devinfos[0][i].unknown4 = -1;
3125 mcman_devinfos[0][i].unknown5 = -1;
3126 mcman_devinfos[1][i].unknown3 = -1;
3127 mcman_devinfos[1][i].unknown4 = -1;
3128 mcman_devinfos[1][i].unknown5 = -1;
3131 memset((void *)mcman_fatcache, -1, sizeof (mcman_fatcache));
3133 for (i = 0; i < MCMAN_MAXSLOT; i++) {
3134 mcman_fatcache[0][i].entry[0] = 0;
3135 mcman_fatcache[1][i].entry[0] = 0;
3139 //--------------------------------------------------------------
3140 int McRetOnly(int fd) // Export #37
3142 #ifdef DEBUG
3143 DPRINTF("mcman: McRetOnly param %x\n", fd);
3144 #endif
3145 return sceMcResSucceed;
3148 //--------------------------------------------------------------
3149 int mcman_clearcache(int port, int slot)
3151 register int i, j;
3152 McCacheEntry **pmce = (McCacheEntry **)pmcman_mccache;
3153 McCacheEntry *mce, *mce_save;
3155 #ifdef DEBUG
3156 DPRINTF("mcman: mcman_clearcache port%d, slot%d\n", port, slot);
3157 #endif
3159 for (i = MAX_CACHEENTRY - 1; i >= 0; i--) {
3160 mce = (McCacheEntry *)pmce[i];
3161 if ((mce->mc_port == port) && (mce->mc_slot == slot) && (mce->cluster >= 0)) {
3162 mce->mc_port = -1;
3163 mce->mc_slot = -1;
3164 mce->wr_flag = 0;
3165 mce->cluster = -1;
3169 for (i = 0; i < (MAX_CACHEENTRY - 1); i++) {
3170 mce = (McCacheEntry *)pmce[i];
3171 mce_save = (McCacheEntry *)pmce[i];
3172 if (mce->cluster < 0) {
3173 for (j = i+1; j < MAX_CACHEENTRY; j++) {
3174 mce = (McCacheEntry *)pmce[j];
3175 if (mce->cluster >= 0)
3176 break;
3178 if (j == MAX_CACHEENTRY)
3179 break;
3181 pmce[i] = (McCacheEntry *)pmce[j];
3182 pmce[j] = (McCacheEntry *)mce_save;
3186 memset((void *)&mcman_fatcache[port][slot], -1, sizeof (McFatCache));
3188 mcman_fatcache[port][slot].entry[0] = 0;
3190 return sceMcResSucceed;
3193 //--------------------------------------------------------------
3194 McCacheEntry *mcman_getcacheentry(int port, int slot, int cluster)
3196 register int i;
3197 McCacheEntry *mce = (McCacheEntry *)pmcman_entrycache;
3199 //DPRINTF("mcman: mcman_getcacheentry port%d slot%d cluster %x\n", port, slot, cluster);
3201 for (i = 0; i < MAX_CACHEENTRY; i++) {
3202 if ((mce->mc_port == port) && (mce->mc_slot == slot) && (mce->cluster == cluster))
3203 return mce;
3204 mce++;
3207 return NULL;
3210 //--------------------------------------------------------------
3211 void mcman_freecluster(int port, int slot, int cluster) // release cluster from entrycache
3213 register int i;
3214 McCacheEntry *mce = (McCacheEntry *)pmcman_entrycache;
3216 for (i = 0; i < MAX_CACHEENTRY; i++) {
3217 if ((mce->mc_port == port) && (mce->mc_slot == slot) && (mce->cluster == cluster)) {
3218 mce->cluster = -1;
3219 mce->wr_flag = 0;
3221 mce++;
3225 //--------------------------------------------------------------
3226 int mcman_getFATindex(int port, int slot, int num)
3228 return mcman_fatcache[port][slot].entry[num];
3231 //--------------------------------------------------------------
3232 void mcman_1stcacheEntsetwrflagoff(void)
3234 McCacheEntry *mce = (McCacheEntry *)*pmcman_mccache;
3236 mce->wr_flag = -1;
3239 //--------------------------------------------------------------
3240 McCacheEntry *mcman_get1stcacheEntp(void)
3242 return *pmcman_mccache;
3245 //--------------------------------------------------------------
3246 void mcman_addcacheentry(McCacheEntry *mce)
3248 register int i;
3249 McCacheEntry **pmce = (McCacheEntry **)pmcman_mccache;
3251 i = MAX_CACHEENTRY - 1;
3253 if (i < 0)
3254 goto lbl1;
3256 do {
3257 if (pmce[i] == mce)
3258 break;
3259 } while (--i >= 0);
3261 if (i != 0) {
3262 lbl1:
3263 do {
3264 pmce[i] = pmce[i-1];
3265 } while (--i != 0);
3268 pmce[0] = (McCacheEntry *)mce;
3271 //--------------------------------------------------------------
3272 int mcman_flushmccache(int port, int slot)
3274 register int i, r;
3275 McCacheEntry **pmce = (McCacheEntry **)pmcman_mccache;
3276 McCacheEntry *mce;
3278 #ifdef DEBUG
3279 DPRINTF("mcman: mcman_flushmccache port%d slot%d\n", port, slot);
3280 #endif
3282 i = MAX_CACHEENTRY - 1;
3284 if (i >= 0) {
3285 do {
3286 mce = (McCacheEntry *)pmce[i];
3287 if ((mce->mc_port == port) && (mce->mc_slot == slot) && (mce->wr_flag != 0)) {
3288 r = mcman_flushcacheentry((McCacheEntry *)mce);
3289 if (r != sceMcResSucceed)
3290 return r;
3292 i--;
3293 } while (i >= 0);
3296 return sceMcResSucceed;
3299 //--------------------------------------------------------------
3300 int mcman_flushcacheentry(McCacheEntry *mce)
3302 register int r, i, j, ecc_count;
3303 register int temp1, temp2, offset, pageindex;
3304 static int clusters_per_block, blocksize, cardtype, pagesize, sparesize, flag, cluster, block, pages_per_fatclust;
3305 McCacheEntry *pmce[16]; // sp18
3306 register MCDevInfo *mcdi;
3307 McCacheEntry *mcee;
3308 static u8 eccbuf[32];
3309 void *p_page, *p_ecc;
3311 #ifdef DEBUG
3312 DPRINTF("mcman: mcman_flushcacheentry mce %x cluster %x\n", (int)mce, (int)mce->cluster);
3313 #endif
3315 if (mce->wr_flag == 0)
3316 return sceMcResSucceed;
3318 mcdi = (MCDevInfo *)&mcman_devinfos[mce->mc_port][mce->mc_slot];
3320 //mcdi->pagesize = sp84
3321 pagesize = mcdi->pagesize; //sp84
3322 cardtype = mcdi->cardtype;
3324 if (cardtype == 0) {
3325 mce->wr_flag = 0;
3326 return sceMcResSucceed;
3329 if ((cardtype == sceMcTypePS1) || (cardtype == sceMcTypePDA)) {
3330 pages_per_fatclust = MCMAN_CLUSTERSIZE / pagesize;
3331 i = mce->cluster; //s0
3332 j = 0; //s1
3333 r = 0;
3335 if (pages_per_fatclust > 0) {
3336 lbl0:
3338 do {
3339 if (((mce->wr_flag >> j) & 1) != 0) {
3340 //DPRINTF("flushing ent %x cl_data %x to page %d offset %d\n", mce, mce->cl_data, i, (pagesize * j));
3341 r = McWritePS1PDACard(mce->mc_port, mce->mc_slot, i, (void *)(mce->cl_data + (pagesize * j)));
3342 if (r == sceMcResFailReplace)
3343 break;
3344 if (r != sceMcResSucceed)
3345 return -50;
3348 i++;
3349 } while (++j < pages_per_fatclust);
3352 if (j == pages_per_fatclust) {
3353 r = mcman_probePS1Card2(mce->mc_port, mce->mc_slot);
3354 if (r == -14)
3355 r = sceMcResFailReplace;
3357 if (cardtype != sceMcTypePS1) {
3358 if (r == sceMcResFailReplace)
3359 return r;
3361 mce->wr_flag = 0;
3362 return sceMcResSucceed;
3364 if (r != 8) {
3365 mce->wr_flag = 0;
3366 return sceMcResSucceed;
3369 if ((mce->wr_flag & ~(-1 << j)) == 0) {
3370 mce->wr_flag = 0;
3371 return sceMcResSucceed;
3374 if (j-- == 0) {
3375 mce->wr_flag = 0;
3376 return sceMcResSucceed;
3379 i--;
3381 do {
3382 if (((mce->wr_flag >> j) & 1) != 0) {
3383 r = mcman_fillPS1backuparea(mce->mc_port, mce->mc_slot, i);
3384 if (r != sceMcResSucceed)
3385 return sceMcResFailReplace;
3387 goto lbl0;
3389 } while (j++);
3391 mce->wr_flag = 0;
3392 return sceMcResSucceed;
3395 clusters_per_block = mcdi->clusters_per_block; //sp7c
3396 block = mce->cluster / mcdi->clusters_per_block; //sp78
3397 blocksize = mcdi->blocksize; //sp80
3398 sparesize = mcman_sparesize(mce->mc_port, mce->mc_slot); //sp84
3399 flag = 0; //sp88
3401 memset((void *)pmce, 0, 64);
3403 i = 0; //s1
3404 if (MAX_CACHEENTRY > 0) {
3405 mcee = (McCacheEntry *)pmcman_entrycache;
3406 do {
3407 if ((*((u32 *)&mcee->mc_slot) & 0xff00ffff) == (*((u32 *)&mce->mc_slot) & 0xff00ffff)) {
3408 temp1 = mcee->cluster / clusters_per_block;
3409 temp2 = mcee->cluster % clusters_per_block;
3411 if (temp1 == block) {
3412 pmce[temp2] = (McCacheEntry *)mcee;
3413 if (mcee->rd_flag == 0)
3414 flag = 1;
3417 mcee++;
3418 } while (++i < MAX_CACHEENTRY);
3421 if (clusters_per_block > 0) {
3422 i = 0; //s1
3423 pageindex = 0; //s5
3424 cluster = block * clusters_per_block; // sp8c
3426 do {
3427 if (pmce[i] != 0) {
3428 j = 0; // s0
3429 offset = 0; //a0
3430 for (j = 0; j < mcdi->pages_per_cluster; j++) {
3431 mcman_pagedata[pageindex + j] = (void *)(pmce[i]->cl_data + offset);
3432 offset += pagesize;
3435 else {
3436 //s3 = s5
3437 // s2 = (cluster + i) * mcdi->pages_per_cluster
3438 j = 0; //s0
3439 do {
3440 offset = (pageindex + j) * pagesize; // t0
3441 mcman_pagedata[pageindex + j] = (void *)(mcman_backupbuf + offset);
3443 r = McReadPage(mce->mc_port, mce->mc_slot, \
3444 ((cluster + i) * mcdi->pages_per_cluster) + j, \
3445 mcman_backupbuf + offset);
3446 if (r != sceMcResSucceed)
3447 return -51;
3449 } while (++j < mcdi->pages_per_cluster);
3452 pageindex += mcdi->pages_per_cluster;
3453 } while (++i < clusters_per_block);
3456 lbl1:
3457 if ((flag != 0) && (mcman_badblock <= 0)) {
3458 r = mcman_eraseblock(mce->mc_port, mce->mc_slot, mcdi->backup_block1, (void**)mcman_pagedata, mcman_eccdata);
3459 if (r == sceMcResFailReplace) {
3460 lbl2:
3461 r = mcman_replaceBackupBlock(mce->mc_port, mce->mc_slot, mcdi->backup_block1);
3462 mcdi->backup_block1 = r;
3463 goto lbl1;
3465 if (r != sceMcResSucceed)
3466 return -52;
3468 *((u32 *)&mcman_pagebuf) = block | 0x80000000;
3469 p_page = (void *)mcman_pagebuf; //s0
3470 p_ecc = (void *)eccbuf; //s2 = sp58
3472 i = 0; //s1
3473 do {
3474 if (pagesize < 0)
3475 ecc_count = (pagesize + 0x7f) >> 7;
3476 else
3477 ecc_count = pagesize >> 7;
3479 if (i >= ecc_count)
3480 break;
3482 McDataChecksum(p_page, p_ecc);
3484 p_ecc += 3;
3485 p_page += 128;
3486 i++;
3487 } while (1);
3490 r = McWritePage(mce->mc_port, mce->mc_slot, mcdi->backup_block2 * blocksize, mcman_pagebuf, eccbuf);
3491 if (r == sceMcResFailReplace)
3492 goto lbl3;
3493 if (r != sceMcResSucceed)
3494 return -53;
3496 if (r < mcdi->blocksize) {
3497 i = 0; //s0
3498 p_ecc = (void *)mcman_eccdata;
3500 do {
3501 r = McWritePage(mce->mc_port, mce->mc_slot, (mcdi->backup_block1 * blocksize) + i, mcman_pagedata[i], p_ecc);
3502 if (r == sceMcResFailReplace)
3503 goto lbl2;
3504 if (r != sceMcResSucceed)
3505 return -54;
3506 p_ecc += sparesize;
3507 } while (++i < mcdi->blocksize);
3510 r = McWritePage(mce->mc_port, mce->mc_slot, (mcdi->backup_block2 * blocksize) + 1, mcman_pagebuf, eccbuf);
3511 if (r == sceMcResFailReplace)
3512 goto lbl3;
3513 if (r != sceMcResSucceed)
3514 return -55;
3517 r = mcman_eraseblock(mce->mc_port, mce->mc_slot, block, (void**)mcman_pagedata, mcman_eccdata);
3518 //if (block == 1) /////
3519 // r = sceMcResFailReplace; /////
3520 if (r == sceMcResFailReplace) {
3521 r = mcman_fillbackupblock1(mce->mc_port, mce->mc_slot, block, (void**)mcman_pagedata, mcman_eccdata);
3522 for (i = 0; i < clusters_per_block; i++) {
3523 if (pmce[i] != 0)
3524 pmce[i]->wr_flag = 0;
3526 if (r == sceMcResFailReplace)
3527 return r;
3528 return -58;
3530 if (r != sceMcResSucceed)
3531 return -57;
3533 if (mcdi->blocksize > 0) {
3534 i = 0; //s0
3535 p_ecc = (void *)mcman_eccdata;
3537 do {
3538 if (pmce[i / mcdi->pages_per_cluster] == 0) {
3539 r = McWritePage(mce->mc_port, mce->mc_slot, (block * blocksize) + i, mcman_pagedata[i], p_ecc);
3540 if (r == sceMcResFailReplace) {
3541 r = mcman_fillbackupblock1(mce->mc_port, mce->mc_slot, block, (void**)mcman_pagedata, mcman_eccdata);
3542 for (i = 0; i < clusters_per_block; i++) {
3543 if (pmce[i] != 0)
3544 pmce[i]->wr_flag = 0;
3546 if (r == sceMcResFailReplace)
3547 return r;
3548 return -58;
3550 if (r != sceMcResSucceed)
3551 return -57;
3553 p_ecc += sparesize;
3554 } while (++i < mcdi->blocksize);
3557 if (mcdi->blocksize > 0) {
3558 i = 0; //s0
3559 p_ecc = (void *)mcman_eccdata;
3561 do {
3562 if (pmce[i / mcdi->pages_per_cluster] != 0) {
3563 r = McWritePage(mce->mc_port, mce->mc_slot, (block * blocksize) + i, mcman_pagedata[i], p_ecc);
3564 if (r == sceMcResFailReplace) {
3565 r = mcman_fillbackupblock1(mce->mc_port, mce->mc_slot, block, (void**)mcman_pagedata, mcman_eccdata);
3566 for (i = 0; i < clusters_per_block; i++) {
3567 if (pmce[i] != 0)
3568 pmce[i]->wr_flag = 0;
3570 if (r == sceMcResFailReplace)
3571 return r;
3572 return -58;
3574 if (r != sceMcResSucceed)
3575 return -57;
3577 p_ecc += sparesize;
3578 } while (++i < mcdi->blocksize);
3581 if (clusters_per_block > 0) {
3582 i = 0;
3583 do {
3584 if (pmce[i] != 0)
3585 pmce[i]->wr_flag = 0;
3586 } while (++i < clusters_per_block);
3589 if ((flag != 0) && (mcman_badblock <= 0)) {
3590 r = mcman_eraseblock(mce->mc_port, mce->mc_slot, mcdi->backup_block2, NULL, NULL);
3591 if (r == sceMcResFailReplace) {
3592 goto lbl3;
3594 if (r != sceMcResSucceed)
3595 return -58;
3597 goto lbl_exit;
3599 lbl3:
3600 r = mcman_replaceBackupBlock(mce->mc_port, mce->mc_slot, mcdi->backup_block2);
3601 mcdi->backup_block2 = r;
3602 goto lbl1;
3604 lbl_exit:
3605 return sceMcResSucceed;
3608 //--------------------------------------------------------------
3609 int mcman_readcluster(int port, int slot, int cluster, McCacheEntry **pmce)
3611 register int r, i, block, block_offset;
3612 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3613 McCacheEntry *mce;
3615 if (mcman_badblock > 0) {
3616 block = cluster / mcdi->clusters_per_block;
3617 block_offset = cluster % mcdi->clusters_per_block;
3619 if ((block == mcman_badblock) && (mcman_badblock_port == port) && (mcman_badblock_slot == slot)) {
3620 cluster = (mcdi->backup_block1 * mcdi->clusters_per_block) + block_offset;
3622 else {
3623 if (mcman_badblock > 0) {
3624 for (i = 0; i < mcdi->clusters_per_block; i++) {
3625 if ((mcman_replacementcluster[i] != 0) && (mcman_replacementcluster[i] == cluster)) {
3626 block_offset = i % mcdi->clusters_per_block;
3627 cluster = (mcdi->backup_block1 * mcdi->clusters_per_block) + block_offset;
3634 mce = mcman_getcacheentry(port, slot, cluster);
3635 if (mce == NULL) {
3636 mce = pmcman_mccache[MAX_CACHEENTRY - 1];
3638 if (mce->wr_flag != 0) {
3639 r = mcman_flushcacheentry((McCacheEntry *)mce);
3640 if (r != sceMcResSucceed)
3641 return r;
3644 mce->mc_port = port;
3645 mce->mc_slot = slot;
3646 mce->cluster = cluster;
3647 mce->rd_flag = 0;
3648 //s3 = (cluster * mcdi->pages_per_cluster);
3650 for (i = 0; i < mcdi->pages_per_cluster; i++) {
3651 r = McReadPage(port, slot, (cluster * mcdi->pages_per_cluster) + i, \
3652 (void *)(mce->cl_data + (i * mcdi->pagesize)));
3653 if (r != sceMcResSucceed)
3654 return -21;
3658 mcman_addcacheentry(mce);
3659 *pmce = (McCacheEntry *)mce;
3661 return sceMcResSucceed;
3664 //--------------------------------------------------------------
3665 int mcman_readdirentry(int port, int slot, int cluster, int fsindex, McFsEntry **pfse) // Export #47 XMCMAN only
3667 register int r, i;
3668 static int maxent, index, clust;
3669 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3670 register McFatCache *fci = &mcman_fatcache[port][slot];
3671 McCacheEntry *mce;
3673 #ifdef DEBUG
3674 DPRINTF("mcman: mcman_readdirentry port%d slot%d cluster %d fsindex %d\n", port, slot, cluster, fsindex);
3675 #endif
3677 maxent = 0x402 / (mcdi->cluster_size >> 9); //a1
3678 index = fsindex / (mcdi->cluster_size >> 9);//s2
3680 clust = cluster;
3681 i = 0; // s0
3682 if ((cluster == 0) && (index != 0)) {
3683 if (index < maxent) {
3684 i = index;
3685 if ((fci->entry[index]) >= 0 )
3686 clust = fci->entry[index];
3688 i = 0;
3689 if (index > 0) {
3690 do {
3691 if (i >= maxent)
3692 break;
3693 if (fci->entry[i] < 0)
3694 break;
3695 clust = fci->entry[i];
3696 } while (++i < index);
3698 i--;
3701 if (i < index) {
3702 do {
3703 r = mcman_getFATentry(port, slot, clust, &clust);
3704 if (r != sceMcResSucceed)
3705 return -70;
3707 if (clust == 0xffffffff)
3708 return sceMcResNoEntry;
3709 clust &= 0x7fffffff;
3711 i++;
3712 if (cluster == 0) {
3713 if (i < maxent)
3714 fci->entry[i] = clust;
3716 } while (i < index);
3719 r = mcman_readcluster(port ,slot, mcdi->alloc_offset + clust, &mce);
3720 if (r != sceMcResSucceed)
3721 return -71;
3723 *pfse = (McFsEntry *)(mce->cl_data + ((fsindex % (mcdi->cluster_size >> 9)) << 9));
3725 return sceMcResSucceed;
3728 //--------------------------------------------------------------
3729 int mcman_readdirentryPS1(int port, int slot, int cluster, McFsEntryPS1 **pfse)
3731 register int r, offset, index, pages_per_fatclust;
3732 McCacheEntry *mce;
3733 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3735 if (cluster >= 15)
3736 return -73;
3738 pages_per_fatclust = MCMAN_CLUSTERSIZE / mcdi->pagesize;
3740 cluster++;
3741 index = cluster / pages_per_fatclust;
3742 offset = cluster % pages_per_fatclust;
3744 r = mcman_readclusterPS1(port, slot, index * pages_per_fatclust, &mce);
3745 if (r != sceMcResSucceed)
3746 return -74;
3748 *pfse = (void *)&mce->cl_data[offset << 7];
3750 if (sio2man_type == XSIO2MAN) {
3751 McFsEntryPS1 *fse = (McFsEntryPS1 *)*pfse; // <--- XMCMAN seems to work with this
3752 fse->field_7d = 0; //
3755 return sceMcResSucceed;
3758 //--------------------------------------------------------------
3759 int mcman_setFATentry(int port, int slot, int fat_index, int fat_entry) // Export #46 XMCMAN only
3761 register int r, ifc_index, indirect_index, indirect_offset, fat_offset;
3762 McCacheEntry *mce;
3763 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3765 //DPRINTF("mcman: mcman_setFATentry port%d slot%d fat_index %x fat_entry %x\n", port, slot, fat_index, fat_entry);
3767 indirect_index = fat_index / mcdi->FATentries_per_cluster;
3768 fat_offset = fat_index % mcdi->FATentries_per_cluster;
3770 ifc_index = indirect_index / mcdi->FATentries_per_cluster;
3771 indirect_offset = indirect_index % mcdi->FATentries_per_cluster;
3773 r = mcman_readcluster(port, slot, mcdi->ifc_list[ifc_index], &mce);
3774 if (r != sceMcResSucceed)
3775 return -75;
3777 McFatCluster *fc = (McFatCluster *)mce->cl_data;
3779 r = mcman_readcluster(port, slot, fc->entry[indirect_offset], &mce);
3780 if (r != sceMcResSucceed)
3781 return -76;
3783 fc = (McFatCluster *)mce->cl_data;
3785 fc->entry[fat_offset] = fat_entry;
3786 mce->wr_flag = 1;
3788 return sceMcResSucceed;
3791 //--------------------------------------------------------------
3792 int mcman_getFATentry(int port, int slot, int fat_index, int *fat_entry) // Export #44 XMCMAN only
3794 register int r, ifc_index, indirect_index, indirect_offset, fat_offset;
3795 McCacheEntry *mce;
3796 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3798 indirect_index = fat_index / mcdi->FATentries_per_cluster;
3799 fat_offset = fat_index % mcdi->FATentries_per_cluster;
3801 ifc_index = indirect_index / mcdi->FATentries_per_cluster;
3802 indirect_offset = indirect_index % mcdi->FATentries_per_cluster;
3804 r = mcman_readcluster(port, slot, mcdi->ifc_list[ifc_index], &mce);
3805 if (r != sceMcResSucceed)
3806 return -78;
3808 McFatCluster *fc = (McFatCluster *)mce->cl_data;
3810 r = mcman_readcluster(port, slot, fc->entry[indirect_offset], &mce);
3811 if (r != sceMcResSucceed)
3812 return -79;
3814 fc = (McFatCluster *)mce->cl_data;
3816 *fat_entry = fc->entry[fat_offset];
3818 return sceMcResSucceed;
3821 //--------------------------------------------------------------
3822 int mcman_readclusterPS1(int port, int slot, int cluster, McCacheEntry **pmce)
3824 register int r, i, pages_per_fatclust;
3825 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3826 McCacheEntry *mce;
3828 mce = mcman_getcacheentry(port, slot, cluster);
3829 if (mce == NULL) {
3830 mce = pmcman_mccache[MAX_CACHEENTRY - 1];
3832 if (mce->wr_flag != 0) {
3833 r = mcman_flushcacheentry((McCacheEntry *)mce);
3834 if (r != sceMcResSucceed)
3835 return r;
3838 mce->mc_port = port;
3839 mce->mc_slot = slot;
3840 mce->cluster = cluster;
3842 pages_per_fatclust = MCMAN_CLUSTERSIZE / mcdi->pagesize;
3844 for (i = 0; i < pages_per_fatclust; i++) {
3845 r = McReadPS1PDACard(port, slot, cluster + i, (void *)(mce->cl_data + (i * mcdi->pagesize)));
3846 if (r != sceMcResSucceed)
3847 return -21;
3851 mcman_addcacheentry(mce);
3852 *pmce = (McCacheEntry *)mce;
3854 return sceMcResSucceed;
3857 //--------------------------------------------------------------
3858 int mcman_replaceBackupBlock(int port, int slot, int block)
3860 register int i;
3861 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3863 if (mcman_badblock > 0)
3864 return sceMcResFailReplace;
3866 for (i = 0; i < 16; i++) {
3867 if (mcdi->bad_block_list[i] == -1)
3868 break;
3871 if (i < 16) {
3872 if ((mcdi->alloc_end - mcdi->max_allocatable_clusters) < 8)
3873 return sceMcResFullDevice;
3875 mcdi->alloc_end -= 8;
3876 mcdi->bad_block_list[i] = block;
3877 mcman_badblock_port = port;
3878 mcman_badblock_slot = slot;
3879 mcman_badblock = -1;
3881 return (mcdi->alloc_offset + mcdi->alloc_end) / mcdi->clusters_per_block;
3884 return sceMcResFullDevice;
3887 //--------------------------------------------------------------
3888 int mcman_fillbackupblock1(int port, int slot, int block, void **pagedata, void *eccdata)
3890 register int r, i, sparesize, page_offset;
3891 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
3892 register u8 *p_ecc;
3894 #ifdef DEBUG
3895 DPRINTF("mcman: mcman_fillbackupblock1 port%d slot%d block %x mcman_badblock %x\n", port, slot, block, mcman_badblock);
3896 #endif
3898 sparesize = mcman_sparesize(port, slot);
3900 if (mcman_badblock != 0) {
3901 if ((mcman_badblock != block) || (mcman_badblock_port != port) || (mcman_badblock_slot != slot))
3902 return sceMcResFailReplace;
3905 if ((mcdi->alloc_offset / mcdi->clusters_per_block) == block) // Appparently this refuse to take care of a bad rootdir cluster
3906 return sceMcResFailReplace;
3908 r = mcman_eraseblock(port, slot, mcdi->backup_block2, NULL, NULL);
3909 if (r != sceMcResSucceed)
3910 return r;
3912 r = mcman_eraseblock(port, slot, mcdi->backup_block1, NULL, NULL);
3913 if (r != sceMcResSucceed)
3914 return r;
3916 for (i = 0; i < 16; i++) {
3917 if (mcdi->bad_block_list[i] == -1)
3918 break;
3921 if (i >= 16)
3922 return sceMcResFailReplace;
3924 page_offset = mcdi->backup_block1 * mcdi->blocksize;
3925 p_ecc = (u8 *)eccdata;
3927 for (i = 0; i < mcdi->blocksize; i++) {
3928 r = McWritePage(port, slot, page_offset + i, pagedata[i], p_ecc);
3929 if (r != sceMcResSucceed)
3930 return r;
3931 p_ecc += sparesize;
3934 mcman_badblock_port = port;
3935 mcman_badblock_slot = slot;
3936 mcman_badblock = block;
3938 i = 15;
3939 do {
3940 mcman_replacementcluster[i] = 0;
3941 } while (--i >= 0);
3943 return sceMcResSucceed;
3946 //--------------------------------------------------------------
3947 int mcman_replacebadblock(void)
3949 register int r, i, curentry, clust, index, offset, numifc, fat_length, temp, length;
3950 register int value, value2, cluster, index2, offset2, s3;
3951 register MCDevInfo *mcdi = &mcman_devinfos[mcman_badblock_port][mcman_badblock_slot];
3952 int fat_entry[16];
3953 int fat_entry2;
3954 McCacheEntry *mce;
3955 McFsEntry *fse;
3957 #ifdef DEBUG
3958 DPRINTF("mcman: mcman_replacebadblock mcman_badblock_port%d mcman_badblock_slot%d mcman_badblock %x\n", mcman_badblock_port, mcman_badblock_slot, mcman_badblock);
3959 #endif
3961 if (mcman_badblock == 0)
3962 return sceMcResSucceed;
3964 if (mcman_badblock >= 0) {
3965 mcman_flushmccache(mcman_badblock_port, mcman_badblock_slot);
3966 mcman_clearcache(mcman_badblock_port, mcman_badblock_slot);
3968 for (i = 0; i <16; i++) {
3969 if (mcdi->bad_block_list[i] == -1)
3970 break;
3972 if (i >= 16)
3973 goto lbl_e168;
3975 if (mcdi->alloc_end >= (mcdi->max_allocatable_clusters + 8)) {
3976 mcdi->max_allocatable_clusters += 8;
3977 mcdi->bad_block_list[i] = mcman_badblock;
3980 fat_length = (((mcdi->clusters_per_card << 2) - 1) / mcdi->cluster_size) + 1;
3981 numifc = (((fat_length << 2) - 1) / mcdi->cluster_size) + 1;
3983 if (numifc > 32) {
3984 numifc = 32;
3985 fat_length = mcdi->FATentries_per_cluster << 5;
3988 i = 0; //sp5c
3989 value = ~(-1 << mcdi->clusters_per_block);
3990 do {
3991 clust = (mcman_badblock * mcdi->clusters_per_block) + i;
3992 if (clust < mcdi->alloc_offset) {
3993 fat_entry[i] = 0;
3995 else {
3996 r = mcman_getFATentry(mcman_badblock_port, mcman_badblock_slot, clust - mcdi->alloc_offset, &fat_entry[i]);
3997 if (r != sceMcResSucceed)
3998 goto lbl_e168;
4000 if (((fat_entry[i] & 0x80000000) == 0) || ((fat_entry[i] < -1) && (fat_entry[i] >= -9)))
4001 value &= ~(1 << i);
4003 } while (++i < mcdi->clusters_per_block);
4005 if (mcdi->clusters_per_block > 0) {
4006 i = 0;
4007 do {
4008 if ((value & (1 << i)) != 0) {
4009 r = mcman_findfree2(mcman_badblock_port, mcman_badblock_slot, 1);
4010 if (r < 0) {
4011 mcman_replacementcluster[i] = r;
4012 goto lbl_e168;
4014 r += mcdi->alloc_offset;
4015 mcman_replacementcluster[i] = r;
4017 } while (++i < mcdi->clusters_per_block);
4020 if (mcdi->clusters_per_block > 0) {
4021 i = 0;
4022 do {
4023 if ((value & (1 << i)) != 0) {
4024 if (fat_entry[i] != 0) {
4025 index = ((fat_entry[i] & 0x7fffffff) + mcdi->alloc_offset) / mcdi->clusters_per_block;
4026 offset = ((fat_entry[i] & 0x7fffffff) + mcdi->alloc_offset) % mcdi->clusters_per_block;
4027 if (index == mcman_badblock) {
4028 fat_entry[i] = (mcman_replacementcluster[offset] - mcdi->alloc_offset) | 0x80000000;
4032 } while (++i < mcdi->clusters_per_block);
4035 if (mcdi->clusters_per_block > 0) {
4036 i = 0;
4037 do {
4038 if ((mcman_replacementcluster[i] != 0) && (fat_entry[i] != 0)) {
4039 r = mcman_setFATentry(mcman_badblock_port, mcman_badblock_slot, mcman_replacementcluster[i] + mcdi->alloc_offset, fat_entry[i]);
4040 if (r != sceMcResSucceed)
4041 goto lbl_e168;
4043 } while (++i < mcdi->clusters_per_block);
4046 for (i = 0; i < numifc; i++) {
4047 index = mcdi->ifc_list[i] / mcdi->clusters_per_block;
4048 offset = mcdi->ifc_list[i] % mcdi->clusters_per_block;
4050 if (index == mcman_badblock) {
4051 value &= ~(1 << offset);
4052 mcdi->ifc_list[i] = mcman_replacementcluster[i];
4056 if (value == 0)
4057 goto lbl_e030;
4059 for (i = 0; i < fat_length; i++) {
4060 index = i / mcdi->FATentries_per_cluster;
4061 offset = i % mcdi->FATentries_per_cluster;
4063 if (offset == 0) {
4064 r = mcman_readcluster(mcman_badblock_port, mcman_badblock_slot, mcdi->ifc_list[index], &mce);
4065 if (r != sceMcResSucceed)
4066 goto lbl_e168;
4068 offset = i % mcdi->FATentries_per_cluster;
4069 index2 = *((u32 *)&mce->cl_data[offset]) / mcdi->clusters_per_block;
4070 offset2 = *((u32 *)&mce->cl_data[offset]) % mcdi->clusters_per_block;
4072 if (index2 == mcman_badblock) {
4073 value &= ~(1 << offset2);
4074 *((u32 *)&mce->cl_data[offset]) = mcman_replacementcluster[offset2];
4075 mce->wr_flag = 1;
4079 mcman_flushmccache(mcman_badblock_port, mcman_badblock_slot);
4080 mcman_clearcache(mcman_badblock_port, mcman_badblock_slot);
4082 if (value == 0)
4083 goto lbl_e030;
4085 value2 = value;
4087 for (i = 0; i < mcdi->alloc_end; i++) {
4088 r = mcman_getFATentry(mcman_badblock_port, mcman_badblock_slot, i, &fat_entry2);
4089 if (r != sceMcResSucceed)
4090 goto lbl_e168;
4092 index = (u32)(((fat_entry2 & 0x7fffffff) + mcdi->alloc_offset) / mcdi->clusters_per_block);
4093 offset = (u32)(((fat_entry2 & 0x7fffffff) + mcdi->alloc_offset) % mcdi->clusters_per_block);
4095 if (index == mcman_badblock) {
4096 value &= ~(1 << offset);
4097 r = mcman_setFATentry(mcman_badblock_port, mcman_badblock_slot, i, (mcman_replacementcluster[offset] - mcdi->alloc_offset) | 0x80000000);
4098 if (r != sceMcResSucceed)
4099 goto lbl_e168;
4103 if (value2 != value)
4104 mcman_flushmccache(mcman_badblock_port, mcman_badblock_slot);
4106 r = mcman_readdirentry(mcman_badblock_port, mcman_badblock_slot, 0, 0, &fse);
4107 if (r != sceMcResSucceed)
4108 goto lbl_e168;
4110 curentry = 2;
4111 s3 = 0;
4112 length = fse->length;
4114 lbl_dd8c:
4115 if (curentry >= length)
4116 goto lbl_ded0;
4118 r = mcman_readdirentry(mcman_badblock_port, mcman_badblock_slot, s3, curentry, &fse);
4119 if (r != sceMcResSucceed)
4120 goto lbl_e168;
4122 cluster = fse->cluster;
4123 index = (fse->cluster + mcdi->alloc_offset) / mcdi->clusters_per_block;
4124 offset = (fse->cluster + mcdi->alloc_offset) % mcdi->clusters_per_block;
4126 temp = fse->length;
4128 if (index == mcman_badblock) {
4129 fse->cluster = mcman_replacementcluster[offset] - mcdi->alloc_offset;
4130 mcman_1stcacheEntsetwrflagoff();
4133 if ((fse->mode & sceMcFileAttrSubdir) == 0) {
4134 curentry++;
4135 goto lbl_dd8c;
4138 r = mcman_readdirentry(mcman_badblock_port, mcman_badblock_slot, cluster, 0, &fse);
4139 if (r != sceMcResSucceed)
4140 goto lbl_e168;
4142 if ((fse->mode & sceMcFileAttrSubdir) == 0) {
4143 curentry++;
4144 goto lbl_dd8c;
4147 if (fse->cluster != 0) {
4148 curentry++;
4149 goto lbl_dd8c;
4152 if (fse->dir_entry != curentry) {
4153 curentry++;
4154 goto lbl_dd8c;
4157 curentry++;
4159 if (strcmp(fse->name, "."))
4160 goto lbl_dd8c;
4162 s3 = cluster;
4163 curentry = 2;
4164 length = temp;
4165 goto lbl_dd8c;
4167 lbl_ded0:
4168 r = mcman_readdirentry(mcman_badblock_port, mcman_badblock_slot, s3, 1, &fse);
4169 if (r != sceMcResSucceed)
4170 goto lbl_e168;
4172 index = (fse->cluster + mcdi->alloc_offset) / mcdi->clusters_per_block;
4173 offset = (fse->cluster + mcdi->alloc_offset) % mcdi->clusters_per_block;
4175 if (index == mcman_badblock) {
4176 fse->cluster = mcman_replacementcluster[offset] - mcdi->alloc_offset;
4177 mcman_1stcacheEntsetwrflagoff();
4180 r = mcman_readdirentry(mcman_badblock_port, mcman_badblock_slot, fse->cluster, fse->dir_entry, &fse);
4181 if (r != sceMcResSucceed)
4182 goto lbl_e168;
4184 length = fse->length;
4186 r = mcman_readdirentry(mcman_badblock_port, mcman_badblock_slot, s3, 0, &fse);
4187 if (r != sceMcResSucceed)
4188 goto lbl_e168;
4190 s3 = fse->cluster;
4191 index = (fse->cluster + mcdi->alloc_offset) / mcdi->clusters_per_block;
4192 offset = (fse->cluster + mcdi->alloc_offset) % mcdi->clusters_per_block;
4193 curentry = fse->dir_entry + 1;
4195 if (index == mcman_badblock) {
4196 fse->cluster = mcman_replacementcluster[offset] - mcdi->alloc_offset;
4197 mcman_1stcacheEntsetwrflagoff();
4200 if (s3 != 0)
4201 goto lbl_dd8c;
4203 if (curentry != 1)
4204 goto lbl_dd8c;
4206 lbl_e030:
4207 if (mcdi->clusters_per_block > 0) {
4208 i = 0;
4209 do {
4210 clust = (mcman_badblock * mcdi->clusters_per_block) + i;
4211 if (clust >= mcdi->alloc_offset) {
4212 r = mcman_setFATentry(mcman_badblock_port, mcman_badblock_slot, clust - mcdi->alloc_offset, 0xfffffffd);
4213 if (r != sceMcResSucceed)
4214 goto lbl_e168;
4216 } while (++i < mcdi->clusters_per_block);
4219 mcman_flushmccache(mcman_badblock_port, mcman_badblock_slot);
4220 mcman_clearcache(mcman_badblock_port, mcman_badblock_slot);
4222 mcman_badblock = 0;
4224 if (mcdi->clusters_per_block > 0) {
4225 i = 0;
4226 do {
4227 if (mcman_replacementcluster[i] != 0) {
4228 r = mcman_readcluster(mcman_badblock_port, mcman_badblock_slot, (mcdi->backup_block1 * mcdi->clusters_per_block) + i, &mce);
4229 if (r != sceMcResSucceed)
4230 goto lbl_e168;
4232 mce->cluster = mcman_replacementcluster[i];
4233 mce->wr_flag = 1;
4235 } while (++i < mcdi->clusters_per_block);
4238 mcman_flushmccache(mcman_badblock_port, mcman_badblock_slot);
4240 else {
4241 mcman_badblock = 0;
4244 r = mcman_clearsuperblock(mcman_badblock_port, mcman_badblock_slot);
4245 return r;
4247 lbl_e168:
4248 mcman_badblock = 0;
4249 return sceMcResFailReplace;
4252 //--------------------------------------------------------------
4253 int mcman_clearsuperblock(int port, int slot)
4255 register int r, i, size, temp;
4256 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
4257 McCacheEntry *mce;
4259 // set superblock magic & version
4260 memset((void *)&mcdi->magic, 0, sizeof (mcdi->magic) + sizeof (mcdi->version));
4261 *((u32 *)&mcdi->magic ) = *((u32 *)&SUPERBLOCK_MAGIC );
4262 *((u32 *)&mcdi->magic + 1) = *((u32 *)&SUPERBLOCK_MAGIC + 1);
4263 *((u32 *)&mcdi->magic + 2) = *((u32 *)&SUPERBLOCK_MAGIC + 2);
4264 *((u32 *)&mcdi->magic + 3) = *((u32 *)&SUPERBLOCK_MAGIC + 3);
4265 *((u32 *)&mcdi->magic + 4) = *((u32 *)&SUPERBLOCK_MAGIC + 4);
4266 *((u32 *)&mcdi->magic + 5) = *((u32 *)&SUPERBLOCK_MAGIC + 5);
4267 *((u32 *)&mcdi->magic + 6) = *((u32 *)&SUPERBLOCK_MAGIC + 6);
4268 *((u8 *)&mcdi->magic + 28) = *((u8 *)&SUPERBLOCK_MAGIC + 28);
4270 strcat((char *)&mcdi->magic, SUPERBLOCK_VERSION);
4272 for (i = 0; (u32)(i < sizeof(MCDevInfo)); i += 1024) {
4273 temp = i;
4274 if (i < 0)
4275 temp = i + 1023;
4276 r = mcman_readcluster(port, slot, temp >> 10, &mce);
4277 if (r != sceMcResSucceed)
4278 return -48;
4279 mce->wr_flag = 1;
4280 size = 1024;
4281 temp = sizeof(MCDevInfo) - i;
4283 if (temp <= 1024)
4284 size = temp;
4286 memcpy((void *)mce->cl_data, (void *)mcdi, size);
4289 r = mcman_flushmccache(port, slot);
4291 return r;
4294 //--------------------------------------------------------------