#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; }