aboutsummaryrefslogtreecommitdiffstats
path: root/usr/ansi.c
diff options
context:
space:
mode:
authoruser <user@clank>2026-07-18 20:41:27 +0200
committeruser <user@clank>2026-07-18 20:41:27 +0200
commit9e7d5f6e5e01b7473b84bc3449d7f8e0f78e7045 (patch)
tree5dcde624f3b366cc9244e08b0d2ca4ab35b338e2 /usr/ansi.c
parentkernel: a real timer source (64 Hz tick IRQ) + uptime(1) (diff)
downloadgbos-9e7d5f6e5e01b7473b84bc3449d7f8e0f78e7045.tar.gz
gbos-9e7d5f6e5e01b7473b84bc3449d7f8e0f78e7045.tar.xz
gbos-9e7d5f6e5e01b7473b84bc3449d7f8e0f78e7045.zip
term: 7-color terminal (per-glyph fg+bg) + ANSI escapes; colorize irc
Fano-plane palette scheme: the 7 colors map onto 7 CGB BG palettes so any color pair shares one palette; a tile's palette is picked from the set of colors its two cells need (tables generated by tools/gencolor.py). Per cell a packed (bg<<4)|fg byte lives alongside the char shadow, and the glyph blitter steers glyph/empty pixels to each cell's fg/bg color slots via plane masks. An ANSI-ish CSI parser (ESC [ .. m) drives it; usr/ansi.c demos it and the irc client now renders hashed nick colors, status dimming and a channel-activity bar.
Diffstat (limited to 'usr/ansi.c')
-rw-r--r--usr/ansi.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/usr/ansi.c b/usr/ansi.c
new file mode 100644
index 0000000..0e73ff8
--- /dev/null
+++ b/usr/ansi.c
@@ -0,0 +1,67 @@
+#include "gbos.h"
+/* ansi - show the terminal's 7-color ANSI support. Also stress-tests per-glyph
+ * coloring: adjacent characters (which share an 8x8 tile) get different colors.
+ *
+ * NB: no initialized statics / pointer arrays here - SDCC would place them in
+ * the _INITIALIZED area at $A000 (the RAM window), overflowing the 16K image. */
+
+static void sgr(unsigned char n) { /* emit ESC [ n m */
+ putc(27);
+ putc('[');
+ putu(n);
+ putc('m');
+}
+
+void main(void) {
+ unsigned char i, c;
+ const char *s;
+
+ puts("ANSI 7-color test"); nl();
+
+ /* each color name printed in its own color (31..37) */
+ sgr(31); puts("red ");
+ sgr(32); puts("green ");
+ sgr(33); puts("yellow ");
+ sgr(34); puts("blue ");
+ sgr(35); puts("magenta ");
+ sgr(36); puts("cyan ");
+ sgr(37); puts("white");
+ sgr(0); nl();
+
+ /* per-glyph stress: 40 bars, color changes every single character, so the
+ * left/right halves of one tile differ - impossible with a per-tile palette */
+ c = 31;
+ for (i = 0; i < 40; i++) {
+ sgr(c);
+ putc('#');
+ if (++c > 37) c = 31;
+ }
+ sgr(0); nl();
+
+ /* one word, one color per letter */
+ c = 31;
+ s = "RAINBOW!";
+ for (i = 0; s[i]; i++) {
+ sgr(c);
+ putc(s[i]);
+ if (++c > 37) c = 31;
+ }
+ sgr(0); nl();
+
+ /* background colors: a block of each (SGR 41..47), default white text */
+ puts("backgrounds:"); nl();
+ c = 41;
+ for (i = 0; i < 7; i++) {
+ putc(27); putc('['); putc('4'); putc((char)('0' + (c - 40))); putc('m');
+ puts(" bg ");
+ if (++c > 47) c = 41;
+ }
+ sgr(0); nl();
+
+ /* foreground-on-background combos (one CSI carries both: ESC[fg;bg m) */
+ puts("\033[37;41m wht/red \033[33;44m yel/blu \033[34;43m blu/yel "
+ "\033[32;45m grn/mag \033[36;41m cyn/red \033[0m"); nl();
+
+ /* per-glyph fg over a shared bg: adjacent letters differ, bg stays green */
+ puts("\033[42m\033[31mR\033[33mA\033[34mI\033[35mN\033[37mBOW\033[0m"); nl();
+}