#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; }