303 lines
7.7 KiB
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;
|
|
}
|