#include "window.h" #include "drive.h" #include "panic.h" #include "util.h" #include #define SETTINGS_FILE "sys/settings.pls" static struct { uint32_t main_start; uint32_t main_entries; uint32_t names_start; uint32_t data_start; } settings_header; enum { ST_SZ_STRING = 0x00, ST_COLOR = 0x01 }; struct main_entry { uint32_t name_offset; uint8_t name_len; uint8_t type; uint16_t pad; union { struct { uint32_t data_offset; uint32_t length; } as_string; struct pixel as_pixel; }; } __attribute__ ((__packed__)); static file_id_t fid; static uint32_t main_end; void close_settings() { drives->free_file(drives, fid); fid = 0; } void init_settings() { fid = drives->get_file(drives, SETTINGS_FILE); if (!fid) PANIC("could not open settings file at \"" SETTINGS_FILE "\"."); fmcpy(&settings_header, drives, fid, 0, 16); main_end = settings_header.main_start + settings_header.main_entries * sizeof(struct main_entry); } bool try_find_setting(const char *name, struct main_entry *entry_out) { if (!fid) PANIC("setting requested after settings file closed"); uint16_t name_len = 0; while (name[name_len]) if (++name_len == 256) return false; for (uint32_t i = settings_header.main_start; i < main_end; i += sizeof(struct main_entry)) { fmcpy(entry_out, drives, fid, i, sizeof(struct main_entry)); if (entry_out->name_len != name_len) continue; char found_name[255]; fmcpy(found_name, drives, fid, settings_header.names_start + entry_out->name_offset, name_len); for (uint8_t j = 0; j < name_len; ++j) if (found_name[j] != name[j]) goto lc; return true; lc: ; } return false; } bool try_get_sz_setting(const char *name, char *out, uint32_t max_len, uint32_t *len_out) { struct main_entry entry; if (!try_find_setting(name, &entry) || (entry.type != ST_SZ_STRING)) return false; const uint32_t len = entry.as_string.length > max_len ? max_len : entry.as_string.length; fmcpy(out, drives, fid, settings_header.data_start + entry.as_string.data_offset, len); out[len] = '\0'; *len_out = len; return true; } bool try_get_color_setting(const char *name, struct pixel *out) { struct main_entry entry; if (!try_find_setting(name, &entry) || (entry.type != ST_COLOR)) return false; *out = entry.as_pixel; return true; }