about summary refs log tree commit diff stats
path: root/mandelbrot-fixed.mu
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-05-09 21:01:16 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-05-09 21:01:16 -0700
commit0b56b7b4d9a780257b43295a9f2100a565b0b10a (patch)
treea2ee27fb68ebb00fea1c4418e74a202a83fea0a6 /mandelbrot-fixed.mu
parent4bfc80ce9aeea7faf6bccdcfac540f8cc49c17fd (diff)
downloadmu-0b56b7b4d9a780257b43295a9f2100a565b0b10a.tar.gz
mandelbrot-fixed: introduce some viewport parameters
Diffstat (limited to 'mandelbrot-fixed.mu')
-rw-r--r--mandelbrot-fixed.mu59
1 files changed, 42 insertions, 17 deletions
diff --git a/mandelbrot-fixed.mu b/mandelbrot-fixed.mu
index e51f5ff5..6d961055 100644
--- a/mandelbrot-fixed.mu
+++ b/mandelbrot-fixed.mu
@@ -11,7 +11,14 @@
 #   $ qemu-system-i386 code.img
 
 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
-  mandelbrot screen
+  # Initially the viewport is centered at 0, 0 in the scene.
+  var scene-cx-f: int
+  var scene-cy-f: int
+  # Initially the viewport shows a section of the scene 4 units wide.
+  var scene-width-f: int
+  copy-to scene-width-f, 0x400/4
+  var tmp-f/eax: int <- copy 0
+  mandelbrot screen, scene-cx-f, scene-cy-f, scene-width-f
 }
 
 # Since they still look like int types, we'll append a '-f' suffix to variable
@@ -108,7 +115,7 @@ fn divide-fixed a-f: int, b-f: int -> _/eax: int {
 
 # adding and subtracting two fixed-point numbers can use existing instructions.
 
-fn mandelbrot screen: (addr screen) {
+fn mandelbrot screen: (addr screen), scene-cx-f: int, scene-cy-f: int, scene-width-f: int {
   var a/eax: int <- copy 0
   var b/ecx: int <- copy 0
   a, b <- screen-size screen
@@ -120,12 +127,12 @@ fn mandelbrot screen: (addr screen) {
   {
     compare y, height
     break-if->=
-    var imaginary-f/ebx: int <- viewport-to-imaginary-f y, width, height
+    var imaginary-f/ebx: int <- viewport-to-imaginary-f y, width, height, scene-cx-f, scene-width-f
     var x/eax: int <- copy 0
     {
       compare x, width
       break-if->=
-      var real-f/edx: int <- viewport-to-real-f x, width
+      var real-f/edx: int <- viewport-to-real-f x, width, scene-cx-f, scene-width-f
       var iterations/esi: int <- mandelbrot-iterations-for-point real-f, imaginary-f, 0x400/max
       compare iterations, 0x400/max
       {
@@ -202,29 +209,47 @@ fn mandelbrot-y x-f: int, y-f: int, imaginary-f: int -> _/ebx: int {
 # ranges from -2 to +2. Viewport height just follows the viewport's aspect
 # ratio.
 
-fn viewport-to-real-f x: int, width: int -> _/edx: int {
-  # (x - width/2)*4/width
+fn viewport-to-real-f x: int, width: int, scene-cx-f: int, scene-width-f: int -> _/edx: int {
+  # 0 in the viewport       goes to scene-cx - scene-width/2 
+  # width in the viewport   goes to scene-cx + scene-width/2
+  # Therefore:
+  # x in the viewport       goes to (scene-cx - scene-width/2) + x*scene-width/width
+  # At most two numbers being multiplied before a divide, so no risk of overflow.
   var result-f/eax: int <- int-to-fixed x
+  result-f <- multiply-fixed result-f, scene-width-f
   var width-f/ecx: int <- copy width
   width-f <- shift-left 8/fixed-precision
-  var half-width-f/edx: int <- copy width-f
-  half-width-f <- shift-right-signed 1/log2
-  result-f <- subtract half-width-f
-  result-f <- shift-left 2/log4
   result-f <- divide-fixed result-f, width-f
+  result-f <- add scene-cx-f
+  var half-scene-width-f/ecx: int <- copy scene-width-f
+  half-scene-width-f <- shift-right 1
+  result-f <- subtract half-scene-width-f
   return result-f
 }
 
-fn viewport-to-imaginary-f y: int, width: int, height: int -> _/ebx: int {
-  # (y - height/2)*4/width
+fn viewport-to-imaginary-f y: int, width: int, height: int, scene-cy-f: int, scene-width-f: int -> _/ebx: int {
+  # 0 in the viewport       goes to scene-cy - scene-width/2*height/width
+  # height in the viewport  goes to scene-cy + scene-width/2*height/width
+  # Therefore:
+  # y in the viewport       goes to (scene-cy - scene-width/2*height/width) + y*scene-width/width
+  #  scene-cy - scene-width/width * (height/2 + y)
+  # At most two numbers being multiplied before a divide, so no risk of overflow.
   var result-f/eax: int <- int-to-fixed y
-  var half-height-f/ecx: int <- copy height
-  half-height-f <- shift-left 8/fixed-precision
-  half-height-f <- shift-right-signed 1/log2
-  result-f <- subtract half-height-f
-  result-f <- shift-left 2/log4
+  result-f <- multiply-fixed result-f, scene-width-f
   var width-f/ecx: int <- copy width
   width-f <- shift-left 8/fixed-precision
   result-f <- divide-fixed result-f, width-f
+  result-f <- add scene-cy-f
+  var second-term-f/edx: int <- copy 0
+  {
+    var _second-term-f/eax: int <- copy scene-width-f
+    _second-term-f <- shift-right 1
+    var height-f/ebx: int <- copy height
+    height-f <- shift-left 8/fixed-precision
+    _second-term-f <- multiply-fixed _second-term-f, height-f
+    _second-term-f <- divide-fixed _second-term-f, width-f
+    second-term-f <- copy _second-term-f
+  }
+  result-f <- subtract second-term-f
   return result-f
 }