aboutsummaryrefslogtreecommitdiff
path: root/projects
diff options
context:
space:
mode:
authorYuchen Pei <me@ypei.me>2018-01-17 12:01:40 +0100
committerYuchen Pei <me@ypei.me>2018-01-17 12:01:40 +0100
commitfef36fd11c9d3d7f632098c5005bf0e3e5ce5ad9 (patch)
treeef7348a6d97b0fb5588dbfebe3b5242f31aab255 /projects
parent3a9265774c48865547702fe58d127c9fe10338a1 (diff)
finished Screen.
- a bit slow though
Diffstat (limited to 'projects')
-rw-r--r--projects/12/MathTest/Math.jack12
-rw-r--r--projects/12/MathTest/Math.vm26
-rw-r--r--projects/12/Screen.jack91
-rw-r--r--projects/12/ScreenTest/Main.vm104
-rw-r--r--projects/12/ScreenTest/Math.jack158
-rw-r--r--projects/12/ScreenTest/Math.vm472
-rw-r--r--projects/12/ScreenTest/Screen.jack138
-rw-r--r--projects/12/ScreenTest/Screen.vm407
8 files changed, 1408 insertions, 0 deletions
diff --git a/projects/12/MathTest/Math.jack b/projects/12/MathTest/Math.jack
index 6bac42e..01bce8f 100644
--- a/projects/12/MathTest/Math.jack
+++ b/projects/12/MathTest/Math.jack
@@ -28,6 +28,18 @@ class Math {
return ~(x & twoToThe[i] = 0);
}
+ function int sign(int x) {
+ if (x > 0) {
+ return 1;
+ } else {
+ if (x < 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ }
+
/** Returns the absolute value of x. */
function int abs(int x) {
if (x > 0){
diff --git a/projects/12/MathTest/Math.vm b/projects/12/MathTest/Math.vm
index dad8ff5..513fc1a 100644
--- a/projects/12/MathTest/Math.vm
+++ b/projects/12/MathTest/Math.vm
@@ -44,6 +44,32 @@ push constant 0
eq
not
return
+function Math.sign 0
+push argument 0
+push constant 0
+gt
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push constant 1
+return
+goto IF_END0
+label IF_FALSE0
+push argument 0
+push constant 0
+lt
+if-goto IF_TRUE1
+goto IF_FALSE1
+label IF_TRUE1
+push constant 1
+neg
+return
+goto IF_END1
+label IF_FALSE1
+push constant 0
+return
+label IF_END1
+label IF_END0
function Math.abs 0
push argument 0
push constant 0
diff --git a/projects/12/Screen.jack b/projects/12/Screen.jack
index 7356d35..337a7e2 100644
--- a/projects/12/Screen.jack
+++ b/projects/12/Screen.jack
@@ -10,34 +10,125 @@
* the screen is indexed (0,0).
*/
class Screen {
+ static Array twoToThe;
+ static Array screen;
+ static boolean color;
/** Initializes the Screen. */
function void init() {
+ var int i, x;
+ let x = 1;
+ let i = 0;
+ let twoToThe = Array.new(16);
+ while (i < 16){
+ let twoToThe[i] = x;
+ let x = x + x;
+ let i = i + 1;
+ }
+ let screen = 16384;
+ return;
}
/** Erases the entire screen. */
function void clearScreen() {
+ var boolean c;
+ let c = color;
+ let color = false;
+ do drawRectangle(0, 0, 511, 255);
+ let color = c;
+ return;
}
/** Sets the current color, to be used for all subsequent drawXXX commands.
* Black is represented by true, white by false. */
function void setColor(boolean b) {
+ let color = b;
+ return;
}
/** Draws the (x,y) pixel, using the current color. */
function void drawPixel(int x, int y) {
+ var int addr, t;
+ if ((x < 0) | (y < 0) | (x > 511) | (y > 255)) {
+ //String.println("drawPixel: coordinates out of range!");
+ //Sys.error(2);
+ return;
+ }
+ let t = x / 16;
+ let addr = 32 * y + t;
+ if (color) {
+ let screen[addr] = screen[addr] | twoToThe[x - (t * 16)];
+ } else {
+ let screen[addr] = screen[addr] & (- (twoToThe[x - (t * 16)] + 1))
+ }
+ return;
}
/** Draws a line from pixel (x1,y1) to pixel (x2,y2), using the current color. */
function void drawLine(int x1, int y1, int x2, int y2) {
+ var int dx, dy, x, y, diff;
+ let x = x1;
+ let y = y1;
+ do drawPixel(x, y);
+ if (x1 = x2) {
+ if (y1 = y2) {
+ return;
+ } else {
+ let diff = 1;
+ }
+ } else {
+ if (y1 = y2) {
+ let diff = -1;
+ } else {
+ let diff = 0;
+ }
+ }
+ let dx = x2 - x1;
+ let dy = y2 - y1;
+ let a = Math.sign(dx);
+ let b = Math.sign(dy);
+ let dx = Math.abs(dx);
+ let dy = Math.abs(dy);
+ while (~((x = x2) & (y = y2))) {
+ if (diff < 0){
+ let x = x + a;
+ let diff = diff + dy;
+ } else {
+ let y = y + b;
+ let diff = diff - dx;
+ }
+ do drawPixel(x, y);
+ }
}
/** Draws a filled rectangle whose top left corner is (x1, y1)
* and bottom right corner is (x2,y2), using the current color. */
function void drawRectangle(int x1, int y1, int x2, int y2) {
+ if ((x1 > x2) | (y1 > y2)) {
+ return;
+ }
+ let x = x1;
+ while (~(x > x2)) {
+ do drawLine(x, y1, x, y2);
+ }
+ return;
}
/** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
function void drawCircle(int x, int y, int r) {
+ var int dx, dy, r2;
+ if (r > 181) {
+ String.println("drawCircle: radius too big!");
+ Sys.error(2);
+ return;
+ }
+ let dy = -r;
+ let r2 = r * r;
+ while (~(dy > r)) {
+ let dx = Math.sqrt(r2 - (dy * dy));
+ do drawLine(x - dx, y + dy, x + dx, y + dy);
+ let dy = dy + 1;
+ }
+ return;
}
}
diff --git a/projects/12/ScreenTest/Main.vm b/projects/12/ScreenTest/Main.vm
new file mode 100644
index 0000000..69e860f
--- /dev/null
+++ b/projects/12/ScreenTest/Main.vm
@@ -0,0 +1,104 @@
+function Main.main 0
+push constant 0
+push constant 220
+push constant 511
+push constant 220
+call Screen.drawLine 4
+pop temp 0
+push constant 280
+push constant 90
+push constant 410
+push constant 220
+call Screen.drawRectangle 4
+pop temp 0
+push constant 0
+call Screen.setColor 1
+pop temp 0
+push constant 350
+push constant 120
+push constant 390
+push constant 219
+call Screen.drawRectangle 4
+pop temp 0
+push constant 292
+push constant 120
+push constant 332
+push constant 150
+call Screen.drawRectangle 4
+pop temp 0
+push constant 0
+not
+call Screen.setColor 1
+pop temp 0
+push constant 360
+push constant 170
+push constant 3
+call Screen.drawCircle 3
+pop temp 0
+push constant 280
+push constant 90
+push constant 345
+push constant 35
+call Screen.drawLine 4
+pop temp 0
+push constant 345
+push constant 35
+push constant 410
+push constant 90
+call Screen.drawLine 4
+pop temp 0
+push constant 140
+push constant 60
+push constant 30
+call Screen.drawCircle 3
+pop temp 0
+push constant 140
+push constant 26
+push constant 140
+push constant 6
+call Screen.drawLine 4
+pop temp 0
+push constant 163
+push constant 35
+push constant 178
+push constant 20
+call Screen.drawLine 4
+pop temp 0
+push constant 174
+push constant 60
+push constant 194
+push constant 60
+call Screen.drawLine 4
+pop temp 0
+push constant 163
+push constant 85
+push constant 178
+push constant 100
+call Screen.drawLine 4
+pop temp 0
+push constant 140
+push constant 94
+push constant 140
+push constant 114
+call Screen.drawLine 4
+pop temp 0
+push constant 117
+push constant 85
+push constant 102
+push constant 100
+call Screen.drawLine 4
+pop temp 0
+push constant 106
+push constant 60
+push constant 86
+push constant 60
+call Screen.drawLine 4
+pop temp 0
+push constant 117
+push constant 35
+push constant 102
+push constant 20
+call Screen.drawLine 4
+pop temp 0
+push constant 0
+return
diff --git a/projects/12/ScreenTest/Math.jack b/projects/12/ScreenTest/Math.jack
new file mode 100644
index 0000000..01bce8f
--- /dev/null
+++ b/projects/12/ScreenTest/Math.jack
@@ -0,0 +1,158 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/12/Math.jack
+
+/**
+ * A library of commonly used mathematical functions.
+ * Note: Jack compilers implement multiplication and division using OS method calls.
+ */
+class Math {
+ static Array twoToThe;
+
+ /** Initializes the library. */
+ function void init() {
+ var int i, x;
+ let x = 1;
+ let i = 0;
+ let twoToThe = Array.new(16);
+ while (i < 16){
+ let twoToThe[i] = x;
+ let x = x + x;
+ let i = i + 1;
+ }
+ return;
+ }
+
+ function boolean bit(int x, int i) {
+ return ~(x & twoToThe[i] = 0);
+ }
+
+ function int sign(int x) {
+ if (x > 0) {
+ return 1;
+ } else {
+ if (x < 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ /** Returns the absolute value of x. */
+ function int abs(int x) {
+ if (x > 0){
+ return x;
+ } else {
+ return -x;
+ }
+ }
+
+ /** Returns the product of x and y.
+ * When a Jack compiler detects the multiplication operator '*' in the
+ * program's code, it handles it by invoking this method. In other words,
+ * the Jack expressions x*y and multiply(x,y) return the same value.
+ */
+ function int multiply(int x, int y) {
+ var int res, shiftedX, i;
+ let shiftedX = x;
+ let i = 0;
+ let res = 0;
+ //while ((~(twoToThe[i] > y)) & (i < 16)) {
+ while (i < 16) {
+ if (Math.bit(y, i)){
+ let res = res + shiftedX;
+ }
+ let shiftedX = shiftedX + shiftedX;
+ let i = i + 1;
+ }
+ return res;
+ }
+
+ /** Returns the integer part of x/y.
+ * When a Jack compiler detects the multiplication operator '/' in the
+ * program's code, it handles it by invoking this method. In other words,
+ * the Jack expressions x/y and divide(x,y) return the same value.
+ */
+ function int divide(int x, int y) {
+ var int ax, ay;
+ if (x > 0) {
+ if (y > 0) {
+ return Math.divide1(x, y);
+ } else {
+ return -Math.divide1(x, -y);
+ }
+ } else {
+ if (y > 0) {
+ return -Math.divide1(-x, y);
+ } else {
+ return Math.divide1(-x, -y);
+ }
+ }
+ }
+
+ function int divide1(int x, int y) {
+ var int q;
+ if (y = 0) {
+ do Output.printString("Error: division by zero.");
+ do Sys.error(0);
+ }
+ if ((y > x) | (y < 0)) {
+ return 0;
+ }
+ let q = Math.divide1(x, y * 2);
+ if (x - (2 * q * y) < y) {
+ return 2 * q;
+ } else {
+ return 2 * q + 1;
+ }
+ }
+
+ function int length(int x){
+ var int n;
+ let n = 14;
+ while (twoToThe[n] > x){
+ let n = n - 1;
+ }
+ return n;
+ }
+
+ /** Returns the integer part of the square root of x. */
+ function int sqrt(int x) {
+ var int y, k, z, w;
+ if (x < 0) {
+ do Output.printString("Error: square rooting a negative number.");
+ do Sys.error(0);
+ }
+ let k = Math.length(x) / 2;
+ let y = 0;
+ while (~(k < 0)) {
+ let z = y + twoToThe[k];
+ let w = z * z;
+ if ((~(w > x)) & (w > 0)) {
+ let y = z;
+ }
+ let k = k - 1;
+ }
+ return y;
+ }
+
+ /** Returns the greater number. */
+ function int max(int a, int b) {
+ if (a > b) {
+ return a;
+ } else {
+ return b;
+ }
+ }
+
+ /** Returns the smaller number. */
+ function int min(int a, int b) {
+ if (a < b) {
+ return a;
+ } else {
+ return b;
+ }
+ }
+}
diff --git a/projects/12/ScreenTest/Math.vm b/projects/12/ScreenTest/Math.vm
new file mode 100644
index 0000000..513fc1a
--- /dev/null
+++ b/projects/12/ScreenTest/Math.vm
@@ -0,0 +1,472 @@
+function Math.init 2
+push constant 1
+pop local 1
+push constant 0
+pop local 0
+push constant 16
+call Array.new 1
+pop static 0
+label WHILE_EXP0
+push local 0
+push constant 16
+lt
+not
+if-goto WHILE_END0
+push local 0
+push static 0
+add
+push local 1
+pop temp 0
+pop pointer 1
+push temp 0
+pop that 0
+push local 1
+push local 1
+add
+pop local 1
+push local 0
+push constant 1
+add
+pop local 0
+goto WHILE_EXP0
+label WHILE_END0
+push constant 0
+return
+function Math.bit 0
+push argument 0
+push argument 1
+push static 0
+add
+pop pointer 1
+push that 0
+and
+push constant 0
+eq
+not
+return
+function Math.sign 0
+push argument 0
+push constant 0
+gt
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push constant 1
+return
+goto IF_END0
+label IF_FALSE0
+push argument 0
+push constant 0
+lt
+if-goto IF_TRUE1
+goto IF_FALSE1
+label IF_TRUE1
+push constant 1
+neg
+return
+goto IF_END1
+label IF_FALSE1
+push constant 0
+return
+label IF_END1
+label IF_END0
+function Math.abs 0
+push argument 0
+push constant 0
+gt
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push argument 0
+return
+goto IF_END0
+label IF_FALSE0
+push argument 0
+neg
+return
+label IF_END0
+function Math.multiply 3
+push argument 0
+pop local 1
+push constant 0
+pop local 2
+push constant 0
+pop local 0
+label WHILE_EXP0
+push local 2
+push constant 16
+lt
+not
+if-goto WHILE_END0
+push argument 1
+push local 2
+call Math.bit 2
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push local 0
+push local 1
+add
+pop local 0
+label IF_FALSE0
+push local 1
+push local 1
+add
+pop local 1
+push local 2
+push constant 1
+add
+pop local 2
+goto WHILE_EXP0
+label WHILE_END0
+push local 0
+return
+function Math.divide 2
+push argument 0
+push constant 0
+gt
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push argument 1
+push constant 0
+gt
+if-goto IF_TRUE1
+goto IF_FALSE1
+label IF_TRUE1
+push argument 0
+push argument 1
+call Math.divide1 2
+return
+goto IF_END1
+label IF_FALSE1
+push argument 0
+push argument 1
+neg
+call Math.divide1 2
+neg
+return
+label IF_END1
+goto IF_END0
+label IF_FALSE0
+push argument 1
+push constant 0
+gt
+if-goto IF_TRUE2
+goto IF_FALSE2
+label IF_TRUE2
+push argument 0
+neg
+push argument 1
+call Math.divide1 2
+neg
+return
+goto IF_END2
+label IF_FALSE2
+push argument 0
+neg
+push argument 1
+neg
+call Math.divide1 2
+return
+label IF_END2
+label IF_END0
+function Math.divide1 1
+push argument 1
+push constant 0
+eq
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push constant 24
+call String.new 1
+push constant 69
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 111
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 58
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 100
+call String.appendChar 2
+push constant 105
+call String.appendChar 2
+push constant 118
+call String.appendChar 2
+push constant 105
+call String.appendChar 2
+push constant 115
+call String.appendChar 2
+push constant 105
+call String.appendChar 2
+push constant 111
+call String.appendChar 2
+push constant 110
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 98
+call String.appendChar 2
+push constant 121
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 122
+call String.appendChar 2
+push constant 101
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 111
+call String.appendChar 2
+push constant 46
+call String.appendChar 2
+call Output.printString 1
+pop temp 0
+push constant 0
+call Sys.error 1
+pop temp 0
+label IF_FALSE0
+push argument 1
+push argument 0
+gt
+push argument 1
+push constant 0
+lt
+or
+if-goto IF_TRUE1
+goto IF_FALSE1
+label IF_TRUE1
+push constant 0
+return
+label IF_FALSE1
+push argument 0
+push argument 1
+push constant 2
+call Math.multiply 2
+call Math.divide1 2
+pop local 0
+push argument 0
+push constant 2
+push local 0
+call Math.multiply 2
+push argument 1
+call Math.multiply 2
+sub
+push argument 1
+lt
+if-goto IF_TRUE2
+goto IF_FALSE2
+label IF_TRUE2
+push constant 2
+push local 0
+call Math.multiply 2
+return
+goto IF_END2
+label IF_FALSE2
+push constant 2
+push local 0
+call Math.multiply 2
+push constant 1
+add
+return
+label IF_END2
+function Math.length 1
+push constant 14
+pop local 0
+label WHILE_EXP0
+push local 0
+push static 0
+add
+pop pointer 1
+push that 0
+push argument 0
+gt
+not
+if-goto WHILE_END0
+push local 0
+push constant 1
+sub
+pop local 0
+goto WHILE_EXP0
+label WHILE_END0
+push local 0
+return
+function Math.sqrt 4
+push argument 0
+push constant 0
+lt
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push constant 40
+call String.new 1
+push constant 69
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 111
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 58
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 115
+call String.appendChar 2
+push constant 113
+call String.appendChar 2
+push constant 117
+call String.appendChar 2
+push constant 97
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 101
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 111
+call String.appendChar 2
+push constant 111
+call String.appendChar 2
+push constant 116
+call String.appendChar 2
+push constant 105
+call String.appendChar 2
+push constant 110
+call String.appendChar 2
+push constant 103
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 97
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 110
+call String.appendChar 2
+push constant 101
+call String.appendChar 2
+push constant 103
+call String.appendChar 2
+push constant 97
+call String.appendChar 2
+push constant 116
+call String.appendChar 2
+push constant 105
+call String.appendChar 2
+push constant 118
+call String.appendChar 2
+push constant 101
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 110
+call String.appendChar 2
+push constant 117
+call String.appendChar 2
+push constant 109
+call String.appendChar 2
+push constant 98
+call String.appendChar 2
+push constant 101
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 46
+call String.appendChar 2
+call Output.printString 1
+pop temp 0
+push constant 0
+call Sys.error 1
+pop temp 0
+label IF_FALSE0
+push argument 0
+call Math.length 1
+push constant 2
+call Math.divide 2
+pop local 1
+push constant 0
+pop local 0
+label WHILE_EXP0
+push local 1
+push constant 0
+lt
+not
+not
+if-goto WHILE_END0
+push local 0
+push local 1
+push static 0
+add
+pop pointer 1
+push that 0
+add
+pop local 2
+push local 2
+push local 2
+call Math.multiply 2
+pop local 3
+push local 3
+push argument 0
+gt
+not
+push local 3
+push constant 0
+gt
+and
+if-goto IF_TRUE1
+goto IF_FALSE1
+label IF_TRUE1
+push local 2
+pop local 0
+label IF_FALSE1
+push local 1
+push constant 1
+sub
+pop local 1
+goto WHILE_EXP0
+label WHILE_END0
+push local 0
+return
+function Math.max 0
+push argument 0
+push argument 1
+gt
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push argument 0
+return
+goto IF_END0
+label IF_FALSE0
+push argument 1
+return
+label IF_END0
+function Math.min 0
+push argument 0
+push argument 1
+lt
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push argument 0
+return
+goto IF_END0
+label IF_FALSE0
+push argument 1
+return
+label IF_END0
diff --git a/projects/12/ScreenTest/Screen.jack b/projects/12/ScreenTest/Screen.jack
new file mode 100644
index 0000000..a370ab9
--- /dev/null
+++ b/projects/12/ScreenTest/Screen.jack
@@ -0,0 +1,138 @@
+// This file is part of www.nand2tetris.org
+// and the book "The Elements of Computing Systems"
+// by Nisan and Schocken, MIT Press.
+// File name: projects/12/Screen.jack
+
+/**
+ * A library of functions for displaying graphics on the screen.
+ * The Hack physical screen consists of 512 rows (indexed 0..511, top to bottom)
+ * of 256 pixels each (indexed 0..255, left to right). The top left pixel on
+ * the screen is indexed (0,0).
+ */
+class Screen {
+ static Array twoToThe;
+ static Array screen;
+ static boolean color;
+
+ /** Initializes the Screen. */
+ function void init() {
+ var int i, x;
+ let x = 1;
+ let i = 0;
+ let twoToThe = Array.new(16);
+ while (i < 16){
+ let twoToThe[i] = x;
+ let x = x + x;
+ let i = i + 1;
+ }
+ let screen = 16384;
+ let color = true;
+ return;
+ }
+
+ /** Erases the entire screen. */
+ function void clearScreen() {
+ var boolean c;
+ let c = color;
+ let color = false;
+ do Screen.drawRectangle(0, 0, 511, 255);
+ let color = c;
+ return;
+ }
+
+ /** Sets the current color, to be used for all subsequent drawXXX commands.
+ * Black is represented by true, white by false. */
+ function void setColor(boolean b) {
+ let color = b;
+ return;
+ }
+
+ /** Draws the (x,y) pixel, using the current color. */
+ function void drawPixel(int x, int y) {
+ var int addr, t;
+ if ((x < 0) | (y < 0) | (x > 511) | (y > 255)) {
+ //String.println("drawPixel: coordinates out of range!");
+ //Sys.error(2);
+ return;
+ }
+ let t = x / 16;
+ let addr = 32 * y + t;
+ if (color) {
+ let screen[addr] = screen[addr] | twoToThe[x - (t * 16)];
+ } else {
+ let screen[addr] = screen[addr] & (- (twoToThe[x - (t * 16)] + 1));
+ }
+ return;
+ }
+
+ /** Draws a line from pixel (x1,y1) to pixel (x2,y2), using the current color. */
+ function void drawLine(int x1, int y1, int x2, int y2) {
+ var int dx, dy, x, y, a, b, diff;
+ let x = x1;
+ let y = y1;
+ do Screen.drawPixel(x, y);
+ if (x1 = x2) {
+ if (y1 = y2) {
+ return;
+ } else {
+ let diff = 1;
+ }
+ } else {
+ if (y1 = y2) {
+ let diff = -1;
+ } else {
+ let diff = 0;
+ }
+ }
+ let dx = x2 - x1;
+ let dy = y2 - y1;
+ let a = Math.sign(dx);
+ let b = Math.sign(dy);
+ let dx = Math.abs(dx);
+ let dy = Math.abs(dy);
+ while (~((x = x2) & (y = y2))) {
+ if (diff < 0){
+ let x = x + a;
+ let diff = diff + dy;
+ } else {
+ let y = y + b;
+ let diff = diff - dx;
+ }
+ do Screen.drawPixel(x, y);
+ }
+ return;
+ }
+
+ /** Draws a filled rectangle whose top left corner is (x1, y1)
+ * and bottom right corner is (x2,y2), using the current color. */
+ function void drawRectangle(int x1, int y1, int x2, int y2) {
+ var int x;
+ if ((x1 > x2) | (y1 > y2)) {
+ return;
+ }
+ let x = x1;
+ while (~(x > x2)) {
+ do Screen.drawLine(x, y1, x, y2);
+ let x = x + 1;
+ }
+ return;
+ }
+
+ /** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
+ function void drawCircle(int x, int y, int r) {
+ var int dx, dy, r2;
+ if (r > 181) {
+ do String.println("drawCircle: radius too big!");
+ do Sys.error(2);
+ return;
+ }
+ let dy = -r;
+ let r2 = r * r;
+ while (~(dy > r)) {
+ let dx = Math.sqrt(r2 - (dy * dy));
+ do Screen.drawLine(x - dx, y + dy, x + dx, y + dy);
+ let dy = dy + 1;
+ }
+ return;
+ }
+}
diff --git a/projects/12/ScreenTest/Screen.vm b/projects/12/ScreenTest/Screen.vm
new file mode 100644
index 0000000..8468225
--- /dev/null
+++ b/projects/12/ScreenTest/Screen.vm
@@ -0,0 +1,407 @@
+function Screen.init 2
+push constant 1
+pop local 1
+push constant 0
+pop local 0
+push constant 16
+call Array.new 1
+pop static 0
+label WHILE_EXP0
+push local 0
+push constant 16
+lt
+not
+if-goto WHILE_END0
+push local 0
+push static 0
+add
+push local 1
+pop temp 0
+pop pointer 1
+push temp 0
+pop that 0
+push local 1
+push local 1
+add
+pop local 1
+push local 0
+push constant 1
+add
+pop local 0
+goto WHILE_EXP0
+label WHILE_END0
+push constant 16384
+pop static 1
+push constant 0
+not
+pop static 2
+push constant 0
+return
+function Screen.clearScreen 1
+push static 2
+pop local 0
+push constant 0
+pop static 2
+push constant 0
+push constant 0
+push constant 511
+push constant 255
+call Screen.drawRectangle 4
+pop temp 0
+push local 0
+pop static 2
+push constant 0
+return
+function Screen.setColor 0
+push argument 0
+pop static 2
+push constant 0
+return
+function Screen.drawPixel 2
+push argument 0
+push constant 0
+lt
+push argument 1
+push constant 0
+lt
+or
+push argument 0
+push constant 511
+gt
+or
+push argument 1
+push constant 255
+gt
+or
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push constant 0
+return
+label IF_FALSE0
+push argument 0
+push constant 16
+call Math.divide 2
+pop local 1
+push constant 32
+push argument 1
+call Math.multiply 2
+push local 1
+add
+pop local 0
+push static 2
+if-goto IF_TRUE1
+goto IF_FALSE1
+label IF_TRUE1
+push local 0
+push static 1
+add
+push local 0
+push static 1
+add
+pop pointer 1
+push that 0
+push argument 0
+push local 1
+push constant 16
+call Math.multiply 2
+sub
+push static 0
+add
+pop pointer 1
+push that 0
+or
+pop temp 0
+pop pointer 1
+push temp 0
+pop that 0
+goto IF_END1
+label IF_FALSE1
+push local 0
+push static 1
+add
+push local 0
+push static 1
+add
+pop pointer 1
+push that 0
+push argument 0
+push local 1
+push constant 16
+call Math.multiply 2
+sub
+push static 0
+add
+pop pointer 1
+push that 0
+push constant 1
+add
+neg
+and
+pop temp 0
+pop pointer 1
+push temp 0
+pop that 0
+label IF_END1
+push constant 0
+return
+function Screen.drawLine 7
+push argument 0
+pop local 2
+push argument 1
+pop local 3
+push local 2
+push local 3
+call Screen.drawPixel 2
+pop temp 0
+push argument 0
+push argument 2
+eq
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push argument 1
+push argument 3
+eq
+if-goto IF_TRUE1
+goto IF_FALSE1
+label IF_TRUE1
+push constant 0
+return
+goto IF_END1
+label IF_FALSE1
+push constant 1
+pop local 6
+label IF_END1
+goto IF_END0
+label IF_FALSE0
+push argument 1
+push argument 3
+eq
+if-goto IF_TRUE2
+goto IF_FALSE2
+label IF_TRUE2
+push constant 1
+neg
+pop local 6
+goto IF_END2
+label IF_FALSE2
+push constant 0
+pop local 6
+label IF_END2
+label IF_END0
+push argument 2
+push argument 0
+sub
+pop local 0
+push argument 3
+push argument 1
+sub
+pop local 1
+push local 0
+call Math.sign 1
+pop local 4
+push local 1
+call Math.sign 1
+pop local 5
+push local 0
+call Math.abs 1
+pop local 0
+push local 1
+call Math.abs 1
+pop local 1
+label WHILE_EXP0
+push local 2
+push argument 2
+eq
+push local 3
+push argument 3
+eq
+and
+not
+not
+if-goto WHILE_END0
+push local 6
+push constant 0
+lt
+if-goto IF_TRUE3
+goto IF_FALSE3
+label IF_TRUE3
+push local 2
+push local 4
+add
+pop local 2
+push local 6
+push local 1
+add
+pop local 6
+goto IF_END3
+label IF_FALSE3
+push local 3
+push local 5
+add
+pop local 3
+push local 6
+push local 0
+sub
+pop local 6
+label IF_END3
+push local 2
+push local 3
+call Screen.drawPixel 2
+pop temp 0
+goto WHILE_EXP0
+label WHILE_END0
+push constant 0
+return
+function Screen.drawRectangle 1
+push argument 0
+push argument 2
+gt
+push argument 1
+push argument 3
+gt
+or
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push constant 0
+return
+label IF_FALSE0
+push argument 0
+pop local 0
+label WHILE_EXP0
+push local 0
+push argument 2
+gt
+not
+not
+if-goto WHILE_END0
+push local 0
+push argument 1
+push local 0
+push argument 3
+call Screen.drawLine 4
+pop temp 0
+push local 0
+push constant 1
+add
+pop local 0
+goto WHILE_EXP0
+label WHILE_END0
+push constant 0
+return
+function Screen.drawCircle 3
+push argument 2
+push constant 181
+gt
+if-goto IF_TRUE0
+goto IF_FALSE0
+label IF_TRUE0
+push constant 27
+call String.new 1
+push constant 100
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 97
+call String.appendChar 2
+push constant 119
+call String.appendChar 2
+push constant 67
+call String.appendChar 2
+push constant 105
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 99
+call String.appendChar 2
+push constant 108
+call String.appendChar 2
+push constant 101
+call String.appendChar 2
+push constant 58
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 114
+call String.appendChar 2
+push constant 97
+call String.appendChar 2
+push constant 100
+call String.appendChar 2
+push constant 105
+call String.appendChar 2
+push constant 117
+call String.appendChar 2
+push constant 115
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 116
+call String.appendChar 2
+push constant 111
+call String.appendChar 2
+push constant 111
+call String.appendChar 2
+push constant 32
+call String.appendChar 2
+push constant 98
+call String.appendChar 2
+push constant 105
+call String.appendChar 2
+push constant 103
+call String.appendChar 2
+push constant 33
+call String.appendChar 2
+call String.println 1
+pop temp 0
+push constant 2
+call Sys.error 1
+pop temp 0
+push constant 0
+return
+label IF_FALSE0
+push argument 2
+neg
+pop local 1
+push argument 2
+push argument 2
+call Math.multiply 2
+pop local 2
+label WHILE_EXP0
+push local 1
+push argument 2
+gt
+not
+not
+if-goto WHILE_END0
+push local 2
+push local 1
+push local 1
+call Math.multiply 2
+sub
+call Math.sqrt 1
+pop local 0
+push argument 0
+push local 0
+sub
+push argument 1
+push local 1
+add
+push argument 0
+push local 0
+add
+push argument 1
+push local 1
+add
+call Screen.drawLine 4
+pop temp 0
+push local 1
+push constant 1
+add
+pop local 1
+goto WHILE_EXP0
+label WHILE_END0
+push constant 0
+return