aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-05-24 18:32:58 +0200
committerBad Diode <bd@badd10de.dev>2021-05-24 18:32:58 +0200
commitf4dd03dd800d7cf2d42169b6f30c10585c5a78c4 (patch)
treeb01cfad554fc82b9b2466b46a63b48eb44151c77
parent3410761714c70480c063112e5a184c93cae39bb3 (diff)
downloaduxngba-f4dd03dd800d7cf2d42169b6f30c10585c5a78c4.tar.gz
uxngba-f4dd03dd800d7cf2d42169b6f30c10585c5a78c4.zip
Update filesystem for writing with offset
-rw-r--r--src/filesystem.c138
1 files changed, 86 insertions, 52 deletions
diff --git a/src/filesystem.c b/src/filesystem.c
index 4a55818..cac2805 100644
--- a/src/filesystem.c
+++ b/src/filesystem.c
@@ -62,18 +62,20 @@ typedef struct FileSystem {
62 FileIndex files[FILE_INDEX_NUM]; 62 FileIndex files[FILE_INDEX_NUM];
63} FileSystem; 63} FileSystem;
64 64
65#define FILE_BLOCK_CAPACITY (FILE_BLOCK_SIZE - sizeof(FileBlock))
66
65EWRAM_BSS 67EWRAM_BSS
66static FileSystem filesystem; 68static FileSystem filesystem;
67 69
68void 70void
69_fs_read(u8 *dst, size_t pos, size_t n_bytes) { 71_fs_read(u8 *dst, u16 pos, u16 n_bytes) {
70 for (size_t i = 0; i < n_bytes; ++i) { 72 for (size_t i = 0; i < n_bytes; ++i) {
71 dst[i] = SRAM[pos + i]; 73 dst[i] = SRAM[pos + i];
72 } 74 }
73} 75}
74 76
75void 77void
76_fs_write(u8 *src, size_t pos, size_t n_bytes) { 78_fs_write(u8 *src, u16 pos, u16 n_bytes) {
77 for (size_t i = 0; i < n_bytes; ++i) { 79 for (size_t i = 0; i < n_bytes; ++i) {
78 SRAM[pos + i] = src[i]; 80 SRAM[pos + i] = src[i];
79 } 81 }
@@ -96,7 +98,7 @@ fs_init(void) {
96 .prev_block = FS_NULL, 98 .prev_block = FS_NULL,
97 }; 99 };
98 for (size_t i = 0; i < FILE_INDEX_NUM; ++i) { 100 for (size_t i = 0; i < FILE_INDEX_NUM; ++i) {
99 size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * i; 101 u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * i;
100 _fs_write(&block, block_pos, sizeof(FileBlock)); 102 _fs_write(&block, block_pos, sizeof(FileBlock));
101 } 103 }
102 104
@@ -112,12 +114,12 @@ fs_init(void) {
112 } 114 }
113} 115}
114 116
115void inline 117void
116_fs_update_filesystem_header(void) { 118_fs_update_filesystem_header(void) {
117 _fs_write(&filesystem, 0, offsetof(FileSystem, files)); 119 _fs_write(&filesystem, 0, offsetof(FileSystem, files));
118}; 120};
119 121
120void inline 122void
121_fs_update_file_index(u16 index) { 123_fs_update_file_index(u16 index) {
122 _fs_write(&filesystem.files[index], 124 _fs_write(&filesystem.files[index],
123 offsetof(FileSystem, files) + index * sizeof(FileIndex), 125 offsetof(FileSystem, files) + index * sizeof(FileIndex),
@@ -132,7 +134,7 @@ typedef enum {
132 134
133typedef struct File { 135typedef struct File {
134 u8 index; 136 u8 index;
135 u16 cur; 137 u16 offset;
136 OpenMode mode; 138 OpenMode mode;
137} File; 139} File;
138 140
@@ -152,8 +154,8 @@ fs_open_file(char *name, OpenMode mode) {
152 154
153 // Create a new file if there is space. 155 // Create a new file if there is space.
154 if (filesystem.num_files < FILE_INDEX_NUM) { 156 if (filesystem.num_files < FILE_INDEX_NUM) {
155 size_t index = filesystem.num_files++; 157 u16 index = filesystem.num_files++;
156 size_t k = 0; 158 u16 k = 0;
157 while(*name) { 159 while(*name) {
158 filesystem.files[index].name[k++] = *name++; 160 filesystem.files[index].name[k++] = *name++;
159 } 161 }
@@ -167,6 +169,20 @@ fs_open_file(char *name, OpenMode mode) {
167 return (File){FS_NULL, 0, mode}; 169 return (File){FS_NULL, 0, mode};
168} 170}
169 171
172u16
173fs_file_size(File *file) {
174 u16 size = 0;
175 FileBlock block;
176 u16 blk_id = filesystem.files[file->index].first_block;
177 while (blk_id != FS_NULL) {
178 u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id;
179 _fs_read(&block, block_pos, sizeof(FileBlock));
180 size += block.size;
181 blk_id = block.next_block;
182 }
183 return size;
184}
185
170u8 186u8
171_fs_init_new_block(void) { 187_fs_init_new_block(void) {
172 // Find free block. 188 // Find free block.
@@ -188,18 +204,18 @@ _fs_init_new_block(void) {
188 204
189#include "text.h" 205#include "text.h"
190 206
191// Recursively free blocks starting at block_id. To improve performance, the 207// Recursively free blocks starting at blk_id. To improve performance, the
192// filesystem header is updated in memory but not written to disk. It is 208// filesystem header is updated in memory but not written to disk. It is
193// responsability of the caller to perform the filesystem update. 209// responsability of the caller to perform the filesystem update.
194void 210void
195_fs_free_blocks(u8 block_id) { 211_fs_free_blocks(u8 blk_id) {
196 if (block_id == FS_NULL) { 212 if (blk_id == FS_NULL) {
197 return; 213 return;
198 } 214 }
199 215
200 // Read block. 216 // Read block.
201 FileBlock block; 217 FileBlock block;
202 size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; 218 u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id;
203 _fs_read(&block, block_pos, sizeof(FileBlock)); 219 _fs_read(&block, block_pos, sizeof(FileBlock));
204 220
205 // Update block. 221 // Update block.
@@ -213,34 +229,31 @@ _fs_free_blocks(u8 block_id) {
213 229
214 // Update dirty and busy blocks. 230 // Update dirty and busy blocks.
215 filesystem.busy_blocks--; 231 filesystem.busy_blocks--;
216 filesystem.used_blocks[block_id / 8] &= ~(1 << (block_id % 8)); 232 filesystem.used_blocks[blk_id / 8] &= ~(1 << (blk_id % 8));
217 233
218 _fs_free_blocks(next_block); 234 _fs_free_blocks(next_block);
219} 235}
220 236
221// Write to block as a new file. 237// Write to block as a new file.
222void 238void
223_fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { 239_fs_write_to_block(u8 *src, u16 n_bytes, u16 blk_offset, u8 blk_id, u8 prev_blk) {
224 // Read initial block. 240 // Read initial block.
225 FileBlock block; 241 FileBlock block;
226 size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; 242 u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id;
227 _fs_read(&block, block_pos, sizeof(FileBlock)); 243 _fs_read(&block, block_pos, sizeof(FileBlock));
228 u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)); 244 u16 block_capacity = FILE_BLOCK_CAPACITY - blk_offset;
229 245
230 // Write capacity. 246 // Write capacity.
231 u16 block_bytes = MIN(block_capacity, n_bytes); 247 u16 block_bytes = MIN(block_capacity, n_bytes);
232 _fs_write(src, block_pos + sizeof(FileBlock), block_bytes); 248 _fs_write(src, block_pos + sizeof(FileBlock) + blk_offset, block_bytes);
233 249
234 if (n_bytes > block_capacity) { 250 if (n_bytes > block_capacity) {
235 if (block.next_block == FS_NULL) { 251 if (block.next_block == FS_NULL) {
236 // Find new available block and initialize it. 252 // Find new available block and initialize it.
237 block.next_block = _fs_init_new_block(); 253 block.next_block = _fs_init_new_block();
238 } 254 }
239 _fs_write_to_block( 255 _fs_write_to_block(src + block_capacity, n_bytes - block_capacity, 0,
240 src + block_capacity, 256 block.next_block, blk_id);
241 n_bytes - block_capacity,
242 block.next_block,
243 block_id);
244 } else if (block.next_block != FS_NULL){ 257 } else if (block.next_block != FS_NULL){
245 // Recursively free unused blocks. 258 // Recursively free unused blocks.
246 _fs_free_blocks(block.next_block); 259 _fs_free_blocks(block.next_block);
@@ -249,18 +262,18 @@ _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) {
249 } 262 }
250 263
251 // Update block header. 264 // Update block header.
252 if (prev_block != FS_NULL) { 265 if (prev_blk != FS_NULL) {
253 block.prev_block = prev_block; 266 block.prev_block = prev_blk;
254 } 267 }
255 block.size = block_bytes; 268 block.size = block_bytes;
256 _fs_write(&block, block_pos, sizeof(FileBlock)); 269 _fs_write(&block, block_pos, sizeof(FileBlock));
257} 270}
258 271
259// void 272// void
260// _fs_append_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { 273// _fs_append_to_block(u8 *src, u16 n_bytes, u8 blk_id, u8 prev_block) {
261// // Read initial block. 274// // Read initial block.
262// FileBlock block; 275// FileBlock block;
263// size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; 276// size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id;
264// _fs_read(&block, block_pos, sizeof(FileBlock)); 277// _fs_read(&block, block_pos, sizeof(FileBlock));
265// u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)) - block.size; 278// u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)) - block.size;
266 279
@@ -270,7 +283,7 @@ _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) {
270 283
271// // txt_printf("cap: %d\n", block_capacity); 284// // txt_printf("cap: %d\n", block_capacity);
272// // txt_printf("bytes: %d\n", n_bytes); 285// // txt_printf("bytes: %d\n", n_bytes);
273// // txt_printf("id: %d\n", block_id); 286// // txt_printf("id: %d\n", blk_id);
274// if (n_bytes > block_capacity) { 287// if (n_bytes > block_capacity) {
275// if (block.next_block == FS_NULL) { 288// if (block.next_block == FS_NULL) {
276// // Find new available block and initialize it. 289// // Find new available block and initialize it.
@@ -282,62 +295,83 @@ _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) {
282// src + block_capacity, 295// src + block_capacity,
283// n_bytes - block_capacity, 296// n_bytes - block_capacity,
284// block.next_block, 297// block.next_block,
285// block_id); 298// blk_id);
286// } 299// }
287 300
288// // Update block header. 301// // Update block header.
289// if (prev_block != FS_NULL) { 302// if (prev_block != FS_NULL) {
290// block.prev_block = prev_block; 303// block.prev_block = prev_bloc7f8k;
291// } 304// }
292// block.size += block_bytes; 305// block.size += block_bytes;
293// _fs_write(&block, block_pos, sizeof(FileBlock)); 306// _fs_write(&block, block_pos, sizeof(FileBlock));
294// } 307// }
295 308
296size_t 309u16
297fs_write(u8 *src, size_t n_bytes, u16 offset, bool append, File *file) { 310fs_write(u8 *src, u16 n_bytes, File *file) {
311 if (file->mode != FS_OPEN_WRITE && file->mode != FS_OPEN_APPEND) {
312 return 0;
313 }
314
298 FileIndex *file_idx = &filesystem.files[file->index]; 315 FileIndex *file_idx = &filesystem.files[file->index];
299 // TODO: Account for offset.
300 316
301 // If this is a new file. 317 u8 blk_id = FS_NULL;
318 u16 offset = file->offset;
302 if (file_idx->first_block == FS_NULL) { 319 if (file_idx->first_block == FS_NULL) {
303 // Check how many blocks will this write require and if we have enough 320 // Check how many blocks will this write requires and if we have enough
304 // available. 321 // available.
305 u16 blocks_required = n_bytes / (FILE_BLOCK_SIZE - sizeof(FileBlock)); 322 u16 blocks_required = n_bytes / FILE_BLOCK_CAPACITY;
306 u16 blocks_available = FILE_N_BLOCKS - filesystem.busy_blocks; 323 u16 blocks_available = FILE_N_BLOCKS - filesystem.busy_blocks;
307 if (blocks_required > blocks_available) { 324 if (blocks_required > blocks_available) {
308 return 0; 325 return 0;
309 } 326 }
310 327
311 // Find the first available block. 328 // Find the first available block.
312 u8 block_id = _fs_init_new_block(); 329 blk_id = _fs_init_new_block();
313 file_idx->first_block = block_id; 330 file_idx->first_block = blk_id;
314 331
315 // Update file index on SRAM. 332 // Update file index on SRAM.
316 _fs_update_file_index(file->index); 333 _fs_update_file_index(file->index);
317 } else { 334 } else {
318 // TODO: Check how many blocks will this write require and if we have 335 // Check how many blocks will this write requires and if we have
319 // enough available. 336 // enough available.
337 u16 file_size = fs_file_size(file);
338 u16 blocks_in_file = file_size / FILE_BLOCK_SIZE;
339 u16 blocks_available = FILE_N_BLOCKS - filesystem.busy_blocks + blocks_in_file;
340 u16 blocks_required = (n_bytes + offset) / FILE_BLOCK_CAPACITY;
341 if (blocks_required > blocks_available) {
342 return 0;
343 }
344
345 blk_id = file_idx->first_block;
346
347 // If there is an offset find the block index and relative offset.
348 if (offset >= FILE_BLOCK_CAPACITY) {
349 u16 n_blocks_offset = offset / FILE_BLOCK_CAPACITY;
350 for (size_t i = 0; i < n_blocks_offset; ++i) {
351 FileBlock block;
352 u16 block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * blk_id;
353 _fs_read(&block, block_pos, sizeof(FileBlock));
354 blk_id = block.next_block;
355 if (blk_id == FS_NULL) {
356 return 0;
357 }
358 }
359 offset = offset % FILE_BLOCK_CAPACITY;
360 }
320 } 361 }
321 // txt_printf("id: %d", file_idx->first_block);
322 362
323 // Write to block. 363 // Write to block.
324 _fs_write_to_block(src, n_bytes, file_idx->first_block, FS_NULL); 364 if (file->mode == FS_OPEN_WRITE) {
325 365 _fs_write_to_block(src, n_bytes, offset, blk_id, FS_NULL);
326 // // Update file index. 366 } else {
327 // if (append) { 367 // TODO: Append...
328 // if (offset + n_bytes > file->size) { 368 }
329 // file->size = offset + n_bytes;
330 // }
331 // } else {
332 // file->size = offset + n_bytes;
333 // }
334 // _fs_write(file, FILE_INDEX_OFFSET + file_index * sizeof(File), sizeof(File));
335 369
336 return n_bytes; 370 return n_bytes;
337} 371}
338 372
339size_t 373u16
340fs_read(u8 *dst, size_t n_bytes, u16 offset, File *file) { 374fs_read(u8 *dst, u16 n_bytes, u16 offset, File *file) {
341 // File *file = &filesystem.files[file_index]; 375 // File *file = &filesystem.files[file_index];
342 376
343 // // Check if the offset is within limits. 377 // // Check if the offset is within limits.