Files
banjo-kazooie/src/core1/io/contpfs.c

303 lines
7.7 KiB
C

#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "controller.h"
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] = 1;
index[1] = 3;
index[2] = 4;
index[3] = 6;
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;
}