1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include "window.h"
#include "drive.h"
#include "panic.h"
#include "util.h"
#include <stdint.h>
#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;
}
|