mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-11 12:05:09 -05:00
140 lines
4.1 KiB
C
140 lines
4.1 KiB
C
|
#include "ultra64.h"
|
||
|
#include "global.h"
|
||
|
#include "ultra64/pfs.h"
|
||
|
|
||
|
s32 osPfsAllocateFile(OSPfs* pfs, u16 companyCode, u32 gameCode, u8* gameName, u8* extName, s32 fileSize, s32* fileNo) {
|
||
|
s32 startPage;
|
||
|
s32 decleared;
|
||
|
s32 prevPage;
|
||
|
s32 oldPrevPage = 0;
|
||
|
s32 ret = 0;
|
||
|
s32 fileSizeInPages;
|
||
|
__OSInode inode;
|
||
|
__OSInode backupInode;
|
||
|
__OSDir dir;
|
||
|
u8 bank;
|
||
|
u8 prevBank = 0;
|
||
|
s32 firsttime = 0;
|
||
|
s32 bytes;
|
||
|
__OSInodeUnit fpage;
|
||
|
|
||
|
if ((companyCode == 0) || (gameCode == 0)) {
|
||
|
return PFS_ERR_INVALID;
|
||
|
}
|
||
|
|
||
|
fileSizeInPages = (fileSize + PFS_PAGE_SIZE - 1) / PFS_PAGE_SIZE;
|
||
|
|
||
|
if (((ret = osPfsFindFile(pfs, companyCode, gameCode, gameName, extName, fileNo)) != 0) &&
|
||
|
(ret != PFS_ERR_INVALID)) {
|
||
|
return ret;
|
||
|
}
|
||
|
if (*fileNo != -1) {
|
||
|
return PFS_ERR_EXIST;
|
||
|
}
|
||
|
|
||
|
ret = osPfsFreeBlocks(pfs, &bytes);
|
||
|
if (fileSize > bytes) {
|
||
|
return PFS_DATA_FULL;
|
||
|
}
|
||
|
|
||
|
if (fileSizeInPages == 0) {
|
||
|
return (PFS_ERR_INVALID);
|
||
|
}
|
||
|
|
||
|
if (((ret = osPfsFindFile(pfs, 0, 0, 0, 0, fileNo)) != 0) && (ret != PFS_ERR_INVALID)) {
|
||
|
return ret;
|
||
|
}
|
||
|
if (*fileNo == -1) {
|
||
|
return PFS_DIR_FULL;
|
||
|
}
|
||
|
|
||
|
for (bank = PFS_ID_BANK_256K; bank < pfs->banks; bank++) {
|
||
|
if ((ret = __osPfsRWInode(pfs, &inode, PFS_READ, bank)) != 0) {
|
||
|
return ret;
|
||
|
}
|
||
|
ret = __osPfsDeclearPage(pfs, &inode, fileSizeInPages, &startPage, bank, &decleared, &prevPage);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
if (startPage != -1) { /* There is free space */
|
||
|
if (firsttime == 0) {
|
||
|
fpage.inode_t.page = (u8)startPage;
|
||
|
fpage.inode_t.bank = bank;
|
||
|
} else { /* Writing previous bank inode */
|
||
|
backupInode.inodePage[oldPrevPage].inode_t.bank = bank;
|
||
|
backupInode.inodePage[oldPrevPage].inode_t.page = (u8)startPage;
|
||
|
if ((ret = __osPfsRWInode(pfs, &backupInode, PFS_WRITE, prevBank)) != 0) {
|
||
|
return ret;
|
||
|
}
|
||
|
}
|
||
|
if (fileSizeInPages > decleared) {
|
||
|
bcopy(&inode, &backupInode, sizeof(__OSInode));
|
||
|
oldPrevPage = prevPage;
|
||
|
prevBank = bank;
|
||
|
fileSizeInPages -= decleared;
|
||
|
firsttime++;
|
||
|
} else {
|
||
|
fileSizeInPages = 0;
|
||
|
if ((ret = __osPfsRWInode(pfs, &inode, PFS_WRITE, bank)) != 0) {
|
||
|
return ret;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ((fileSizeInPages > 0) || (startPage == -1)) {
|
||
|
return PFS_ERR_INCONSISTENT;
|
||
|
}
|
||
|
|
||
|
dir.start_page = fpage;
|
||
|
dir.company_code = companyCode;
|
||
|
dir.game_code = gameCode;
|
||
|
dir.data_sum = 0;
|
||
|
|
||
|
bcopy(gameName, dir.game_name, PFS_FILE_NAME_LEN);
|
||
|
bcopy(extName, dir.ext_name, PFS_FILE_EXT_LEN);
|
||
|
|
||
|
return __osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + *fileNo, (u8*)&dir, 0);
|
||
|
}
|
||
|
|
||
|
s32 __osPfsDeclearPage(OSPfs* pfs, __OSInode* inode, s32 fileSizeInPages, s32* startPage, u8 bank, s32* decleared,
|
||
|
s32* finalPage) {
|
||
|
s32 j;
|
||
|
s32 spage, prevPage;
|
||
|
s32 ret = 0;
|
||
|
s32 offset = ((bank > PFS_ID_BANK_256K) ? 1 : pfs->inodeStartPage);
|
||
|
|
||
|
for (j = offset; j < PFS_INODE_SIZE_PER_PAGE; j++) {
|
||
|
if (inode->inodePage[j].ipage == PFS_PAGE_NOT_USED) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (j == PFS_INODE_SIZE_PER_PAGE) {
|
||
|
*startPage = -1;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
spage = j;
|
||
|
*decleared = 1;
|
||
|
prevPage = j;
|
||
|
j++;
|
||
|
while ((fileSizeInPages > *decleared) && (j < PFS_INODE_SIZE_PER_PAGE)) {
|
||
|
if (inode->inodePage[j].ipage == PFS_PAGE_NOT_USED) {
|
||
|
inode->inodePage[prevPage].inode_t.bank = (u8)bank;
|
||
|
inode->inodePage[prevPage].inode_t.page = (u8)j;
|
||
|
prevPage = j;
|
||
|
(*decleared)++;
|
||
|
}
|
||
|
j++;
|
||
|
}
|
||
|
|
||
|
*startPage = spage;
|
||
|
if ((j == (PFS_INODE_SIZE_PER_PAGE)) && (fileSizeInPages > *decleared)) {
|
||
|
*finalPage = prevPage;
|
||
|
} else {
|
||
|
inode->inodePage[prevPage].ipage = PFS_EOF;
|
||
|
*finalPage = 0;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|