1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#include "ultra64.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;
}
|