aboutsummaryrefslogtreecommitdiffstats
path: root/sumart.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sumart.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/sumart.c b/sumart.c
new file mode 100644
index 0000000..e5ae509
--- /dev/null
+++ b/sumart.c
@@ -0,0 +1,215 @@
+/* See LICENSE file for copyright and license details. */
+#include <libsimple.h>
+#include <libsimple-arg.h>
+
+USAGE("[rows columns] [checksum]");
+
+#define BITS 2
+
+
+int
+main(int argc, char *argv[])
+{
+#if BITS == 5
+ static const ssize_t x_movements[1 << BITS] = {
+ -3, -2, -1, +1, +2, +3,
+ -3, -2, -1, +1, +2, +3,
+ -3, -2, +2, +3,
+ -3, -2, +2, +3,
+ -3, -2, -1, +1, +2, +3,
+ -3, -2, -1, +1, +2, +3,
+ };
+ static const ssize_t y_movements[1 << BITS] = {
+ -3, -3, -3, -3, -3, -3,
+ -2, -2, -2, -2, -2, -2,
+ -1, -1, -1, -1,
+ +1, +1, +1, +1,
+ +2, +2, +2, +2, +2, +2,
+ +3, +3, +3, +3, +3, +3,
+ };
+#elif BITS == 4
+ static const ssize_t x_movements[1 << BITS] = {
+ -2, -1, 0, 0, +1, +2,
+ -2, -1, +1, +2,
+ -2, -1, 0, 0, +1, +2
+ };
+ static const ssize_t y_movements[1 << BITS] = {
+ -2, -1, -2, -1, -2, -1,
+ 0, 0, 0, 0,
+ +1, +2, +1, +2, +1, +2
+ };
+#elif BITS == 3
+ static const ssize_t x_movements[1 << BITS] = {
+ -1, 0, +1,
+ -1, +1,
+ -1, 0, +1
+ };
+ static const ssize_t y_movements[1 << BITS] = {
+ -1, -1, -1,
+ 0, 0,
+ +1, +1, +1
+ };
+#elif BITS == 2
+# if 0
+ static const ssize_t x_movements[1 << BITS] = {
+ -1, +1,
+ -1, +1
+ };
+ static const ssize_t y_movements[1 << BITS] = {
+ -1, -1,
+ +1, +1
+ };
+# else
+ static const ssize_t x_movements[1 << BITS] = {
+ 0, -1,
+ +1, 0
+ };
+ static const ssize_t y_movements[1 << BITS] = {
+ -1, 0,
+ 0, +1
+ };
+# endif
+#endif
+
+ static const char *const symbols[] = {
+ ":", ".", "+", "=",
+ "¤", "o", "*", "£",
+ "X", "%", "&", "B",
+ "@", "#", "/", "^"
+ };
+ static const char *const colours[] = {
+ "", "34;1", "33;1"
+ };
+
+ const char *checksum;
+ char *data = NULL, *end;
+ size_t size = 0u;
+ size_t len = 0u, cell;
+ size_t i, n, x[2], y[2], v, bits;
+ int d, colour;
+ ssize_t r;
+ size_t rows = 15u, cols = 32u;
+ unsigned char *art;
+
+ ARGBEGIN {
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc > 1) {
+ if ('1' > argv[0][0u] || argv[0][0u] > '9' ||
+ '1' > argv[1][0u] || argv[1][0u] > '9')
+ usage();
+
+ errno = 0;
+ rows = strtouz(argv[0], &end, 10);
+ if (!rows || *end || errno)
+ usage();
+ cols = strtouz(argv[1], &end, 10);
+ if (!cols || *end || errno)
+ usage();
+
+ argc -= 2;
+ argv += 2;
+ }
+
+ if (argc > 1)
+ usage();
+
+ if (argc) {
+ checksum = *argv;
+ } else {
+ for (;;) {
+ if (len == size)
+ data = erealloc(data, size += 128u);
+ r = read(STDIN_FILENO, &data[len], size - len);
+ if (r <= 0) {
+ if (!r)
+ break;
+ if (errno == EINVAL)
+ continue;
+ eprintf("read <stdin>:");
+ }
+ n = len + (size_t)r;
+ for (i = len; i < n; i++) {
+ if (('0' <= data[i] && data[i] <= '9') ||
+ ('A' <= data[i] && data[i] <= 'F') ||
+ ('a' <= data[i] && data[i] <= 'f'))
+ data[len++] = data[i];
+ }
+ }
+ data = erealloc(data, len + 1u);
+ data[len] = '\0';
+ checksum = data;
+ }
+
+ art = ecalloc(rows, cols);
+
+ x[0] = x[1] = cols / 2u;
+ y[0] = y[1] = rows / 2u;
+
+ colour = 0;
+ v = 0u;
+ bits = 0u;
+ for (i = 0u; checksum[i]; i++) {
+ if (('0' > checksum[i] || checksum[i] > '9') &&
+ ('A' > checksum[i] || checksum[i] > 'F') &&
+ ('a' > checksum[i] || checksum[i] > 'f'))
+ continue;
+ d = ((int)checksum[i] & 15) + (checksum[i] > '9' ? 9 : 0);
+ v <<= 4;
+ v |= (size_t)d;
+ bits += 4u;
+ while (bits >= BITS) {
+ x[colour] += (size_t)x_movements[v % ELEMSOF(x_movements)];
+ y[colour] += (size_t)y_movements[v % ELEMSOF(y_movements)];
+ x[colour] %= cols;
+ y[colour] %= rows;
+ cell = y[colour] * cols + x[colour];
+ art[cell] = (unsigned char)(art[cell] + (colour ? 0x20u : 1u));
+ art[cell] &= 0xEFu;
+ v >>= BITS;
+ bits -= BITS;
+ if (ELEMSOF(colours) > 1u)
+ colour ^= 1;
+ }
+ }
+ if (bits) {
+ x[colour] += (size_t)x_movements[v % ELEMSOF(x_movements)];
+ y[colour] += (size_t)y_movements[v % ELEMSOF(y_movements)];
+ x[colour] %= cols;
+ y[colour] %= rows;
+ cell = y[colour] * cols + x[colour];
+ art[cell] = (unsigned char)(art[cell] + (colour ? 0x20u : 1u));
+ art[cell] &= 0xEFu;
+ }
+
+ printf("+");
+ for (i = 0u; i < cols; i++)
+ printf("-");
+ printf("+\n");
+ for (*y = 0u; *y < rows; ++*y) {
+ printf("|");
+ for (*x = 0u; *x < cols; ++*x) {
+ cell = *y * cols + *x;
+ if (!art[cell]) {
+ printf(" ");
+ continue;
+ }
+ printf("\033[%sm%s\033[m",
+ colours[(art[cell] / 0x20u) % ELEMSOF(colours)],
+ symbols[(art[cell] & 0x0Fu) % ELEMSOF(symbols)]);
+ }
+ printf("|\n");
+ }
+ printf("+");
+ for (i = 0u; i < cols; i++)
+ printf("-");
+ printf("+\n");
+
+ if (ferror(stdout) || fclose(stdout))
+ eprintf("printf:");
+ free(art);
+ free(data);
+ return 0;
+}