From 4c11579938d768ce51598268ccf2116721c06c95 Mon Sep 17 00:00:00 2001 From: Ryan Myers Date: Thu, 21 Oct 2021 09:01:37 -0400 Subject: [PATCH] Match contpfs from libreultra --- include/PR/pfs.h | 21 +-- lib/src/os/contpfs.c | 306 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 307 insertions(+), 20 deletions(-) diff --git a/include/PR/pfs.h b/include/PR/pfs.h index 68c16aba..4bf0b9ab 100644 --- a/include/PR/pfs.h +++ b/include/PR/pfs.h @@ -116,16 +116,17 @@ typedef struct { u8 game_name[PFS_FILE_NAME_LEN]; } __OSDir; -typedef struct { - u32 repaired; - u32 random; - u64 serialMid; - u64 serialLow; - u16 deviceid; - u8 banks; - u8 version; - u16 checksum; - u16 invertedChecksum; +typedef struct +{ + /* 0x0 */ u32 repaired; + /* 0x4 */ u32 random; + /* 0x8 */ u64 serial_mid; + /* 0x10 */ u64 serial_low; + /* 0x18 */ u16 deviceid; + /* 0x1A */ u8 banks; + /* 0x1B */ u8 version; + /* 0x1C */ u16 checksum; + /* 0x1E */ u16 inverted_checksum; } __OSPackId; typedef struct { diff --git a/lib/src/os/contpfs.c b/lib/src/os/contpfs.c index df2ee653..592e5ab8 100644 --- a/lib/src/os/contpfs.c +++ b/lib/src/os/contpfs.c @@ -1,15 +1,301 @@ /* The comment below is needed for this file to be picked up by generate_ld */ /* RAM_POS: 0x800D52EC */ - #include "macros.h" #include "libultra_internal.h" -#include "viint.h" +#include "controller.h" -GLOBAL_ASM("lib/asm/non_matchings/unknown_0D3020/__osSumcalc.s") -GLOBAL_ASM("lib/asm/non_matchings/unknown_0D3020/__osIdCheckSum.s") -GLOBAL_ASM("lib/asm/non_matchings/unknown_0D3020/__osRepairPackId.s") -GLOBAL_ASM("lib/asm/non_matchings/unknown_0D3020/__osCheckPackId.s") -GLOBAL_ASM("lib/asm/non_matchings/unknown_0D3020/__osGetId.s") -GLOBAL_ASM("lib/asm/non_matchings/unknown_0D3020/__osCheckId.s") -GLOBAL_ASM("lib/asm/non_matchings/unknown_0D3020/__osPfsRWInode.s") -GLOBAL_ASM("lib/asm/non_matchings/unknown_0D3020/__osPfsSelectBank.s") +u16 __osSumcalc(u8 *ptr, int length) +{ + int i; + u32 sum; + u8 *tmp; + + sum = 0; + tmp = ptr; + for (i = 0; i < length; i++) + { + sum += *tmp++; + sum &= 0xffff; + } + return sum; +} +s32 __osIdCheckSum(u16 *ptr, u16 *csum, u16 *icsum) +{ + u16 data; + u32 j; + data = 0; + *icsum = 0; + *csum = *icsum; + for (j = 0; j < 28; j += 2) + { + //feels like this should be a compiler optimization not manual.. + //but it doesn't match and I'm pretty sure this is just -O1 + data = *(u16 *)((u8 *)ptr + j); + //data = ptr[j] + *csum += data; + *icsum += ~data; + } + return 0; +} +s32 __osRepairPackId(OSPfs *pfs, __OSPackId *badid, __OSPackId *newid) +{ + + s32 ret; + u8 temp[32]; + u8 comp[32]; + u8 mask; + int i; + int j; + u16 index[4]; + + ret = 0; + mask = 0; + SET_ACTIVEBANK_TO_ZERO; + newid->repaired = -1; + newid->random = osGetCount(); + newid->serial_mid = badid->serial_mid; + newid->serial_low = badid->serial_low; + for (j = 0; j < PFS_MAX_BANKS;) + { + pfs->activebank = j; + ERRCK(__osPfsSelectBank(pfs)) + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, (u8*)&temp)); //TODO: fix magic number + temp[0] = j | 0x80; + for (i = 1; i < ARRLEN(temp); i++) + { + + temp[i] = ~temp[i]; + } + + ERRCK(__osContRamWrite(pfs->queue, pfs->channel, 0, (u8*)temp, FALSE)); //oddr 0, don't force + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, (u8*)&comp)); + + for (i = 0; i < ARRLEN(temp); i++) + { + if (comp[i] != temp[i]) + break; + } + if (i != ARRLEN(temp)) + break; + if (j > 0) + { + pfs->activebank = 0; + ERRCK(__osPfsSelectBank(pfs)); + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 0, (u8*)temp)); + if (temp[0] != 128) + break; //TODO: remove magic constant + } + j++; + } + pfs->activebank = 0; + ERRCK(__osPfsSelectBank(pfs)); + if (j > 0) + mask = 1; + else + mask = 0; + newid->deviceid = (badid->deviceid & (u16)~1) | mask; + newid->banks = j; + newid->version = badid->version; + __osIdCheckSum((u16*)newid, &newid->checksum, &newid->inverted_checksum); + index[0] = PFS_ID_0AREA; + index[1] = PFS_ID_1AREA; + index[2] = PFS_ID_2AREA; + index[3] = PFS_ID_3AREA; + for (i = 0; i < ARRLEN(index); i++) + { + ERRCK(__osContRamWrite(pfs->queue, pfs->channel, index[i], (u8*)newid, TRUE)); + } + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 1, (u8*)temp)); + for (i = 0; i < ARRLEN(temp); i++) + { + if (temp[i] != ((u8 *)newid)[i]) + return PFS_ERR_ID_FATAL; + } + return 0; +} + +s32 __osCheckPackId(OSPfs *pfs, __OSPackId *temp) +{ + u16 index[4]; + s32 ret; + u16 sum; + u16 isum; + int i; + int j; + + ret = 0; + SET_ACTIVEBANK_TO_ZERO; + index[0] = 1; + index[1] = 3; + index[2] = 4; + index[3] = 6; + for (i = 1; i < ARRLEN(index); i++) + { + ERRCK(__osContRamRead(pfs->queue, pfs->channel, index[i], (u8*)temp)); + __osIdCheckSum((u16 *)temp, &sum, &isum); + if (temp->checksum == sum && temp->inverted_checksum == isum) + break; + } + if (i == ARRLEN(index)) + return PFS_ERR_ID_FATAL; + + for (j = 0; j < ARRLEN(index); j++) + { + if (j != i) + { + ERRCK(__osContRamWrite(pfs->queue, pfs->channel, index[j], (u8*)temp, TRUE)); + } + } + return 0; +} + +s32 __osGetId(OSPfs *pfs) +{ + int k; + u16 sum; + u16 isum; + u8 temp[32]; + __OSPackId newid; + s32 ret; + __OSPackId *id; + + SET_ACTIVEBANK_TO_ZERO; + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 1, (u8*)temp)); + __osIdCheckSum((u16*)temp, &sum, &isum); + id = (__OSPackId*)temp; + if (id->checksum != sum || id->inverted_checksum != isum) + { + ret = __osCheckPackId(pfs, id); + if (ret == PFS_ERR_ID_FATAL) + { + ERRCK(__osRepairPackId(pfs, id, &newid)); + id = &newid; + } + else if (ret != 0) + { + return ret; + } + } + if ((id->deviceid & 1) == 0) //TODO: remove magic constant + { + ERRCK(__osRepairPackId(pfs, id, &newid)); + id = &newid; + if ((id->deviceid & 1) == 0) + return PFS_ERR_DEVICE; + } + for (k = 0; k < ARRLEN(pfs->id); k++) + { + pfs->id[k] = ((u8 *)id)[k]; + } + pfs->version = id->version; + pfs->banks = id->banks; + pfs->inode_start_page = pfs->banks * 2 + 3; //TODO: loads of magic constants.. + pfs->dir_size = 16; + pfs->inode_table = 8; + pfs->minode_table = pfs->banks * PFS_ONE_PAGE + 8; + pfs->dir_table = pfs->minode_table + pfs->banks * PFS_ONE_PAGE; + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 7, pfs->label)); + return 0; +} + +s32 __osCheckId(OSPfs *pfs) +{ + int k; + u8 temp[32]; + s32 ret; + + SET_ACTIVEBANK_TO_ZERO; + ret = __osContRamRead(pfs->queue, pfs->channel, 1, (u8*)temp); + if (ret != 0) + { + if (ret != 2) + return ret; + else + ERRCK(__osContRamRead(pfs->queue, pfs->channel, 1, (u8*)temp)); + } + + for (k = 0; k < ARRLEN(temp); k++) + { + if (pfs->id[k] != temp[k]) + return PFS_ERR_NEW_PACK; + } + + return 0; +} + +s32 __osPfsRWInode(OSPfs *pfs, __OSInode *inode, u8 flag, u8 bank) +{ + u8 sum; + int j; + s32 ret; + int offset; + u8 *addr; + + SET_ACTIVEBANK_TO_ZERO; + + if (bank > 0) + offset = 1; + else + offset = pfs->inode_start_page; + + if (flag == PFS_WRITE) + inode->inode_page[0].inode_t.page = __osSumcalc((u8*)&inode->inode_page[offset], (-offset) * 2 + 256); + + for (j = 0; j < 8; j++) + { + addr = ((u8 *)inode->inode_page + j * 32); //TODO: don't like this =/ //maybe &inode->inode_table[j*PFS_ONE_PAGE].ipage or something + if (flag == PFS_WRITE) + { + ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->inode_table + bank * 8 + j, addr, FALSE); + ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->minode_table + bank * 8 + j, addr, FALSE); + } + else + { + ret = __osContRamRead(pfs->queue, pfs->channel, pfs->inode_table + bank * 8 + j, addr); + } + if (ret != 0) + return ret; + } + if (flag == PFS_READ) + { + sum = __osSumcalc((u8*)&inode->inode_page[offset], (-offset) * 2 + 256); + if (sum != inode->inode_page[0].inode_t.page) + { + for (j = 0; j < PFS_ONE_PAGE; j++) + { + addr = ((u8 *)inode->inode_page + j * 32); + ret = __osContRamRead(pfs->queue, pfs->channel, pfs->minode_table + bank * PFS_ONE_PAGE + j, addr); + } + if (sum != inode->inode_page[0].inode_t.page) + return PFS_ERR_INCONSISTENT; + for (j = 0; j < PFS_ONE_PAGE; j++) + { + addr = ((u8 *)inode->inode_page + j * 32); + ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->inode_table + bank * PFS_ONE_PAGE + j, addr, FALSE); + } + } + else + { + for (j = 0; j < PFS_ONE_PAGE; j++) + { + addr = ((u8 *)inode->inode_page + j * 32); + ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->minode_table + bank * PFS_ONE_PAGE + j, addr, FALSE); + } + } + } + return 0; +} + +s32 __osPfsSelectBank(OSPfs *pfs) +{ + u8 temp[BLOCKSIZE]; + int i; + s32 ret; + ret = 0; + for (i = 0; i < ARRLEN(temp); i++) + { + temp[i] = pfs->activebank; + } + ret = __osContRamWrite(pfs->queue, pfs->channel, 1024, (u8*)temp, FALSE); + return ret; +}