#include "libultra_internal.h" #include "controller.h" s32 corrupted_init(OSPfs *pfs, __OSInodeCache *cache); s32 corrupted(OSPfs *pfs, __OSInodeUnit fpage, __OSInodeCache *cache); s32 osPfsChecker(OSPfs *pfs) { int j; //1156 s32 ret; //1152 __OSInodeUnit next_page; __OSInode checked_inode; __OSInode tmp_inode; //636 __OSDir tmp_dir; __OSInodeUnit file_next_node[16]; __OSInodeCache cache; //56 int fixed; //52 u8 bank; //51 s32 cc; //44 s32 cl; //40 int offset; //36 fixed = 0; ret = __osCheckId(pfs); if (ret == PFS_ERR_NEW_PACK) ret = __osGetId(pfs); if (ret != 0) return ret; ERRCK(corrupted_init(pfs, &cache)); for (j = 0; j < pfs->dir_size; j++) { ERRCK(__osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tmp_dir)); if (tmp_dir.company_code != 0 && tmp_dir.game_code != 0) { next_page = tmp_dir.start_page; cc = 0; cl = 0; bank = 255; while (next_page.ipage >= pfs->inode_start_page && next_page.inode_t.bank < pfs->banks && next_page.inode_t.page > 0 && next_page.inode_t.page < 128) { if (bank != next_page.inode_t.bank) { bank = next_page.inode_t.bank; ret = __osPfsRWInode(pfs, &tmp_inode, OS_READ, bank); if (ret != 0 && ret != PFS_ERR_INCONSISTENT) return ret; } cc = corrupted(pfs, next_page, &cache) - cl; if (cc != 0) break; cl = 1; next_page = tmp_inode.inode_page[next_page.inode_t.page]; } if (cc == 0 && next_page.ipage == 1) continue; tmp_dir.company_code = 0; tmp_dir.game_code = 0; tmp_dir.start_page.ipage = 0; tmp_dir.status = DIR_STATUS_EMPTY; tmp_dir.data_sum = 0; SET_ACTIVEBANK_TO_ZERO; ERRCK(__osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tmp_dir, false)); fixed++; } else { if (tmp_dir.company_code == 0 && tmp_dir.game_code == 0) continue; tmp_dir.company_code = 0; tmp_dir.game_code = 0; tmp_dir.start_page.ipage = 0; tmp_dir.status = DIR_STATUS_EMPTY; tmp_dir.data_sum = 0; SET_ACTIVEBANK_TO_ZERO; ERRCK(__osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tmp_dir, false)); fixed++; } } for (j = 0; j < pfs->dir_size; j++) { ERRCK(__osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tmp_dir)); if (tmp_dir.company_code != 0 && tmp_dir.game_code != 0 && tmp_dir.start_page.ipage >= ((__OSInodeUnit *)&(pfs->inode_start_page) + 1)->ipage) //weird { file_next_node[j].ipage = tmp_dir.start_page.ipage; } else { file_next_node[j].ipage = 0; } } for (bank = 0; bank < pfs->banks; bank++) { ret = __osPfsRWInode(pfs, &tmp_inode, 0, bank); if (ret != 0 && ret != PFS_ERR_INCONSISTENT) return ret; if (bank > 0) { offset = 1; } else { offset = pfs->inode_start_page; } for (j = 0; j < offset; j++) { checked_inode.inode_page[j].ipage = tmp_inode.inode_page[j].ipage; } for (; j < 128; j++) { checked_inode.inode_page[j].ipage = 3; } for (j = 0; j < pfs->dir_size; j++) { while (file_next_node[j].inode_t.bank == bank && file_next_node[j].ipage >= ((__OSInodeUnit *)&(pfs->inode_start_page) + 1)->ipage) { u8 pp = file_next_node[j].inode_t.page; file_next_node[j] = checked_inode.inode_page[pp] = tmp_inode.inode_page[pp]; } } ERRCK(__osPfsRWInode(pfs, &checked_inode, OS_WRITE, bank)); } if (fixed) pfs->status |= PFS_CORRUPTED; else pfs->status &= ~PFS_CORRUPTED; return 0; } s32 corrupted_init(OSPfs *pfs, __OSInodeCache *cache) { int i; int n; int offset; u8 bank; __OSInodeUnit tpage; __OSInode tmp_inode; s32 ret; for (i = 0; i < ARRLEN(cache->map); i++) cache->map[i] = 0; cache->bank = -1; for (bank = 0; bank < pfs->banks; bank++) { if (bank > 0) offset = 1; else offset = pfs->inode_start_page; ret = __osPfsRWInode(pfs, &tmp_inode, OS_READ, bank); if (ret != 0 && ret != PFS_ERR_INCONSISTENT) return ret; for (i = offset; i < ARRLEN(tmp_inode.inode_page); i++) { tpage = tmp_inode.inode_page[i]; if (tpage.ipage >= pfs->inode_start_page && tpage.inode_t.bank != bank) { n = (tpage.inode_t.page / 4) + ((tpage.inode_t.bank % PFS_ONE_PAGE) * BLOCKSIZE); cache->map[n] |= 1 << (bank % PFS_ONE_PAGE); } } } return 0; } s32 corrupted(OSPfs *pfs, __OSInodeUnit fpage, __OSInodeCache *cache) { int j; int n; int hit; u8 bank; int offset; s32 ret; hit = 0; ret = 0; n = (fpage.inode_t.page / 4) + (fpage.inode_t.bank % 8) * BLOCKSIZE; for (bank = 0; bank < pfs->banks; bank++) { if (bank > 0) offset = 1; else offset = pfs->inode_start_page; if (bank == fpage.inode_t.bank || cache->map[n] & (1 << (bank % 8))) { if (bank != cache->bank) { ret = __osPfsRWInode(pfs, &cache->inode, 0, bank); if (ret != 0 && ret != PFS_ERR_INCONSISTENT) return ret; cache->bank = bank; } for (j = offset; hit < 2 && (j < ARRLEN(cache->inode.inode_page)); j++) { if (cache->inode.inode_page[j].ipage == fpage.ipage) hit++; } if (1 < hit) return PFS_ERR_NEW_PACK; } } return hit; }