diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-09-19 13:17:14 +1200 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-09-19 13:32:32 +1200 |
commit | bb1aa5958d1b67707dcf0f6b08bfaf0b408bd46e (patch) | |
tree | b26d07ed58aaf7a5230fc3e28c103d616abfa9b8 /arm9/source/types/pathbuf.c | |
parent | 9612c307f00c4313d73fe0c3a86c05c8d8cd514e (diff) | |
download | bedrock-nds-bb1aa5958d1b67707dcf0f6b08bfaf0b408bd46e.zip |
Massive rewrite
This commit rewrites the emulator halfway from scratch to make it
easier to change and maintain in the future. The emulator core was
rewritten to adhere to the released Bedrock specification (earlier
versions implemented an older prototype specification, which is no
longer relevant).
This commit also adds proper support for running multiple concurrent
Bedrock instances. This was previously supported in a limited manner
for the on-screen keyboard, but now works for any regular program as
well, with switching being performed by pressing the L or R bumper
buttons. This is disabled by default, as programs will still need to
be baked into the emulator and hand-loaded.
Diffstat (limited to 'arm9/source/types/pathbuf.c')
-rw-r--r-- | arm9/source/types/pathbuf.c | 111 |
1 files changed, 79 insertions, 32 deletions
diff --git a/arm9/source/types/pathbuf.c b/arm9/source/types/pathbuf.c index 1a610c8..e94b955 100644 --- a/arm9/source/types/pathbuf.c +++ b/arm9/source/types/pathbuf.c @@ -1,52 +1,99 @@ -#include <nds.h> #include "pathbuf.h" -u8 pb_read(PathBuf *buf) { + +// Read the next byte of the path buffer, or zero if all bytes have been read. +u8 pathbuf_read(PathBuf *buf) { u8 output = buf->mem[buf->p]; if (output) buf->p++; return output; } -void pb_clear(PathBuf *buf) { - memset(&buf->mem, 0, 256); +// Clear a path buffer. +void pathbuf_clear(PathBuf *buf) { + for (int i=0; i<256; i++) buf->mem[i] = 0; + buf->p = 0; } -void pb_reset(PathBuf *buf, bool to_name) { +// Move the pointer to either the start of the path buffer or to the start of +// the final path component. +void pathbuf_set_pointer(PathBuf *buf, bool to_final_component) { buf->p = 0; - if (to_name) for (int i=0; i<255; i++) { - if (buf->mem[i] == '/') { - buf->p = i+1; - } else if (buf->mem[i] == 0) { - break; + if (to_final_component) { + for (int i=0; i<255; i++) { + if (buf->mem[i] == '/') { + buf->p = i+1; + } else if (buf->mem[i] == 0) { + break; + } } } } -// Push a byte to a PathBuf, return true and reset the pointer if byte is null. -bool pb_push_byte(PathBuf *buf, u8 byte) { - // Stop before overwriting the pointer. - if (buf->p != 0xff) { - buf->mem[buf->p++] = byte; - } - if (byte == 0) { - buf->p = 0; - return true; - } else { - return false; - } +// Populate a path buffer with a bytestring. +void pathbuf_populate(PathBuf *buf, u8 *path) { + pathbuf_clear(buf); + u8 c; + for (int i=0; i<256; i++) { + c = path[i]; + buf->mem[i] = c; + if (c == 0) return; + }; } -bool pb_is_terminated(PathBuf *buf) { - for (int i=0; i<255; i++) { - if (buf->mem[i] == 0) { - return true; - } - } - return false; +// Push a byte to a path buffer, return true and reset pointer if byte is null. +bool pathbuf_push(PathBuf *buf, u8 byte) { + buf->mem[buf->p++] = byte; + return byte == 0; } -void pb_populate(PathBuf *buf, u8 *path) { - strncpy((char*) &buf->mem[0], (char*) path, 254); - buf->p = 0; +// Check if a path buffer is empty. +bool pathbuf_is_empty(PathBuf *buf) { + return buf->mem[0] == 0; +} + +// Check if a path buffer contains the path of the root directory. +bool pathbuf_is_root(PathBuf *buf) { + return buf->mem[0] == '/' && buf->mem[1] == 0; +} + +// Check if a path buffer contains a valid path. +bool pathbuf_is_valid(PathBuf *buf) { + // Test that path begins with a forward slash and ends with a null byte. + if (buf->mem[0x00] != '/') return false; + if (buf->mem[0xFF] != 0 ) return false; + // Find the length of the path. + int len = 0; + for (; len<256; len++) if (buf->mem[len] == 0) break; + // End early if path is the root directory. + if (len == 1) return true; + // Test that path contains no control characters. + for (int i=0; i<len; i++) if (buf->mem[i] < 0x20) return false; + // Test that path contains no empty or relative components. This also + // happens to test that it doesn't end with a slash. + bool is_empty = false; + bool all_dots = false; + int dot_count = 0; + u8 c; + for (int i=0; i<=len; i++) { + c = buf->mem[i]; + if (c == '/' || c == 0) { + // Test if component is empty. + if (is_empty) return false; + // Test if component is one or two periods. + if (all_dots && dot_count < 3) return false; + // Reset flags. + is_empty = true; + all_dots = true; + dot_count = 0; + } else { + is_empty = false; + if (c == '.') { + dot_count++; + } else { + all_dots = false; + } + } + } + return true; } |