diff options
Diffstat (limited to 'arm9/source/types')
-rw-r--r-- | arm9/source/types/circbuf.c | 10 | ||||
-rw-r--r-- | arm9/source/types/circbuf.h | 18 | ||||
-rw-r--r-- | arm9/source/types/pathbuf.c | 111 | ||||
-rw-r--r-- | arm9/source/types/pathbuf.h | 24 | ||||
-rw-r--r-- | arm9/source/types/readbuf.c | 14 | ||||
-rw-r--r-- | arm9/source/types/readbuf.h | 13 | ||||
-rw-r--r-- | arm9/source/types/wakequeue.c | 30 | ||||
-rw-r--r-- | arm9/source/types/wakequeue.h | 13 |
8 files changed, 172 insertions, 61 deletions
diff --git a/arm9/source/types/circbuf.c b/arm9/source/types/circbuf.c index 532a5a0..0398254 100644 --- a/arm9/source/types/circbuf.c +++ b/arm9/source/types/circbuf.c @@ -1,6 +1,8 @@ #include "circbuf.h" -u8 cb_read_byte(CircBuf *buf) { + +// Read a byte from a circular buffer, or zero if the buffer is empty. +u8 circbuf_read(CircBuf *buf) { if (buf->front != buf->back) { return buf->mem[buf->front++]; } else { @@ -8,13 +10,15 @@ u8 cb_read_byte(CircBuf *buf) { } } -void cb_write_byte(CircBuf *buf, u8 byte) { +// Write a byte to a circular buffer if the buffer is not full. +void circbuf_write(CircBuf *buf, u8 byte) { if (((buf->back+1)&0xff) != buf->front) { buf->mem[buf->back++] = byte; } } -void cb_clear(CircBuf *buf) { +// Clear a circular buffer. +void circbuf_clear(CircBuf *buf) { buf->front = 0; buf->back = 0; } diff --git a/arm9/source/types/circbuf.h b/arm9/source/types/circbuf.h index 305f8bf..15b3b63 100644 --- a/arm9/source/types/circbuf.h +++ b/arm9/source/types/circbuf.h @@ -1,16 +1,18 @@ -#include <nds.h> - #ifndef CIRCBUF_H_ #define CIRCBUF_H_ + #include "../bang.h" + + + // A 256-byte circular buffer. typedef struct { u8 mem[256]; - u8 front; // start of buffer, read from here until back - u8 back; // end of buffer, write past here until front + u8 front; // start of buffer, read from here up to back + u8 back; // end of buffer, write past here up to front } CircBuf; - u8 cb_read_byte(CircBuf *buf); - void cb_write_byte(CircBuf *buf, u8 byte); - void cb_clear(CircBuf *buf); - + // Methods. + u8 circbuf_read(CircBuf *buf); + void circbuf_write(CircBuf *buf, u8 byte); + void circbuf_clear(CircBuf *buf); #endif 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; } diff --git a/arm9/source/types/pathbuf.h b/arm9/source/types/pathbuf.h index 7fd7251..a926262 100644 --- a/arm9/source/types/pathbuf.h +++ b/arm9/source/types/pathbuf.h @@ -1,18 +1,22 @@ -#include <nds.h> - #ifndef PATHBUF_H_ #define PATHBUF_H_ + #include "../bang.h" + + + // A 255-byte path buffer. typedef struct { - u8 mem[255]; + u8 mem[256]; u8 p; } PathBuf; - u8 pb_read(PathBuf *buf); - void pb_clear(PathBuf *buf); - void pb_reset(PathBuf *buf, bool to_name); - bool pb_push_byte(PathBuf *buf, u8 byte); - bool pb_is_terminated(PathBuf *buf); - void pb_populate(PathBuf *buf, u8 *path); - + // Methods. + u8 pathbuf_read(PathBuf *buf); + void pathbuf_clear(PathBuf *buf); + void pathbuf_set_pointer(PathBuf *buf, bool to_final_component); + void pathbuf_populate(PathBuf *buf, u8 *path); + bool pathbuf_push(PathBuf *buf, u8 byte); + bool pathbuf_is_empty(PathBuf *buf); + bool pathbuf_is_root(PathBuf *buf); + bool pathbuf_is_valid(PathBuf *buf); #endif diff --git a/arm9/source/types/readbuf.c b/arm9/source/types/readbuf.c index eaee27a..750ac4d 100644 --- a/arm9/source/types/readbuf.c +++ b/arm9/source/types/readbuf.c @@ -1,12 +1,20 @@ -#include <nds.h> #include "readbuf.h" -u8 rb_read(ReadBuf *buf) { + +// Populate a read buffer with a pointer to a string. +void readbuf_populate(ReadBuf *buf, u8 *string) { + buf->mem = string; + buf->p = 0; +} + +// Read the next byte of a read buffer, or zero if all bytes have been read. +u8 readbuf_read(ReadBuf *buf) { u8 output = buf->mem[buf->p]; if (output) buf->p++; return output; } -void rb_reset(ReadBuf *buf) { +// Move the pointer to the start of the buffer. +void readbuf_set_pointer(ReadBuf *buf) { buf->p = 0; } diff --git a/arm9/source/types/readbuf.h b/arm9/source/types/readbuf.h index 9077a69..a88934b 100644 --- a/arm9/source/types/readbuf.h +++ b/arm9/source/types/readbuf.h @@ -1,14 +1,17 @@ -#include <nds.h> - #ifndef READBUF_H_ #define READBUF_H_ + #include "../bang.h" + + + // A variable-length read buffer. typedef struct { u8 *mem; u8 p; } ReadBuf; - u8 rb_read(ReadBuf *buf); - void rb_reset(ReadBuf *buf); - + // Methods. + void readbuf_populate(ReadBuf *buf, u8 *string); + u8 readbuf_read(ReadBuf *buf); + void readbuf_set_pointer(ReadBuf *buf); #endif diff --git a/arm9/source/types/wakequeue.c b/arm9/source/types/wakequeue.c new file mode 100644 index 0000000..8876123 --- /dev/null +++ b/arm9/source/types/wakequeue.c @@ -0,0 +1,30 @@ +#include "wakequeue.h" + +/* +TODO: This is unused at the moment. It will eventually be used for keeping +track of which device last woke a Bedrock instance, to optimally choose +which device to use when waking from sleep. +*/ + +// Reset a wake queue. +void wakequeue_reset(WakeQueue *queue) { + // Populate the queue with fifteen slot numbers. Slot zero is excluded, + // as it always comes last in the wake order. + for (int i=0; i<15; i++) queue->mem[i] = i+1; +} + +// TODO: Not quite done yet. +bool wakequeue_wake(WakeQueue *queue, u16 device_list) { + // Test each entry in the queue against the device list. + for (int i=0; i<15; i++) { + u8 slot_number = queue->mem[i]; + if (TEST(device_list, 0x8000 >> slot_number)) { + // Move the matched entry to the back of the queue. + for (; i<14; i++) queue->mem[i] = queue->mem[i+1]; + queue->mem[14] = slot_number; + return true; + } + } + // Test system device last. + return TEST(device_list, 0x8000); +} diff --git a/arm9/source/types/wakequeue.h b/arm9/source/types/wakequeue.h new file mode 100644 index 0000000..ed07d6d --- /dev/null +++ b/arm9/source/types/wakequeue.h @@ -0,0 +1,13 @@ +#ifndef WAKEQUEUE_H_ + #define WAKEQUEUE_H_ + + #include "../bang.h" + + + // A variable-length read buffer. + typedef struct { + u8 mem[15]; // List of slot numbers + } WakeQueue; + + // Methods. +#endif |