From 80e0d08636d3205d58ea8d5e3cc146224d2b5066 Mon Sep 17 00:00:00 2001 From: The Dust Council Date: Fri, 12 Jun 2026 11:20:25 -0700 Subject: [PATCH] First remote version --- .claude/scheduled_tasks.lock | 1 - .claude/settings.local.json | 13 +- c64/Makefile | 55 ------- c64/c64-vg.cfg | 51 ------ c64/vectorgons.c | 311 ----------------------------------- c64/vectorgons.d64 | Bin 174848 -> 0 bytes c64/vectorgons.o | Bin 38111 -> 0 bytes c64/vectorgons.prg | Bin 4330 -> 0 bytes vectorgons | Bin 249280 -> 249280 bytes vectorgons.c | 2 +- vectorgons.exe | Bin 532480 -> 532480 bytes vectorgons.scr | Bin 532480 -> 532480 bytes web/vectorgons.wasm | Bin 508761 -> 508757 bytes 13 files changed, 13 insertions(+), 420 deletions(-) delete mode 100644 .claude/scheduled_tasks.lock delete mode 100644 c64/Makefile delete mode 100644 c64/c64-vg.cfg delete mode 100644 c64/vectorgons.c delete mode 100644 c64/vectorgons.d64 delete mode 100644 c64/vectorgons.o delete mode 100644 c64/vectorgons.prg diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock deleted file mode 100644 index c7c5ae6..0000000 --- a/.claude/scheduled_tasks.lock +++ /dev/null @@ -1 +0,0 @@ -{"sessionId":"dca9796d-8a4b-4077-8999-f6dfc6f287a1","pid":12539,"procStart":"661839","acquiredAt":1780643072550} \ No newline at end of file diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 233ab4e..cd0bfce 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -162,7 +162,18 @@ "Bash(DISPLAY=:0 timeout 60 firefox --headless --window-size=1920,1080 --screenshot /tmp/fsshot.png file:///tmp/fstest.html)", "Bash(grep -oE 'getFramebufferSize[^,;]{0,120}' web/vectorgons.js)", "Bash(grep -oE 'onCanvasResize[^,;{]{0,60}|setWindowSize[^,;{]{0,80}' web/vectorgons.js)", - "Bash(DISPLAY=:0 timeout 60 firefox --headless --window-size=1920,1080 --screenshot /tmp/fsshot2.png file:///tmp/fstest2.html)" + "Bash(DISPLAY=:0 timeout 60 firefox --headless --window-size=1920,1080 --screenshot /tmp/fsshot2.png file:///tmp/fstest2.html)", + "Bash(cp ~/.vectorgons /tmp/vectorgons.settings.bak)", + "Bash(printf 'multicolor=1\\\\nfullscreen=0\\\\n')", + "Bash(identify /tmp/osd.png)", + "Bash(DISPLAY=:0 convert /tmp/osd.png -crop 300x150+0+95 +repage -scale 250% /tmp/osd_crop2.png)", + "Bash(DISPLAY=:0 convert /tmp/osd.png -crop 320x80+0+248 +repage -scale 250% /tmp/osd_color.png)", + "Bash(DISPLAY=:0 convert /tmp/osd.png -crop 360x70+0+250 +repage -scale 240% /tmp/osd_color2.png)", + "Bash(cp /tmp/vectorgons.settings.bak ~/.vectorgons)", + "Bash(rm -f ~/.vectorgons)", + "Bash(rm -f /tmp/osd*.png /tmp/conv.log /tmp/imp.log)", + "Bash(apt-get download *)", + "Bash(awk '{print $5, $9}')" ] } } diff --git a/c64/Makefile b/c64/Makefile deleted file mode 100644 index 43b99c8..0000000 --- a/c64/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# =========================================================================== -# Vectorgons -- Commodore 64 build -# --------------------------------------------------------------------------- -# Cross-compiles the C64 edition with cc65 and packs it onto a .d64 disk -# image with VICE's c1541. -# -# make -> vectorgons.prg (raw C64 program, loads at $0801) -# make d64 -> vectorgons.d64 (bootable disk image) -# make run -> build + launch in the VICE x64sc emulator -# make clean -# -# cc65 need not be on PATH: set CC65_HOME / CL65 to point at an extracted -# install if it lives somewhere non-standard, e.g. -# make CL65=/path/to/cl65 CC65_HOME=/path/to/share/cc65 -# =========================================================================== - -CL65 ?= cl65 -C1541 ?= c1541 -X64 ?= x64sc - -TARGET = vectorgons -PRG = $(TARGET).prg -D64 = $(TARGET).d64 -CFG = c64-vg.cfg -SRC = vectorgons.c - -# Name shown in the C64 disk directory (PETSCII, <=16 chars). -DISKNAME = vectorgons -DISKID = vg -# Filename on the disk that the user LOADs. -DISKFILE = vectorgons - -CL65FLAGS = -t c64 -O -C $(CFG) - -.PHONY: all d64 run clean - -all: $(PRG) - -$(PRG): $(SRC) $(CFG) - $(CL65) $(CL65FLAGS) $(SRC) -o $(PRG) - -# Build a fresh, formatted .d64 and write the program into it. -d64: $(D64) - -$(D64): $(PRG) - $(C1541) -format "$(DISKNAME),$(DISKID)" d64 $(D64) \ - -write $(PRG) $(DISKFILE) - @echo "Wrote $(PRG) -> $(D64) as \"$(DISKFILE)\"" - @$(C1541) $(D64) -dir - -run: $(D64) - $(X64) -autostart $(D64) - -clean: - rm -f $(PRG) $(D64) *.map *.o shot*.png seq_*.png f_*.png diff --git a/c64/c64-vg.cfg b/c64/c64-vg.cfg deleted file mode 100644 index ed4cb42..0000000 --- a/c64/c64-vg.cfg +++ /dev/null @@ -1,51 +0,0 @@ -# Custom cc65 C64 linker config for Vectorgons. -# Code/RO/DATA live below the hi-res bitmap ($0801-$1FFF); the bitmap occupies -# $2000-$3FFF; BSS/heap/C-stack live above it ($4000-$CFFF). This guarantees -# the VIC-II bitmap region is never clobbered by program data. -FEATURES { - STARTADDRESS: default = $0801; -} -SYMBOLS { - __LOADADDR__: type = import; - __EXEHDR__: type = import; - __STACKSIZE__: type = weak, value = $0800; # 2k C stack - __HIMEM__: type = weak, value = $D000; -} -MEMORY { - ZP: file = "", define = yes, start = $0002, size = $001A; - LOADADDR: file = %O, start = %S - 2, size = $0002; - HEADER: file = %O, define = yes, start = %S, size = $000D; - # Code, read-only and initialized data: must end before the bitmap at $2000. - MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = $2000 - __HEADER_LAST__; - # $2000-$3FFF is reserved for the VIC-II hi-res bitmap (not mapped here). - # BSS / heap / C-stack live above the bitmap. - BSS: file = "", start = $4000, size = __HIMEM__ - __STACKSIZE__ - $4000; -} -SEGMENTS { - ZEROPAGE: load = ZP, type = zp; - LOADADDR: load = LOADADDR, type = ro; - EXEHDR: load = HEADER, type = ro; - STARTUP: load = MAIN, type = ro; - LOWCODE: load = MAIN, type = ro, optional = yes; - CODE: load = MAIN, type = ro; - RODATA: load = MAIN, type = ro; - DATA: load = MAIN, type = rw; - INIT: load = MAIN, type = rw; - ONCE: load = MAIN, type = ro, define = yes; - BSS: load = BSS, type = bss, define = yes; -} -FEATURES { - CONDES: type = constructor, - label = __CONSTRUCTOR_TABLE__, - count = __CONSTRUCTOR_COUNT__, - segment = ONCE; - CONDES: type = destructor, - label = __DESTRUCTOR_TABLE__, - count = __DESTRUCTOR_COUNT__, - segment = RODATA; - CONDES: type = interruptor, - label = __INTERRUPTOR_TABLE__, - count = __INTERRUPTOR_COUNT__, - segment = RODATA, - import = __CALLIRQ__; -} diff --git a/c64/vectorgons.c b/c64/vectorgons.c deleted file mode 100644 index a0e2e14..0000000 --- a/c64/vectorgons.c +++ /dev/null @@ -1,311 +0,0 @@ -/* =========================================================================== - * VECTORGONS -- Commodore 64 edition - * --------------------------------------------------------------------------- - * A tumbling-wireframe vector demo for the C64, a tiny cousin of the desktop / - * web Vectorgons. The 1 MHz 6510 has no FPU, so everything here is integer - * fixed-point: a 256-entry signed sine table (scale 128) drives the 3-D - * rotation, points are perspective-projected with integer division, and edges - * are drawn into the VIC-II hi-res bitmap with a Bresenham line routine. - * - * Per the brief the glass / metal / mirror objects are dropped (no shading on - * a 1-bit bitmap) -- what remains is the heart of Vectorgons: rotating - * polytopes, cycling through a small library of 3-D shapes plus a 4-D - * tesseract shadow, in classic monochrome vector-graphics style. - * - * Display : 320x200 hi-res bitmap at $2000, colour cells in screen RAM $0400. - * Build : cc65 (cl65 -t c64 -C c64-vg.cfg). See the Makefile in this dir. - * Controls: press any key to quit back to BASIC. - * =========================================================================== - */ - -#include -#include - -/* ---- VIC-II / memory layout ------------------------------------------- */ -#define BITMAP ((unsigned char *)0x2000) /* 8 KB hi-res bitmap */ -#define SCREEN ((unsigned char *)0x0400) /* colour cells (1000 bytes) */ -#define VIC_D011 0xD011 -#define VIC_D016 0xD016 -#define VIC_D018 0xD018 -#define VIC_D020 0xD020 /* border colour */ -#define VIC_D021 0xD021 /* background colour */ -#define KBD_NDX 0x00C6 /* keyboard buffer count */ - -/* ---- projection constants (model units) ------------------------------- */ -#define PROJ 224 /* focal length */ -#define DIST 140 /* camera distance */ -#define SCRW 320 -#define SCRH 200 - -#define MAXV 16 /* tesseract has the most vertices */ - -/* round(127 * sin(i * 2pi / 256)) -- fixed-point scale 128 (>>7) */ -static const signed char sintab[256] = { - 0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, - 49, 51, 54, 57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88, - 90, 92, 94, 96, 98, 100, 102, 104, 106, 107, 109, 111, 112, 113, 115, 116, - 117, 118, 120, 121, 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127, - 127, 127, 127, 127, 126, 126, 126, 125, 125, 124, 123, 122, 122, 121, 120, 118, - 117, 116, 115, 113, 112, 111, 109, 107, 106, 104, 102, 100, 98, 96, 94, 92, - 90, 88, 85, 83, 81, 78, 76, 73, 71, 68, 65, 63, 60, 57, 54, 51, - 49, 46, 43, 40, 37, 34, 31, 28, 25, 22, 19, 16, 12, 9, 6, 3, - 0, -3, -6, -9, -12, -16, -19, -22, -25, -28, -31, -34, -37, -40, -43, -46, - -49, -51, -54, -57, -60, -63, -65, -68, -71, -73, -76, -78, -81, -83, -85, -88, - -90, -92, -94, -96, -98, -100, -102, -104, -106, -107, -109, -111, -112, -113, -115, -116, - -117, -118, -120, -121, -122, -122, -123, -124, -125, -125, -126, -126, -126, -127, -127, -127, - -127, -127, -127, -127, -126, -126, -126, -125, -125, -124, -123, -122, -122, -121, -120, -118, - -117, -116, -115, -113, -112, -111, -109, -107, -106, -104, -102, -100, -98, -96, -94, -92, - -90, -88, -85, -83, -81, -78, -76, -73, -71, -68, -65, -63, -60, -57, -54, -51, - -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3, -}; - -/* =========================================================================== - * Shape library. Vertices are signed-char model coords (~ +/-45); edges are - * vertex-index pairs. Skip metal/glass/mirror -- pure wireframe polytopes. - * =========================================================================== - */ -static const signed char tetra_v[4][3] = { - { 45, 45, 45}, { 45,-45,-45}, {-45, 45,-45}, {-45,-45, 45} -}; -static const unsigned char tetra_e[6][2] = { - {0,1},{0,2},{0,3},{1,2},{1,3},{2,3} -}; - -static const signed char cube_v[8][3] = { - {-40,-40,-40},{ 40,-40,-40},{ 40, 40,-40},{-40, 40,-40}, - {-40,-40, 40},{ 40,-40, 40},{ 40, 40, 40},{-40, 40, 40} -}; -static const unsigned char cube_e[12][2] = { - {0,1},{1,2},{2,3},{3,0}, {4,5},{5,6},{6,7},{7,4}, {0,4},{1,5},{2,6},{3,7} -}; - -static const signed char octa_v[6][3] = { - { 50,0,0},{-50,0,0},{0, 50,0},{0,-50,0},{0,0, 50},{0,0,-50} -}; -static const unsigned char octa_e[12][2] = { - {0,2},{0,3},{0,4},{0,5},{1,2},{1,3},{1,4},{1,5},{2,4},{2,5},{3,4},{3,5} -}; - -static const signed char pyra_v[5][3] = { - {-40,-30,-40},{ 40,-30,-40},{ 40,-30, 40},{-40,-30, 40},{ 0, 48, 0} -}; -static const unsigned char pyra_e[8][2] = { - {0,1},{1,2},{2,3},{3,0},{4,0},{4,1},{4,2},{4,3} -}; - -/* Stellated "star": two interpenetrating tetrahedra (Stella octangula). */ -static const signed char star_v[8][3] = { - { 45, 45, 45},{ 45,-45,-45},{-45, 45,-45},{-45,-45, 45}, - {-45,-45,-45},{-45, 45, 45},{ 45,-45, 45},{ 45, 45,-45} -}; -static const unsigned char star_e[12][2] = { - {0,1},{0,2},{0,3},{1,2},{1,3},{2,3}, - {4,5},{4,6},{4,7},{5,6},{5,7},{6,7} -}; - -/* Tesseract shadow: an inner cube nested in an outer cube, corners linked. */ -static const signed char tess_v[16][3] = { - {-20,-20,-20},{ 20,-20,-20},{ 20, 20,-20},{-20, 20,-20}, - {-20,-20, 20},{ 20,-20, 20},{ 20, 20, 20},{-20, 20, 20}, - {-46,-46,-46},{ 46,-46,-46},{ 46, 46,-46},{-46, 46,-46}, - {-46,-46, 46},{ 46,-46, 46},{ 46, 46, 46},{-46, 46, 46} -}; -static const unsigned char tess_e[32][2] = { - {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}, - {8,9},{9,10},{10,11},{11,8},{12,13},{13,14},{14,15},{15,12}, - {8,12},{9,13},{10,14},{11,15}, - {0,8},{1,9},{2,10},{3,11},{4,12},{5,13},{6,14},{7,15} -}; - -typedef struct { - const signed char (*v)[3]; - unsigned char nv; - const unsigned char (*e)[2]; - unsigned char ne; -} Shape; - -static const Shape shapes[] = { - { cube_v, 8, cube_e, 12 }, - { octa_v, 6, octa_e, 12 }, - { tetra_v, 4, tetra_e, 6 }, - { star_v, 8, star_e, 12 }, - { pyra_v, 5, pyra_e, 8 }, - { tess_v, 16, tess_e, 32 } -}; -#define NSHAPES (sizeof(shapes) / sizeof(shapes[0])) - -/* Foreground colours cycled per shape (upper nibble; background black). */ -static const unsigned char palette[] = { 3, 14, 1, 7, 13, 5, 4 }; -#define NCOL (sizeof(palette) / sizeof(palette[0])) - -/* ---- precomputed bitmap address tables (built at startup) ------------- */ -static unsigned int ytab[SCRH]; /* (y>>3)*320 + (y&7) */ -static unsigned int xtab[SCRW]; /* (x>>3)*8 */ -static unsigned char mtab[SCRW]; /* 0x80 >> (x&7) */ - -/* ---- per-frame projected coordinates ---------------------------------- */ -static int sx[MAXV], sy[MAXV]; /* current frame */ -static int psx[MAXV], psy[MAXV]; /* previous frame */ - -static void build_tables(void) -{ - unsigned int y, x; - for (y = 0; y < SCRH; ++y) - ytab[y] = (unsigned int)((y >> 3) * 320 + (y & 7)); - for (x = 0; x < SCRW; ++x) { - xtab[x] = (unsigned int)((x >> 3) * 8); - mtab[x] = (unsigned char)(0x80 >> (x & 7)); - } -} - -/* Set bitmap mode, bitmap @ $2000, colour cells @ $0400, black border. */ -static void gfx_on(unsigned char colour) -{ - memset(BITMAP, 0, 8000); /* clear bitmap */ - memset(SCREEN, colour, 1000); /* fg/bg per cell */ - POKE(VIC_D020, 0); /* black border */ - POKE(VIC_D021, 0); /* black background */ - POKE(VIC_D018, 0x18); /* screen $0400, bmp $2000 */ - POKE(VIC_D016, PEEK(VIC_D016) & 0xEF);/* hi-res (MCM off) */ - POKE(VIC_D011, PEEK(VIC_D011) | 0x20);/* bitmap mode (BMM on) */ -} - -/* Restore the normal text screen on the way out. */ -static void gfx_off(void) -{ - POKE(VIC_D011, PEEK(VIC_D011) & 0xDF);/* BMM off */ - POKE(VIC_D018, 0x15); /* default char/screen */ - POKE(VIC_D020, 14); /* default border */ - POKE(VIC_D021, 6); /* default background */ - memset(SCREEN, 0x20, 1000); /* blank text screen */ - memset((unsigned char *)0xD800, 14, 1000); /* light-blue text */ -} - -/* Plot one pixel. set != 0 turns the pixel on, otherwise clears it. - * Off-screen points are silently clipped. */ -static void plot(int x, int y, unsigned char set) -{ - unsigned char *p; - if (x < 0 || x >= SCRW || y < 0 || y >= SCRH) - return; - p = BITMAP + ytab[y] + xtab[x]; - if (set) - *p |= mtab[x]; - else - *p &= (unsigned char)~mtab[x]; -} - -/* Integer Bresenham line from (x0,y0) to (x1,y1). */ -static void line(int x0, int y0, int x1, int y1, unsigned char set) -{ - int dx = (x1 > x0) ? (x1 - x0) : (x0 - x1); - int dy = -((y1 > y0) ? (y1 - y0) : (y0 - y1)); - int sx0 = (x0 < x1) ? 1 : -1; - int sy0 = (y0 < y1) ? 1 : -1; - int err = dx + dy; - int e2; - for (;;) { - plot(x0, y0, set); - if (x0 == x1 && y0 == y1) - break; - e2 = err << 1; - if (e2 >= dy) { err += dy; x0 += sx0; } - if (e2 <= dx) { err += dx; y0 += sy0; } - } -} - -/* Rotate the current shape's vertices by (ax,ay,az) and perspective-project - * into sx[]/sy[]. All maths integer; sin/cos read from sintab (>>7). */ -static void project(const Shape *sh, - unsigned char ax, unsigned char ay, unsigned char az) -{ - int sinx = sintab[ax]; - int cosx = sintab[(unsigned char)(ax + 64)]; - int siny = sintab[ay]; - int cosy = sintab[(unsigned char)(ay + 64)]; - int sinz = sintab[az]; - int cosz = sintab[(unsigned char)(az + 64)]; - unsigned char i; - - for (i = 0; i < sh->nv; ++i) { - int x = sh->v[i][0]; - int y = sh->v[i][1]; - int z = sh->v[i][2]; - int t; - int denom; - - /* rotate about X */ - t = (y * cosx - z * sinx) >> 7; - z = (y * sinx + z * cosx) >> 7; - y = t; - /* rotate about Y */ - t = (x * cosy + z * siny) >> 7; - z = (z * cosy - x * siny) >> 7; - x = t; - /* rotate about Z */ - t = (x * cosz - y * sinz) >> 7; - y = (x * sinz + y * cosz) >> 7; - x = t; - - denom = z + DIST; /* always positive given coord ranges */ - sx[i] = 160 + (x * PROJ) / denom; - sy[i] = 100 - (y * PROJ) / denom; - } -} - -void main(void) -{ - unsigned char shape = 0; - unsigned char colidx = 0; - unsigned char ax = 0, ay = 0, az = 0; - unsigned int frame = 0; - unsigned char first = 1; - const Shape *sh; - unsigned char i; - - build_tables(); - POKE(KBD_NDX, 0); /* flush keyboard buffer */ - gfx_on(palette[0] << 4); - - sh = &shapes[0]; - - for (;;) { - /* --- advance rotation (three different rates => tumble) --- */ - ax += 2; - ay += 3; - az += 1; - - project(sh, ax, ay, az); - - /* --- erase previous frame's edges, then draw the new ones --- */ - if (!first) { - for (i = 0; i < sh->ne; ++i) { - unsigned char a = sh->e[i][0], b = sh->e[i][1]; - line(psx[a], psy[a], psx[b], psy[b], 0); - } - } - for (i = 0; i < sh->ne; ++i) { - unsigned char a = sh->e[i][0], b = sh->e[i][1]; - line(sx[a], sy[a], sx[b], sy[b], 1); - } - for (i = 0; i < sh->nv; ++i) { psx[i] = sx[i]; psy[i] = sy[i]; } - first = 0; - - /* --- cycle to the next shape every ~200 frames --- */ - if (++frame >= 200) { - frame = 0; - shape = (unsigned char)((shape + 1) % NSHAPES); - colidx = (unsigned char)((colidx + 1) % NCOL); - sh = &shapes[shape]; - first = 1; - memset(BITMAP, 0, 8000); /* fresh canvas */ - memset(SCREEN, palette[colidx] << 4, 1000); - } - - /* --- quit on any keypress --- */ - if (PEEK(KBD_NDX) != 0) - break; - } - - gfx_off(); -} diff --git a/c64/vectorgons.d64 b/c64/vectorgons.d64 deleted file mode 100644 index 8d272efd4f94aa32ea516f62911dcd3bbc0a1194..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174848 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
vTYc+lT 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 AivR!s diff --git a/vectorgons b/vectorgons index 95ac78252dc9e0d6550462c9992ce85dfeae98f9..b5d4ae1c1369fd7cefbbd81b56180df278f52c0c 100755 GIT binary patch delta 484 zcmX>woBzOU{tXSxB6W|qOs~{^z`|Y|8CW5cTUmO_`uFB3%tFeH^_!QgiHI}yP2OXx z$!I_MnXM|L?`9r5Rz}9;$wKzK84pfAXTO0_YjVBAW5&42$&ObU=S{YB+RgZD@>d`k zHhH7-3C5+9t6WYBO3F90g+yr0Hj_xHvB$sau=Cx?6VGM<|J)MJTK_*^E2&-^jAi`zkl@%jO|`vMpk zKtjzpzi5r zu;8@Gg}ysQq6K0TYTY;h;y{ub+lxyor4}O;uKnqVy4)t5E z#0nGxxyzslq=fhHbYyoO04fvREayLgiE-BC^??P9){_;2oEVuWCkOd59+Lo}3qK$LKeCZLkEFK2WF?Xbh{)kGYl)28uO%|EwQhg-jOjQNGcZWDFMG)(^#lOcrnDFU delta 486 zcmX>woBzOU{tXSxBAUDh3(mR~#@{wLHfv#MhiSQ@!1T>in1z%XTQ)CO6A@>eJb90; zCZo&bXSS-0L7RE(SQ!~JCJWi`W;{0eoc#ty{mJzXj~SCECp%tcTs+y*X*c8l$zOqF z^yH1sCm2^vu5vjkG{$1KJ&-eE^Y@I#v2Ue?h9aG z0I7Fvy$v*8e)DQiGbRC%*O zB`%;C$Xy0aASJv^KrX^v2Y||?Hp}@>U}Bs 0.001f) LINE("HUE CYCLE C/V %.0f%%", cfg.hue_cycle); else LINE("%s", "HUE CYCLE C/V OFF"); - LINE("COLOR M %s", cfg.multicolor ? "MULTICOLOR" : "SINGLE"); + LINE("COLOR M %s", cfg.multicolor ? "MULTI" : "SINGLE"); LINE("GLOW O/L %.0f%%", cfg.glow); LINE("FLICKER G/H %.0f%%", cfg.flicker); LINE("MAGNIFY B/P %d", cfg.mag_count); diff --git a/vectorgons.exe b/vectorgons.exe index a5c9e34684d376d7f756651c9579cdd8fe6b26a6..612bc058930f6bff8153b898e09421a5666bc86a 100755 GIT binary patch delta 225 zcmZoTpwMtYVL}J9T)oo7ZeONHl8v`oZ!xysVrsp`+;>n+xk8jN4JFVSRmW0u?P z$H3sz%exLp?FwLEU~p}H>(k46BLpO>yL3B;F6&7~#(UE*>9NjabeW!`&pLx~^>kJP z)|pb$-V6+_2TEjIx^#aa&l4M^S|Zp!LnHhn=hs|5?tO$_bVvsr;>n+xk8jQcTFVSRmW0pJM z$H3sz%exs!?FwLEU~p}H>(k46BLpO>yJ|a!F6&7~#>dky>9Nja^qiif&pLx~!*o^y z)|pZY-V6+_2TEjIx;>n+yhJdA3T;`uU1H+55%fJ7-bh9>VGBA90;g9*}(RtIOm-YPiv&O9M%raA4 zpu#@AtP{K$7<{9 delta 266 zcmZoTpwMtYVL}J9r-S0eZeJ#zwT-u0Z!xysVrsp`+;>n+yhJd9!6n|N6#^D!Qp zE+)g8%ow-5N`}>3T!z_$f#F5j<=_8Zx>=hw85lmh@W=e~=)CFC%X($|Sz}grW|^5T zP+^~5)(PGW47&mt7#LhzPx|!oR%|ygXFbEnxO@6v3)WeT3e#s;vd&~|n{H&qI$QRO z14!B167gnRV&vko?HR}v!uGuyW3?(4x{^@G= ztX7PP(-ZAkMY!C6!eCv_+w1LF<#kw{{eAp{rq9b}b!~r<%?iY9+h1g}OKbrE`ovkB diff --git a/web/vectorgons.wasm b/web/vectorgons.wasm index 1c5500ca9bab6ec812605794f973d3c4d5e692fe..f9757ff7f18d7cec00a1e437f7440b3b83e2c192 100755 GIT binary patch delta 609 zcmX|-Ur3Wt7{<@@eP`z@XSrSM#$D{g{!!bvEklY*@I+FEUA57srZf^_b<<5WArc18 zo4RT9K+s(<3`dJ_r*5LrMG`4eSlcL^7>z{1WYE8h`o4)?Je=S2p7TC0?Jk5igx91KnznPA?0_9Yc@6;3A22KPO5E{*Hp6c6jPD>J zN6A0cUlzX**CU9~tdGx&nF#J_Ijb|Th~fbH#q%g!cq8Yccn$j4;A=9|j}&Ot z%ijt85)zyAaGP2Okw8tP2Qg0b2G0q72)A4d{>Jd1*1)+2tLv(`9K}BQeh7UE9tb0b z{hMJIW9URJm5ITWVoEhdP1$57#tJEX5xpzyfa{Ur_)ObCyL51JoDgfvv>abyVfa@K zN11l-BCWinnB}a0%a$!Ww|!f&Y*N}+Sp?>PUs+?rDi+1tb#@Lyx_+=%iofpNYM!=U zZ}_%s!LoO^v!rD|3AN7rNXhm(`)ETkyYmk_feqQzp~bb9Wv_1I`i(Zt%_lv4S|(3w zLc@}DpVpi(PorCF+0#5xKox|K?yy&a^6XWu>J&#tv@^Ez;oeY>OpIs&X5(Lv**oRb IsFpkRAJ&$_m;e9( delta 613 zcmX|-TS!zv9LDE6XLhDs%k^Pj^udE&q>kr!0SUT*Q!Qw02<6gxNoh%lt(P8(6e2-z zedh;Jvxl>iCRYH?FmP*fV7<+6>U3oq0UinBg8UM?WU zRbvh=*W$aJJdP@)<<@!(Vor|M<0AX#>ZGK65<#=N9>IXI`$n0rd^F;L6wQTS^ZU|W zgzO<}rslB>o2wp=%5zaf>8vd#V$#s%0e8brc{Y_jo%U>x^8aE{=>Imzj%RRk_SQ`!M!k^Ix_PD=Mdo$9di#+wuwPd@(N+{YB!r z>e|mG$DArW%=4jlC&cr%<=z@W8bow%^53gaHD~y2e$LTIxW4vKUAXR;Ea~7i>Ou#1 N86|qDhn@V