about summary refs log tree commit diff stats
path: root/apps/mandelbrot-silhouette.mu
diff options
context:
space:
mode:
Diffstat (limited to 'apps/mandelbrot-silhouette.mu')
-rw-r--r--apps/mandelbrot-silhouette.mu150
1 files changed, 150 insertions, 0 deletions
diff --git a/apps/mandelbrot-silhouette.mu b/apps/mandelbrot-silhouette.mu
new file mode 100644
index 00000000..0d9a137c
--- /dev/null
+++ b/apps/mandelbrot-silhouette.mu
@@ -0,0 +1,150 @@
+# Mandelbrot set
+#
+# Install:
+#   $ git clone https://github.com/akkartik/mu
+#   $ cd mu
+# Build on Linux:
+#   $ ./translate apps/mandelbrot.mu
+# Build on other platforms (slow):
+#   $ ./translate_emulated apps/mandelbrot.mu
+# Run:
+#   $ qemu-system-i386 code.img
+
+fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
+  mandelbrot screen
+}
+
+fn mandelbrot screen: (addr screen) {
+  var a/eax: int <- copy 0
+  var b/ecx: int <- copy 0
+  a, b <- screen-size screen
+  var width/esi: int <- copy a
+  width <- shift-left 3/log2-font-width
+  var height/edi: int <- copy b
+  height <- shift-left 4/log2-font-height
+  var y/ecx: int <- copy 0
+  {
+    compare y, height
+    break-if->=
+    var imaginary/xmm1: float <- viewport-to-imaginary y, width, height
+    var x/edx: int <- copy 0
+    {
+      compare x, width
+      break-if->=
+      var real/xmm0: float <- viewport-to-real x, width
+      var iterations/eax: int <- mandelbrot-iterations-for-point real, imaginary, 0x400/max
+      compare iterations, 0x400/max
+      {
+        break-if->=
+        pixel screen, x, y, 0xf/white
+      }
+      compare iterations, 0x400/max
+      {
+        break-if-<
+        pixel screen, x, y, 0/black
+      }
+      x <- increment
+      loop
+    }
+    y <- increment
+    loop
+  }
+}
+
+fn mandelbrot-iterations-for-point real: float, imaginary: float, max: int -> _/eax: int {
+  var zero: float
+  var x/xmm0: float <- copy zero
+  var y/xmm1: float <- copy zero
+  var iterations/ecx: int <- copy 0
+  {
+    var done?/eax: boolean <- mandelbrot-done? x, y
+    compare done?, 0/false
+    break-if-!=
+    compare iterations, max
+    break-if->=
+    var newx/xmm2: float <- mandelbrot-x x, y, real
+    var newy/xmm3: float <- mandelbrot-y x, y, imaginary
+    x <- copy newx
+    y <- copy newy
+    iterations <- increment
+    loop
+  }
+  return iterations
+}
+
+fn mandelbrot-done? x: float, y: float -> _/eax: boolean {
+  # x*x + y*y > 4
+  var x2/xmm0: float <- copy x
+  x2 <- multiply x
+  var y2/xmm1: float <- copy y
+  y2 <- multiply y
+  var sum/xmm0: float <- copy x2
+  sum <- add y2
+  var four/eax: int <- copy 4
+  var four-f/xmm1: float <- convert four
+  compare sum, four-f
+  {
+    break-if-float>
+    return 0/false
+  }
+  return 1/true
+}
+
+fn mandelbrot-x x: float, y: float, real: float -> _/xmm2: float {
+  # x*x - y*y + real
+  var x2/xmm0: float <- copy x
+  x2 <- multiply x
+  var y2/xmm1: float <- copy y
+  y2 <- multiply y
+  var result/xmm0: float <- copy x2
+  result <- subtract y2
+  result <- add real
+  return result
+}
+
+fn mandelbrot-y x: float, y: float, imaginary: float -> _/xmm3: float {
+  # 2*x*y + imaginary
+  var two/eax: int <- copy 2
+  var result/xmm0: float <- convert two
+  result <- multiply x
+  result <- multiply y
+  result <- add imaginary
+  return result
+}
+
+# Scale (x, y) pixel coordinates to a complex plane where the viewport width
+# ranges from -2 to +2. Viewport height just follows the viewport's aspect
+# ratio.
+
+fn viewport-to-real x: int, width: int -> _/xmm0: float {
+  # (x - width/2)*4/width
+  var result/xmm0: float <- convert x
+  var width-f/xmm1: float <- convert width
+  var two/eax: int <- copy 2
+  var two-f/xmm2: float <- convert two
+  var half-width-f/xmm2: float <- reciprocal two-f
+  half-width-f <- multiply width-f
+  result <- subtract half-width-f
+  var four/eax: int <- copy 4
+  var four-f/xmm2: float <- convert four
+  result <- multiply four-f
+  result <- divide width-f
+  return result
+}
+
+fn viewport-to-imaginary y: int, width: int, height: int -> _/xmm1: float {
+  # (y - height/2)*4/width
+  var result/xmm0: float <- convert y
+  var height-f/xmm1: float <- convert height
+  var half-height-f/xmm1: float <- copy height-f
+  var two/eax: int <- copy 2
+  var two-f/xmm2: float <- convert two
+  half-height-f <- divide two-f
+  result <- subtract half-height-f
+  var four/eax: int <- copy 4
+  var four-f/xmm1: float <- convert four
+  result <- multiply four-f
+  var width-f/xmm1: float <- convert width
+  result <- divide width-f
+  return result
+}