mini.c (4885B)
1 /* mini.c - ver mini.h */ 2 #include <string.h> 3 #include "mini.h" 4 5 Rng mini_rng; 6 void (*mini_art)(Surface *s); 7 int mini_menu_top = 84; 8 9 static const char *g_title; 10 static Color g_accent; 11 12 /* ------------------------------------------------------------ azar */ 13 14 int mini_rand(int n) { return n > 0 ? (int)rng_below(&mini_rng, (uint32_t)n) : 0; } 15 16 void mini_shuffle(uint8_t *a, int n) 17 { 18 for (int i = n - 1; i > 0; i--) { 19 int j = mini_rand(i + 1); 20 uint8_t t = a[i]; a[i] = a[j]; a[j] = t; 21 } 22 } 23 24 /* ------------------------------------------------------------ texto grande */ 25 26 int mini_big_text(Surface *s, const Font *f, int x, int y, int scale, const char *t, Color c) 27 { 28 int x0 = x, ch; 29 while ((ch = utf8_next(&t)) != 0) { 30 if (ch < 32 || ch > 255) ch = '?'; 31 const uint8_t *g = f->bits + (ch - 32) * f->h; 32 for (int row = 0; row < f->h; row++) 33 for (int col = 0; col < 8; col++) 34 if (g[row] & (0x80 >> col)) gfx_rect(s, x + col * scale, y + row * scale, scale, scale, c); 35 x += f->w * scale; 36 } 37 return x - x0; 38 } 39 40 int mini_big_w(const Font *f, int scale, const char *t) { return gfx_text_w(f, t) * scale; } 41 42 void mini_big_center(Surface *s, const Font *f, int y, int scale, const char *t, Color c) 43 { 44 int x = (s->w - mini_big_w(f, scale, t)) / 2; 45 mini_big_text(s, f, x + scale / 2 + 1, y + scale / 2 + 1, scale, t, C_BLACK); /* sombra */ 46 mini_big_text(s, f, x, y, scale, t, c); 47 } 48 49 int str_time(char *buf, int n, int pos, uint32_t ms) 50 { 51 uint32_t sec = ms / 1000; 52 pos = str_int(buf, n, pos, (long)(sec / 60)); 53 pos = str_put(buf, n, pos, sec % 60 < 10 ? ":0" : ":"); 54 return str_int(buf, n, pos, (long)(sec % 60)); 55 } 56 57 /* ------------------------------------------------------------ menus */ 58 59 static int backdrop(Surface *s, bool compact) 60 { 61 (void)compact; 62 gfx_rect(s, 0, 0, s->w, s->h, RGB(16, 20, 30)); 63 for (int y = 0; y < s->h; y += 8) gfx_rect(s, 0, y, s->w, 1, RGB(22, 27, 40)); 64 mini_big_center(s, &font_bold, 14, 3, g_title, g_accent); 65 if (mini_art) mini_art(s); 66 return mini_menu_top; 67 } 68 69 static void paint_form(Surface *s, void *ctx) { gfx_form(s, ctx, 0); } 70 71 int mini_form(Form *f) 72 { 73 bool dirty = true; 74 for (;;) { 75 if (dirty) { hal_draw(paint_form, f); dirty = false; } 76 int k = hal_key(); 77 if (k < 0) { hal_sleep(10); continue; } 78 dirty = true; 79 if (k == 0) continue; 80 int r = form_key(f, k); 81 if (r != FORM_NONE) return r; 82 } 83 } 84 85 void mini_notice(const char *title, const char *text) 86 { 87 Form f; 88 form_begin(&f, title); 89 form_label(&f, text); 90 form_button(&f, 1, "OK"); 91 f.cur = 1; 92 mini_form(&f); 93 } 94 95 /* ------------------------------------------------------------ guardado */ 96 97 static char store[2048]; 98 99 static char *find(const char *key) 100 { 101 int kl = (int)strlen(key); 102 for (char *p = store; *p; ) { 103 if (!strncmp(p, key, (size_t)kl) && p[kl] == ' ') return p; 104 char *e = strchr(p, '\n'); 105 if (!e) break; 106 p = e + 1; 107 } 108 return 0; 109 } 110 111 const char *mini_get_str(const char *key) 112 { 113 static char val[256]; 114 char *p = find(key); 115 if (!p) return 0; 116 p += strlen(key) + 1; 117 int i = 0; 118 while (p[i] && p[i] != '\n' && i < (int)sizeof val - 1) { val[i] = p[i]; i++; } 119 val[i] = 0; 120 return val; 121 } 122 123 long mini_get(const char *key, long def) 124 { 125 const char *v = mini_get_str(key); 126 long x; 127 return v && str_scan_int(v, &x) ? x : def; 128 } 129 130 void mini_set_str(const char *key, const char *v) 131 { 132 char *p = find(key); 133 if (p) { /* sacar la linea vieja */ 134 char *e = strchr(p, '\n'); 135 if (e) memmove(p, e + 1, strlen(e + 1) + 1); 136 else *p = 0; 137 } 138 int n = (int)strlen(store); 139 if (n + (int)strlen(key) + (int)strlen(v) + 3 > (int)sizeof store) return; 140 n = str_put(store, sizeof store, n, key); 141 n = str_put(store, sizeof store, n, " "); 142 n = str_put(store, sizeof store, n, v); 143 str_put(store, sizeof store, n, "\n"); 144 } 145 146 void mini_set(const char *key, long v) 147 { 148 char b[24]; 149 str_int(b, sizeof b, 0, v); 150 mini_set_str(key, b); 151 } 152 153 bool mini_save(void) { return hal_store_save(store, (int)strlen(store)); } 154 155 /* ------------------------------------------------------------ arranque */ 156 157 void mini_start(const char *title, Color accent) 158 { 159 hal_init(); 160 g_title = title; 161 g_accent = accent; 162 gfx_form_backdrop = backdrop; 163 rng_seed(&mini_rng, ((uint64_t)hal_random() << 32) | hal_random(), hal_random() | 1); 164 int n = hal_store_load(store, sizeof store - 1); 165 store[n > 0 ? n : 0] = 0; 166 /* un .SAV nuevo esta lleno de ceros o basura: quedarse solo con texto */ 167 for (int i = 0; store[i]; i++) 168 if ((store[i] < 32 && store[i] != '\n') || (unsigned char)store[i] > 126) { store[0] = 0; break; } 169 }