From 26d456155d6e812420217494e1944f0df2f01e83 Mon Sep 17 00:00:00 2001 From: Kristopher38 Date: Wed, 21 Feb 2024 12:33:25 +0100 Subject: [PATCH] Prepare ZOSIA demo --- litex/soc/cores/cpu/coreblocks/core.py | 2 +- litex/soc/software/demo/Makefile | 2 +- litex/soc/software/demo/donut2.c | 241 +++++++ litex/soc/software/demo/lena.c | 246 +++++++ litex/soc/software/demo/main.c | 21 + litex/soc/software/demo/mandelbrot.c | 79 +++ litex/soc/software/demo/nyancat.c | 940 +++++++++++++++++++++++++ litex/soc/software/demo/qrcode.c | 431 ++++++++++++ litex/soc/software/demo/spirograph.c | 433 ++++++++++++ 9 files changed, 2393 insertions(+), 2 deletions(-) create mode 100644 litex/soc/software/demo/donut2.c create mode 100644 litex/soc/software/demo/lena.c create mode 100644 litex/soc/software/demo/mandelbrot.c create mode 100644 litex/soc/software/demo/nyancat.c create mode 100644 litex/soc/software/demo/qrcode.c create mode 100644 litex/soc/software/demo/spirograph.c diff --git a/litex/soc/cores/cpu/coreblocks/core.py b/litex/soc/cores/cpu/coreblocks/core.py index 55015bc44..491a9fd0b 100644 --- a/litex/soc/cores/cpu/coreblocks/core.py +++ b/litex/soc/cores/cpu/coreblocks/core.py @@ -25,7 +25,7 @@ GCC_FLAGS = { "minimal": "-march=rv32e2p1 -mabi=ilp32 ", - "standard": "-march=rv32i2p1_zicsr -mabi=ilp32 ", + "standard": "-march=rv32im2p1_zicsr -mabi=ilp32 ", "full": "-march=rv32i2p1_mc_zba_zbb_zbc_zbs_zicsr -mabi=ilp32 ", } diff --git a/litex/soc/software/demo/Makefile b/litex/soc/software/demo/Makefile index a30071a51..f13ef6c75 100644 --- a/litex/soc/software/demo/Makefile +++ b/litex/soc/software/demo/Makefile @@ -3,7 +3,7 @@ BUILD_DIR?=../build/ include $(BUILD_DIR)/software/include/generated/variables.mak include $(SOC_DIRECTORY)/software/common.mak -OBJECTS = donut.o helloc.o crt0.o main.o +OBJECTS = qrcode.o spirograph.o nyancat.o mandelbrot.o donut2.o donut.o helloc.o crt0.o main.o ifdef WITH_CXX OBJECTS += hellocpp.o CFLAGS += -DWITH_CXX diff --git a/litex/soc/software/demo/donut2.c b/litex/soc/software/demo/donut2.c new file mode 100644 index 000000000..569125b06 --- /dev/null +++ b/litex/soc/software/demo/donut2.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2023 Andy Sloane + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Source: https://github.com/a1k0n/donut-raymarch + * Modified by Jim Huang + * - Refine the comments + * - Colorize the renderer + * - Support nanosleep + */ + +/* An ASCII donut renderer that relies solely on shifts, additions, + * subtractions, and does not use sine, cosine, square root, division, or + * multiplication instructions. It operates without requiring framebuffer + * memory throughout the entire process. + */ + +#include +#include +#include +// #include + +/* 0 for 80x24, 1 for 160x48, etc. */ +enum { + RESX_SHIFT = 0, + RESY_SHIFT = 0, +}; + +/* Torus radius and camera distance. + * These values are closely tied to other constants, so modifying them + * significantly may lead to unexpected behavior. + */ +static const int dz = 5, r1 = 1, r2 = 2; + +/* "Magic Circle Algorithm" or DDA? + * This algorithm, which I have encountered in several sources including Hal + * Chamberlain's "Musical Applications of Microprocessors," lacks a clear + * theoretical justification. It effectively rotates around a point "near" the + * origin without significant magnitude loss, provided there is sufficient + * precision in the x and y values. Here, I'm using 14 bits. + */ +#define R(s, x, y) \ + x -= (y >> s); \ + y += (x >> s) + +/* CORDIC algorithm used to calculate the magnitude of the vector |x, y| by + * rotating the vector onto the x-axis. This operation also transforms vector + * (x2, y2) accordingly, and updates the value of x2. This rotation is employed + * to align the lighting vector with the normal of the torus surface relative + * to the camera, enabling the determination of lighting intensity. It is worth + * noting that only one of the two lighting normal coordinates needs to be + * retained. + */ +#define N_CORDIC 6 +static int length_cordic(int16_t x, int16_t y, int16_t *x2_, int16_t y2) +{ + int x2 = *x2_; + if (x < 0) { // start in right half-plane + x = -x; + x2 = -x2; + } + for (int i = 0; i < N_CORDIC; i++) { + int t = x; + int t2 = x2; + if (y < 0) { + x -= y >> i; + y += t >> i; + x2 -= y2 >> i; + y2 += t2 >> i; + } else { + x += y >> i; + y -= t >> i; + x2 += y2 >> i; + y2 -= t2 >> i; + } + } + /* Divide by 0.625 as a rough approximation to the 0.607 scaling factor + * introduced by this algorithm + * See https://en.wikipedia.org/wiki/CORDIC + */ + *x2_ = (x2 >> 1) + (x2 >> 3) - (x2 >> 6); + return (x >> 1) + (x >> 3) - (x >> 6); +} + +void donut2(void); +void donut2(void) +{ + /* Precise rotation directions, sines, cosines, and their products */ + int16_t sB = 0, cB = 16384; + int16_t sA = 11583, cA = 11583; + int16_t sAsB = 0, cAsB = 0; + int16_t sAcB = 11583, cAcB = 11583; + + for (int count = 0; count < 500; count++) { + /* This is a multiplication, but since dz is 5, it is equivalent to + * (sb + (sb << 2)) >> 6. + */ + const int16_t p0x = dz * sB >> 6; + const int16_t p0y = dz * sAcB >> 6; + const int16_t p0z = -dz * cAcB >> 6; + + const int r1i = r1 * 256; + const int r2i = r2 * 256; + + int niters = 0; + int nnormals = 0; + /* per-row increments + * These can all be compiled into two shifts and an add. + */ + int16_t yincC = (12 * cA) >> (8 + RESY_SHIFT); + int16_t yincS = (12 * sA) >> (8 + RESY_SHIFT); + + /* per-column increments */ + int16_t xincX = (6 * cB) >> (8 + RESX_SHIFT); + int16_t xincY = (6 * sAsB) >> (8 + RESX_SHIFT); + int16_t xincZ = (6 * cAsB) >> (8 + RESX_SHIFT); + + /* top row y cosine/sine */ + int16_t ycA = -((cA >> 1) + (cA >> 4)); // -12 * yinc1 = -9*cA >> 4; + int16_t ysA = -((sA >> 1) + (sA >> 4)); // -12 * yinc2 = -9*sA >> 4; + + for (int j = 0; j < (24 << RESY_SHIFT) - 1; + j++, ycA += yincC, ysA += yincS) { + /* left columnn x cosines/sines */ + int xsAsB = (sAsB >> 4) - sAsB; // -40 * xincY + int xcAsB = (cAsB >> 4) - cAsB; // -40 * xincZ; + + /* ray direction */ + int16_t vxi14 = (cB >> 4) - cB - sB; // -40 * xincX - sB; + int16_t vyi14 = (ycA - xsAsB - sAcB); + int16_t vzi14 = (ysA + xcAsB + cAcB); + + for (int i = 0; i < ((80 << RESX_SHIFT) - 1); + i++, vxi14 += xincX, vyi14 -= xincY, vzi14 += xincZ) { + int t = 512; // (256 * dz) - r2i - r1i; + + /* Assume t = 512, t * vxi >> 8 == vxi << 1 */ + int16_t px = p0x + (vxi14 >> 5); + int16_t py = p0y + (vyi14 >> 5); + int16_t pz = p0z + (vzi14 >> 5); + int16_t lx0 = sB >> 2; + int16_t ly0 = (sAcB - cA) >> 2; + int16_t lz0 = (-cAcB - sA) >> 2; + for (;;) { + int t0, t1, t2, d; + int16_t lx = lx0, ly = ly0, lz = lz0; + t0 = length_cordic(px, py, &lx, ly); + t1 = t0 - r2i; + t2 = length_cordic(pz, t1, &lz, lx); + d = t2 - r1i; + t += d; + + if (t > 8 * 256) { + putchar(' '); + break; + } else if (d < 2) { + int N = lz >> 9; + static const char charset[] = ".,-~:;!*=#$@"; + printf("\033[48;05;%dm%c\033[0m", N / 4 + 1, + charset[N > 0 ? N < 12 ? N : 11 : 0]); + nnormals++; + break; + } + + { + /* equivalent to: + * px += d*vxi14 >> 14; + * py += d*vyi14 >> 14; + * pz += d*vzi14 >> 14; + * + * idea is to make a 3d vector mul hw peripheral + * equivalent to this algorithm + */ + + /* 11x1.14 fixed point 3x parallel multiply only 16 bit + * registers needed; starts from highest bit to lowest + * d is about 2..1100, so 11 bits are sufficient. + */ + int16_t dx = 0, dy = 0, dz = 0; + int16_t a = vxi14, b = vyi14, c = vzi14; + while (d) { + if (d & 1024) { + dx += a; + dy += b; + dz += c; + } + d = (d & 1023) << 1; + a >>= 1; + b >>= 1; + c >>= 1; + } + /* We have already shifted down by 10 bits, so this + * extracts the last four bits. + */ + px += dx >> 4; + py += dy >> 4; + pz += dz >> 4; + } + + niters++; + } + } + puts(""); + } + printf("%d iterations %d lit pixels\x1b[K", niters, nnormals); + fflush(stdout); + + /* Rotate sines, cosines, and their products to animate the torus + * rotation about two axes. + */ + R(5, cA, sA); + R(5, cAsB, sAsB); + R(5, cAcB, sAcB); + R(6, cB, sB); + R(6, cAcB, cAsB); + R(6, sAcB, sAsB); + + /* FIXME: Adjust tv_nsec to align with runtime expectations. */ + // struct timespec ts = {.tv_sec = 0, .tv_nsec = 30000}; + // nanosleep(&ts, &ts); + + printf("\r\x1b[%dA", (24 << RESY_SHIFT) - 1); + } +} diff --git a/litex/soc/software/demo/lena.c b/litex/soc/software/demo/lena.c new file mode 100644 index 000000000..0f1fa68f2 --- /dev/null +++ b/litex/soc/software/demo/lena.c @@ -0,0 +1,246 @@ +/* + * This tiny C program outputs a 128x128 RGB image file to the standard output + * using the portable pixmap file format (PPM). + * + * Source: https://bellard.org/ioccc_lena/ + */ + +#include +#include +#include + +#define ACTX_SIGN 3 +#define ACTX_VDATA 4 +#define ACTX_LEN 5 +#define ACTX_LEVEL 25 +#define ACTX_IPRED 73 +#define ACTX_UE_LEN 10 +#define ACTX_COUNT2 166 +#define ACTX_EOB2 61 + +static char *inp = + " { k /; y{  q ; } c { @; ={  S} c} W; ; { 4} k " + "|; w{ + 9; {; 8; 9{ S; /} y{ K} { ;} l { { ~{ ; V} " + "k} g < t{ E v; M{  B} y} <{ 7; /;  Y} t } k p; Y} $ H  a{ e}  " + "w} ;} R} /{ >} a ; } ; ` $ W -} D} B;  e; f; *; ~; A; s " + "O{ o; >{ 1; m{ `} R} ]{ T} v} ={ I } ; } a ? &; A} $; W; R{ u} `; j} W; " + "s{ e} A; [ R;  X  P; 4 , F; ({ < 8{ #; %} @ J{ )} } o ^ *{ u /{ " + "'} ]{ * } } ; { r} f /; } e} } w{ ${ { ; ,; @ d $} ]; " + "> (} I{ d} &; U} { y; Y} { P{ R} T} _{ } R } l { T} " + "'; | ; ${ =} H} (} } 8{ c p{ s} #} +} 3} k F} < H .{ } G} " + "x; r D  c{ ; W; { b; 6; k{ } B; *} ; ]} ~ { ; ;} !} } x} " + "v} n; ^; 6 V} Y{ h; ~ % *} ! H; G{ r{ f; Y{ i} z} N  %} .{ ; ( " + " v} _} h; 7; <} ^; Z; 0; ; <; <; M; N{ }  _{ O} !{ f{ ]{ " + "M{ ; A{ } 0; S} ${ @; x} y} @ L; 1 t{ 3{ c{ s{ _{ `{ D{ ]} " + "!; ${ _ J; v + } 3{ B;  ]{ } E 6 . x{ ? +; { x; } v{ $} ; 6} T; " + "O; ; (} X 7} j; @} :} # c{ !{ } x K X t} >; ?{ c; ; W; ; l; } " + "h} p} i{ % } P} /{ *}  % L; ; !{  S{ n }  " + " x;  { 1  J; v{ U} ({ @ X{ k} H; 4; e J 6; ; v; G{ { ] &{ " + "A d{ l M{ ; K ;; 4 -{ }} p h{ ; { r W; v{ ; f} } 1{ ^ &{ 9{ " + "{ ; ~; n; q{ 9  R 6{ { u; a; ; U; ; Y} +} } 2 s k; 8 { J " + "K; ' i; ; $; W{ P !{ { { P } [; (; Q; U n; +}  g{ C; { " + "{ ; <{ v  S} b; 6 ` } ?{ + %; } n; q{ r} k; ; { c{ S} 2} " + "~{ 4; R W v}  R; k I} |;  d; [ O} 5; ; ; } Z d {  { &; h o{ " + "V v ; _{ { /} F{ f{ r{ 4{ { ?{ 4; S} :; ] ; E} ; &} # e !{ " + ">{ H; { O{ 0; } H; p ; w}  >{ 1} { -} 4 ; " + "S} } u L{ y} %; 2  |{ (} /; ,{  )} Y; g} G} v; T} }; } i {{ " + "}; [{ E{ q} g; T{ ={ } R; k{ j; _; h} g P c; ({ F; 6} }} 3 ,} <; " + "0  P; { ' t} u} ; } U} s{ 8{ E}  >{ } E { G { H :{  Y o " + "g} } F D{ R{ -; M ?; = q} _ U { ;  I  { |{ { }   1{ " + ",} { x{ { U{ s; J} }  6{ > 7 ; ,{ D{ {{ ; ]} ; M; &} { V}  " + "n{ & T ~; ({ } [; r{ # u{ X 9; L; U f} )}  { T}  p{ N; " + ">{ > }  } D} m { 1{ { } X ; o} w} $} ^ v} K  f ,} ^ 3; " + "{ @{ _} _{ o; 4} h} H; # .{ {} ; <{ { G{ $; { " + "z { a{ { D; ? |} { { ; `}  } Q} j; 4}  3{ Q} { * ; } r{ " + "a} } R { p @;  N{ { f; A; 8} L $} { } } J{ } k{ r}  { [; " + "-; p{ I{  { &} J; T} ?{ Z{ >; 5 >; ];  w z ^} u; ); H} ; " + "L &; V E{ 1{ g; C}  V} ~; U; ^{ J; { /} {; (} y} a K  /} .} " + "; K; N{ w{ `{ }  T{ l `; #; N{ l X; ?; +} {  w{ ; q; z; _; " + "y} 8}  &{ X} V{ W G}  ,; [} U{ v{ Q; w{  [  Y} N Y u i{ " + "{ ! A{ }{ b 0; X ~} ; -; 8{ E  } ; F{ y {} {  "; + +#define IMG_SIZE_MAX_LOG2 20 + +#define DCT_BITS 10 +#define DCT_SIZE_LOG2_MAX 5 +#define DCT_SIZE_MAX 32 /* (1 << DCT_SIZE_LOG2_MAX) */ +#define DCT_SIZE_MAX4 128 /* 4 * DCT_SIZE_MAX */ +#define DCT_SIZE_MAX_SQ2 2048 /* 2 * DCT_SIZE_MAX^2 */ + +#define FREQ_MAX 63 +#define SYM_COUNT 1968 + +static int img_data[3][1 << IMG_SIZE_MAX_LOG2]; +static int a_ctx[ACTX_COUNT2]; +static int a_low, a_range = 1, stride, y_scale, c_scale; +static int dct_coef[DCT_SIZE_MAX4]; + +int get_bit(int c) +{ + int v, *p = a_ctx + c * 2, b = *p + 1, s = b + p[1] + 1; + if (a_range < SYM_COUNT) { + a_range *= SYM_COUNT; + a_low *= SYM_COUNT; + if ((v = *inp)) { + /* char conversion */ + a_low += (v - 1 - (v > 10) - (v > 13) - (v > 34) - (v > 92)) << 4; + /* space conversion */ + v = *++inp; + inp++; + a_low += v < 33 ? (v ^ 8) * 2 % 5 + : (v ^ 6) % 3 * 4 + (*inp++ ^ 8) * 2 % 5 + 4; + } + } + /* 0 < range0 < a_range */ + v = a_range * b / s; + if ((b = (a_low >= v))) { + a_low -= v; + a_range -= v; + } else + a_range = v; + p[b]++; + if (s > FREQ_MAX) { + *p /= 2; + p[1] /= 2; + } + return b; +} + +/* positive number, Golomb encoding */ +int get_ue(int c) +{ + int i = 0, v = 1; + while (!get_bit(c + i)) + i++; + while (i--) + v += v + get_bit(ACTX_VDATA); + return v - 1; +} + +void idct(int *dst, + int dst_stride, + int *src, + int src_stride, + int stride2, + int n, + int rshift) +{ + for (int l = 0; l < n; l++) + for (int i = 0; i < n; i++) { + int sum = 1 << (rshift - 1); + for (int j = 0; j < n; j++) + sum += src[j * src_stride + l * stride2] * + dct_coef[(2 * i + 1) * j * DCT_SIZE_MAX / n % + DCT_SIZE_MAX4]; + dst[i * dst_stride + l * stride2] = sum >> rshift; + } +} + +static int buf1[DCT_SIZE_MAX_SQ2]; +void decode_rec(int x, int y, int w_log2) +{ + int b; + int w = 1 << w_log2, n = w * w; + + if ((w_log2 > DCT_SIZE_LOG2_MAX) || (w_log2 > 2 && get_bit(w_log2 - 3))) { + w /= 2; + for (int i = 0; i < 4; i++) + decode_rec(x + i % 2 * w, y + i / 2 * w, w_log2 - 1); + return; + } + + int pred_idx = get_ue(ACTX_IPRED); + for (int c_idx = 0; c_idx < 3; c_idx++) { + int *out = img_data[c_idx] + y * stride + x; + int c_idx1 = c_idx > 0; + + /* decode coefs */ + memset(buf1, 0, n * sizeof(int)); + for (int i = 0; i < n; i++) { + if (get_bit(ACTX_EOB2 + w_log2 * 2 + c_idx1)) + break; + i += get_ue(ACTX_LEN + c_idx1 * ACTX_UE_LEN); + b = 1 - 2 * get_bit(ACTX_SIGN); + buf1[i] = + b * + (get_ue(ACTX_LEVEL + (c_idx1 + (i < n / 8) * 2) * ACTX_UE_LEN) + + 1) * + (c_idx ? c_scale : y_scale); + } + + /* DC prediction */ + if (!pred_idx) { + int dc = 0; + for (int i = 0; i < w; i++) { + dc += y ? out[-stride + i] : 0; + dc += x ? out[i * stride - 1] : 0; + } + *buf1 += x && y ? dc / 2 : dc; + } + + /* horizontal */ + idct(buf1 + n, 1, buf1, 1, w, w, DCT_BITS); + /* vertical */ + idct(out, stride, buf1 + n, w, 1, w, DCT_BITS + w_log2); + + if (!pred_idx) + continue; + + /* directional prediction */ + int swap = pred_idx < 17, frac; + int delta = swap ? 9 - pred_idx : pred_idx - 25; + for (int i = 0; i < w; i++) + for (int j = 0; j < w; j++) { + for (int k = 0; k < 2; k++) { + int x1 = i * delta + delta; + frac = x1 & 7; + x1 = (x1 >> 3) + j + k; + if ((b = (x1 < 0))) + x1 = (x1 * 8 + delta / 2) / delta - 2; + x1 = x1 < w ? x1 : w - 1; + buf1[k] = + b ^ swap ? out[x1 * stride - 1] : out[-stride + x1]; + } + out[swap ? j * stride + i : i * stride + j] += + (*buf1 * (8 - frac) + buf1[1] * frac + 4) >> 3; + } + } +} + +void lena(void); +void lena(void) +{ + int a = 0; + int b = 74509276; + for (int i = 0; i < 128; i++) { + dct_coef[i + 96 & 127] = ((a >> 19) + 1) >> 1; + int c = b; + b = (2144896910LL * b >> 30) - a; + a = c; + } + + *dct_coef = 1024; + int w_log2 = get_ue(ACTX_LEN); + stride = 1 << w_log2; + int h = stride - get_ue(ACTX_LEN); + y_scale = get_ue(ACTX_LEN); + c_scale = get_ue(ACTX_LEN); + + decode_rec(0, 0, w_log2); + + /* output */ + FILE *fp = fopen("lena.ppm", "wb"); + fprintf(fp, "P6 %d %d 255 ", stride, h); + for (int i = 0; i < h * stride; i++) { + int y = img_data[0][i], cg = img_data[1][i], co = img_data[2][i]; + int t = y - cg; +#define PUT(v) fprintf(fp, "%c", (v < 0) ? 0 : (v > 255) ? 255 : v) + PUT(t + co); + PUT(y + cg); + PUT(t - co); +#undef PUT + } + fclose(fp); + + return 0; +} diff --git a/litex/soc/software/demo/main.c b/litex/soc/software/demo/main.c index 38c451fa6..4834d5164 100644 --- a/litex/soc/software/demo/main.c +++ b/litex/soc/software/demo/main.c @@ -87,6 +87,11 @@ static void help(void) puts("led - Led demo"); #endif puts("donut - Spinning Donut demo"); + puts("donut2 - Spinning Donut demo (no multiplication)"); + puts("mandelbrot - Mandelbrot fractal renderer"); + puts("nyancat - Cat"); + puts("spirograph - Contains flashing images"); + puts("qrcode - Generate QR code"); puts("helloc - Hello C"); #ifdef WITH_CXX puts("hellocpp - Hello C++"); @@ -142,6 +147,12 @@ static void donut_cmd(void) donut(); } +extern void donut2(void); +extern void mandelbrot(void); +extern void nyancat(void); +extern void spirograph(void); +extern void qrcode(void); + extern void helloc(void); static void helloc_cmd(void) @@ -184,6 +195,16 @@ static void console_service(void) donut_cmd(); else if(strcmp(token, "helloc") == 0) helloc_cmd(); + else if(strcmp(token, "donut2") == 0) + donut2(); + else if(strcmp(token, "mandelbrot") == 0) + mandelbrot(); + else if(strcmp(token, "nyancat") == 0) + nyancat(); + else if(strcmp(token, "spirograph") == 0) + spirograph(); + else if(strcmp(token, "qrcode") == 0) + qrcode(); #ifdef WITH_CXX else if(strcmp(token, "hellocpp") == 0) hellocpp_cmd(); diff --git a/litex/soc/software/demo/mandelbrot.c b/litex/soc/software/demo/mandelbrot.c new file mode 100644 index 000000000..450f66428 --- /dev/null +++ b/litex/soc/software/demo/mandelbrot.c @@ -0,0 +1,79 @@ +/* + * ASCII rendered Mandelbrot Set fractal using 16 bits of fixed point integer + * arithmetic with a selectable fractional precision in bits. + * + * The fixed point implementation uses "8.8" encoding in 16 bit "short" + * integers, where for example decimal 3.5 is hex 0x380 and decimal 2.25 is + * hex 0x240 (0x40 being 1/4 of 0x100). + * + * Originally written by John Lonergan: https://github.com/Johnlon/mandelbrot + */ + +#include +#include +#include +#include + +/* convert decimal value to a fixed point value in the given precision */ +#if 0 +short toPrec(double f, int bitsPrecision) +{ + short whole = ((short) floor(f) << (bitsPrecision)); + short part = (f - floor(f)) * (pow(2, bitsPrecision)); + short ret = whole + part; + printf("%x\n", ret); + return ret; +} +#endif + +static const int width = 64; /* basic width */ +static const int height = 32; /* basic width */ +static const int zoom = 1; /* leave at 1 for 32x22 */ + +void mandelbrot(void); +void mandelbrot(void) +{ + const short bitsPrecision = 6; + + const short X1 = 0xE0; /* toPrec(3.5, bitsPrecision) / zoom */ + const short X2 = 0x90; /* toPrec(2.25, bitsPrecision) */ + const short Y1 = 0xC0; /* toPrec(3, bitsPrecision) / zoom : horiz pos */ + const short Y2 = 0x60; /* toPrec(1.5, bitsPrecision) : vert pos */ + const short LIMIT = 0x100; /* toPrec(4, bitsPrecision) */ + + /* fractal */ + const char* charset = ".:-=X$#@ "; + const short max_iter = sizeof(charset) - 1; + + for (short py = 0; py < height * zoom; py++) { + for (short px = 0; px < width * zoom; px++) { + short x0 = ((px * X1) / width) - X2; + short y0 = ((py * Y1) / height) - Y2; + short x = 0, y = 0; + + short i; + for (i = 0; i < max_iter; i++) { + short xSqr = (x * x) >> bitsPrecision; + short ySqr = (y * y) >> bitsPrecision; + + /* Breakout if sum is > the limit OR breakout also if sum is + * negative which indicates overflow of the addition has + * occurred The overflow check is only needed for precisions of + * over 6 bits because for 7 and above the sums come out + * overflowed and negative therefore we always run to max_iter + * and we see nothing. By including the overflow break out we + * can see the fractal again though with noise. + */ + if ((xSqr + ySqr) >= LIMIT) + break; + + short xt = xSqr - ySqr + x0; + y = (((x * y) >> bitsPrecision) * 2) + y0; + x = xt; + } + printf("\033[48;05;%dm%c\033[0m", i, charset[i - 1]); + } + + printf("\n"); + } +} diff --git a/litex/soc/software/demo/nyancat.c b/litex/soc/software/demo/nyancat.c new file mode 100644 index 000000000..da374b5da --- /dev/null +++ b/litex/soc/software/demo/nyancat.c @@ -0,0 +1,940 @@ +/* + * Copyright (c) 2011-2018 K. Lange. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal with the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimers. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimers in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the Association for Computing Machinery, K. + * Lange, nor the names of its contributors may be used to endorse + * or promote products derived from this Software without specific prior + * written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * WITH THE SOFTWARE. + */ + +static const char *frame0[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ".,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ",,>>>>>>>>,,,,,,,,>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + ">>&&&&&&&&>>>>>>>>&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,", + "&&++++++++&&&&&&&&'''++'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,", + "++++++++++++++++++**''+'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,", + "++++++++++++++++++'**'''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,", + "++########++++++++''**''@$$$$$$-'*************',,,,,,,,,,,,,,,,,", + "###################''**'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,", + "####################''''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,", + "##========########====''@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,", + "======================='@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,", + "==;;;;;;;;.=======;;;;'''@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;'***''''''''''''''''''',,,,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;'**'','*',,,,,'*','**',,,,,,,,,,,,,,,,,,,,,", + ";;,,,,,.,,;;;.;;;;,,,'''',,'',,,,,,,'',,'',,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +static const char *frame1[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ",,>>>>>>>>,,,,,,,,>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + ">>&&&&&&&&>>>>>>>>&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,", + "&&++++++++&&&&&&&&+++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++'+++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,", + "++++++++++++++++++'*'++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,", + "++########++++++++'*''''@$$$$$$-$'*************',,,,,,,,,,,,,,,,", + "###################****'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,", + "###################''**'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,", + "##========########==='''@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,", + "======================='@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,", + "==;;;;;;;;========;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;'**','*',,,,,,**','**',,,,,,,,,,,,,,,,,,,,", + ";;,,,.,,,,;;;;;;;;,,,,''',,,'',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,..,,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +static const char *frame2[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,..,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,.", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.", + ">>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + "&&>>>>>>>&&&&&&&&>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,", + "++&&&&&&&++++++++&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,", + "##+++++++########++++++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,", + "######################''@$$$$$$-$'*************',,,,,,,,,,,,,,,,", + "###################'''''@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,", + "==#######========#'****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,", + "==================='''='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,", + ";;=======;;;;;;;;======'@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,", + ";.;;;;;;;;;;;;;;;;;;;;;'*'''''''''''''''''''',,,,,,,,,,,,,,,,,,,", + ".,.;;;;;;,,,,,,,,;;;;;;'**',**',,,,,,**','**',,,,,,,,,,,,,,,,,,,", + ",.,,,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +static const char *frame3[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,", + ">>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + "&&>>>>>>>&&&&&&&&>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,", + "++&&&&&&&++++++++&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,", + "##+++++++########++++++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,", + "#####################'''@$$$$$$-$'*************',,,,,,,,,,,,,,,,", + "###################''**'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,", + "==#######========##****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,", + "=================='*'=='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,", + ";;=======;;;;;;;;=='==='@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,", + ",,;;;;;;;,,,,,,,,;;;;;'**','*',,,,,,'*','**',,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,''',,,'',,,,,,,'',,''',,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +static const char *frame4[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,", + ",,>>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + ">>&&&&&&&&>>>>>>>>&&&&&'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,", + "&&++++++++&&&&&&&&+++++'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,", + "++++++++++++++++++'''++'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,", + "++########+++++++'**''''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,", + "#################'****''@$$$$$$-'*************',,,,,,,,,,,,,,,,,", + "##################''''*'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,", + "##========########==='''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,", + "======================='@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,", + "==;;;;;;;;========;;;;''@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;''''@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;'***'''''''''''''''''''',,,,,,,,,,,,,,,,,,,,", + ";;,,,,,,,,;;;;;;;;,,'**','**,,,,,,'**,'**',,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,''',,,'',,,,,,,'',,''',,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,..,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +static const char *frame5[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,>>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + ">>&&&&&&&&>>>>>>>>&&&&&'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$''$$$@@','',,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$'**'-$$@''**',,,,,,,,,,,,,,,,,,", + "&&++++++++&&&&&&&&+++++'@$$$$$$$$'***$$$@'***',,,,,,,,,,,,,,,,,,", + "+++++++++++++++++++'+++'@$$$$$-$$'***''''****',,,,,,,,,,,,,,,,,,", + "++++++++++++++++++'*'++'@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,", + "++########++++++++'*''''@$$$$$$$'*************',,,,,,,,,,,,,,,,,", + "###################****'@$$$$$$-'***.'****.'**',,,,,,,,,,,,,,,,,", + "###################''**'@$-$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,", + "##========########==='''@$$$$$$$'*%%********%%',,,,,,,,,,,,,,,,,", + "======================='@@$$$-$$$'***''''''**',,,,,,,,,,,,,,,,,,", + "==;;;;;;;;========;;;;''@@@$$$$$$$'*********',,,,,,,,,,,,,,,,,,.", + ";;;;;;;;;;;;;;;;;;;;;'*''@@@@@@@@@@''''''''',,,,,,,,,,,,,,,,,,,.", + ";;;;;;;;;;;;;;;;;;;;'***''''''''''''''''*',,,,,,,,,,,,,,,,,,,,,,", + ";;,,,,,,,,;;;;;;;;,,'**','**,,,,,,'**,'**',,,,,,,,,,,,,,,,,,..,.", + ",,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +static const char *frame6[] = { + ".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,..,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>,,,,,,,>>>>>>>>,,,,,,,'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&>>>>>>>&&&&&&&&>>>>>>'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,", + "++&&&&&&&++++++++&'''&&'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,", + "++++++++++++++++++'*''+'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,", + "++++++++++++++++++'**'''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,", + "##+++++++########++'**''@$$$$$$-'*************',,,,,,,,,,,,,,,,,", + "###################''**'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,", + "####################''''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,", + "==#######========#####''@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,", + "======================='@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,", + ";;=======;;;;;;;;====='''@@@@@@@@@'*********',,,,,,,,,,,.,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;'***''''''''''''''''''',,,,,,,,,,.,,,.,,,,,", + ";;;;;;;;;;;;;;;;;;;;;'**'','*',,,,,'**,'**',,,,,,,,,,,,,,,,,,,,,", + ",,;;;;;;;,,,,,,,,;;;;'''',,'',,,,,,,'',,'',,,,,,,,,,,.,,,,,.,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +static const char *frame7[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,..,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>,,,,,,,>>>>>>>>,,,,,,,'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&>>>>>>>&&&&&&&&>>>>>>'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,", + "++&&&&&&&++++++++&&&&&&'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++'+++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,", + "++++++++++++++++++'*'++'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,", + "##+++++++########+'*''''@$$$$$$-$'*************',,,,,,,,,,,,,,,,", + "###################****'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,", + "###################''**'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,", + "==#######========####'''@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,", + "======================='@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,", + ";;=======;;;;;;;;======''@@@@@@@@@@'*********',,,.,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;'**','*',,,,,,**','**',,,,,,,,,,,,,,,,,,,,", + ",,;;;;;;;,,,,,,,,;;;;;''',,,'',,,,,,''',,''',,.,,,,.,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +static const char *frame8[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,..,...,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,>>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + ">>&&&&&&&&>>>>>>>>&&&&&'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,", + "&&++++++++&&&&&&&&+++++'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,", + "++########++++++++#####'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,", + "######################''@$$$$$$-$'*************',,,,,,,,,,,,,,,,", + "###################'''''@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,", + "##========########'****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,", + "==================='''='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,", + "==;;;;;;;;========;;;;;'@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;;'*'''''''''''''''''''',,,,,,,,,,,,,,,,,,,", + ";;,,,,,,,,;;;;;;;;,,,,,'**',**',,,,,,**'.'**',,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,", +}; + +static const char *frame9[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,.,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,.,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,>>>>>>>>,,,,,,,,>>>>>>>''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + ">>&&&&&&&&>>>>>>>>&&&&&'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$$''-$$@',,'',,,,,,,,,,,,,,,,,,", + "&&++++++++&&&&&&&&+++++'@$$$$$$$$$'**'$$@','**',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$-$$$'***$$@''***',,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,", + "++########++++++++#####'@$$$$$$$$$'***********',,,,,,,,,,,,,,,,,", + "#####################'''@$$$$$$-$'*************',,,,,,,,,,,,,,,,", + "###################''**'@$-$$$$$$'***.'****.'**',,,,,,,,,,,,,,,,", + "##========########=****'@$$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,", + "=================='*'=='@@$$$-$$$'*%%********%%',,,,,,,,,,,,,,,,", + "==;;;;;;;;========;';;;'@@@$$$$$$$'***''''''**',,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;;''@@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;;'**'''''''''''''''''''',,,,,,,,,,,,,,,,,,,", + ";;,,,,,,,,;;;;;;;;,,,,'**','*',,..,.**','**',,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,''',,,'',,,,.,''',,''',,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,.,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,", +}; + +static const char *frame10[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,.,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,.,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ">>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + "&&>>>>>>>&&&&&&&&>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$-$$$$@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$$''$-$$@','',,,,,,,,,,,,,,,,,,,", + "++&&&&&&&++++++++&&&&&&'@$$$$$$$$'**'$$$@''**',,,,,,,,,,,,,,,,,,", + "+++++++++++++++++++++++'@$$$$$-$$'***$$$@'***',,,,,,,,,,,,,,,,,,", + "++++++++++++++++++'''++'@$$$$$$$$'***''''****',,,,,,,,,,,,,,,,,,", + "##+++++++########'**''''@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,", + "#################'****''@$$$$$$-'*************',,,,,,,,,,,,,,,,,", + "##################''''*'@$-$$$$$'***.'****.'**',,,,,,,,,,,,,,,,,", + "==#######========####'''@$$$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,", + "======================='@@$$$-$$'*%%********%%',,,,,,,,,,,,,,,,,", + ";;=======;;;;;;;;=====''@@@$$$$$$'***''''''**',,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;;''''@@@@@@@@@'*********',,,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;'***'''''''''''''''''''',,,,,,,,,,,,,,,,,,,,", + ",,;;;;;;;,,,,,,,,;;;'**'.'**..,,,,'**''**',,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,''',,,'',,,,,,,''',''',,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ".,.,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +static const char *frame11[] = { + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ">>,,,,,,,>>>>>>>>,,,,,,,,''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,", + ">>>>>>>>>>>>>>>>>>>>>>>>'@@@@@@@@@@@@@@@',,,,,,,,,,,,,,,,,,,,,,,", + "&&>>>>>>>&&&&&&&&>>>>>>'@@@$$$$$$$$$$$@@@',,,,,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@@$$$$$-$$''$$$@@','',,,,,,,,,,,,,,,,,,,", + "&&&&&&&&&&&&&&&&&&&&&&&'@$$-$$$$$'**'-$$@''**',,,,,,,,,,,,,,,,,,", + "++&&&&&&&++++++++&&&&&&'@$$$$$$$$'***$$$@'***',,,,,,,,,,,,,,,,,,", + "+++++++++++++++++++'+++'@$$$$$-$$'***''''****',,,,,,,,,,,,,,,,,,", + "++++++++++++++++++'*'++'@$$$$$$$$'***********',,,,,,,,,,,,,,,,,,", + "##+++++++########+'*''''@$$$$$$$'*************',,,,,,,,,,,,,,,,,", + "###################****'@$$$$$$-'***.'****.'**',,,,,,,,,,,,,,,,,", + "###################''**'@$-$$$$$'***''**'*''**',,,,,,,,,,,,,,,,,", + "==#######========####'''@$$$$$$$'*%%********%%',,,,,,,,,,,,,,,,,", + "======================='@@$$$-$$$'***''''''**',,,,,,,,,,,,,,,,,,", + ";;=======;;;;;;;;=.===''@@@$$$$$$$'*********',,,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;.'*''@@@@@@@@@@''''''''',,,,,,,,,,,,,,,,,,,,", + ";;;;;;;;;;;;;;;;;;;;'***''''''''''''''''*',,,,,,,,,,,,,,,,,,,,,,", + ",,;;;;;;;,,,,,,,.;;;'**','**,,,,,,'**''**',,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,''',,''',,,,,,''',,''',,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,.,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", +}; + +#include + +const char **frames[] = { + frame0, frame1, frame2, frame3, frame4, frame5, frame6, + frame7, frame8, frame9, frame10, frame11, NULL, +}; + +#define FRAME_WIDTH 64 +#define FRAME_HEIGHT 64 + +#include +#include + +#define WIDTH 80 +#define HEIGHT 24 + +const char *colors[256] = {NULL}; +const char *output = " "; + +static int min_row = -1, max_row = -1; +static int min_col = -1, max_col = -1; + +static void finish(void) +{ + printf("\033[?25h\033[0m\033[H\033[2J"); + exit(0); +} + +static void update_window_size(void) +{ + min_col = (FRAME_WIDTH - WIDTH / 2) / 2; + max_col = (FRAME_WIDTH + WIDTH / 2) / 2; + + min_row = (FRAME_HEIGHT - (HEIGHT - 1)) / 2; + max_row = (FRAME_HEIGHT + (HEIGHT - 1)) / 2; +} + +static void newline(int n) +{ + for (int i = 0; i < n; ++i) + putc('\n', stdout); +} + +void nyancat(void); +void nyancat(void) +{ + /* Assume xterm */ + { + colors[','] = "\033[48;5;17m"; + colors['.'] = "\033[48;5;231m"; + colors['\''] = "\033[48;5;16m"; + colors['@'] = "\033[48;5;230m"; + colors['$'] = "\033[48;5;175m"; + colors['-'] = "\033[48;5;162m"; + colors['>'] = "\033[48;5;196m"; + colors['&'] = "\033[48;5;214m"; + colors['+'] = "\033[48;5;226m"; + colors['#'] = "\033[48;5;118m"; + colors['='] = "\033[48;5;33m"; + colors[';'] = "\033[48;5;19m"; + colors['*'] = "\033[48;5;240m"; + colors['%'] = "\033[48;5;175m"; + } + + update_window_size(); + printf("\033[H\033[2J\033[?25l"); + + size_t i = 0; + unsigned int f = 0; + char last = 0; + while (1) { + printf("\033[H"); + for (int y = min_row; y < max_row; ++y) { + for (int x = min_col; x < max_col; ++x) { + char color; + if (y > 23 && y < 43 && x < 0) { + int mod_x = ((-x + 2) % 16) / 8; + if ((i / 2) % 2) + mod_x = 1 - mod_x; + const char *rainbow = ",,>>&&&+++###==;;;,,"; + color = rainbow[mod_x + y - 23]; + if (color == 0) + color = ','; + } else if (x < 0 || y < 0 || y >= FRAME_HEIGHT || + x >= FRAME_WIDTH) { + color = ','; + } else { + color = frames[i][y][x]; + } + + if (color != last && colors[(int) color]) { + last = color; + printf("%s%s", colors[(int) color], output); + } else { + printf("%s", output); + } + } + newline(1); + } + + last = 0; + if (++f == 60) + finish(); + if (!frames[++i]) + i = 0; + + } +} diff --git a/litex/soc/software/demo/qrcode.c b/litex/soc/software/demo/qrcode.c new file mode 100644 index 000000000..34bce4c72 --- /dev/null +++ b/litex/soc/software/demo/qrcode.c @@ -0,0 +1,431 @@ +/* + * QR123: minimal fast QR encoder for version 1, 2, 3. + * + * Copyright (c) 2019 Ling LI . + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Verify results here: + * https://www.nayuki.io/page/creating-a-qr-code-step-by-step + */ + +#include +#include +#include +#include +#include + +typedef unsigned uint; + +/* + * QR_OPT: use log/exp LUT-based GF MUL. + */ +#define QR_OPT 1 + +#define QR_LINES 29 + +typedef struct qr_ctx { + uint8_t size; // 21, 25 or 29 (ver*4+17) + uint8_t len; // length of input data. + const uint8_t *data; // input data. + void *params; // data and ECC parameters. + uint32_t bmp[QR_LINES]; // QR code bitmap, 1 word per line. +} qr_ctx; + +/* + * Get dots for display. + */ +static inline bool qr_getdot(qr_ctx *ctx, uint x, uint y) +{ + return ctx->bmp[y] << x >> 31; +} + +/* + * Draw finders, timing pattern, alignment pattern, and the dark dot. + * And now the format bits for fixed mask 0. + */ +static void _init_bmp(uint32_t A[], uint size) +{ + /* Draw top-left finder. */ + A[0] = A[6] = 0xFE000000; + A[1] = A[5] = 0x82000000; + A[2] = A[3] = A[4] = 0xBA000000; + + /* Replicate to bottom-left then top-right. */ + int y; + for (y = 0; y < 7; y++) { + A[size - 1 - y] = A[y]; + A[y] |= A[y] >> (size - 7); + } + + /* Horizontal timing pattern. */ + A[6] |= 0xAAA800; + + /* Vertical timing pattern. */ + for (y = 9; y < size - 7; y++) + A[y] = ((y + 1) & 1) << 25; + + /* The dark dot, then some format bits. */ + y -= 1; // size-9 + for (int i = 0; i < 8; i++) { + if (i == 4) + continue; + A[y + i] |= 0x800000; + } + + /* More format bits. */ + A[2] |= 0x800000; + A[7] = 0x800000; + A[8] = 0xEF800000 | 0x31 << (34 - size); + + /* Alignment pattern for version 2 & 3. */ + if (size > 21) { + uint pat = 0x1F << (36 - size); + A[size - 9] |= pat; + A[size - 5] |= pat; + pat = 0x11 << (36 - size); + A[size - 8] |= pat; + A[size - 6] |= pat; + A[size - 7] |= 0x15 << (36 - size); + } +} + +typedef struct qr_params { + uint8_t capa; /* total capacity in bytes. */ + uint8_t eccdeg; /* ECC degree/byte count. */ + uint8_t gen[]; /* ECC generator polynomial. */ +} qr_params; + +/* + * Check capacity then setup parameters. + * + * Return false if version number is invalid or input exceeds the capacity of + * specified version. + * - Parameters are written to the context. + * - Must evaluate before encoding. + * - Must fail if evaluation fails. + * Capacity: V1 17B, V2 32B, V3 53B. + */ +bool qr_eval(qr_ctx *ctx, uint ver, const uint8_t *data, uint len) +{ + static const uint8_t _params_blob[] = { + // + 26, 7, 0x7f, 0x7a, 0x9a, 0xa4, 0x0b, 0x44, 0x75, // V1 + 44, 10, 0xd8, 0xc2, 0x9f, 0x6f, 0xc7, 0x5e, 0x5f, + 0x71, 0x9d, 0xc1, // V2 + 70, 15, 0x1d, 0xc4, 0x6f, 0xa3, 0x70, 0x4a, 0x0a, + 0x69, 0x69, 0x8b, // V3 + 0x84, 0x97, 0x20, 0x86, 0x1a}; + + if (!ctx) + return false; + ctx->data = data; + ctx->len = len; + + uintptr_t params = (uintptr_t) _params_blob; /* intentional */ + /* Skip-overs, cross check with the blob layout. */ + switch (ver) { + case 1: + break; + case 2: + params += 9; + break; + case 3: + params += 21; + break; + default: + return false; + } + + uint size = ver * 4 + 17; + ctx->params = (void *) params; + /* 4b mode, 8b count, 4b terminator. */ + uint usable = + ((qr_params *) params)->capa - ((qr_params *) params)->eccdeg - 2; + if (usable < len) + return false; + + ctx->size = size; + _init_bmp(ctx->bmp, ctx->size); + return true; +} + +/* + * Prepare all the data bits before ECC. + */ +static void _serialize_data(qr_ctx *ctx, uint8_t *buf) +{ + /* Mode bits and length bits. */ + uint b = 4 << 8 | ctx->len; + buf[0] = b >> 4; + uint i = 0; + while (i < ctx->len) { + b <<= 8; + b |= ctx->data[i++]; + buf[i] = b >> 4; + } + + /* Final 4 bits with terminator. */ + i++; + buf[i++] = b << 4; + + /* Byte padding. */ + b = 0xEC; + qr_params *para = (qr_params *) ctx->params; + while (i < para->capa - para->eccdeg) { + buf[i++] = b; + b ^= 0xFD; /* alternating EC, 11. */ + } + + /* Clear out the rest bytes for ECC; also clear 1 extra byte for the spare + * bits (v2 & v3 have 7 unused). + */ + while (i <= para->capa) + buf[i++] = 0; +} + +#if defined(QR_OPT) +/* + * The GF(2^8, 285) finite field element multiplication. + * Basic iterative, unrolled, and log/exp LUT versions are implemented. + */ +static inline uint _rs_mul(uint x, uint y) +{ + static const uint8_t _luts[2][256] = { + // Log table. + {0, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, + 199, 75, 4, 100, 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, + 200, 8, 76, 113, 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, + 142, 218, 240, 18, 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, + 201, 154, 9, 120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221, + 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148, 206, + 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, + 182, 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61, + 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, 243, + 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, + 49, 197, 254, 24, 227, 165, 153, 119, 38, 184, 180, 124, 17, 68, + 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149, 188, 207, 205, + 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, 171, 20, 42, + 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31, 45, 67, 216, + 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111, 246, 108, 161, + 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, + 203, 89, 95, 176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, + 44, 215, 79, 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, + 168, 80, 88, 175}, + // Exponential table. + {1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, + 19, 38, 76, 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, + 24, 48, 96, 192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, + 181, 119, 238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, + 93, 186, 105, 210, 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, + 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187, + 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, 175, + 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, + 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, + 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, + 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85, 170, 73, 146, + 57, 114, 228, 213, 183, 115, 230, 209, 191, 99, 198, 145, 63, 126, + 252, 229, 215, 179, 123, 246, 241, 255, 227, 219, 171, 75, 150, 49, + 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, 130, 25, 50, 100, + 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 81, 162, + 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, + 18, 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, + 11, 22, 44, 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, + 173, 71, 142, 1}, + }; + + if (!x || !y) + return 0; + uint xp = _luts[0][x] + _luts[0][y]; + if (xp > 255) + xp -= 255; + return _luts[1][xp]; +} + +#else /* use iterative GF MUL */ +static inline uint _rs_mul(uint x, uint y) +{ + uint z = 0; + /* This is called (133, 340, 825) times in V(1, 2, 3) ECC calculation. */ + for (int i = 7; i >= 0; i--) { + /* And this body is run 1064, 2720, 6600 times. */ + z = (z << 1) ^ ((z >> 7) * 0x11D); + z ^= ((y >> i) & 1) * x; + } + return z; +} +#endif + +/* + * Calculate the ECC bytes. + */ +static void _reed_solomon(qr_ctx *ctx, uint8_t *buf) +{ + qr_params *para = (qr_params *) ctx->params; + uint deg = para->eccdeg; + uint8_t *gen = para->gen; + uint len = para->capa - para->eccdeg; + uint8_t *res = buf + len; + for (uint i = 0; i < len; i++) { + uint factor = buf[i] ^ res[0]; + for (uint j = 1; j < deg; j++) + res[j - 1] = res[j]; + res[deg - 1] = 0; + for (uint j = 0; j < deg; j++) + res[j] ^= _rs_mul(gen[j], factor); + } +} + +/* + * Return if dot (x,y) is for data (i.e. not function patterns). + */ +static inline bool _is_data(uint x, uint y, uint size_m1) +{ + if (x == 6 || y == 6) + return false; + if (y <= 8) + return x >= 9 && x <= size_m1 - 8; + if (y >= size_m1 - 7 && x <= 8) + return false; + if (size_m1 > 20 && x >= size_m1 - 8 && x <= size_m1 - 4 && + y >= size_m1 - 8 && y <= size_m1 - 4) + return false; + return true; +} + +typedef union poly64_t { + uint64_t bits; + uint32_t u[2]; + struct { + uint32_t u0; + uint32_t u1; + }; +} poly64_t; + +/* + * The QR zig-zag sequence generator. + * + * To iterate through all valid data positions: call with initial x and y = + * size-1, feed back the result as input, and repeat the call-feed cycle. + */ +static uint64_t zigzag_step(uint x, uint y, uint size_m1) +{ + poly64_t r; + while (true) { + switch ((x - (x > 6)) & 3) { + case 0: + if (y < size_m1) + x += 1, y += 1; + else + x -= 1; + break; + case 1: + x -= 1; + break; + case 2: + if (y > 0) + x += 1, y -= 1; + else { + x -= 1; + if (x == 6) + x = 5; + } + break; + default: + x -= 1; + } + if (_is_data(x, y, size_m1)) + break; + } + r.u0 = x, r.u1 = y; + return r.bits; +} + +/* + * Put data bits to the QR bitmap. + * Fixed masking (0) is applied on the fly. + */ +static void _place_data(qr_ctx *ctx, const uint8_t *buf) +{ + uint size_m1 = ctx->size - 1; + poly64_t xy = {.u0 = size_m1, .u1 = size_m1}; + qr_params *para = (qr_params *) ctx->params; + uint nbits = para->capa * 8; + + /* NB: count in the unused bits in V2 and V3. */ + if (size_m1 > 20) + nbits += 7; + + for (int i = 0; i < nbits; i++) { + bool mask0 = (xy.u0 + xy.u1) % 2 == 0; + bool dot = buf[i / 8] & (0x80u >> i % 8); + if (dot ^ mask0) + ctx->bmp[xy.u1] |= 0x80000000u >> xy.u0; + xy.bits = zigzag_step(xy.u0, xy.u1, size_m1); + } +} + +/* + * The actual encoding. + */ +void qr_encode(qr_ctx *ctx) +{ + if (!ctx) + return; + + uint8_t dbuf[72]; // V3 capacity 70 and extra 2. + _serialize_data(ctx, dbuf); + _reed_solomon(ctx, dbuf); + _place_data(ctx, dbuf); +} + +void dump_bmp(qr_ctx *ctx) +{ + for (int i = 0; i < ctx->size + 2; i++) + printf("██"); + printf("\n"); + + for (int y = 0; y < ctx->size; y++) { + printf("██"); + for (int x = 0; x < ctx->size; x++) + if (qr_getdot(ctx, x, y)) + printf(" "); + else + printf("██"); + printf("██\n"); + } + for (int i = 0; i < ctx->size + 2; i++) + printf("██"); + printf("\n"); +} + +void qrcode(void); +void qrcode(void) +{ + qr_ctx ctx[1]; + const char *str = "https://github.com/sysprog21/rv32emu"; + + if (!qr_eval(ctx, /* version */ 3, (const uint8_t *) str, strlen(str))) { + printf("Evaluation failed. Version invalid or data too long?\n"); + return -2; + } + qr_encode(ctx); + dump_bmp(ctx); + return 0; +} diff --git a/litex/soc/software/demo/spirograph.c b/litex/soc/software/demo/spirograph.c new file mode 100644 index 000000000..995e2f07f --- /dev/null +++ b/litex/soc/software/demo/spirograph.c @@ -0,0 +1,433 @@ +/** + * Functions to display graphics in the terminal, using ANSI sequences. + * Copyright (c) 2024 Bruno Levy + * + * Source: https://github.com/BrunoLevy/TinyPrograms + */ + +#include +#include +#include +#include + +#ifndef GL_FPS +#define GL_FPS 30 +#endif + +#ifndef GL_width +#define GL_width 80 +#endif + +#ifndef GL_height +#define GL_height 25 +#endif + +/** + * \brief Sets the current graphics position + * \param[in] x typically in 0,79 + * \param[in] y typically in 0,24 + */ +static inline void GL_gotoxy(int x, int y) +{ + printf("\033[%d;%dH", y, x); +} + +/** + * \brief Sets the current graphics position + * \param[in] R , G , B the RGB color of the pixel, in [0..255] + * \details Typically used by programs that draw all pixels sequentially, + * like a raytracer. After each line, one can either printf("\n") or + * call GL_gotoxy(). If you want to draw individual pixels in an + * arbitrary order, use GL_setpixelRGB(x,y,R,G,B) + */ +static inline void GL_setpixelRGBhere(uint8_t R, uint8_t G, uint8_t B) +{ + // set background color, print space + printf("\033[48;2;%d;%d;%dm ", (int) R, (int) G, (int) B); +} + +/** + * \brief Draws two "pixels" at the current + * cursor position and advances the current cursor + * position. + * \details Characters are roughly twice as high as wide. + * To generate square pixels, this function draws two pixels in + * the same character, using the special lower-half white / upper-half + * black character, and setting the background and foreground colors. + */ +static inline void GL_set2pixelsRGBhere(uint8_t r1, + uint8_t g1, + uint8_t b1, + uint8_t r2, + uint8_t g2, + uint8_t b2) +{ + if ((r2 == r1) && (g2 == g1) && (b2 == b1)) { + GL_setpixelRGBhere(r1, g1, b1); + } else { + printf("\033[48;2;%d;%d;%dm", (int) r1, (int) g1, (int) b1); + printf("\033[38;2;%d;%d;%dm", (int) r2, (int) g2, (int) b2); + // https://www.w3.org/TR/xml-entity-names/025.html + // https://onlineunicodetools.com/convert-unicode-to-utf8 + // https://copypastecharacter.com/ + printf("\xE2\x96\x83"); + } +} + +#define GL_RGB(R, G, B) #R ";" #G ";" #B + +static inline void GL_setpixelIhere(const char **cmap, int c) +{ + /* set background color, print space */ + printf("\033[48;2;%sm ", cmap[c]); +} + +static inline void GL_set2pixelsIhere(const char **cmap, int c1, int c2) +{ + if (c1 == c2) { + GL_setpixelIhere(cmap, c1); + } else { + printf("\033[48;2;%sm", cmap[c1]); + printf("\033[38;2;%sm", cmap[c2]); + // https://www.w3.org/TR/xml-entity-names/025.html + // https://onlineunicodetools.com/convert-unicode-to-utf8 + // https://copypastecharacter.com/ + printf("\xE2\x96\x83"); + } +} + +/** + * \brief Moves the cursor position to the next line. + * \details Background and foreground colors are set to black. + */ +static inline void GL_newline() +{ + printf("\033[38;2;0;0;0m"); + printf("\033[48;2;0;0;0m\n"); +} + +/** + * \brief Sets the color of a pixel + * \param[in] x typically in 0,79 + * \param[in] y typically in 0,24 + * \param[in] R , G , B the RGB color of the pixel, in [0..255] + */ +static inline void GL_setpixelRGB(int x, int y, uint8_t R, uint8_t G, uint8_t B) +{ + GL_gotoxy(x, y); + GL_setpixelRGBhere(R, G, B); +} + +/** + * \brief restore default foreground and background colors + */ +static inline void GL_restore_default_colors() +{ + printf( + "\033[48;5;16m" // set background color black + "\033[38;5;15m" // set foreground color white + ); +} + +/** + * \brief Call this function each time graphics should be cleared + */ +static inline void GL_clear() +{ + GL_restore_default_colors(); + printf("\033[2J"); // clear screen +} + +/** + * \brief Moves current drawing position to top-left corner + * \see GL_setpixelRGBhere() and GL_set2pixelsRGBhere() + */ +static inline void GL_home() +{ + printf("\033[H"); +} + +/** + * \brief Call this function before starting drawing graphics + * or each time graphics should be cleared + */ +static inline void GL_init() +{ + printf("\033[?25l"); // hide cursor + GL_home(); + GL_clear(); +} + +/** + * \brief Call this function at the end of the program + */ +static inline void GL_terminate() +{ + GL_restore_default_colors(); + GL_gotoxy(0, GL_height); + printf("\033[?25h"); // show cursor +} + +/** + * \brief Flushes pending graphic operations and waits a bit + */ +static inline void GL_swapbuffers() +{ +#ifdef __linux__ + usleep(1000000 / GL_FPS); +#endif +} + +typedef void ( + *GL_pixelfunc_RGB)(int x, int y, uint8_t *r, uint8_t *g, uint8_t *b); +typedef void (*GL_pixelfunc_RGBf)(int x, int y, float *r, float *g, float *b); + +/** + * \brief Draws an image by calling a user-specified function for each pixel. + * \param[in] width , height dimension of the image in square pixels + * \param[in] do_pixel the user function to be called for each pixel + * (a "shader"), that determines the (integer) components r,g,b of + * the pixel's color. + * \details Uses half-charater pixels. + */ +static inline void GL_scan_RGB(int width, int height, GL_pixelfunc_RGB do_pixel) +{ + uint8_t r1, g1, b1; + uint8_t r2, g2, b2; + GL_home(); + for (int j = 0; j < height; j += 2) { + for (int i = 0; i < width; i++) { + do_pixel(i, j, &r1, &g1, &b1); + do_pixel(i, j + 1, &r2, &g2, &b2); + GL_set2pixelsRGBhere(r1, g1, b1, r2, g2, b2); + if (i == width - 1) { + GL_newline(); + } + } + } +} + +/** + * brief Converts a floating point value to a byte. + * \param[in] the floating point value in [0,1] + * \return the byte, in [0,255] + * \details the input value is clamped to [0,1] + */ +static inline uint8_t GL_ftoi(float f) +{ + f = (f < 0.0f) ? 0.0f : f; + f = (f > 1.0f) ? 1.0f : f; + return (uint8_t) (255.0f * f); +} + +/** + * \brief Draws an image by calling a user-specified function for each pixel. + * \param[in] width , height dimension of the image in square pixels + * \param[in] do_pixel the user function to be called for each pixel + * (a "shader"), that determines the (floating-point) components + * fr,fg,fb of the pixel's color. + * \details Uses half-charater pixels. + */ +static inline void GL_scan_RGBf(int width, + int height, + GL_pixelfunc_RGBf do_pixel) +{ + float fr1, fg1, fb1; + float fr2, fg2, fb2; + uint8_t r1, g1, b1; + uint8_t r2, g2, b2; + GL_home(); + for (int j = 0; j < height; j += 2) { + for (int i = 0; i < width; i++) { + do_pixel(i, j, &fr1, &fg1, &fb1); + r1 = GL_ftoi(fr1); + g1 = GL_ftoi(fg1); + b1 = GL_ftoi(fb1); + do_pixel(i, j + 1, &fr2, &fg2, &fb2); + r2 = GL_ftoi(fr2); + g2 = GL_ftoi(fg2); + b2 = GL_ftoi(fb2); + GL_set2pixelsRGBhere(r1, g1, b1, r2, g2, b2); + if (i == width - 1) { + GL_newline(); + } + } + } +} + +#define INSIDE 0 +#define LEFT 1 +#define RIGHT 2 +#define BOTTOM 4 +#define TOP 8 + +#define XMIN 0 +#define XMAX (GL_width - 1) +#define YMIN 0 +#define YMAX (GL_height - 1) + +#define code(x, y) \ + ((x) < XMIN) | (((x) > XMAX) << 1) | (((y) < YMIN) << 2) | \ + (((y) > YMAX) << 3) + +static inline void GL_line(int x1, int y1, int x2, int y2, int R, int G, int B) +{ + int x, y, dx, dy, sy, tmp; + + /* Cohen-Sutherland line clipping. */ + int code1 = code(x1, y1); + int code2 = code(x2, y2); + int codeout; + + for (;;) { + /* Both points inside. */ + if (code1 == 0 && code2 == 0) + break; + + /* No point inside. */ + if (code1 & code2) + return; + + /* One of the points is outside. */ + codeout = code1 ? code1 : code2; + + /* Compute intersection. */ + if (codeout & TOP) { + x = x1 + (x2 - x1) * (YMAX - y1) / (y2 - y1); + y = YMAX; + } else if (codeout & BOTTOM) { + x = x1 + (x2 - x1) * (YMIN - y1) / (y2 - y1); + y = YMIN; + } else if (codeout & RIGHT) { + y = y1 + (y2 - y1) * (XMAX - x1) / (x2 - x1); + x = XMAX; + } else if (codeout & LEFT) { + y = y1 + (y2 - y1) * (XMIN - x1) / (x2 - x1); + x = XMIN; + } + + /* Replace outside point with intersection. */ + if (codeout == code1) { + x1 = x; + y1 = y; + code1 = code(x1, y1); + } else { + x2 = x; + y2 = y; + code2 = code(x2, y2); + } + } + + /* Swap both extremities to ensure x increases */ + if (x2 < x1) { + tmp = x2; + x2 = x1; + x1 = tmp; + tmp = y2; + y2 = y1; + y1 = tmp; + } + + /* Bresenham line drawing */ + dy = y2 - y1; + sy = 1; + if (dy < 0) { + sy = -1; + dy = -dy; + } + + dx = x2 - x1; + + x = x1; + y = y1; + + if (dy > dx) { + int ex = (dx << 1) - dy; + for (int u = 0; u < dy; u++) { + GL_setpixelRGB(x, y, R, G, B); + y += sy; + if (ex >= 0) { + x++; + ex -= dy << 1; + GL_setpixelRGB(x, y, R, G, B); + } + while (ex >= 0) { + x++; + ex -= dy << 1; + putchar(' '); + } + ex += dx << 1; + } + } else { + int ey = (dy << 1) - dx; + for (int u = 0; u < dx; u++) { + GL_setpixelRGB(x, y, R, G, B); + x++; + while (ey >= 0) { + y += sy; + ey -= dx << 1; + GL_setpixelRGB(x, y, R, G, B); + } + ey += dy << 1; + } + } +} + +/* Display rotating squares */ +static const int sintab[64] = { + 0, 25, 49, 74, 97, 120, 142, 162, 181, 197, 212, + 225, 236, 244, 251, 254, 256, 254, 251, 244, 236, 225, + 212, 197, 181, 162, 142, 120, 97, 74, 49, 25, 0, + -25, -49, -74, -97, -120, -142, -162, -181, -197, -212, -225, + -236, -244, -251, -254, -256, -254, -251, -244, -236, -225, -212, + -197, -181, -162, -142, -120, -97, -74, -49, -25, +}; + +void spirograph(void); +void spirograph(void) +{ + GL_init(); + GL_clear(); + int frame = 0; + for (;;) { + int pts[8]; + + if (frame & (1 << 6)) + GL_clear(); + + int a = frame << 1; + int scaling = sintab[frame & 63] + 200; + + int Ux = (sintab[a & 63] * scaling) >> 12; + int Uy = (sintab[(a + 16) & 63] * scaling) >> 12; + int Vx = -Uy; + int Vy = Ux; + + pts[0] = (GL_width / 2) + Ux + Vx; + pts[1] = (GL_height / 2) + Uy + Vy; + + pts[2] = (GL_width / 2) - Ux + Vx; + pts[3] = (GL_height / 2) - Uy + Vy; + + pts[4] = (GL_width / 2) - Ux - Vx; + pts[5] = (GL_height / 2) - Uy - Vy; + + pts[6] = (GL_width / 2) + Ux - Vx; + pts[7] = (GL_height / 2) + Uy - Vy; + + int R = frame & 255; + int G = (frame >> 2) & 255; + int B = 255 - R; + + GL_line(pts[0], pts[1], pts[2], pts[3], R, G, B); + GL_line(pts[2], pts[3], pts[4], pts[5], R, G, B); + GL_line(pts[4], pts[5], pts[6], pts[7], R, G, B); + GL_line(pts[6], pts[7], pts[0], pts[1], R, G, B); + + GL_swapbuffers(); + + if (++frame > 14000) + break; + } + GL_terminate(); +}