#include "ultra64.h" #include "global.h" #include "ultra64/pfs.h" #define CHECK_IPAGE(p) \ (((p).ipage >= pfs->inodeStartPage) && ((p).inode_t.bank < pfs->banks) && ((p).inode_t.page >= 0x01) && \ ((p).inode_t.page < 0x80)) s32 osPfsChecker(OSPfs* pfs) { s32 j; s32 ret; __OSInodeUnit next; __OSInode checkedInode; __OSInode tempInode; __OSDir tempDir; __OSInodeUnit nextNodeInFile[16]; __OSInodeCache cache; s32 fixed = 0; u8 bank, prevBank = 254; s32 cc, cl; s32 offset; ret = __osCheckId(pfs); if (ret == PFS_ERR_NEW_PACK) { ret = __osGetId(pfs); } if (ret) { return ret; } if ((ret = func_80105788(pfs, &cache)) != 0) { return ret; } for (j = 0; j < pfs->dir_size; j++) { if ((ret = __osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tempDir)) != 0) { return ret; } if ((tempDir.company_code != 0) || (tempDir.game_code != 0)) { if ((tempDir.company_code == 0) || (tempDir.game_code == 0)) { cc = -1; } else { next = tempDir.start_page; cl = cc = 0; bank = 255; while (CHECK_IPAGE(next)) { if (bank != next.inode_t.bank) { bank = next.inode_t.bank; if (prevBank != bank) { ret = __osPfsRWInode(pfs, &tempInode, PFS_READ, bank); prevBank = bank; } if ((ret != 0) && (ret != PFS_ERR_INCONSISTENT)) { return ret; } } if ((cc = func_80105A60(pfs, next, &cache) - cl) != 0) { break; } cl = 1; next = tempInode.inodePage[next.inode_t.page]; } } if ((cc != 0) || (next.ipage != PFS_EOF)) { bzero(&tempDir, sizeof(__OSDir)); if (pfs->activebank != 0) { if ((ret = __osPfsSelectBank(pfs, 0)) != 0) { return ret; } } if ((ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tempDir, 0)) != 0) { return ret; } fixed++; } } } for (j = 0; j < pfs->dir_size; j++) { if ((ret = __osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tempDir)) != 0) { return ret; } if ((tempDir.company_code != 0) && (tempDir.game_code != 0) && (tempDir.start_page.ipage >= (u16)pfs->inodeStartPage)) { // cast required nextNodeInFile[j].ipage = tempDir.start_page.ipage; } else { nextNodeInFile[j].ipage = 0; } } for (bank = 0; bank < pfs->banks; bank++) { ret = __osPfsRWInode(pfs, &tempInode, PFS_READ, bank); if ((ret != 0) && (ret != PFS_ERR_INCONSISTENT)) { return (ret); } offset = ((bank > PFS_ID_BANK_256K) ? 1 : pfs->inodeStartPage); for (j = 0; j < offset; j++) { checkedInode.inodePage[j].ipage = tempInode.inodePage[j].ipage; } for (; j < PFS_INODE_SIZE_PER_PAGE; j++) { checkedInode.inodePage[j].ipage = PFS_PAGE_NOT_USED; } for (j = 0; j < pfs->dir_size; j++) { while (nextNodeInFile[j].inode_t.bank == bank && nextNodeInFile[j].ipage >= (u16)pfs->inodeStartPage) { // cast required u8 val; val = nextNodeInFile[j].inode_t.page; nextNodeInFile[j] = checkedInode.inodePage[val] = tempInode.inodePage[val]; } } if ((ret = __osPfsRWInode(pfs, &checkedInode, PFS_WRITE, bank)) != 0) { return ret; } } if (fixed != 0) { pfs->status |= PFS_CORRUPTED; } else { pfs->status &= ~PFS_CORRUPTED; } return 0; } // Original name: corrupted_init (probably needs better name) s32 func_80105788(OSPfs* pfs, __OSInodeCache* cache) { s32 i; s32 n; s32 offset; u8 bank; __OSInodeUnit tpage; __OSInode tempInode; s32 ret; for (i = 0; i < PFS_INODE_DIST_MAP; i++) { cache->map[i] = 0; } cache->bank = 255; for (bank = PFS_ID_BANK_256K; bank < pfs->banks; bank++) { offset = ((bank > PFS_ID_BANK_256K) ? 1 : pfs->inodeStartPage); ret = __osPfsRWInode(pfs, &tempInode, PFS_READ, bank); if ((ret != 0) && (ret != PFS_ERR_INCONSISTENT)) { return ret; } for (i = offset; i < PFS_INODE_SIZE_PER_PAGE; i++) { tpage = tempInode.inodePage[i]; if ((tpage.ipage >= pfs->inodeStartPage) && (tpage.inode_t.bank != bank)) { n = ((tpage.inode_t.page & 0x7F) / PFS_SECTOR_SIZE) + PFS_SECTOR_PER_BANK * (tpage.inode_t.bank % PFS_BANK_LAPPED_BY); cache->map[n] |= (1 << (bank % PFS_BANK_LAPPED_BY)); } } } return 0; } // original name: corrupted (probably needs a better name) s32 func_80105A60(OSPfs* pfs, __OSInodeUnit fpage, __OSInodeCache* cache) { s32 j; s32 n; s32 hit = 0; u8 bank; s32 offset; s32 ret = 0; n = (fpage.inode_t.page / PFS_SECTOR_SIZE) + PFS_SECTOR_PER_BANK * (fpage.inode_t.bank % PFS_BANK_LAPPED_BY); for (bank = PFS_ID_BANK_256K; bank < pfs->banks; bank++) { offset = ((bank > PFS_ID_BANK_256K) ? 1 : pfs->inodeStartPage); if ((bank == fpage.inode_t.bank) || (cache->map[n] & (1 << (bank % PFS_BANK_LAPPED_BY))) != 0) { if (bank != cache->bank) { ret = __osPfsRWInode(pfs, &(cache->inode), PFS_READ, bank); if (ret && (ret != PFS_ERR_INCONSISTENT)) { return ret; } cache->bank = bank; } for (j = offset; ((hit < 2) && (j < PFS_INODE_SIZE_PER_PAGE)); j++) { if (cache->inode.inodePage[j].ipage == fpage.ipage) { hit++; } } if (hit >= 2) { return 2; } } } return hit; }