/* See LICENSE file for copyright and license details. */ #include #include 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 :"); } 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; }