From af98fa608fb4ba98138e2b1239f173e6d74d6d86 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Fri, 21 May 2021 17:17:52 +0200 Subject: Add incomplete filesystem prototype --- src/filesystem.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/filesystem.c (limited to 'src/filesystem.c') diff --git a/src/filesystem.c b/src/filesystem.c new file mode 100644 index 0000000..2da77be --- /dev/null +++ b/src/filesystem.c @@ -0,0 +1,118 @@ +// We need 64 * 32 bytes (2K) of SRAM for file indexes. To avoid corruption +// issues we ignore the first file (32 bytes). +// Note that the filename should include the null terminator if we want to use +// strcmp. +#define FILE_NAME_SIZE 27 +#define FILE_CAPACITY 63 +#define FILE_HEADER_OFFSET 2 +#define FILE_INDEX_OFFSET 32 +#define FILE_DATA_OFFSET KB(2) +#define FILE_MAX_SIZE KB(1) +#define SRAM ((vu8*)(MEM_CART)) + +typedef struct File { + char name[FILE_NAME_SIZE + 1]; + u16 size; + u16 mem_offset; // NOTE: Unused... +} File; + +// The filesystem header. +typedef struct FileSystem { + u16 num_files; + u16 data_size; // NOTE: Unused... + u16 data_capacity; // NOTE: Unused... + File files[FILE_CAPACITY]; +} FileSystem; + +static FileSystem filesystem; + +void +_fs_read(u8 *dst, size_t pos, size_t n_bytes) { + for (size_t i = 0; i < n_bytes; ++i) { + dst[i] = SRAM[pos + i]; + } +} + +void +_fs_write(u8 *src, size_t pos, size_t n_bytes) { + for (size_t i = 0; i < n_bytes; ++i) { + SRAM[pos + i] = src[i]; + } +} + +void +fs_init() { + // Load header if existing. + _fs_read(&filesystem, FILE_HEADER_OFFSET, offsetof(FileSystem, files)); + if (filesystem.num_files == 0xFFFF + && filesystem.data_capacity == 0xFFFF + && filesystem.data_size == 0xFFFF) { + filesystem.num_files = 0; + filesystem.data_size = 0; + filesystem.data_capacity = 27 * FILE_MAX_SIZE; + memset(&filesystem.files, 0, FILE_CAPACITY * sizeof(File)); + _fs_write(&filesystem, FILE_HEADER_OFFSET, offsetof(FileSystem, files)); + } else { + _fs_read(&filesystem.files, FILE_INDEX_OFFSET, sizeof(File) * filesystem.num_files); + } +} + +int +fs_open_file(char *name) { + // Try to find an existing file. + for (size_t i = 0; i < filesystem.num_files; ++i) { + // TODO: Replace strcmp with vectorized fixed size char comparison. + if (strcmp(name, filesystem.files[i].name) == 0) { + return i; + } + } + // Create a new file if there is space. + if (filesystem.num_files < FILE_CAPACITY) { + size_t index = filesystem.num_files++; + size_t k = 0; + while(*name) { + filesystem.files[index].name[k++] = *name++; + } + filesystem.files[index].size = 0; + filesystem.files[index].mem_offset = 0; + + // Update file index. + _fs_write(&filesystem.files[index], + FILE_INDEX_OFFSET + index * sizeof(File), + sizeof(File)); + + // Update header. + _fs_write(&filesystem, FILE_HEADER_OFFSET, offsetof(FileSystem, files)); + + return index; + } + return -1; +} + +int +fs_write(u8 *src, size_t n_bytes, u16 file_index, u16 offset, bool append) { + File *file = &filesystem.files[file_index]; + + // Check if there is enough capacity for this write operation. + if (offset + n_bytes >= FILE_MAX_SIZE) { + return -1; + } + + // Write data to file block. + _fs_write(src, FILE_DATA_OFFSET + FILE_MAX_SIZE * file_index + offset, n_bytes); + + // Update file index. + if (append) { + if (offset + n_bytes > file->size) { + file->size = offset + n_bytes; + } + } else { + file->size = offset + n_bytes; + } + _fs_write(file, FILE_INDEX_OFFSET + file_index * sizeof(File), sizeof(File)); + + // Update header. + _fs_write(&filesystem, FILE_HEADER_OFFSET, offsetof(FileSystem, files)); + + return n_bytes; +} -- cgit v1.2.1