M README.md => README.md +8 -0
@@ 37,6 37,14 @@ To display the list of operators inside of Orca, use `CmdOrCtrl+G`.
- `*` **bang**: Bangs neighboring operands.
- `#` **comment**: Halts a line.
+## Syntax Highlight
+
+- `1` locked
+- `2` port(left)
+- `3` operator
+- `4` port(right)
+- `5` port(output)
+
## TODOs
- Default values
D abflm-expected.orca => abflm-expected.orca +0 -10
@@ 1,10 0,0 @@
-.A.aA..AaaAa1AA2AZ
-.0..a..a..k..B..1.
-.B.aB..BaaBa1BA2BZ
-.0..a..a..0..9..X.
-.F.aF..FaaFa1FAzFZ
-.*........*.......
-.L.aL..LaaLa1LAzLZ
-..........a..1..Z.
-.M.aM..MaaMa1MAzMZ
-.0..0..0..s..A..1.
D abflm-result.orca => abflm-result.orca +0 -22
@@ 1,22 0,0 @@
-.A.aA..AaaAa1AA2AZ
-.0..a..a..k.......
-.B.aB..BaaBa1BA2BZ
-.0..a..a..0.......
-.F.aF..FaaFa1FAzFZ
-.*........*.......
-.L.aL..LaaLa1LAzLZ
-..........a.......
-.M.aM..MaaMa1MAzMZ
-.0..0..0..s.......
-
-234234234234344444
-050050050050000000
-234234234234344444
-050050050050000000
-234234234234344444
-050050050050000000
-234234234234344444
-050050050050000000
-234234234234344444
-050050050050000000
-
D abflm.orca => abflm.orca +0 -10
@@ 1,10 0,0 @@
-.A.aA..AaaAa1AA2AZ
-..................
-.B.aB..BaaBa1BA2BZ
-..................
-.F.aF..FaaFa1FAzFZ
-..................
-.L.aL..LaaLa1LAzLZ
-..................
-.M.aM..MaaMa1MAzMZ
-..................
M build.sh => build.sh +13 -15
@@ 1,20 1,18 @@
#!/bin/bash
+clang-format -i sim.c
+clang-format -i sim.h
+clang-format -i cli.c
clang-format -i toy.c
-rm -f ./toy
-
-# GNU/Linux
-# cc -std=c89 -DDEBUG -Wall -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined -o toy toy.c
-
-# GNU/Linux
-cc toy.c -std=c89 -O2 -DNDEBUG -g0 -s -Wall -o toy
+# cli
+# rm -f ./cli
+# cc -std=c89 -DDEBUG -Wall -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined -o cli cli.c sim.c
+# cc cli.c sim.c -std=c89 -O2 -DNDEBUG -g0 -s -Wall -o cli
+# ./cli demo.orca
-# Plan9
-# pcc toy.c -o toy
-
-# ./toy abflm.orca > abflm-result.orca
-# diff abflm-result.orca abflm-expected.orca
-
-# time ./toy ~/Git/orca-examples/benchmarks/logic.orca
-./toy demo.orca
+# toy
+rm -f ./toy
+cc -std=c89 -DDEBUG -Wall -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined -L/usr/local/lib -lSDL2 toy.c sim.c -o toy
+# cc toy.c sim.c -std=c89 -O2 -DNDEBUG -g0 -s -Wall -L/usr/local/lib -lSDL2 -o toy
+./toy
A cli => cli +0 -0
A cli.c => cli.c +33 -0
@@ 0,0 1,33 @@
+#include <stdio.h>
+#include "sim.h"
+
+int
+error(char *name)
+{
+ printf("Error: %s\n", name);
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ FILE *f;
+ int limit = 3;
+ Grid g;
+ g.w = 0;
+ g.h = 0;
+ g.f = 0;
+ g.r = 1;
+ if(argc < 2)
+ return error("No input.");
+ f = fopen(argv[1], "r");
+ if(!f)
+ return error("Missing input.");
+ if(!disk(f, &g))
+ return error("Invalid grid");
+ while(g.f < limit) {
+ run(&g);
+ print(&g);
+ }
+ return 0;
+}
A sim.c => sim.c +555 -0
@@ 0,0 1,555 @@
+#include <stdio.h>
+#include "sim.h"
+
+int
+ciuc(char c)
+{
+ return c >= 'A' && c <= 'Z';
+}
+
+int
+cilc(char c)
+{
+ return c >= 'a' && c <= 'z';
+}
+
+int
+cinu(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+int
+cisp(char c)
+{
+ return !ciuc(c) && !cilc(c) && !cinu(c) && c != '.';
+}
+
+int
+clca(int c)
+{
+ return ciuc(c) ? c + ('a' - 'A') : c;
+}
+
+int
+cint(char c)
+{
+ if(c == '.')
+ return 0;
+ if(cinu(c))
+ return c - '0';
+ if(cilc(c))
+ return c - 'a' + 10;
+ if(ciuc(c))
+ return c - 'A' + 10;
+ return 0;
+}
+
+char
+cchr(int v, int cap)
+{
+ v %= 36;
+ v *= v < 0 ? -1 : 1;
+ if(v >= 0 && v <= 9)
+ return '0' + v;
+ if(cap)
+ return 'A' + (v - 10);
+ return 'a' + (v - 10);
+}
+
+int
+valid(Grid *g, int x, int y)
+{
+ return x >= 0 && x <= g->w && y >= 0 && y <= g->h;
+}
+
+int
+random(Grid *g)
+{
+ (void)g;
+ return 0;
+ /*
+ g->r *= 1103515245;
+ return ((g->r / 65536 * g->f) % 32768) ^ g->f;
+ */
+}
+
+/* IO */
+
+char
+get(Grid *g, int x, int y)
+{
+ if(valid(g, x, y))
+ return g->data[x + (y * g->w)];
+ return '.';
+}
+
+void
+set(Grid *g, int x, int y, char c)
+{
+ if(valid(g, x, y))
+ g->data[x + (y * g->w)] = c;
+}
+
+/* Locks */
+
+void
+lock(Grid *g, int x, int y)
+{
+ if(valid(g, x, y)) {
+ g->lock[x + (y * g->w)] = 1;
+ g->type[x + (y * g->w)] = 1;
+ }
+}
+
+/* Variables */
+
+void
+save(Grid *g, char key, char val)
+{
+ g->vars[cint(key)] = val;
+}
+
+char
+load(Grid *g, char key)
+{
+ return g->vars[cint(key)];
+}
+
+/* Syntax */
+
+int
+gettype(Grid *g, int x, int y)
+{
+ if(valid(g, x, y))
+ return g->type[x + (y * g->w)];
+ return 0;
+}
+
+void
+settype(Grid *g, int x, int y, int t)
+{
+ if(valid(g, x, y))
+ g->type[x + (y * g->w)] = t;
+}
+
+/* Port Setters */
+
+void
+setport(Grid *g, int x, int y, char c)
+{
+ lock(g, x, y);
+ settype(g, x, y, 5);
+ set(g, x, y, c);
+}
+
+int
+getport(Grid *g, int x, int y, int l)
+{
+ if(l) {
+ lock(g, x, y);
+ settype(g, x, y, 4);
+ } else
+ settype(g, x, y, 2);
+ return get(g, x, y);
+}
+
+int
+bang(Grid *g, int x, int y)
+{
+ return get(g, x - 1, y) == '*' || get(g, x + 1, y) == '*' || get(g, x, y - 1) == '*' || get(g, x, y + 1) == '*';
+}
+
+/* Library */
+
+void
+opa(Grid *g, int x, int y, char c)
+{
+ char a = getport(g, x - 1, y, 0);
+ char b = getport(g, x + 1, y, 1);
+ setport(g, x, y + 1, cchr(cint(a) + cint(b), ciuc(b)));
+ (void)c;
+}
+
+void
+opb(Grid *g, int x, int y, char c)
+{
+ char a = getport(g, x - 1, y, 0);
+ char b = getport(g, x + 1, y, 1);
+ setport(g, x, y + 1, cchr(cint(a) - cint(b), ciuc(b)));
+ (void)c;
+}
+
+void
+opc(Grid *g, int x, int y, char c)
+{
+ char rate = getport(g, x - 1, y, 0);
+ char mod = getport(g, x + 1, y, 1);
+ setport(g, x, y + 1, cchr(g->f / rate % mod, ciuc(mod)));
+ (void)c;
+}
+
+void
+opd(Grid *g, int x, int y, char c)
+{
+ char rate = getport(g, x - 1, y, 0);
+ char mod = getport(g, x + 1, y, 1);
+ setport(g, x, y + 1, g->f % (rate * mod) == 0 ? '*' : '.');
+ (void)c;
+}
+
+void
+ope(Grid *g, int x, int y, char c)
+{
+ if(x == g->w || get(g, x + 1, y) != '.')
+ set(g, x, y, '*');
+ else {
+ set(g, x, y, '.');
+ setport(g, x + 1, y, c);
+ }
+}
+
+void
+opf(Grid *g, int x, int y, char c)
+{
+ setport(g, x, y + 1, getport(g, x - 1, y, 0) == getport(g, x + 1, y, 1) ? '*' : '.');
+ (void)c;
+}
+
+void
+opg(Grid *g, int x, int y, char c)
+{
+ int tx = cint(getport(g, x - 3, y, 0));
+ int ty = cint(getport(g, x - 2, y, 0));
+ int i, len = cint(getport(g, x - 1, y, 0));
+ for(i = 0; i < len; ++i)
+ setport(g, x + i + tx, y + 1 + ty, getport(g, x + 1 + i, y, 1));
+ (void)c;
+}
+
+void
+oph(Grid *g, int x, int y, char c)
+{
+ getport(g, x, y + 1, 1);
+ (void)c;
+}
+
+void
+opi(Grid *g, int x, int y, char c)
+{
+ char step = getport(g, x - 1, y, 0);
+ char mod = getport(g, x + 1, y, 1);
+ char val = getport(g, x, y + 1, 1);
+ setport(g, x, y + 1, cchr((cint(val) + cint(step)) % (cint(mod) || 1), ciuc(mod)));
+ (void)c;
+}
+
+void
+opj(Grid *g, int x, int y, char c)
+{
+ int i;
+ char link = getport(g, x, y - 1, 0);
+ if(link != c) {
+ for(i = 1; y + i < g->h; ++i)
+ if(get(g, x, y + i) != c)
+ break;
+ setport(g, x, y + i, link);
+ }
+}
+
+void
+opk(Grid *g, int x, int y, char c)
+{
+ int i, len = cint(getport(g, x - 1, y, 0));
+ for(i = 0; i < len; ++i) {
+ char key = getport(g, x + 1 + i, y, 1);
+ if(key == '.')
+ continue;
+ setport(g, x + 1 + i, y + 1, load(g, key));
+ }
+ (void)c;
+}
+
+void
+opl(Grid *g, int x, int y, char c)
+{
+ char a = getport(g, x - 1, y, 0);
+ char b = getport(g, x + 1, y, 1);
+ setport(g, x, y + 1, cint(a) < cint(b) ? a : b);
+ (void)c;
+}
+
+void
+opm(Grid *g, int x, int y, char c)
+{
+ char a = getport(g, x - 1, y, 0);
+ char b = getport(g, x + 1, y, 1);
+ setport(g, x, y + 1, cchr(cint(a) * cint(b), ciuc(b)));
+ (void)c;
+}
+
+void
+opn(Grid *g, int x, int y, char c)
+{
+ if(y == 0 || get(g, x, y - 1) != '.')
+ set(g, x, y, '*');
+ else {
+ set(g, x, y, '.');
+ setport(g, x, y - 1, c);
+ }
+}
+
+void
+opo(Grid *g, int x, int y, char c)
+{
+ int tx = cint(getport(g, x - 2, y, 0));
+ int ty = cint(getport(g, x - 1, y, 0));
+ setport(g, x, y + 1, getport(g, x + 1 + tx, y + ty, 1));
+ (void)c;
+}
+
+void
+opp(Grid *g, int x, int y, char c)
+{
+ int key = cint(getport(g, x - 2, y, 0));
+ int i, len = cint(getport(g, x - 1, y, 0));
+ /* TODO */
+ for(i = 0; i < len; ++i)
+ lock(g, x + i, y + 1);
+ setport(g, x + (key % len), y + 1, get(g, x + 1, y));
+ (void)c;
+}
+
+void
+opq(Grid *g, int x, int y, char c)
+{
+ int tx = cint(getport(g, x - 3, y, 0));
+ int ty = cint(getport(g, x - 2, y, 0));
+ int i, len = cint(getport(g, x - 1, y, 0));
+ for(i = 0; i < len; ++i)
+ setport(g, x + 1 - len + i, y + 1, getport(g, x + 1 + tx + i, y + ty, 1));
+ (void)c;
+}
+
+void
+opr(Grid *g, int x, int y, char c)
+{
+ int min = cint(getport(g, x - 1, y, 0));
+ char max = getport(g, x + 1, y, 1);
+ setport(g, x, y + 1, cchr((random(g) % ((cint(max) - min) || 1)) + min, ciuc(max)));
+ (void)c;
+}
+
+void
+ops(Grid *g, int x, int y, char c)
+{
+ if(y == g->h || get(g, x, y + 1) != '.')
+ set(g, x, y, '*');
+ else {
+ set(g, x, y, '.');
+ setport(g, x, y + 1, c);
+ }
+}
+
+void
+opt(Grid *g, int x, int y, char c)
+{
+ int key = cint(getport(g, x - 2, y, 0));
+ int i, len = cint(getport(g, x - 1, y, 0));
+ for(i = 0; i < len; ++i)
+ lock(g, x + 1 + i, y);
+ setport(g, x, y + 1, getport(g, x + 1 + (key % len), y, 1));
+ (void)c;
+}
+
+void
+opu(Grid *g, int x, int y, char c)
+{
+ int max = cint(getport(g, x - 1, y, 0));
+ int step = cint(getport(g, x + 1, y, 1));
+ int bucket = (step * (g->f + max - 1)) % max + step;
+ setport(g, x, y + 1, bucket >= max ? '*' : '.');
+ (void)c;
+}
+
+void
+opv(Grid *g, int x, int y, char c)
+{
+ char w = getport(g, x - 1, y, 0);
+ char r = getport(g, x + 1, y, 1);
+ if(w != '.')
+ save(g, w, r);
+ else if(w == '.' && r != '.')
+ setport(g, x, y + 1, load(g, r));
+ (void)c;
+}
+
+void
+opw(Grid *g, int x, int y, char c)
+{
+ if(x == 0 || get(g, x - 1, y) != '.')
+ set(g, x, y, '*');
+ else {
+ set(g, x, y, '.');
+ setport(g, x - 1, y, c);
+ }
+}
+
+void
+opx(Grid *g, int x, int y, char c)
+{
+ int tx = cint(getport(g, x - 2, y, 0));
+ int ty = cint(getport(g, x - 1, y, 0));
+ setport(g, x + tx, y + ty + 1, getport(g, x + 1, y, 1));
+ (void)c;
+}
+
+void
+opy(Grid *g, int x, int y, char c)
+{
+ int i;
+ char link = getport(g, x - 1, y, 0);
+ if(link != c) {
+ for(i = 1; x + i < g->w; ++i)
+ if(get(g, x + i, y) != c)
+ break;
+ setport(g, x + i, y, link);
+ }
+}
+
+void
+opz(Grid *g, int x, int y, char c)
+{
+ int rate = cint(getport(g, x - 1, y, 0));
+ char target = getport(g, x + 1, y, 1);
+ char val = cint(getport(g, x, y + 1, 1));
+ int t = cint(target);
+ int mod = val < t ? rate : val > t ? -rate : 0;
+ setport(g, x, y + 1, cchr(val + mod, ciuc(target)));
+ (void)c;
+}
+
+void
+opcomment(Grid *g, int x, int y)
+{
+ int i;
+ for(i = 1; x + i < g->w; ++i) {
+ lock(g, x + i, y);
+ if(get(g, x + i, y) == '#')
+ break;
+ }
+}
+
+void
+opspecial(Grid *g, int x, int y)
+{
+ int i, b = bang(g, x, y);
+ for(i = 0; x + i < g->w; ++i) {
+ char c = getport(g, x + i, y, 1);
+ if(c == '.')
+ break;
+ if(b)
+ printf("%c", c);
+ }
+ if(b)
+ printf("\n");
+}
+
+void
+operate(Grid *g, int x, int y, char c)
+{
+ switch(clca(c)) {
+ case 'a': opa(g, x, y, c); break;
+ case 'b': opb(g, x, y, c); break;
+ case 'c': opc(g, x, y, c); break;
+ case 'd': opd(g, x, y, c); break;
+ case 'e': ope(g, x, y, c); break;
+ case 'f': opf(g, x, y, c); break;
+ case 'g': opg(g, x, y, c); break;
+ case 'h': oph(g, x, y, c); break;
+ case 'i': opi(g, x, y, c); break;
+ case 'k': opk(g, x, y, c); break;
+ case 'j': opj(g, x, y, c); break;
+ case 'l': opl(g, x, y, c); break;
+ case 'm': opm(g, x, y, c); break;
+ case 'n': opn(g, x, y, c); break;
+ case 'o': opo(g, x, y, c); break;
+ case 'p': opp(g, x, y, c); break;
+ case 'q': opq(g, x, y, c); break;
+ case 'r': opr(g, x, y, c); break;
+ case 's': ops(g, x, y, c); break;
+ case 't': opt(g, x, y, c); break;
+ case 'u': opu(g, x, y, c); break;
+ case 'v': opv(g, x, y, c); break;
+ case 'w': opw(g, x, y, c); break;
+ case 'x': opx(g, x, y, c); break;
+ case 'y': opy(g, x, y, c); break;
+ case 'z': opz(g, x, y, c); break;
+ case '*': set(g, x, y, '.'); break;
+ case '#': opcomment(g, x, y); break;
+ default: opspecial(g, x, y);
+ }
+ settype(g, x, y, 3);
+}
+
+/* General */
+
+void
+print(Grid *g)
+{
+ int x, y;
+ for(y = 0; y < g->h; ++y)
+ for(x = 0; x < g->w; ++x) {
+ putchar(get(g, x, y));
+ if(x == g->w - 1)
+ putchar('\n');
+ }
+ putchar('\n');
+ for(y = 0; y < g->h; ++y)
+ for(x = 0; x < g->w; ++x) {
+ printf("%d", gettype(g, x, y));
+ if(x == g->w - 1)
+ putchar('\n');
+ }
+ putchar('\n');
+}
+
+int
+run(Grid *g)
+{
+ int i, x, y;
+ for(i = 0; i < g->l; ++i) {
+ g->lock[i] = 0;
+ g->type[i] = 0;
+ }
+ for(i = 0; i < g->l; ++i) {
+ char c = g->data[i];
+ x = i % g->w;
+ y = i / g->w;
+ if(c == '.' || g->lock[i])
+ continue;
+ if(cilc(c) && !bang(g, x, y))
+ continue;
+ operate(g, x, y, c);
+ }
+ g->f++;
+ return 1;
+}
+
+int
+disk(FILE *f, Grid *g)
+{
+ char c;
+ g->l = 0;
+ while((c = fgetc(f)) != EOF && g->l < MAXSZ) {
+ if(c == '\n') {
+ if(g->w == 0)
+ g->w = g->l;
+ g->h = g->l / g->w;
+ } else {
+ g->type[g->l] = 0;
+ g->data[g->l++] = c;
+ }
+ }
+ return g->w > 2 && g->h > 2;
+}
A sim.h => sim.h +17 -0
@@ 0,0 1,17 @@
+#pragma once
+
+#include <stdio.h>
+
+#define MAXSZ 128 * 128
+
+typedef struct Grid {
+ int w, h, l, f, r;
+ int lock[MAXSZ];
+ int type[MAXSZ];
+ char vars[36];
+ char data[MAXSZ];
+} Grid;
+
+void print(Grid *g);
+int run(Grid *g);
+int disk(FILE *f, Grid *g);
M toy.c => toy.c +232 -530
@@ 1,603 1,305 @@
+#include <SDL2/SDL.h>
#include <stdio.h>
+#include "sim.h"
+
+#define HOR 32
+#define VER 16
+#define PAD 8
+#define ZOOM 1
+#define color1 0x000000
+#define color2 0x72DEC2
+#define color3 0x888888
+#define color4 0xFFFFFF
+#define color0 0x222222
+
+#define PLIMIT 256
+#define SZ (HOR * VER * 16)
+
+typedef struct {
+ int x, y;
+} Point2d;
-#define MAXSZ 128 * 128
-
-typedef struct Grid {
- int w, h, l, f, r;
- int lock[MAXSZ];
- int type[MAXSZ];
- char vars[36];
- char data[MAXSZ];
-} Grid;
+typedef struct {
+ int x, y, w, h;
+} Rect2d;
-/* Port types
-1 - locked
-2 - port(left)
-3 - operator
-4 - port(right)
-5 - port(output)
-*/
+unsigned char chrbuf[SZ];
+int colors[] = {color1, color2, color3, color4, color0};
+int WIDTH = 8 * HOR + PAD * 2;
+int HEIGHT = 8 * VER + PAD * 2;
+int FPS = 30;
+int GUIDES = 1;
+int COLOR = 3;
+SDL_Window *gWindow = NULL;
+SDL_Renderer *gRenderer = NULL;
+SDL_Texture *gTexture = NULL;
+uint32_t *pixels;
-int
-ciuc(char c)
-{
- return c >= 'A' && c <= 'Z';
-}
+Rect2d selection;
-int
-cilc(char c)
+Point2d
+Pt2d(int x, int y)
{
- return c >= 'a' && c <= 'z';
+ Point2d p;
+ p.x = x;
+ p.y = y;
+ return p;
}
-int
-cinu(char c)
-{
- return c >= '0' && c <= '9';
-}
+/* chr */
int
-cisp(char c)
+rowchr(int x, int y)
{
- return !ciuc(c) && !cilc(c) && !cinu(c) && c != '.';
+ return (y % 8) + ((x / 8 + y / 8 * HOR) * 16);
}
int
-clca(int c)
+getchr(int x, int y)
{
- return ciuc(c) ? c + ('a' - 'A') : c;
-}
-
-int
-cint(char c)
-{
- if(c == '.')
+ int ch1, ch2;
+ int r = rowchr(x, y);
+ int px = x % 8;
+ if(r < 0 || r > SZ - 8)
return 0;
- if(cinu(c))
- return c - '0';
- if(cilc(c))
- return c - 'a' + 10;
- if(ciuc(c))
- return c - 'A' + 10;
- return 0;
-}
-
-char
-cchr(int v, int cap)
-{
- v %= 36;
- v *= v < 0 ? -1 : 1;
- if(v >= 0 && v <= 9)
- return '0' + v;
- if(cap)
- return 'A' + (v - 10);
- return 'a' + (v - 10);
-}
-
-int
-valid(Grid *g, int x, int y)
-{
- return x >= 0 && x <= g->w && y >= 0 && y <= g->h;
-}
-
-int
-random(Grid *g)
-{
- (void)g;
- return 0;
- /*
- g->r *= 1103515245;
- return ((g->r / 65536 * g->f) % 32768) ^ g->f;
- */
-}
-
-/* IO */
-
-char
-get(Grid *g, int x, int y)
-{
- if(valid(g, x, y))
- return g->data[x + (y * g->w)];
- return '.';
-}
-
-void
-set(Grid *g, int x, int y, char c)
-{
- if(valid(g, x, y))
- g->data[x + (y * g->w)] = c;
-}
-
-/* Locks */
-
-void
-lock(Grid *g, int x, int y)
-{
- if(valid(g, x, y)) {
- g->lock[x + (y * g->w)] = 1;
- g->type[x + (y * g->w)] = 1;
+ ch1 = (chrbuf[r] >> (7 - px)) & 1;
+ ch2 = (chrbuf[r + 8] >> (7 - px)) & 1;
+ return ch1 && !ch2 ? 1 : !ch1 && ch2 ? 2 : ch1 && ch2 ? 3 : 0;
+}
+
+void
+putchr(int x, int y, int color)
+{
+ int r = rowchr(x, y);
+ int px = x % 8;
+ if(x < 0 || y < 0 || x > 8 * HOR || y > 8 * VER || r > SZ - 8)
+ return;
+ if(color == 0) {
+ chrbuf[r] &= ~(1UL << (7 - px));
+ chrbuf[r + 8] &= ~(1UL << (7 - px));
+ } else if(color == 2) {
+ chrbuf[r] |= 1UL << (7 - px);
+ chrbuf[r + 8] &= ~(1UL << (7 - px));
+ } else if(color == 1) {
+ chrbuf[r] &= ~(1UL << (7 - px));
+ chrbuf[r + 8] |= 1UL << (7 - px);
+ } else if(color == 3) {
+ chrbuf[r] |= 1UL << (7 - px);
+ chrbuf[r + 8] |= 1UL << (7 - px);
}
}
-/* Variables */
-
void
-save(Grid *g, char key, char val)
+newchr(void)
{
- g->vars[cint(key)] = val;
-}
-
-char
-load(Grid *g, char key)
-{
- return g->vars[cint(key)];
+ int i;
+ for(i = 0; i < SZ; ++i)
+ chrbuf[i] = 0x00;
}
-/* Syntax */
+/* misc */
int
-gettype(Grid *g, int x, int y)
+guide(int x, int y)
{
- if(valid(g, x, y))
- return g->type[x + (y * g->w)];
+ if(!GUIDES)
+ return 0;
+ if(x % 32 == 0 && y % 32 == 0)
+ return 3;
+ else if(x % 8 == 0 && y % 8 == 0)
+ return 4;
return 0;
}
void
-settype(Grid *g, int x, int y, int t)
-{
- if(valid(g, x, y))
- g->type[x + (y * g->w)] = t;
-}
-
-/* Port Setters */
-
-void
-setport(Grid *g, int x, int y, char c)
-{
- lock(g, x, y);
- settype(g, x, y, 5);
- set(g, x, y, c);
-}
-
-int
-getport(Grid *g, int x, int y, int l)
-{
- if(l) {
- lock(g, x, y);
- settype(g, x, y, 4);
- } else
- settype(g, x, y, 2);
- return get(g, x, y);
-}
-
-int
-bang(Grid *g, int x, int y)
-{
- return get(g, x - 1, y) == '*' || get(g, x + 1, y) == '*' || get(g, x, y - 1) == '*' || get(g, x, y + 1) == '*';
-}
-
-/* Library */
-
-void
-opa(Grid *g, int x, int y, char c)
-{
- char a = getport(g, x - 1, y, 0);
- char b = getport(g, x + 1, y, 1);
- setport(g, x, y + 1, cchr(cint(a) + cint(b), ciuc(b)));
- (void)c;
-}
-
-void
-opb(Grid *g, int x, int y, char c)
-{
- char a = getport(g, x - 1, y, 0);
- char b = getport(g, x + 1, y, 1);
- setport(g, x, y + 1, cchr(cint(a) - cint(b), ciuc(b)));
- (void)c;
-}
-
-void
-opc(Grid *g, int x, int y, char c)
+draw(uint32_t *dst)
{
- char rate = getport(g, x - 1, y, 0);
- char mod = getport(g, x + 1, y, 1);
- setport(g, x, y + 1, cchr(g->f / rate % mod, ciuc(mod)));
- (void)c;
+ int b, i, j, id = 0;
+ for(b = 0; b < SZ; b += 16)
+ for(i = 0; i < 8; i++)
+ for(j = 7; j >= 0; j--) {
+ int ch1 = chrbuf[b + i];
+ int ch2 = chrbuf[b + i + 8];
+ int color = ((ch1 >> j) & 0x1) + (((ch2 >> j) & 0x1) << 1);
+ int ti = id / 64;
+ int tx = ti % HOR;
+ int ty = ti / HOR;
+ int odd = (ti + (ti / HOR + 2)) % 2 == 0;
+ int px = (ti / (HOR * VER)) * (8 * HOR) + tx * 8 + (id % 8);
+ int py = ((ti / HOR) * 8) + ((id % 64) / 8);
+ if(tx == selection.x && ty == selection.y)
+ dst[(py + PAD) * WIDTH + (px + PAD)] = colors[1];
+ else
+ dst[(py + PAD) * WIDTH + (px + PAD)] = colors[GUIDES && odd && color == 0 ? 4 : color];
+ id++;
+ }
+ SDL_UpdateTexture(gTexture, NULL, dst, WIDTH * sizeof(uint32_t));
+ SDL_RenderClear(gRenderer);
+ SDL_RenderCopy(gRenderer, gTexture, NULL, NULL);
+ SDL_RenderPresent(gRenderer);
}
void
-opd(Grid *g, int x, int y, char c)
+select(int x, int y, int w, int h)
{
- char rate = getport(g, x - 1, y, 0);
- char mod = getport(g, x + 1, y, 1);
- setport(g, x, y + 1, g->f % (rate * mod) == 0 ? '*' : '.');
- (void)c;
+ selection.x = x;
+ selection.y = y;
+ selection.w = w;
+ selection.h = h;
+ draw(pixels);
}
void
-ope(Grid *g, int x, int y, char c)
+move(int x, int y)
{
- if(x == g->w || get(g, x + 1, y) != '.')
- set(g, x, y, '*');
- else {
- set(g, x, y, '.');
- setport(g, x + 1, y, c);
+ int reqdraw = 0;
+ if((x < 0 && selection.x > 0) || (x > 0 && selection.x < HOR - 1)) {
+ selection.x += x;
+ reqdraw = 1;
}
-}
-
-void
-opf(Grid *g, int x, int y, char c)
-{
- setport(g, x, y + 1, getport(g, x - 1, y, 0) == getport(g, x + 1, y, 1) ? '*' : '.');
- (void)c;
-}
-
-void
-opg(Grid *g, int x, int y, char c)
-{
- int tx = cint(getport(g, x - 3, y, 0));
- int ty = cint(getport(g, x - 2, y, 0));
- int i, len = cint(getport(g, x - 1, y, 0));
- for(i = 0; i < len; ++i)
- setport(g, x + i + tx, y + 1 + ty, getport(g, x + 1 + i, y, 1));
- (void)c;
-}
-
-void
-oph(Grid *g, int x, int y, char c)
-{
- getport(g, x, y + 1, 1);
- (void)c;
-}
-
-void
-opi(Grid *g, int x, int y, char c)
-{
- char step = getport(g, x - 1, y, 0);
- char mod = getport(g, x + 1, y, 1);
- char val = getport(g, x, y + 1, 1);
- setport(g, x, y + 1, cchr((cint(val) + cint(step)) % (cint(mod) || 1), ciuc(mod)));
- (void)c;
-}
-
-void
-opj(Grid *g, int x, int y, char c)
-{
- int i;
- char link = getport(g, x, y - 1, 0);
- if(link != c) {
- for(i = 1; y + i < g->h; ++i)
- if(get(g, x, y + i) != c)
- break;
- setport(g, x, y + i, link);
+ if((y < 0 && selection.y > 0) || (y > 0 && selection.y < VER - 1)) {
+ selection.y += y;
+ reqdraw = 1;
}
+ if(reqdraw)
+ draw(pixels);
}
-void
-opk(Grid *g, int x, int y, char c)
-{
- int i, len = cint(getport(g, x - 1, y, 0));
- for(i = 0; i < len; ++i) {
- char key = getport(g, x + 1 + i, y, 1);
- if(key == '.')
- continue;
- setport(g, x + 1 + i, y + 1, load(g, key));
- }
- (void)c;
-}
-
-void
-opl(Grid *g, int x, int y, char c)
-{
- char a = getport(g, x - 1, y, 0);
- char b = getport(g, x + 1, y, 1);
- setport(g, x, y + 1, cint(a) < cint(b) ? a : b);
- (void)c;
-}
-
-void
-opm(Grid *g, int x, int y, char c)
-{
- char a = getport(g, x - 1, y, 0);
- char b = getport(g, x + 1, y, 1);
- setport(g, x, y + 1, cchr(cint(a) * cint(b), ciuc(b)));
- (void)c;
-}
-
-void
-opn(Grid *g, int x, int y, char c)
-{
- if(y == 0 || get(g, x, y - 1) != '.')
- set(g, x, y, '*');
- else {
- set(g, x, y, '.');
- setport(g, x, y - 1, c);
- }
-}
-
-void
-opo(Grid *g, int x, int y, char c)
-{
- int tx = cint(getport(g, x - 2, y, 0));
- int ty = cint(getport(g, x - 1, y, 0));
- setport(g, x, y + 1, getport(g, x + 1 + tx, y + ty, 1));
- (void)c;
-}
-
-void
-opp(Grid *g, int x, int y, char c)
-{
- int key = cint(getport(g, x - 2, y, 0));
- int i, len = cint(getport(g, x - 1, y, 0));
- /* TODO */
- for(i = 0; i < len; ++i)
- lock(g, x + i, y + 1);
- setport(g, x + (key % len), y + 1, get(g, x + 1, y));
- (void)c;
-}
-
-void
-opq(Grid *g, int x, int y, char c)
-{
- int tx = cint(getport(g, x - 3, y, 0));
- int ty = cint(getport(g, x - 2, y, 0));
- int i, len = cint(getport(g, x - 1, y, 0));
- for(i = 0; i < len; ++i)
- setport(g, x + 1 - len + i, y + 1, getport(g, x + 1 + tx + i, y + ty, 1));
- (void)c;
-}
-
-void
-opr(Grid *g, int x, int y, char c)
-{
- int min = cint(getport(g, x - 1, y, 0));
- char max = getport(g, x + 1, y, 1);
- setport(g, x, y + 1, cchr((random(g) % ((cint(max) - min) || 1)) + min, ciuc(max)));
- (void)c;
-}
-
-void
-ops(Grid *g, int x, int y, char c)
-{
- if(y == g->h || get(g, x, y + 1) != '.')
- set(g, x, y, '*');
- else {
- set(g, x, y, '.');
- setport(g, x, y + 1, c);
- }
-}
-
-void
-opt(Grid *g, int x, int y, char c)
-{
- int key = cint(getport(g, x - 2, y, 0));
- int i, len = cint(getport(g, x - 1, y, 0));
- for(i = 0; i < len; ++i)
- lock(g, x + 1 + i, y);
- setport(g, x, y + 1, getport(g, x + 1 + (key % len), y, 1));
- (void)c;
-}
-
-void
-opu(Grid *g, int x, int y, char c)
-{
- int max = cint(getport(g, x - 1, y, 0));
- int step = cint(getport(g, x + 1, y, 1));
- int bucket = (step * (g->f + max - 1)) % max + step;
- setport(g, x, y + 1, bucket >= max ? '*' : '.');
- (void)c;
-}
-
-void
-opv(Grid *g, int x, int y, char c)
-{
- char w = getport(g, x - 1, y, 0);
- char r = getport(g, x + 1, y, 1);
- if(w != '.')
- save(g, w, r);
- else if(w == '.' && r != '.')
- setport(g, x, y + 1, load(g, r));
- (void)c;
-}
-
-void
-opw(Grid *g, int x, int y, char c)
-{
- if(x == 0 || get(g, x - 1, y) != '.')
- set(g, x, y, '*');
- else {
- set(g, x, y, '.');
- setport(g, x - 1, y, c);
- }
-}
-
-void
-opx(Grid *g, int x, int y, char c)
-{
- int tx = cint(getport(g, x - 2, y, 0));
- int ty = cint(getport(g, x - 1, y, 0));
- setport(g, x + tx, y + ty + 1, getport(g, x + 1, y, 1));
- (void)c;
-}
-
-void
-opy(Grid *g, int x, int y, char c)
+int
+error(char *msg, const char *err)
{
- int i;
- char link = getport(g, x - 1, y, 0);
- if(link != c) {
- for(i = 1; x + i < g->w; ++i)
- if(get(g, x + i, y) != c)
- break;
- setport(g, x + i, y, link);
- }
+ printf("Error %s: %s\n", msg, err);
+ return 1;
}
void
-opz(Grid *g, int x, int y, char c)
+quit(void)
{
- int rate = cint(getport(g, x - 1, y, 0));
- char target = getport(g, x + 1, y, 1);
- char val = cint(getport(g, x, y + 1, 1));
- int t = cint(target);
- int mod = val < t ? rate : val > t ? -rate : 0;
- setport(g, x, y + 1, cchr(val + mod, ciuc(target)));
- (void)c;
+ free(pixels);
+ SDL_DestroyTexture(gTexture);
+ gTexture = NULL;
+ SDL_DestroyRenderer(gRenderer);
+ gRenderer = NULL;
+ SDL_DestroyWindow(gWindow);
+ gWindow = NULL;
+ SDL_Quit();
+ exit(0);
}
void
-opcomment(Grid *g, int x, int y)
+render(void)
{
- int i;
- for(i = 1; x + i < g->w; ++i) {
- lock(g, x + i, y);
- if(get(g, x + i, y) == '#')
- break;
- }
+ newchr();
+ draw(pixels);
}
void
-opspecial(Grid *g, int x, int y)
+domouse(SDL_Event *event)
{
- int i, b = bang(g, x, y);
- for(i = 0; x + i < g->w; ++i) {
- char c = getport(g, x + i, y, 1);
- if(c == '.')
- break;
- if(b)
- printf("%c", c);
+ Point2d touch = Pt2d(
+ (event->motion.x - (PAD * ZOOM)) / ZOOM,
+ (event->motion.y - (PAD * ZOOM)) / ZOOM);
+ switch(event->type) {
+ case SDL_MOUSEBUTTONUP:
+ printf("mouse-up\n");
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ printf("mouse-down\n");
+ break;
+ case SDL_MOUSEMOTION:
+ break;
}
- if(b)
- printf("\n");
}
void
-operate(Grid *g, int x, int y, char c)
-{
- switch(clca(c)) {
- case 'a': opa(g, x, y, c); break;
- case 'b': opb(g, x, y, c); break;
- case 'c': opc(g, x, y, c); break;
- case 'd': opd(g, x, y, c); break;
- case 'e': ope(g, x, y, c); break;
- case 'f': opf(g, x, y, c); break;
- case 'g': opg(g, x, y, c); break;
- case 'h': oph(g, x, y, c); break;
- case 'i': opi(g, x, y, c); break;
- case 'k': opk(g, x, y, c); break;
- case 'j': opj(g, x, y, c); break;
- case 'l': opl(g, x, y, c); break;
- case 'm': opm(g, x, y, c); break;
- case 'n': opn(g, x, y, c); break;
- case 'o': opo(g, x, y, c); break;
- case 'p': opp(g, x, y, c); break;
- case 'q': opq(g, x, y, c); break;
- case 'r': opr(g, x, y, c); break;
- case 's': ops(g, x, y, c); break;
- case 't': opt(g, x, y, c); break;
- case 'u': opu(g, x, y, c); break;
- case 'v': opv(g, x, y, c); break;
- case 'w': opw(g, x, y, c); break;
- case 'x': opx(g, x, y, c); break;
- case 'y': opy(g, x, y, c); break;
- case 'z': opz(g, x, y, c); break;
- case '*': set(g, x, y, '.'); break;
- case '#': opcomment(g, x, y); break;
- default: opspecial(g, x, y);
+dokey(SDL_Event *event)
+{
+ switch(event->key.keysym.sym) {
+ case SDLK_UP:
+ move(0, -1);
+ printf("up\n");
+ break;
+ case SDLK_DOWN:
+ move(0, 1);
+ printf("down\n");
+ break;
+ case SDLK_LEFT:
+ move(-1, 0);
+ printf("left\n");
+ break;
+ case SDLK_RIGHT:
+ move(1, 0);
+ printf("right\n");
+ break;
}
- settype(g, x, y, 3);
-}
-
-/* General */
-
-void
-print(Grid *g)
-{
- int x, y;
- for(y = 0; y < g->h; ++y)
- for(x = 0; x < g->w; ++x) {
- putchar(get(g, x, y));
- if(x == g->w - 1)
- putchar('\n');
- }
- putchar('\n');
- for(y = 0; y < g->h; ++y)
- for(x = 0; x < g->w; ++x) {
- printf("%d", gettype(g, x, y));
- if(x == g->w - 1)
- putchar('\n');
- }
- putchar('\n');
+ /* update(); */
}
int
-run(Grid *g)
-{
- int i, x, y;
- for(i = 0; i < g->l; ++i) {
- g->lock[i] = 0;
- g->type[i] = 0;
- }
- for(i = 0; i < g->l; ++i) {
- char c = g->data[i];
- x = i % g->w;
- y = i / g->w;
- if(c == '.' || g->lock[i])
- continue;
- if(cilc(c) && !bang(g, x, y))
- continue;
- operate(g, x, y, c);
- }
- g->f++;
+init(void)
+{
+ int i, j;
+ if(SDL_Init(SDL_INIT_VIDEO) < 0)
+ return error("Init", SDL_GetError());
+ gWindow = SDL_CreateWindow("Toy",
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ WIDTH * ZOOM,
+ HEIGHT * ZOOM,
+ SDL_WINDOW_SHOWN);
+ if(gWindow == NULL)
+ return error("Window", SDL_GetError());
+ gRenderer = SDL_CreateRenderer(gWindow, -1, 0);
+ if(gRenderer == NULL)
+ return error("Renderer", SDL_GetError());
+ gTexture = SDL_CreateTexture(gRenderer,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_STATIC,
+ WIDTH,
+ HEIGHT);
+ if(gTexture == NULL)
+ return error("Texture", SDL_GetError());
+ pixels = (uint32_t *)malloc(WIDTH * HEIGHT * sizeof(uint32_t));
+ if(pixels == NULL)
+ return error("Pixels", "Failed to allocate memory");
+ for(i = 0; i < HEIGHT; i++)
+ for(j = 0; j < WIDTH; j++)
+ pixels[i * WIDTH + j] = color1;
return 1;
}
int
-disk(FILE *f, Grid *g)
-{
- char c;
- g->l = 0;
- while((c = fgetc(f)) != EOF && g->l < MAXSZ) {
- if(c == '\n') {
- if(g->w == 0)
- g->w = g->l;
- g->h = g->l / g->w;
- } else {
- g->type[g->l] = 0;
- g->data[g->l++] = c;
- }
- }
- return g->w > 2 && g->h > 2;
-}
-
-int
-error(char *name)
-{
- printf("Error: %s\n", name);
- return 0;
-}
-
-int
main(int argc, char *argv[])
{
- FILE *f;
- int limit = 3;
- Grid g;
- g.w = 0;
- g.h = 0;
- g.f = 0;
- g.r = 1;
- if(argc < 2)
- return error("No input.");
- f = fopen(argv[1], "r");
- if(!f)
- return error("Missing input.");
- if(!disk(f, &g))
- return error("Invalid grid");
- while(g.f < limit) {
- run(&g);
- print(&g);
+ int ticknext = 0;
+
+ if(!init())
+ return error("Init", "Failure");
+
+ newchr();
+ select(0, 0, 0, 0);
+ draw(pixels);
+
+ while(1) {
+ int tick = SDL_GetTicks();
+ SDL_Event event;
+ if(tick < ticknext)
+ SDL_Delay(ticknext - tick);
+ ticknext = tick + (1000 / FPS);
+ while(SDL_PollEvent(&event) != 0) {
+ if(event.type == SDL_QUIT)
+ quit();
+ else if(event.type == SDL_MOUSEBUTTONUP ||
+ event.type == SDL_MOUSEBUTTONDOWN ||
+ event.type == SDL_MOUSEMOTION) {
+ domouse(&event);
+ } else if(event.type == SDL_KEYDOWN)
+ dokey(&event);
+ else if(event.type == SDL_WINDOWEVENT)
+ if(event.window.event == SDL_WINDOWEVENT_EXPOSED)
+ draw(pixels);
+ }
}
+ quit();
return 0;
}