summaryrefslogtreecommitdiff
path: root/src/libultra_code_O2/pfschecker.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libultra_code_O2/pfschecker.c')
-rw-r--r--src/libultra_code_O2/pfschecker.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/src/libultra_code_O2/pfschecker.c b/src/libultra_code_O2/pfschecker.c
new file mode 100644
index 000000000..e4934a17a
--- /dev/null
+++ b/src/libultra_code_O2/pfschecker.c
@@ -0,0 +1,203 @@
+#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, &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, &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, &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;
+}