summaryrefslogtreecommitdiff
path: root/src/libultra_code_O2/contpfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libultra_code_O2/contpfs.c')
-rw-r--r--src/libultra_code_O2/contpfs.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/src/libultra_code_O2/contpfs.c b/src/libultra_code_O2/contpfs.c
new file mode 100644
index 000000000..a9b2028ee
--- /dev/null
+++ b/src/libultra_code_O2/contpfs.c
@@ -0,0 +1,314 @@
+#include "ultra64.h"
+#include "global.h"
+
+extern __OSInode __osPfsInodeCache; // bss
+s32 __osPfsInodeCacheChannel = -1;
+u8 __osPfsInodeCacheBank = 250;
+
+u16 __osSumcalc(u8* ptr, s32 length) {
+ s32 i;
+ u32 sum = 0;
+ u8* temp;
+
+ temp = ptr;
+ for (i = 0; i < length; i++) {
+ sum += *temp++;
+ }
+ return sum & 0xFFFF;
+}
+
+s32 __osIdCheckSum(u16* ptr, u16* checkSum, u16* idSum) {
+
+ u16 data = 0;
+ u32 i;
+
+ *checkSum = *idSum = 0;
+ for (i = 0; i < ((sizeof(__OSPackId) - sizeof(u32)) / sizeof(u8)); i += 2) {
+ data = *((u16*)((u32)ptr + i));
+ *checkSum += data;
+ *idSum += ~data;
+ }
+ return 0;
+}
+
+s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) {
+ s32 ret = 0;
+ u8 temp[BLOCKSIZE];
+ u8 comp[BLOCKSIZE];
+ u8 mask = 0;
+ s32 i, j = 0;
+ u16 index[4];
+
+ newid->repaired = 0xFFFFFFFF;
+ newid->random = osGetCount();
+ newid->serialMid = badid->serialMid;
+ newid->serialLow = badid->serialLow;
+
+ if ((pfs->activebank != 0) && ((ret = __osPfsSelectBank(pfs, 0)) != 0)) {
+ return ret;
+ }
+
+ do {
+ if ((ret = __osPfsSelectBank(pfs, j)) != 0) {
+ return ret;
+ }
+
+ if ((ret = __osContRamRead(pfs->queue, pfs->channel, 0, temp)) != 0) {
+ return ret;
+ }
+ temp[0] = j | 0x80;
+ for (i = 1; i < BLOCKSIZE; i++) {
+ temp[i] = ~temp[i];
+ }
+
+ if ((ret = __osContRamWrite(pfs->queue, pfs->channel, 0, temp, 0)) != 0) {
+ return ret;
+ }
+ if ((ret = __osContRamRead(pfs->queue, pfs->channel, 0, comp)) != 0) {
+ return (ret);
+ }
+ for (i = 0; i < BLOCKSIZE; i++) {
+ if (comp[i] != temp[i]) {
+ break;
+ }
+ }
+ if (i != BLOCKSIZE) {
+ break;
+ }
+
+ if (j > 0) {
+ if ((ret = __osPfsSelectBank(pfs, 0)) != 0) {
+ return ret;
+ }
+ if ((ret = __osContRamRead(pfs->queue, pfs->channel, 0, temp)) != 0) {
+ return ret;
+ }
+ if (temp[0] != 0x80) {
+ break;
+ }
+ }
+
+ j++;
+ } while (j < PFS_MAX_BANKS);
+
+ if ((pfs->activebank != 0) && (ret = __osPfsSelectBank(pfs, 0)) != 0) {
+ return ret;
+ }
+
+ mask = (j > 0) ? 1 : 0;
+ newid->deviceid = (badid->deviceid & 0xFFFE) | mask;
+ newid->banks = j;
+ newid->version = badid->version;
+ __osIdCheckSum(newid, &newid->checksum, &newid->invertedChecksum);
+
+ index[0] = PFS_ID_0AREA;
+ index[1] = PFS_ID_1AREA;
+ index[2] = PFS_ID_2AREA;
+ index[3] = PFS_ID_3AREA;
+ for (i = 0; i < 4; i++) {
+ if ((ret = __osContRamWrite(pfs->queue, pfs->channel, index[i], newid, PFS_FORCE)) != 0) {
+ return ret;
+ }
+ }
+ if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, temp)) != 0) {
+ return ret;
+ }
+ for (i = 0; i < BLOCKSIZE; i++) {
+ if (temp[i] != *(u8*)((s32)newid + i)) {
+ return PFS_ERR_DEVICE;
+ }
+ }
+ return 0;
+}
+
+s32 __osCheckPackId(OSPfs* pfs, __OSPackId* temp) {
+
+ u16 index[4];
+ s32 ret = 0;
+ u16 sum;
+ u16 idSum;
+ s32 i;
+ s32 j;
+
+ if ((pfs->activebank != 0) && (ret = __osPfsSelectBank(pfs, 0)) != 0) {
+ return ret;
+ }
+
+ index[0] = PFS_ID_0AREA;
+ index[1] = PFS_ID_1AREA;
+ index[2] = PFS_ID_2AREA;
+ index[3] = PFS_ID_3AREA;
+ for (i = 1; i < 4; i++) {
+ if ((ret = __osContRamRead(pfs->queue, pfs->channel, index[i], temp)) != 0) {
+ return ret;
+ }
+ __osIdCheckSum(temp, &sum, &idSum);
+ if ((temp->checksum == sum) && (temp->invertedChecksum == idSum)) {
+ break;
+ }
+ }
+ if (i == 4) {
+ return PFS_ERR_ID_FATAL;
+ }
+
+ for (j = 0; j < 4; j++) {
+ if (j != i) {
+ if ((ret = __osContRamWrite(pfs->queue, pfs->channel, index[j], temp, PFS_FORCE)) != 0) {
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+s32 __osGetId(OSPfs* pfs) {
+ u16 sum;
+ u16 isum;
+ u8 temp[BLOCKSIZE];
+ __OSPackId* id;
+ __OSPackId newid;
+ s32 ret;
+
+ if (pfs->activebank != 0) {
+ if ((ret = __osPfsSelectBank(pfs, 0)) != 0) {
+ return ret;
+ }
+ }
+
+ if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, temp)) != 0) {
+ return ret;
+ }
+
+ __osIdCheckSum((u16*)temp, &sum, &isum);
+ id = (__OSPackId*)temp;
+ if ((id->checksum != sum) || (id->invertedChecksum != isum)) {
+ if ((ret = __osCheckPackId(pfs, id)) == PFS_ERR_ID_FATAL) {
+ ret = __osRepairPackId(pfs, id, &newid);
+ if (ret) {
+ return ret;
+ }
+ id = &newid;
+ } else if (ret != 0) {
+ return ret;
+ }
+ }
+
+ if ((id->deviceid & 0x01) == 0) {
+ ret = __osRepairPackId(pfs, id, &newid);
+ if (ret) {
+ return ret;
+ }
+ id = &newid;
+ if ((id->deviceid & 0x01) == 0) {
+ return PFS_ERR_DEVICE;
+ }
+ }
+
+ bcopy(id, pfs->id, BLOCKSIZE);
+
+ if (0) {}
+
+ pfs->version = id->version;
+
+ pfs->banks = id->banks;
+ pfs->inodeStartPage = 1 + DEF_DIR_PAGES + (2 * pfs->banks);
+ pfs->dir_size = DEF_DIR_PAGES * PFS_ONE_PAGE;
+ pfs->inode_table = 1 * PFS_ONE_PAGE;
+ pfs->minode_table = (1 + pfs->banks) * PFS_ONE_PAGE;
+ pfs->dir_table = pfs->minode_table + (pfs->banks * PFS_ONE_PAGE);
+
+ if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_LABEL_AREA, pfs->label)) != 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+s32 __osCheckId(OSPfs* pfs) {
+ u8 temp[BLOCKSIZE];
+ s32 ret;
+
+ if (pfs->activebank != 0) {
+ ret = __osPfsSelectBank(pfs, 0);
+ if (ret == PFS_ERR_NEW_PACK) {
+ ret = __osPfsSelectBank(pfs, 0);
+ }
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, temp)) != 0) {
+ if (ret != PFS_ERR_NEW_PACK) {
+ return ret;
+ }
+ if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, temp)) != 0) {
+ return ret;
+ }
+ }
+
+ if (bcmp(pfs->id, temp, BLOCKSIZE) != 0) {
+ return PFS_ERR_NEW_PACK;
+ }
+
+ return 0;
+}
+
+s32 __osPfsRWInode(OSPfs* pfs, __OSInode* inode, u8 flag, u8 bank) {
+ u8 sum;
+ s32 j;
+ s32 ret;
+ s32 offset;
+ u8* addr;
+
+ if (flag == PFS_READ && bank == __osPfsInodeCacheBank && (pfs->channel == __osPfsInodeCacheChannel)) {
+ bcopy(&__osPfsInodeCache, inode, sizeof(__OSInode));
+ return 0;
+ }
+
+ if ((pfs->activebank != 0) && (ret = __osPfsSelectBank(pfs, 0)) != 0) {
+ return ret;
+ }
+
+ offset = ((bank > 0) ? 1 : pfs->inodeStartPage);
+
+ if (flag == PFS_WRITE) {
+ inode->inodePage[0].inode_t.page =
+ __osSumcalc(inode->inodePage + offset, (PFS_INODE_SIZE_PER_PAGE - offset) * 2);
+ }
+
+ for (j = 0; j < PFS_ONE_PAGE; j++) {
+ addr = (u8*)(((u8*)inode) + (j * BLOCKSIZE));
+ if (flag == PFS_WRITE) {
+ ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->inode_table + (bank * PFS_ONE_PAGE) + j, addr, 0);
+ ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->minode_table + (bank * PFS_ONE_PAGE) + j, addr, 0);
+ } else {
+ ret = __osContRamRead(pfs->queue, pfs->channel, pfs->inode_table + (bank * PFS_ONE_PAGE) + j, addr);
+ }
+ if (ret) {
+ return ret;
+ }
+ }
+
+ if (flag == PFS_READ) {
+ sum = __osSumcalc((u8*)(inode->inodePage + offset), (PFS_INODE_SIZE_PER_PAGE - offset) * 2);
+ if (sum != inode->inodePage[0].inode_t.page) {
+ for (j = 0; j < PFS_ONE_PAGE; j++) {
+ addr = (u8*)(((u8*)inode) + (j * BLOCKSIZE));
+ ret = __osContRamRead(pfs->queue, pfs->channel, pfs->minode_table + (bank * PFS_ONE_PAGE) + j, addr);
+ }
+ sum = __osSumcalc(inode->inodePage + offset, (PFS_INODE_SIZE_PER_PAGE - offset) * 2);
+ if (sum != inode->inodePage[0].inode_t.page) {
+ return PFS_ERR_INCONSISTENT;
+ }
+ for (j = 0; j < PFS_ONE_PAGE; j++) {
+ addr = (u8*)(((u8*)inode) + (j * BLOCKSIZE));
+ ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->inode_table + (bank * PFS_ONE_PAGE) + j, addr, 0);
+ }
+ }
+ }
+ __osPfsInodeCacheBank = bank;
+ bcopy(inode, &__osPfsInodeCache, sizeof(__OSInode));
+ __osPfsInodeCacheChannel = pfs->channel;
+ return 0;
+}