| 1 |
module test30; |
|---|
| 2 |
|
|---|
| 3 |
import qd, SDL_image, tools.base, SDL_ttf, tools.log; |
|---|
| 4 |
|
|---|
| 5 |
class VM { |
|---|
| 6 |
float[16] regs; |
|---|
| 7 |
ubyte[] program; |
|---|
| 8 |
int pc; |
|---|
| 9 |
this() { |
|---|
| 10 |
program.length = 1024; |
|---|
| 11 |
} |
|---|
| 12 |
void reset() { |
|---|
| 13 |
regs[] = 0f; |
|---|
| 14 |
pc = 0; |
|---|
| 15 |
} |
|---|
| 16 |
void run(int cycles, lazy float randf) { |
|---|
| 17 |
while (cycles--) { |
|---|
| 18 |
auto inst = program[pc]; |
|---|
| 19 |
int cmd = inst & 15, param = inst >> 4; |
|---|
| 20 |
cmd &= 7; // ignore high bit |
|---|
| 21 |
switch (cmd) { |
|---|
| 22 |
case 0: |
|---|
| 23 |
version(LOG) logln("branch to ", pc, "+", param + 1); |
|---|
| 24 |
pc = (pc + param) % program.length; |
|---|
| 25 |
break; |
|---|
| 26 |
case 1: |
|---|
| 27 |
version(LOG) logln("store 0(", regs[0], ") to ", param); |
|---|
| 28 |
regs[param] = regs[0]; |
|---|
| 29 |
break; |
|---|
| 30 |
case 2: |
|---|
| 31 |
version(log) logln("skip cond on ", regs[0], " => ", atan2(regs[0]) / (PI/4) + 0.5); |
|---|
| 32 |
if (atan(regs[0]) / (PI/4) + 0.5 > randf()) pc++; |
|---|
| 33 |
break; |
|---|
| 34 |
/*version(LOG) logln("skip if ", regs[0], " > 0"); |
|---|
| 35 |
if (regs[0] > 0) pc++; |
|---|
| 36 |
break;*/ |
|---|
| 37 |
case 3: |
|---|
| 38 |
version(LOG) logln("load ", (param - 8) / 6f); |
|---|
| 39 |
regs[0] = (param - 8) / 6f; |
|---|
| 40 |
break; |
|---|
| 41 |
case 4: |
|---|
| 42 |
version(LOG) logln("swap 0(", regs[0], ") and ", param, "(", regs[param], ")"); |
|---|
| 43 |
swap(regs[0], regs[param]); |
|---|
| 44 |
break; |
|---|
| 45 |
case 5: |
|---|
| 46 |
version(LOG) logln("add 0(", regs[0], ") + ", param, "(", regs[param], ")"); |
|---|
| 47 |
regs[0] += regs[param]; |
|---|
| 48 |
break; |
|---|
| 49 |
case 6: |
|---|
| 50 |
version(LOG) logln("mul 0(", regs[0], ") + ", param, "(", regs[param], ")"); |
|---|
| 51 |
regs[0] *= regs[param]; |
|---|
| 52 |
break; |
|---|
| 53 |
case 7: |
|---|
| 54 |
version(LOG) logln("div 0(", regs[0], ") / (1 + ", param, "(", regs[param], ") )"); |
|---|
| 55 |
regs[0] /= regs[param] + 1; |
|---|
| 56 |
break; |
|---|
| 57 |
} |
|---|
| 58 |
pc++; |
|---|
| 59 |
if (pc == program.length) pc = 0; |
|---|
| 60 |
} |
|---|
| 61 |
} |
|---|
| 62 |
void generate(uint delegate() dg) { |
|---|
| 63 |
foreach (ref val; program) { |
|---|
| 64 |
val = dg() % 256; |
|---|
| 65 |
} |
|---|
| 66 |
} |
|---|
| 67 |
} |
|---|
| 68 |
|
|---|
| 69 |
long atol(string s) { |
|---|
| 70 |
long res; |
|---|
| 71 |
s = s.strip(); |
|---|
| 72 |
while (s.length) { |
|---|
| 73 |
auto ch = s.take(); |
|---|
| 74 |
assert(ch >= '0' && ch <= '9'); |
|---|
| 75 |
res = res * 10L + (ch - '0'); |
|---|
| 76 |
} |
|---|
| 77 |
return res; |
|---|
| 78 |
} |
|---|
| 79 |
|
|---|
| 80 |
// Thank you George Marsaglia .. you're a lifesaver |
|---|
| 81 |
|
|---|
| 82 |
class KISS { |
|---|
| 83 |
uint z, w, jcong, jsr; |
|---|
| 84 |
void reset() { |
|---|
| 85 |
z = 362436069; |
|---|
| 86 |
w = 521288629; |
|---|
| 87 |
jcong = 380116160; |
|---|
| 88 |
jsr = 123456789; |
|---|
| 89 |
} |
|---|
| 90 |
this() { reset; } |
|---|
| 91 |
uint znew() { return z = 36969 * (z & 65535) + (z >> 16); } |
|---|
| 92 |
uint wnew() { return w = 18000 * (w & 65535) + (w >> 16); } |
|---|
| 93 |
uint mwc() { return (znew << 16) + wnew; } |
|---|
| 94 |
uint cong() { return jcong = 69069 * jcong + 1234567; } |
|---|
| 95 |
uint shr3() { |
|---|
| 96 |
jsr ^= jsr << 17; |
|---|
| 97 |
jsr ^= jsr >> 13; |
|---|
| 98 |
jsr ^= jsr << 5; |
|---|
| 99 |
return jsr; |
|---|
| 100 |
} |
|---|
| 101 |
uint kiss() { return (mwc() ^ cong()) + shr3; } |
|---|
| 102 |
alias kiss rand; |
|---|
| 103 |
float randf() { return rand() * 1f / typeof(rand()).max; } |
|---|
| 104 |
} |
|---|
| 105 |
|
|---|
| 106 |
import tools.mersenne, tools.time; |
|---|
| 107 |
void main(string[] args) { |
|---|
| 108 |
auto exec = args.take(); |
|---|
| 109 |
auto a2 = args; |
|---|
| 110 |
int steps = 1024; |
|---|
| 111 |
ulong seed; |
|---|
| 112 |
bool filter = true, show = true, quiet = false; |
|---|
| 113 |
int aa; |
|---|
| 114 |
string output; |
|---|
| 115 |
int w = 640, h = 480; |
|---|
| 116 |
while (args.length) { |
|---|
| 117 |
auto flag = args.take(); |
|---|
| 118 |
switch (flag) { |
|---|
| 119 |
case "-steps": steps = args.take().atoi(); break; |
|---|
| 120 |
case "-seed": seed = args.take().atol(); filter = false; break; |
|---|
| 121 |
case "-o": output = args.take(); break; |
|---|
| 122 |
case "-nofilter": filter = false; break; |
|---|
| 123 |
case "-filter": filter = true; break; |
|---|
| 124 |
case "-noshow": show = false; break; |
|---|
| 125 |
case "-aa": aa = args.take().atoi(); break; |
|---|
| 126 |
case "-w": w = args.take().atoi(); break; |
|---|
| 127 |
case "-h": h = args.take().atoi(); break; |
|---|
| 128 |
case "-q": quiet = true; break; |
|---|
| 129 |
} |
|---|
| 130 |
} |
|---|
| 131 |
auto test = new VM; |
|---|
| 132 |
screen(w, h, 0, !show); |
|---|
| 133 |
auto last = sec(); |
|---|
| 134 |
while (true) {continue_outer: |
|---|
| 135 |
auto sv = µsec(); |
|---|
| 136 |
if (seed) sv = seed; |
|---|
| 137 |
void update() { |
|---|
| 138 |
if (sec() - last > 0.2) { |
|---|
| 139 |
if (!quiet) |
|---|
| 140 |
print(10, 10, Bottom|Right, Back = Black, Format("::", sv)); |
|---|
| 141 |
flip; |
|---|
| 142 |
events; |
|---|
| 143 |
last = sec(); |
|---|
| 144 |
} |
|---|
| 145 |
} |
|---|
| 146 |
auto rng = new Mersenne(sv); |
|---|
| 147 |
test.generate(&rng.rand); |
|---|
| 148 |
const STEP = 1; |
|---|
| 149 |
bool testmode = filter; |
|---|
| 150 |
rerun: |
|---|
| 151 |
int fail; |
|---|
| 152 |
rgb prev; |
|---|
| 153 |
auto rung = new KISS; |
|---|
| 154 |
rgb eval(float x, float y) { |
|---|
| 155 |
test.reset; |
|---|
| 156 |
if (testmode) rung.reset(); |
|---|
| 157 |
test.regs[4] = (x - 0.5) * 4f; |
|---|
| 158 |
test.regs[5] = (y - 0.5) * 4f; |
|---|
| 159 |
test.run(steps, rung.randf); |
|---|
| 160 |
// logln("post-register file ", test.regs); |
|---|
| 161 |
rgb col; |
|---|
| 162 |
foreach (i, ref val; test.regs[1..4]) { |
|---|
| 163 |
auto ub = cast(ubyte) (val * 255); |
|---|
| 164 |
if (ub > 0) { |
|---|
| 165 |
if (ub < 128) col.values[i] = ub * 2; |
|---|
| 166 |
else if (ub < 256) col.values[i] = (255 - ub) * 2; |
|---|
| 167 |
} |
|---|
| 168 |
} |
|---|
| 169 |
return col; |
|---|
| 170 |
} |
|---|
| 171 |
for (int y = 0; y < screen.h; y += STEP) { |
|---|
| 172 |
for (int x = 0; x < screen.w; x += STEP) { |
|---|
| 173 |
rgb col; |
|---|
| 174 |
if (aa) { |
|---|
| 175 |
int[3] sums; |
|---|
| 176 |
for (int y2 = 0; y2 < aa; ++y2) { |
|---|
| 177 |
for (int x2 = 0; x2 < aa; ++x2) { |
|---|
| 178 |
auto lc = eval((x * 1f + x2 * 1f / aa) / screen.w, (y * 1f + y2 * 1f / aa) / screen.h); |
|---|
| 179 |
foreach (i, v; lc.values) |
|---|
| 180 |
sums[i] += v; |
|---|
| 181 |
} |
|---|
| 182 |
} |
|---|
| 183 |
foreach (k, ref v; col.values) |
|---|
| 184 |
v = sums[k] / (aa*aa); |
|---|
| 185 |
} else { |
|---|
| 186 |
col = eval(x * 1f / screen.w, y * 1f / screen.h); |
|---|
| 187 |
} |
|---|
| 188 |
if (col == prev) fail++; |
|---|
| 189 |
else fail = 0; |
|---|
| 190 |
prev = col; |
|---|
| 191 |
if (testmode) { |
|---|
| 192 |
if (filter && y < 16 && fail > 4096) { |
|---|
| 193 |
// logln("Giving up. "); |
|---|
| 194 |
goto continue_outer; |
|---|
| 195 |
} |
|---|
| 196 |
if (y !< 16) { |
|---|
| 197 |
testmode = false; |
|---|
| 198 |
goto rerun; // redo |
|---|
| 199 |
} |
|---|
| 200 |
} |
|---|
| 201 |
putpixel32(x, y, col); |
|---|
| 202 |
} |
|---|
| 203 |
update; |
|---|
| 204 |
} |
|---|
| 205 |
auto bmpname = Format("temp_", sv, ".bmp"); |
|---|
| 206 |
SaveBMP(display, bmpname); |
|---|
| 207 |
auto dest = output; |
|---|
| 208 |
if (!dest.length) dest = Format("images/", sv, ".png"); |
|---|
| 209 |
string num = Format(steps); |
|---|
| 210 |
while (num.length < 6) num = "0" ~ num; |
|---|
| 211 |
dest = dest.replace("%NUM%", num); |
|---|
| 212 |
system(Format("convert ", bmpname, " ", dest, " && rm ", bmpname).toStringz()); |
|---|
| 213 |
logln("Saved to ", dest); |
|---|
| 214 |
if (seed) break; |
|---|
| 215 |
} |
|---|
| 216 |
} |
|---|