about summary refs log tree commit diff stats
path: root/baremetal/vga_palette.c
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2021-01-12 19:50:22 -0800
committerKartik Agaram <vc@akkartik.com>2021-01-12 19:50:22 -0800
commite59086e65a204740da5ba1cf6a70c262bfc03b69 (patch)
treec2f55702aab0ed1d0195092ccbd56100d95183c3 /baremetal/vga_palette.c
parent0d12f6676bab81d1d68239dcd26089612450232d (diff)
downloadmu-e59086e65a204740da5ba1cf6a70c262bfc03b69.tar.gz
7503 - baremetal: noodling on default VGA palette
Diffstat (limited to 'baremetal/vga_palette.c')
-rw-r--r--baremetal/vga_palette.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/baremetal/vga_palette.c b/baremetal/vga_palette.c
new file mode 100644
index 00000000..11a440ce
--- /dev/null
+++ b/baremetal/vga_palette.c
@@ -0,0 +1,168 @@
+/* Visualize the standard VGA palette.
+ * Based on https://github.com/canidlogic/vgapal (MIT License) */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+char* bar(int n) {
+  char* result = calloc(65, 1);
+  int i;
+  for (i = 0; i < n; ++i)
+    result[i] = '.';
+  for (; i < 64; ++i)
+    result[i] = ' ';
+  result[64] = '\0';
+  return result;
+}
+
+void addColor(int r, int g, int b) {
+  static int i = 0;
+//?   printf("%02x %02x %02x\n", r, g, b);
+  printf("%3d: %2d %2d %2d %s %s %s\n", i, r, g, b, bar(r), bar(g), bar(b));
+  ++i;
+}
+
+void addGrayColor(int v) {
+  addColor(v, v, v);
+}
+
+void add16Color(int lo, int melo, int mehi, int hi) {
+  int r, g, b, i, h, l;
+
+  for (i = 0; i < 8; i++) {
+    r = g = b = lo;
+    if (i & 4) r = mehi;
+    if (i & 2) g = (i==6)?melo:mehi;  /* exception: color 6 is brown rather than dark yellow */
+    if (i & 1) b = mehi;
+    addColor(r, g, b);
+  }
+
+  for (i = 0; i < 8; i++) {
+    r = g = b = melo;
+    if (i & 4) r = hi;
+    if (i & 2) g = hi;
+    if (i & 1) b = hi;
+    addColor(r, g, b);
+  }
+}
+
+/* Add four colors to the palette corresponding to a "run" within an RGB cycle.
+ *
+ * start - high and low starting states for each channel at the start of the run
+ * ch - the channel to change from high to low or low to high */
+void addRun(int start, int ch, int lo, int melo, int me, int mehi, int hi) {
+  int r, g, b, i, up;
+
+  /* Check parameters */
+  if (start < 0 || start > 7)
+    abort();
+  if (ch != 1 && ch != 2 && ch != 4)
+    abort();
+
+  /* Get the starting RGB color and add it */
+  r = lo;
+  g = lo;
+  b = lo;
+  if ((start & 4) == 4)
+    r = hi;
+  if ((start & 2) == 2)
+    g = hi;
+  if ((start & 1) == 1)
+    b = hi;
+  addColor(r, g, b);
+
+  /* If selected channel starts high, we're going down; otherwise we're going up */
+  up = (start & ch) != ch;
+
+  /* Add remaining three colors of the run */
+  switch (ch) {
+  case 4:  r = up?melo:mehi; break;
+  case 2:  g = up?melo:mehi; break;
+  case 1:  b = up?melo:mehi; break;
+  }
+  addColor(r, g, b);
+
+  switch (ch) {
+  case 4:  r = me; break;
+  case 2:  g = me; break;
+  case 1:  b = me; break;
+  }
+  addColor(r, g, b);
+
+  switch (ch) {
+  case 4:  r = up?mehi:melo; break;
+  case 2:  g = up?mehi:melo; break;
+  case 1:  b = up?mehi:melo; break;
+  }
+  addColor(r, g, b);
+}
+
+/* A cycle consists of six 4-color runs, each of which transitions from
+ * one hue to another until arriving back at starting position. */
+void addCycle(int lo, int melo, int me, int mehi, int hi) {
+  int hue = 1;  /* blue */
+  addRun(hue, 4, lo, melo, me, mehi, hi);
+  hue ^= 4;
+  assert(hue == 5);
+  addRun(hue, 1, lo, melo, me, mehi, hi);
+  hue ^= 1;
+  assert(hue == 4);
+  addRun(hue, 2, lo, melo, me, mehi, hi);
+  hue ^= 2;
+  assert(hue == 6);
+  addRun(hue, 4, lo, melo, me, mehi, hi);
+  hue ^= 4;
+  assert(hue == 2);
+  addRun(hue, 1, lo, melo, me, mehi, hi);
+  hue ^= 1;
+  assert(hue == 3);
+  addRun(hue, 2, lo, melo, me, mehi, hi);
+}
+
+int main(void) {
+  int i;
+
+  /* 16-color palette */
+  add16Color(0, 21, 42, 63);
+
+  /* 16 shades of gray */
+  addGrayColor( 0);
+  addGrayColor( 5);
+  addGrayColor( 8);
+  addGrayColor(11);
+  addGrayColor(14);
+  addGrayColor(17);
+  addGrayColor(20);
+  addGrayColor(24);
+  addGrayColor(28);
+  addGrayColor(32);
+  addGrayColor(36);
+  addGrayColor(40);
+  addGrayColor(45);
+  addGrayColor(50);
+  addGrayColor(56);
+  addGrayColor(63);
+
+  /* Nine RGB cycles organized in three groups of three cycles,
+   * The groups represent high/medium/low value,
+   * and the cycles within the groups represent high/medium/low saturation. */
+  addCycle( 0, 16, 31, 47, 63);
+  addCycle(31, 39, 47, 55, 63);
+  addCycle(45, 49, 54, 58, 63);
+
+  addCycle( 0,  7, 14, 21, 28);
+  addCycle(14, 17, 21, 24, 28);
+  addCycle(20, 22, 24, 26, 28);
+
+  addCycle( 0,  4,  8, 12, 16);
+  addCycle( 8, 10, 12, 14, 16);
+  addCycle(11, 12, 13, 15, 16);
+
+  /* final eight palette entries are full black */
+  for (i = 0; i < 8; ++i)
+    addGrayColor(0);
+
+  return 0;
+}