summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-11-04 19:13:16 -0500
committerWormHeamer2025-11-04 19:13:16 -0500
commit02e1a8abb7d43c8cb6e7fbf473c8ddc7f9eee37a (patch)
treeee5ce1374c4e796f665278e283ff7229af3145f8
parente379662045c4dc6e149b84ab9e43ceecb427451e (diff)
stuff
-rw-r--r--main.c188
1 files changed, 119 insertions, 69 deletions
diff --git a/main.c b/main.c
index 0468589..71d3afc 100644
--- a/main.c
+++ b/main.c
@@ -96,6 +96,9 @@ VuiWindow vui_win = {
.back = &vui_win.buf2,
};
+#define LINES (vui_win.height)
+#define COLS (vui_win.width)
+
#define BCHR(b,x,y) ((b)->chr[(x) + (y) * (b)->width])
#define BATTR(b,x,y) ((b)->attr[(x) + (y) * (b)->width])
#define CHR(x,y) BCHR(vui_win.front, x, y)
@@ -159,14 +162,14 @@ static void resize_buf(VuiBuffer *buf, unsigned nw, unsigned nh) {
static void vui_resize(unsigned nw, unsigned nh) {
resize_buf(&vui_win.buf1, nw, nh);
resize_buf(&vui_win.buf2, nw, nh);
- vui_win.width = nw;
+ vui_win.width = nw;
vui_win.height = nh;
}
static void vui_adjust(void) {
unsigned w, h;
vui_getwinsz(&w, &h);
- if (w != vui_win.width || h != vui_win.height) {
+ if (w != COLS || h != LINES) {
vui_resize(w, h);
vui_win.redraw_all = 1;
}
@@ -212,40 +215,61 @@ static void free_buf(VuiBuffer *buf) {
buf->height = 0;
}
+static inline int bchr_equiv(VuiBuffer *back, VuiBuffer *front, int x, int y) {
+ return BCHR(back,x,y) == BCHR(front,x,y)
+ && (BATTR(back,x,y) == BATTR(front,x,y)
+ /* || BCHR(back,x,y) == ' ' */);
+}
+
+static char *vui_out = NULL;
+static size_t vui_outn = 0;
+static size_t vui_out_cap = 0;
+
void vui_fini(void) {
tcsetattr(STDIN_FILENO, TCSANOW, &vui_init_stdin_tos);
tcsetattr(STDOUT_FILENO, TCSANOW, &vui_init_stdout_tos);
vui_curs_vis(1);
free_buf(&vui_win.buf1);
free_buf(&vui_win.buf2);
+ free(vui_out);
+ vui_out = NULL;
+ vui_out_cap = 0;
printf(CSI "H" CSI "2J" CSI "0m");
}
-static inline int bchr_equiv(VuiBuffer *back, VuiBuffer *front, int x, int y) {
- return BCHR(back,x,y) == BCHR(front,x,y)
- && (BATTR(back,x,y) == BATTR(front,x,y)
- /* || BCHR(back,x,y) == ' ' */);
+void vui_out_fit(size_t n) {
+ size_t c = stdc_bit_ceil(n);
+ if (c > vui_out_cap) {
+ char *p = realloc(vui_out, c);
+ if (!p) {
+ vui_fini();
+ fprintf(stderr, "failed to reallocate vui output buffer\n");
+ exit(1);
+ }
+ vui_out = p;
+ vui_out_cap = c;
+ }
}
-static char vui_out[65536];
-static unsigned short vui_outn = 0;
-
void vui_outf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int n = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
va_start(ap, fmt);
+ vui_out_fit(vui_outn + n);
vsprintf(&vui_out[vui_outn], fmt, ap);
vui_outn += n;
va_end(ap);
}
static inline void vui_outc(char c) {
+ vui_out_fit(vui_outn + 1);
vui_out[vui_outn++] = c;
}
static inline void vui_outsn(const char *s, unsigned n) {
+ vui_out_fit(vui_outn + n);
memcpy(&vui_out[vui_outn], s, n);
vui_outn += n;
}
@@ -257,7 +281,7 @@ static inline void vui_outs(const char *s) {
static inline void vui_out_flush(void) {
fwrite(vui_out, 1, vui_outn, stdout);
fflush(stdout);
-#if 1
+#if 0
static unsigned out_frame = 0;
FILE *f = fopen("out_log.txt", "a");
assert(f);
@@ -287,9 +311,9 @@ static inline void curs_move(int src_x, int src_y, int dst_x, int dst_y) {
}
} else if (src_y != dst_y) {
if (dst_y == src_y - 1) {
- vui_outs("\x1bM");
+ vui_outs("\x1b" "M");
} else if (dst_y == src_y + 1) {
- vui_outs("\x1bD");
+ vui_outs("\x1b" "D");
} if (dst_y > 0) {
vui_outf(CSI "%dd", dst_y + 1);
} else {
@@ -302,12 +326,17 @@ static void attr_chg(VuiAttr *ptr, VuiAttr to) {
VuiAttr from = *ptr;
if (from == to) return;
- int chg_attr = (ATTR_A(from) != ATTR_A(to));
- chg_attr = 0;
+ int attr_chg_count = stdc_count_ones(ATTR_A(from) ^ ATTR_A(to));
+ int chg_attr = !!attr_chg_count;
+ if (!chg_attr) goto chg_colors;
+
+ /* deduct color changes */
+ attr_chg_count -= (ATTR_FG(to) == ATTR_FG(from)) && (ATTR_FG(to) != ATTR_DEFAULT);
+ attr_chg_count -= (ATTR_BG(to) == ATTR_BG(from)) && (ATTR_BG(to) != ATTR_DEFAULT);
- /* popcnt(f_attr ^ t_attr) to detect nr. of changes */
+ int should_rebuild = (attr_chg_count > 1) || to == ATTR_DEFAULT;
- if (chg_attr) {
+ if (should_rebuild) {
vui_outs(CSI "0");
if (to & A_BOLD) vui_outs(";1");
if (to & A_DIM) vui_outs(";2");
@@ -318,8 +347,29 @@ static void attr_chg(VuiAttr *ptr, VuiAttr to) {
from = ATTR_DEFAULT;
assert(ATTR_FG(from) == FG_WHITE);
assert(ATTR_BG(from) == BG_BLACK);
+ } else {
+ vui_outs(CSI);
+ if ((to ^ from) & A_BOLD) {
+ if (to & A_BOLD) vui_outs(";1");
+ else {
+ vui_outs(";22");
+ from &= (~A_BOLD & ~A_DIM);
+ }
+ }
+ if ((to ^ from) & A_DIM) {
+ if (to & A_BOLD) vui_outs(";2");
+ else {
+ vui_outs(";22");
+ from &= (~A_BOLD & ~A_DIM);
+ }
+ }
+ if ((to ^ from) & A_ITALIC) vui_outs((to & A_ITALIC) ? ";3" : ";23");
+ if ((to ^ from) & A_UNDERSCORE) vui_outs((to & A_UNDERSCORE) ? ";4" : ";24");
+ if ((to ^ from) & A_BLINK) vui_outs((to & A_BLINK) ? ";5" : ";25");
+ if ((to ^ from) & A_REVERSE) vui_outs((to & A_REVERSE) ? ";7" : ";27");
}
+chg_colors:
int f_fg = ATTR_FG(from);
int f_bg = ATTR_BG(from);
int t_fg = ATTR_FG(to);
@@ -352,6 +402,7 @@ static void attr_chg(VuiAttr *ptr, VuiAttr to) {
unsigned vui_changes = 0;
unsigned vui_max_change = 0;
unsigned vui_out_chars = 0;
+int scrolled_x = 0, scrolled_y = 0;
void vui_scroll_buf(VuiBuffer *b, int dx, int dy);
@@ -362,15 +413,20 @@ void vui_blit(void) {
vui_outf(CSI "H" CSI "0m");
VuiAttr attr_last = ATTR_DEFAULT;
+ scrolled_x = vui_win.scroll_x;
+ scrolled_y = vui_win.scroll_y;
+
if (vui_win.redraw_all) {
- vui_changes = vui_win.width * vui_win.height;
- for (unsigned y = 0; y < vui_win.height; y++) {
- for (unsigned x = 0; x < vui_win.width; x++) {
+ vui_changes = COLS * LINES;
+ for (unsigned y = 0; y < LINES; y++) {
+ for (unsigned x = 0; x < COLS; x++) {
attr_chg(&attr_last, ATTR(x, y));
vui_outc(CHR(x, y));
}
}
vui_win.redraw_all = 0;
+ vui_win.scroll_x = 0;
+ vui_win.scroll_y = 0;
goto copy_buf;
}
@@ -390,24 +446,25 @@ void vui_blit(void) {
*/
if (vui_win.scroll_x || vui_win.scroll_y) {
- if (abs(vui_win.scroll_x) >= vui_win.width || abs(vui_win.scroll_y) > vui_win.height) {
+ if (abs(vui_win.scroll_x) >= COLS || abs(vui_win.scroll_y) > LINES) {
vui_outs(CSI "2J");
goto scrolled;
}
if (vui_win.scroll_x < 0) {
- for (unsigned y = 0; y < vui_win.height; y++) {
+ for (unsigned y = 0; y < LINES; y++) {
curs_move(cur_x, cur_y, 0, y);
vui_outf(CSI "%dP", -vui_win.scroll_x);
cur_y = y;
}
} else if (vui_win.scroll_x > 0) {
- for (unsigned y = 0; y < vui_win.height; y++) {
+ for (unsigned y = 0; y < LINES; y++) {
curs_move(cur_x, cur_y, 0, y);
vui_outf(CSI "%d@", vui_win.scroll_x);
cur_y = y;
}
}
+
if (vui_win.scroll_y < 0) {
if (vui_win.scroll_y == -1) vui_outs(CSI "S");
else vui_outf(CSI "%dS", -vui_win.scroll_y);
@@ -422,14 +479,17 @@ scrolled:
vui_win.scroll_y = 0;
}
- for (unsigned y = 0; y < vui_win.height; y++) {
+ vui_win.scroll_x = 0;
+ vui_win.scroll_y = 0;
+
+ for (unsigned y = 0; y < LINES; y++) {
unsigned x = 0;
- while (x < vui_win.width) {
- while (x < vui_win.width && bchr_equiv(back, front, x, y)) x++;
- if (x >= vui_win.width) break;
+ while (x < COLS) {
+ while (x < COLS && bchr_equiv(back, front, x, y)) x++;
+ if (x >= COLS) break;
unsigned x0 = x;
VuiAttr a = ATTR(x0, y);
- while (x < vui_win.width && !bchr_equiv(back, front, x, y) && ATTR(x, y) == a) x++;
+ while (x < COLS && !bchr_equiv(back, front, x, y) && ATTR(x, y) == a) x++;
if (x0 != x) {
vui_changes++;
curs_move(cur_x, cur_y, x0, y);
@@ -452,7 +512,7 @@ copy_buf:
}
void vui_chra(int x, int y, char c, VuiAttr a) {
- if (x >= 0 && x < (int)vui_win.width && y >= 0 && y < (int)vui_win.height) {
+ if (x >= 0 && x < (int)COLS && y >= 0 && y < (int)LINES) {
CHR(x, y) = c;
ATTR(x, y) = a;
}
@@ -463,18 +523,17 @@ void vui_chr(int x, int y, char c) {
}
int vui_avprintf(int x, int y, VuiAttr a, const char *fmt, va_list ap) {
- //return 0;
va_list ap2;
va_copy(ap2, ap);
int n = vsnprintf(NULL, 0, fmt, ap);
- if (x < 0) x = vui_win.width + x - (n - 1);
- if (y < 0) y = vui_win.height + y;
- if (x >= vui_win.width || y >= vui_win.height) return n;
+ if (x < 0) x = COLS + x - (n - 1);
+ if (y < 0) y = LINES + y;
+ if (x >= COLS || y >= LINES) return n;
if (n > 0) {
char buf[n + 1];
vsnprintf(buf, n + 1, fmt, ap2);
- memcpy(&CHR(x,y), buf, n < vui_win.width - x ? n : vui_win.width - x);
- for (unsigned x1 = x; x1 < vui_win.width && x1 < x + n; x1++) {
+ memcpy(&CHR(x,y), buf, n < COLS - x ? n : COLS - x);
+ for (unsigned x1 = x; x1 < COLS && x1 < x + n; x1++) {
ATTR(x1, y) = a;
}
}
@@ -524,22 +583,14 @@ void vui_scroll_buf(VuiBuffer *b, int dx, int dy) {
}
if (dx > 0) {
for (unsigned i = 0; i < b->height; i++) {
- memmove(b->chr + (i * b->width) + dx, b->chr + (i * b->width), sizeof(*b->chr) * (b->width - dx));
- }
- for (unsigned i = 0; i < b->height; i++) {
+ memmove(b->chr + (i * b->width) + dx, b->chr + (i * b->width), sizeof(*b->chr) * (b->width - dx));
memmove(b->attr + (i * b->width) + dx, b->attr + (i * b->width), sizeof(*b->attr) * (b->width - dx));
- }
- for (unsigned i = 0; i < b->height; i++) {
vui_clrspan(b, 0, dx, i);
}
} else if (dx < 0) {
for (unsigned i = 0; i < b->height; i++) {
memmove(b->chr + (i * b->width), b->chr + (i * b->width) - dx, sizeof(*b->chr) * (b->width + dx));
- }
- for (unsigned i = 0; i < b->height; i++) {
memmove(b->attr + (i * b->width), b->attr + (i * b->width) - dx, sizeof(*b->attr) * (b->width + dx));
- }
- for (unsigned i = 0; i < b->height; i++) {
vui_clrspan(b, b->width + dx - 1, b->width, i);
}
@@ -557,7 +608,7 @@ int dx = 0, dy = 0;
int camx = 0, camy = 0;
int C = '*';
unsigned frame = 0;
-int half_y = 1;
+int half_y = 0;
void draw(void *ctx) {
(void)ctx;
@@ -568,9 +619,9 @@ void draw(void *ctx) {
vui_chra(x, y-1, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE);
vui_chra(x, y+1, C, ((x + y) & 0xf) | BG_BLUE | A_UNDERSCORE);
- vui_printf(-1, -1, "(%u, %u)", vui_win.width, vui_win.height);
- //vui_printf(0, -1, "front buffer = %p", (void*)vui_win.front);
- vui_printf(-1, 0, "longest change = %3u, changes = %5u, output = %5u, chars = %5u", vui_max_change, vui_changes, vui_out_chars, vui_win.width * vui_win.height);
+ vui_printf(-1, -1, "(%u, %u)", COLS, LINES);
+ vui_printf(0, -1, "scrolled (%d, %d)", scrolled_x, scrolled_y);
+ vui_printf(-1, 0, "longest change = %3u, changes = %5u, output = %5u, chars = %5u", vui_max_change, vui_changes, vui_out_chars, COLS * LINES);
vui_blit();
}
@@ -581,18 +632,15 @@ int main(int argc, const char **argv) {
for (;;) {
frame++;
- //camx += dx;
x += dx;
int ydy = dy;
- if (half_y) {
- ydy = (frame & 1) ? (dy / 2) : dy - (dy / 2);
- }
+ if (half_y) ydy = (frame & 1) ? (dy / 2) : dy - (dy / 2);
y += ydy;
- unsigned left = 32;
- unsigned right = vui_win.width - (left + 1);
- unsigned top = left >> half_y;
- unsigned bottom = vui_win.height - (top + 1);
+ int left = 32;
+ int right = COLS - (left + 1);
+ int top = left >> half_y;
+ int bottom = LINES - (top + 1);
int lcamx = camx, lcamy = camy;
if (x < left) { camx += x - left; x = left; }
@@ -616,21 +664,25 @@ int main(int argc, const char **argv) {
#if 1
/* weird cellular automata */
if (!paused) {
- // int dx = 0, dy = 0; /* shadow on purpose */
-
- for (int y = 0; y < vui_win.height; y++) {
- for (int x = 0; x < vui_win.width; x++) {
+ int vsteps = (COLS * LINES) / 2048;
+ if (!vsteps) vsteps++;
+ vsteps = 1;
+ int y0 = LINES * (frame % vsteps) / vsteps;
+ int y1 = y0 + LINES / vsteps;
+ if (y1 > LINES) y1 = LINES;
+ for (int y = y0; y < y1; y++) {
+ for (int x = 0; x < COLS; x++) {
if (frame & 1) {
int txa = x, tya = y, txc = x, tyc = y;
txa += (random() % 3) - 1;
tya += (random() % 3) - 1;
txc += (random() % 3) - 1;
tyc += (random() % 3) - 1;
- if (txa >= 0 && txa < vui_win.width && tya >= 0 && tya < vui_win.height) {
+ if (txa >= 0 && txa < COLS && tya >= 0 && tya < LINES) {
ATTR(txa, tya) = (BATTR(vui_win.back,x,y) & ~0xf) | (ATTR(txa,tya) & 0xf);
if (!(random() & 127)) ATTR(x,y) = ATTR_DEFAULT;
}
- if (txc >= 0 && txc < vui_win.width && tyc >= 0 && tyc < vui_win.height) {
+ if (txc >= 0 && txc < COLS && tyc >= 0 && tyc < LINES) {
CHR(txc, tyc) = BCHR(vui_win.back, x, y);
ATTR(txc, tyc) = (ATTR(txc,tyc) & ~0xf) | (BATTR(vui_win.back,x,y) & 0xf);
if (!(random() & 127)) CHR(x,y) = ' ';
@@ -639,10 +691,9 @@ int main(int argc, const char **argv) {
}
}
- //vui_win.redraw_all = 1;
- for (unsigned i = 0; i < isqrt(vui_win.width * vui_win.height) / 10; i++) {
- int tx = random() % vui_win.width;
- int ty = random() % vui_win.height;
+ for (unsigned i = 0; i < isqrt(COLS * LINES) / 10; i++) {
+ int tx = random() % COLS;
+ int ty = random() % LINES;
VuiAttr a = ((random()&15) << 4) | (random()&15);
vui_chra(tx, ty, ' ' + (random() % 0x5f), a);
}
@@ -650,8 +701,8 @@ int main(int argc, const char **argv) {
#else
vui_clear();
- for (unsigned y = 0; y < vui_win.height; y++) {
- for (unsigned x = 0; x < vui_win.width; x++) {
+ for (unsigned y = 0; y < LINES; y++) {
+ for (unsigned x = 0; x < COLS; x++) {
int tx = x + camx, ty = y + camy;
char ch = " ',."[(tx^ty)&3];
ch = ' ';
@@ -660,7 +711,6 @@ int main(int argc, const char **argv) {
}
}
#endif
- // win.redraw_all = 1;
draw(NULL);
clock_nanosleep(CLOCK_MONOTONIC, 0, &(struct timespec) { .tv_nsec = 15 * 1000000 }, NULL);
@@ -684,6 +734,6 @@ int main(int argc, const char **argv) {
}
}
vui_fini();
- printf(CSI "2J" CSI "H %u, %u\n", vui_win.width, vui_win.height);
+ printf(CSI "2J" CSI "H %u, %u\n", COLS, LINES);
return 0;
}