diff options
author | Bad Diode <bd@badd10de.dev> | 2021-05-24 17:02:29 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-05-24 17:02:29 +0200 |
commit | 3410761714c70480c063112e5a184c93cae39bb3 (patch) | |
tree | c955c7e6cb8a783b5a76c3e40b01c58313cd9f7d | |
parent | e07f072de45d23ab17661e3ea6bd3c707f04aa35 (diff) | |
download | uxngba-3410761714c70480c063112e5a184c93cae39bb3.tar.gz uxngba-3410761714c70480c063112e5a184c93cae39bb3.zip |
Add experimental block based filesystem
-rw-r--r-- | src/common.h | 7 | ||||
-rw-r--r-- | src/filesystem.c | 361 | ||||
-rw-r--r-- | src/main.c | 39 |
3 files changed, 322 insertions, 85 deletions
diff --git a/src/common.h b/src/common.h index 39f3ada..bfa3903 100644 --- a/src/common.h +++ b/src/common.h | |||
@@ -716,10 +716,13 @@ wait_vsync(void) { | |||
716 | #define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) | 716 | #define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) |
717 | #define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0])) | 717 | #define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0])) |
718 | 718 | ||
719 | // IWRAM allocation macros for devkitARM. | 719 | // |
720 | #define IWRAM_CODE __attribute__((section(".iwram"), long_call, target("arm"))) | 720 | // Memory section macros for devkitARM. |
721 | // | ||
721 | #define IWRAM_DATA __attribute__((section(".iwram"))) | 722 | #define IWRAM_DATA __attribute__((section(".iwram"))) |
723 | #define IWRAM_CODE __attribute__((section(".iwram"), long_call, target("arm"))) | ||
722 | #define EWRAM_DATA __attribute__((section(".ewram"))) | 724 | #define EWRAM_DATA __attribute__((section(".ewram"))) |
725 | #define EWRAM_CODE __attribute__((section(".ewram"), long_call)) | ||
723 | #define EWRAM_BSS __attribute__((section(".sbss"))) | 726 | #define EWRAM_BSS __attribute__((section(".sbss"))) |
724 | 727 | ||
725 | #endif // GBAEXP_COMMON_H | 728 | #endif // GBAEXP_COMMON_H |
diff --git a/src/filesystem.c b/src/filesystem.c index 6737386..4a55818 100644 --- a/src/filesystem.c +++ b/src/filesystem.c | |||
@@ -1,29 +1,68 @@ | |||
1 | // We need 64 * 32 bytes (2K) of SRAM for file indexes. To avoid corruption | 1 | // This file implements a filesystem with a minimum block size of 256 bytes. The |
2 | // issues we ignore the first file (32 bytes). | 2 | // maximum number of files depends on the block size. The default 1KB block size |
3 | // Note that the filename should include the null terminator if we want to use | 3 | // will give us 32-64 files depending on the size of MEM_CART. In case we want |
4 | // strcmp. | 4 | // to use a block size of 512 bytes, we will have up to 128 file available. |
5 | #define FILE_NAME_SIZE 27 | 5 | // Blocks of 256 bytes will give us the maximum of 255 files available, since |
6 | #define FILE_CAPACITY 4 | 6 | // a block index of 0xFF will be considered as a null block. |
7 | #define FILE_HEADER_OFFSET 2 | ||
8 | #define FILE_INDEX_OFFSET 32 | ||
9 | #define FILE_DATA_OFFSET KB(2) | ||
10 | #define FILE_MAX_SIZE KB(16) | ||
11 | #define SRAM ((vu8*)(MEM_CART)) | ||
12 | 7 | ||
13 | typedef struct File { | 8 | // A fileblock of 1KB give us a maximum of 64 files. |
14 | char name[FILE_NAME_SIZE + 1]; | 9 | #define FILE_BLOCK_SIZE KB(1) |
10 | #define FILE_MAX_FILES 64 | ||
11 | #define FILE_N_BLOCKS 62 | ||
12 | |||
13 | // With this file name size sizeof(FileIndex) will be 32 bytes. 32 * 64 files | ||
14 | // give us 2KB spent on file index that we can't use for data (so maximum of 62 | ||
15 | // files without accounting for the block index). | ||
16 | #define FILE_NAME_SIZE 30 | ||
17 | #define FILE_INDEX_NUM 62 | ||
18 | |||
19 | // Since we are reserving the first 2K bytes for the filesystem, we have 60 | ||
20 | // blocks available for writing data. If you were to change the previous | ||
21 | // parameters, you *must* recalculate the initial block start location. | ||
22 | #define FILE_DATA_START KB(2) | ||
23 | |||
24 | // We must write to the SRAM using the 8bit bus. | ||
25 | #define SRAM ((vu8*)(MEM_CART)) | ||
26 | |||
27 | // Special filesystem constants. | ||
28 | enum { FS_INIT_PATTERN = 0xBA, FS_NULL = 0xFF }; | ||
29 | |||
30 | typedef struct FileBlock { | ||
31 | // Size used in the current block (in bytes). Should be smaller than: | ||
32 | // FILE_BLOCK_SIZE - sizeof(FileBlock) | ||
15 | u16 size; | 33 | u16 size; |
16 | u16 mem_offset; // NOTE: Unused... | 34 | // The index for the next block. Set to FS_NULL if there is none. |
17 | } File; | 35 | u8 next_block; |
36 | u8 prev_block; | ||
37 | } FileBlock; | ||
38 | |||
39 | typedef struct FileIndex { | ||
40 | // File name. | ||
41 | char name[FILE_NAME_SIZE + 1]; | ||
42 | // Index to the first block of this file. If set to FS_NULL this file | ||
43 | // has not yet been written to. | ||
44 | u8 first_block; | ||
45 | } FileIndex; | ||
18 | 46 | ||
19 | // The filesystem header. | 47 | // The filesystem header. |
20 | typedef struct FileSystem { | 48 | typedef struct FileSystem { |
21 | u16 num_files; | 49 | // The first byte of the SRAM can become corrupted in some situations, like |
22 | u16 data_size; // NOTE: Unused... | 50 | // changing cartridges for example. |
23 | u16 data_capacity; // NOTE: Unused... | 51 | u8 blank; |
24 | File files[FILE_CAPACITY]; | 52 | // If the filesystem exists, this will be set to FS_INIT_PATTERN. |
53 | u8 initialized; | ||
54 | // Number of blocks in use. | ||
55 | u8 busy_blocks; | ||
56 | // Number of files currently existing in the filesystem. | ||
57 | u8 num_files; | ||
58 | // This stores a bitmap pattern to keep track of the blocks in use by the | ||
59 | // filesystem. The first byte maps the first 8 blocks and so on. | ||
60 | u8 used_blocks[FILE_MAX_FILES / 8]; | ||
61 | // The list of possible file indexes. | ||
62 | FileIndex files[FILE_INDEX_NUM]; | ||
25 | } FileSystem; | 63 | } FileSystem; |
26 | 64 | ||
65 | EWRAM_BSS | ||
27 | static FileSystem filesystem; | 66 | static FileSystem filesystem; |
28 | 67 | ||
29 | void | 68 | void |
@@ -41,114 +80,278 @@ _fs_write(u8 *src, size_t pos, size_t n_bytes) { | |||
41 | } | 80 | } |
42 | 81 | ||
43 | void | 82 | void |
44 | fs_init() { | 83 | fs_init(void) { |
45 | // Load header if existing. | 84 | // Load filesystem if existing. |
46 | _fs_read(&filesystem, FILE_HEADER_OFFSET, offsetof(FileSystem, files)); | 85 | _fs_read(&filesystem, 0, sizeof(FileSystem)); |
47 | if (filesystem.num_files == 0xFFFF | 86 | if (filesystem.initialized != FS_INIT_PATTERN) { |
48 | && filesystem.data_capacity == 0xFFFF | ||
49 | && filesystem.data_size == 0xFFFF) { | ||
50 | // Clear SRAM. | 87 | // Clear SRAM. |
51 | for (size_t i = 0; i < KB(64); ++i) { | 88 | for (size_t i = 0; i < KB(64) / 8; ++i) { |
52 | SRAM[i] = 0; | 89 | SRAM[i] = 0x00; |
90 | } | ||
91 | |||
92 | // Initialize block headers. | ||
93 | FileBlock block = { | ||
94 | .size = 0, | ||
95 | .next_block = FS_NULL, | ||
96 | .prev_block = FS_NULL, | ||
97 | }; | ||
98 | for (size_t i = 0; i < FILE_INDEX_NUM; ++i) { | ||
99 | size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * i; | ||
100 | _fs_write(&block, block_pos, sizeof(FileBlock)); | ||
53 | } | 101 | } |
54 | 102 | ||
55 | // Initialize filesystem. | 103 | // Initialize filesystem. |
56 | filesystem.num_files = 0; | 104 | memset(&filesystem, 0, sizeof(FileSystem)); |
57 | filesystem.data_size = 0; | 105 | filesystem.initialized = FS_INIT_PATTERN; |
58 | filesystem.data_capacity = (u16)(FILE_CAPACITY * FILE_MAX_SIZE); | 106 | for (size_t i = 0; i < FILE_INDEX_NUM; ++i) { |
59 | memset(&filesystem.files, 0, FILE_CAPACITY * sizeof(File)); | 107 | filesystem.files[i].first_block = FS_NULL; |
60 | _fs_write(&filesystem, FILE_HEADER_OFFSET, offsetof(FileSystem, files)); | 108 | } |
61 | } else { | 109 | |
62 | _fs_read(&filesystem.files, FILE_INDEX_OFFSET, sizeof(File) * filesystem.num_files); | 110 | // Write the FS to disk. |
111 | _fs_write(&filesystem, 0, sizeof(FileSystem)); | ||
63 | } | 112 | } |
64 | } | 113 | } |
65 | 114 | ||
115 | void inline | ||
116 | _fs_update_filesystem_header(void) { | ||
117 | _fs_write(&filesystem, 0, offsetof(FileSystem, files)); | ||
118 | }; | ||
119 | |||
120 | void inline | ||
121 | _fs_update_file_index(u16 index) { | ||
122 | _fs_write(&filesystem.files[index], | ||
123 | offsetof(FileSystem, files) + index * sizeof(FileIndex), | ||
124 | sizeof(FileIndex)); | ||
125 | } | ||
126 | |||
66 | typedef enum { | 127 | typedef enum { |
67 | OPEN_READ, | 128 | FS_OPEN_READ, |
68 | OPEN_WRITE, | 129 | FS_OPEN_WRITE, |
130 | FS_OPEN_APPEND, | ||
69 | } OpenMode; | 131 | } OpenMode; |
70 | 132 | ||
71 | int | 133 | typedef struct File { |
134 | u8 index; | ||
135 | u16 cur; | ||
136 | OpenMode mode; | ||
137 | } File; | ||
138 | |||
139 | File | ||
72 | fs_open_file(char *name, OpenMode mode) { | 140 | fs_open_file(char *name, OpenMode mode) { |
73 | // Try to find an existing file. | 141 | // Try to find an existing file. |
74 | for (size_t i = 0; i < filesystem.num_files; ++i) { | 142 | for (size_t i = 0; i < filesystem.num_files; ++i) { |
75 | // TODO: Replace strcmp with vectorized fixed size char comparison. | 143 | // TODO: Replace strcmp with vectorized fixed size char comparison. |
76 | if (strcmp(name, filesystem.files[i].name) == 0) { | 144 | if (strcmp(name, filesystem.files[i].name) == 0) { |
77 | return i; | 145 | return (File){i, 0, mode}; |
78 | } | 146 | } |
79 | } | 147 | } |
80 | 148 | ||
81 | if (mode == OPEN_READ) { | 149 | if (mode == FS_OPEN_READ) { |
82 | return -1; | 150 | return (File){FS_NULL, 0, mode}; |
83 | } | 151 | } |
84 | 152 | ||
85 | // Create a new file if there is space. | 153 | // Create a new file if there is space. |
86 | if (filesystem.num_files < FILE_CAPACITY) { | 154 | if (filesystem.num_files < FILE_INDEX_NUM) { |
87 | size_t index = filesystem.num_files++; | 155 | size_t index = filesystem.num_files++; |
88 | size_t k = 0; | 156 | size_t k = 0; |
89 | while(*name) { | 157 | while(*name) { |
90 | filesystem.files[index].name[k++] = *name++; | 158 | filesystem.files[index].name[k++] = *name++; |
91 | } | 159 | } |
92 | filesystem.files[index].size = 0; | ||
93 | filesystem.files[index].mem_offset = 0; | ||
94 | 160 | ||
95 | // Update file index. | 161 | // Update file index and filesystem on SRAM. |
96 | _fs_write(&filesystem.files[index], | 162 | _fs_update_file_index(index); |
97 | FILE_INDEX_OFFSET + index * sizeof(File), | 163 | _fs_update_filesystem_header(); |
98 | sizeof(File)); | ||
99 | 164 | ||
100 | // Update header. | 165 | return (File){index, 0, mode}; |
101 | _fs_write(&filesystem, FILE_HEADER_OFFSET, offsetof(FileSystem, files)); | 166 | } |
167 | return (File){FS_NULL, 0, mode}; | ||
168 | } | ||
102 | 169 | ||
103 | return index; | 170 | u8 |
171 | _fs_init_new_block(void) { | ||
172 | // Find free block. | ||
173 | u8 block_index = 0; | ||
174 | for (size_t j = 0; j < LEN(filesystem.used_blocks); ++j) { | ||
175 | for (size_t i = 0; i < 8; ++i, block_index++) { | ||
176 | u8 blk = (filesystem.used_blocks[j] >> i) & 0x1; | ||
177 | if (blk == 0) { | ||
178 | // Initialize the block. | ||
179 | filesystem.busy_blocks++; | ||
180 | filesystem.used_blocks[j] |= (1 << i); | ||
181 | _fs_update_filesystem_header(); | ||
182 | return block_index; | ||
183 | } | ||
184 | } | ||
104 | } | 185 | } |
105 | return -1; | 186 | return FS_NULL; |
106 | } | 187 | } |
107 | 188 | ||
108 | size_t | 189 | #include "text.h" |
109 | fs_write(u8 *src, size_t n_bytes, u16 file_index, u16 offset, bool append) { | ||
110 | File *file = &filesystem.files[file_index]; | ||
111 | 190 | ||
112 | // Check if there is enough capacity for this write operation. | 191 | // Recursively free blocks starting at block_id. To improve performance, the |
113 | if (offset + n_bytes >= FILE_MAX_SIZE) { | 192 | // filesystem header is updated in memory but not written to disk. It is |
114 | return 0; | 193 | // responsability of the caller to perform the filesystem update. |
194 | void | ||
195 | _fs_free_blocks(u8 block_id) { | ||
196 | if (block_id == FS_NULL) { | ||
197 | return; | ||
115 | } | 198 | } |
116 | 199 | ||
117 | // Write data to file block. | 200 | // Read block. |
118 | _fs_write(src, FILE_DATA_OFFSET + FILE_MAX_SIZE * file_index + offset, n_bytes); | 201 | FileBlock block; |
202 | size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; | ||
203 | _fs_read(&block, block_pos, sizeof(FileBlock)); | ||
204 | |||
205 | // Update block. | ||
206 | u8 next_block = block.next_block; | ||
207 | block = (FileBlock){ | ||
208 | .size = 0, | ||
209 | .next_block = FS_NULL, | ||
210 | .prev_block = FS_NULL, | ||
211 | }; | ||
212 | _fs_write(&block, block_pos, sizeof(FileBlock)); | ||
213 | |||
214 | // Update dirty and busy blocks. | ||
215 | filesystem.busy_blocks--; | ||
216 | filesystem.used_blocks[block_id / 8] &= ~(1 << (block_id % 8)); | ||
217 | |||
218 | _fs_free_blocks(next_block); | ||
219 | } | ||
220 | |||
221 | // Write to block as a new file. | ||
222 | void | ||
223 | _fs_write_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { | ||
224 | // Read initial block. | ||
225 | FileBlock block; | ||
226 | size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; | ||
227 | _fs_read(&block, block_pos, sizeof(FileBlock)); | ||
228 | u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)); | ||
119 | 229 | ||
120 | // Update file index. | 230 | // Write capacity. |
121 | if (append) { | 231 | u16 block_bytes = MIN(block_capacity, n_bytes); |
122 | if (offset + n_bytes > file->size) { | 232 | _fs_write(src, block_pos + sizeof(FileBlock), block_bytes); |
123 | file->size = offset + n_bytes; | 233 | |
234 | if (n_bytes > block_capacity) { | ||
235 | if (block.next_block == FS_NULL) { | ||
236 | // Find new available block and initialize it. | ||
237 | block.next_block = _fs_init_new_block(); | ||
124 | } | 238 | } |
239 | _fs_write_to_block( | ||
240 | src + block_capacity, | ||
241 | n_bytes - block_capacity, | ||
242 | block.next_block, | ||
243 | block_id); | ||
244 | } else if (block.next_block != FS_NULL){ | ||
245 | // Recursively free unused blocks. | ||
246 | _fs_free_blocks(block.next_block); | ||
247 | _fs_update_filesystem_header(); | ||
248 | block.next_block = FS_NULL; | ||
249 | } | ||
250 | |||
251 | // Update block header. | ||
252 | if (prev_block != FS_NULL) { | ||
253 | block.prev_block = prev_block; | ||
254 | } | ||
255 | block.size = block_bytes; | ||
256 | _fs_write(&block, block_pos, sizeof(FileBlock)); | ||
257 | } | ||
258 | |||
259 | // void | ||
260 | // _fs_append_to_block(u8 *src, size_t n_bytes, u8 block_id, u8 prev_block) { | ||
261 | // // Read initial block. | ||
262 | // FileBlock block; | ||
263 | // size_t block_pos = FILE_DATA_START + FILE_BLOCK_SIZE * block_id; | ||
264 | // _fs_read(&block, block_pos, sizeof(FileBlock)); | ||
265 | // u16 block_capacity = (FILE_BLOCK_SIZE - sizeof(FileBlock)) - block.size; | ||
266 | |||
267 | // // Write capacity. | ||
268 | // u16 block_bytes = MIN(block_capacity, n_bytes); | ||
269 | // _fs_write(src, block_pos + sizeof(FileBlock), block_bytes); | ||
270 | |||
271 | // // txt_printf("cap: %d\n", block_capacity); | ||
272 | // // txt_printf("bytes: %d\n", n_bytes); | ||
273 | // // txt_printf("id: %d\n", block_id); | ||
274 | // if (n_bytes > block_capacity) { | ||
275 | // if (block.next_block == FS_NULL) { | ||
276 | // // Find new available block and initialize it. | ||
277 | // block.next_block = _fs_init_new_block(); | ||
278 | // // TODO: Don't forget to set the block_prev of the next block as | ||
279 | // // this one. | ||
280 | // } | ||
281 | // _fs_write_to_block( | ||
282 | // src + block_capacity, | ||
283 | // n_bytes - block_capacity, | ||
284 | // block.next_block, | ||
285 | // block_id); | ||
286 | // } | ||
287 | |||
288 | // // Update block header. | ||
289 | // if (prev_block != FS_NULL) { | ||
290 | // block.prev_block = prev_block; | ||
291 | // } | ||
292 | // block.size += block_bytes; | ||
293 | // _fs_write(&block, block_pos, sizeof(FileBlock)); | ||
294 | // } | ||
295 | |||
296 | size_t | ||
297 | fs_write(u8 *src, size_t n_bytes, u16 offset, bool append, File *file) { | ||
298 | FileIndex *file_idx = &filesystem.files[file->index]; | ||
299 | // TODO: Account for offset. | ||
300 | |||
301 | // If this is a new file. | ||
302 | if (file_idx->first_block == FS_NULL) { | ||
303 | // Check how many blocks will this write require and if we have enough | ||
304 | // available. | ||
305 | u16 blocks_required = n_bytes / (FILE_BLOCK_SIZE - sizeof(FileBlock)); | ||
306 | u16 blocks_available = FILE_N_BLOCKS - filesystem.busy_blocks; | ||
307 | if (blocks_required > blocks_available) { | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | // Find the first available block. | ||
312 | u8 block_id = _fs_init_new_block(); | ||
313 | file_idx->first_block = block_id; | ||
314 | |||
315 | // Update file index on SRAM. | ||
316 | _fs_update_file_index(file->index); | ||
125 | } else { | 317 | } else { |
126 | file->size = offset + n_bytes; | 318 | // TODO: Check how many blocks will this write require and if we have |
319 | // enough available. | ||
127 | } | 320 | } |
128 | _fs_write(file, FILE_INDEX_OFFSET + file_index * sizeof(File), sizeof(File)); | 321 | // txt_printf("id: %d", file_idx->first_block); |
129 | 322 | ||
130 | // Update header. | 323 | // Write to block. |
131 | _fs_write(&filesystem, FILE_HEADER_OFFSET, offsetof(FileSystem, files)); | 324 | _fs_write_to_block(src, n_bytes, file_idx->first_block, FS_NULL); |
325 | |||
326 | // // Update file index. | ||
327 | // if (append) { | ||
328 | // if (offset + n_bytes > file->size) { | ||
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)); | ||
132 | 335 | ||
133 | return n_bytes; | 336 | return n_bytes; |
134 | } | 337 | } |
135 | 338 | ||
136 | size_t | 339 | size_t |
137 | fs_read(u8 *dst, size_t n_bytes, u16 file_index, u16 offset) { | 340 | fs_read(u8 *dst, size_t n_bytes, u16 offset, File *file) { |
138 | File *file = &filesystem.files[file_index]; | 341 | // File *file = &filesystem.files[file_index]; |
139 | 342 | ||
140 | // Check if the offset is within limits. | 343 | // // Check if the offset is within limits. |
141 | if (file->size == 0 || offset >= file->size - 1) { | 344 | // if (file->size == 0 || offset >= file->size - 1) { |
142 | return 0; | 345 | // return 0; |
143 | } | 346 | // } |
144 | 347 | ||
145 | // Read as much as we can. | 348 | // // Read as much as we can. |
146 | if (offset + n_bytes > file->size) { | 349 | // if (offset + n_bytes > file->size) { |
147 | n_bytes = file->size - offset; | 350 | // n_bytes = file->size - offset; |
148 | } | 351 | // } |
149 | 352 | ||
150 | // Copy n_bytes to destination. | 353 | // // Copy n_bytes to destination. |
151 | _fs_read(dst, FILE_DATA_OFFSET + FILE_MAX_SIZE * file_index + offset, n_bytes); | 354 | // _fs_read(dst, FILE_DATA_OFFSET + FILE_MAX_SIZE * file_index + offset, n_bytes); |
152 | 355 | ||
153 | return n_bytes; | 356 | return n_bytes; |
154 | } | 357 | } |
@@ -124,13 +124,20 @@ file_talk(Device *d, u8 b0, u8 w) { | |||
124 | u16 result = 0, length = mempeek16(d->dat, 0xa); | 124 | u16 result = 0, length = mempeek16(d->dat, 0xa); |
125 | u16 offset = mempeek16(d->dat, 0x4); | 125 | u16 offset = mempeek16(d->dat, 0x4); |
126 | u16 addr = mempeek16(d->dat, b0 - 1); | 126 | u16 addr = mempeek16(d->dat, b0 - 1); |
127 | int file_idx = fs_open_file(name, read ? OPEN_READ : OPEN_WRITE); | 127 | File file = fs_open_file(name, read ? FS_OPEN_READ : FS_OPEN_WRITE); |
128 | if (file_idx >= 0) { | 128 | if (file.index != FS_NULL) { |
129 | txt_position(9, 9); | ||
130 | // TODO: Use file.cur pointer and fs_seek instead of offset. | ||
131 | // TODO: Remove append, that should be a write mode. | ||
129 | if (read) { | 132 | if (read) { |
130 | result = fs_read(&d->mem[addr], length, file_idx, offset); | 133 | result = fs_read(&d->mem[addr], length, offset, &file); |
131 | } else { | 134 | } else { |
132 | result = fs_write(&d->mem[addr], length, file_idx, offset, offset > 0); | 135 | result = fs_write(&d->mem[addr], length, offset, offset > 0, &file); |
136 | txt_printf("WROTE: %d\n", result); | ||
133 | } | 137 | } |
138 | } else { | ||
139 | // txt_position(9, 9); | ||
140 | // txt_printf("NOT FOUND"); | ||
134 | } | 141 | } |
135 | mempoke16(d->dat, 0x2, result); | 142 | mempoke16(d->dat, 0x2, result); |
136 | } | 143 | } |
@@ -353,14 +360,38 @@ int main(void) { | |||
353 | txt_init(1, TEXT_LAYER); | 360 | txt_init(1, TEXT_LAYER); |
354 | txt_position(0,0); | 361 | txt_position(0,0); |
355 | 362 | ||
363 | u8 test_data_a[1020]; | ||
364 | u8 test_data_b[2038]; | ||
365 | memset(&test_data_a, 0xAA, sizeof(test_data_a)); | ||
366 | memset(&test_data_b, 0xbb, sizeof(test_data_b)); | ||
367 | |||
368 | txt_position(0, 8); | ||
369 | File file_a = fs_open_file("file_a", FS_OPEN_WRITE); | ||
370 | File file_b = fs_open_file("file_b", FS_OPEN_WRITE); | ||
371 | fs_write(&test_data_b, sizeof(test_data_b), 0, 0, &file_a); | ||
372 | fs_write(&test_data_a, sizeof(test_data_a), 0, 0, &file_a); | ||
373 | // fs_write(&test_data_a, sizeof(test_data_a), 0, 0, &file_a); | ||
374 | // fs_write(&test_data_b, sizeof(test_data_b), 0, 0, &file_b); | ||
375 | |||
356 | // Main loop. | 376 | // Main loop. |
357 | int frame_counter = 0; | 377 | int frame_counter = 0; |
358 | evaluxn(&u, 0x0100); | 378 | evaluxn(&u, 0x0100); |
379 | u32 flip_cycles = 0; | ||
359 | while(true) { | 380 | while(true) { |
360 | bios_vblank_wait(); | 381 | bios_vblank_wait(); |
382 | profile_start(); | ||
361 | handle_input(&u); | 383 | handle_input(&u); |
384 | u32 input_cycles = profile_stop(); | ||
385 | profile_start(); | ||
362 | evaluxn(&u, mempeek16(devscreen->dat, 0)); | 386 | evaluxn(&u, mempeek16(devscreen->dat, 0)); |
387 | u32 eval_cycles = profile_stop(); | ||
388 | txt_position(0, 8); | ||
389 | // txt_printf("INPUT: %lu \n", input_cycles); | ||
390 | // txt_printf("EVAL: %lu \n", eval_cycles); | ||
391 | // txt_printf("FLIP: %lu \n", flip_cycles); | ||
392 | profile_start(); | ||
363 | flipbuf(&ppu); | 393 | flipbuf(&ppu); |
394 | flip_cycles = profile_stop(); | ||
364 | frame_counter++; | 395 | frame_counter++; |
365 | } | 396 | } |
366 | 397 | ||