diff --git a/12/Array.jack b/12/Array.jack new file mode 100644 index 0000000..efc7e9c --- /dev/null +++ b/12/Array.jack @@ -0,0 +1,22 @@ +// 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/Array.jack +/** + * Represents an array. + * In the Jack language, arrays are instances of the Array class. + * Once declared, the array entries can be accessed using the usual + * syntax arr[i]. Each array entry can hold a primitive data type as + * well as any object type. Different array entries can have different + * data types. + */ +class Array { + + /** Constructs a new Array of the given size. */ + function Array new(int size) { + } + + /** Disposes this array. */ + method void dispose() { + } +} diff --git a/12/ArrayTest/ArrayTest.tst b/12/ArrayTest/ArrayTest.tst new file mode 100644 index 0000000..89934b9 --- /dev/null +++ b/12/ArrayTest/ArrayTest.tst @@ -0,0 +1,15 @@ +// 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/ArrayTest/ArrayTest.tst + +load, +output-file ArrayTest.out, +compare-to ArrayTest.cmp, +output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1; + +repeat 1000000 { + vmstep; +} + +output; diff --git a/12/ArrayTest/Main.jack b/12/ArrayTest/Main.jack new file mode 100644 index 0000000..439770a --- /dev/null +++ b/12/ArrayTest/Main.jack @@ -0,0 +1,40 @@ +// 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/ArrayTest/Main.jack + +/** Test program for the OS Array class. */ +class Main { + + /** Performs several Array manipulations. */ + function void main() { + var Array r; // stores test results + var Array a, b, c; + + let r = 8000; + + let a = Array.new(3); + let a[2] = 222; + let r[0] = a[2]; // RAM[8000] = 222 + + let b = Array.new(3); + let b[1] = a[2] - 100; + let r[1] = b[1]; // RAM[8001] = 122 + + let c = Array.new(500); + let c[499] = a[2] - b[1]; + let r[2] = c[499]; // RAM[8002] = 100 + + do a.dispose(); + do b.dispose(); + + let b = Array.new(3); + let b[0] = c[499] - 90; + let r[3] = b[0]; // RAM[8003] = 10 + + do c.dispose(); + do b.dispose(); + + return; + } +} diff --git a/12/Keyboard.jack b/12/Keyboard.jack new file mode 100644 index 0000000..d90e547 --- /dev/null +++ b/12/Keyboard.jack @@ -0,0 +1,55 @@ +// 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/Keyboard.jack +/** + * A library for handling user input from the keyboard. + */ +class Keyboard { + + /** Initializes the keyboard. */ + function void init() { + } + + /** + * Returns the character of the currently pressed key on the keyboard; + * if no key is currently pressed, returns 0. + * + * Recognizes all ASCII characters, as well as the following keys: + * new line = 128 = String.newline() + * backspace = 129 = String.backspace() + * left arrow = 130 + * up arrow = 131 + * right arrow = 132 + * down arrow = 133 + * home = 134 + * End = 135 + * page up = 136 + * page down = 137 + * insert = 138 + * delete = 139 + * ESC = 140 + * F1 - F12 = 141 - 152 + */ + function char keyPressed() { + } + + /** Waits until a key is pressed on the keyboard and released, + * then echoes the key to the screen, and returns the character + * of the pressed key. */ + function char readChar() { + } + + /** Displays the message on the screen, reads from the keyboard the entered + * text until a newline character is detected, echoes the text to the screen, + * and returns its value. Also handles user backspaces. */ + function String readLine(String message) { + } + + /** Displays the message on the screen, reads from the keyboard the entered + * text until a newline character is detected, echoes the text to the screen, + * and returns its integer value (until the first non-digit character in the + * entered text is detected). Also handles user backspaces. */ + function int readInt(String message) { + } +} diff --git a/12/KeyboardTest/KeyboardTestOutput.png b/12/KeyboardTest/KeyboardTestOutput.png new file mode 100644 index 0000000..ad7f798 Binary files /dev/null and b/12/KeyboardTest/KeyboardTestOutput.png differ diff --git a/12/KeyboardTest/Main.jack b/12/KeyboardTest/Main.jack new file mode 100644 index 0000000..59ae501 --- /dev/null +++ b/12/KeyboardTest/Main.jack @@ -0,0 +1,93 @@ +// 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/KeyboardTest/Main.jack + +/** Test program for the OS Keyboard class. */ +class Main { + + /** Gets input from the user and verifies its contents. */ + function void main() { + var char c, key; + var String s; + var int i; + var boolean ok; + + let ok = false; + do Output.printString("keyPressed test:"); + do Output.println(); + while (~ok) { + do Output.printString("Please press the 'space' key"); + while (key = 0) { + let key = Keyboard.keyPressed(); + } + let c = key; + while (~(key = 0)) { + let key = Keyboard.keyPressed(); + } + + do Output.println(); + + if (c = 32) { + do Output.printString("ok"); + do Output.println(); + let ok = true; + } + } + + let ok = false; + do Output.printString("readChar test:"); + do Output.println(); + do Output.printString("(Verify that the pressed character is echoed to the screen)"); + do Output.println(); + while (~ok) { + do Output.printString("Please press the number '3': "); + let c = Keyboard.readChar(); + + do Output.println(); + + if (c = 51) { + do Output.printString("ok"); + do Output.println(); + let ok = true; + } + } + + let ok = false; + do Output.printString("readLine test:"); + do Output.println(); + do Output.printString("(Verify echo and usage of 'backspace')"); + do Output.println(); + while (~ok) { + let s = Keyboard.readLine("Please type 'JACK' and press enter: "); + + if (s.length() = 4) { + if ((s.charAt(0) = 74) & (s.charAt(1) = 65) & (s.charAt(2) = 67) & (s.charAt(3) = 75)) { + do Output.printString("ok"); + do Output.println(); + let ok = true; + } + } + } + + let ok = false; + do Output.printString("readInt test:"); + do Output.println(); + do Output.printString("(Verify echo and usage of 'backspace')"); + do Output.println(); + while (~ok) { + let i = Keyboard.readInt("Please type '-32123' and press enter: "); + + if (i = (-32123)) { + do Output.printString("ok"); + do Output.println(); + let ok = true; + } + } + + do Output.println(); + do Output.printString("Test completed successfully"); + + return; + } +} diff --git a/12/Math.jack b/12/Math.jack new file mode 100644 index 0000000..446df75 --- /dev/null +++ b/12/Math.jack @@ -0,0 +1,49 @@ +// 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. + * All functions runs in O(n), where n is the number of bits used + * for representing a two's complement integer value (16 in the Hack computer). + * Note: Jack compilers implement multiplication and division + * using calls to OS functions in this class. + */ +class Math { + static int n; // Number of bits used for representing a two's complement integer + static Array powersOfTwo; // Stores 2^0, 2^1, 2^2,..., 2^(n-1) + + // Initializes the Math library. + function void init() { + } + + /** Returns the product of x and y. + * When a Jack compiler detects the multiplication operator '*' + * in an expression, it handles it by invoking this method. + * Thus, in Jack, x * y and Math.multiply(x,y) return the same value. */ + function int multiply(int x, int y) { + } + + /** Returns the integer part of x / y. + * When a Jack compiler detects the division operator '/' + * an an expression, it handles it by invoking this method. + * Thus, x/y and Math.divide(x,y) return the same value. */ + function int divide(int x, int y) { + } + + /** Returns the integer part of the square root of x. */ + function int sqrt(int x) { + } + + /** Returns the greater value. */ + function int max(int a, int b) { + } + + /** Returns the smaller value. */ + function int min(int a, int b) { + } + + /** Returns the absolute value of x. */ + function int abs(int x) { + } +} diff --git a/12/MathTest/Main.jack b/12/MathTest/Main.jack new file mode 100644 index 0000000..a35c730 --- /dev/null +++ b/12/MathTest/Main.jack @@ -0,0 +1,34 @@ +// 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/MathTest/Main.jack + +// Tests the OS Math class. +class Main { + + // Performs various mathematical operations, using calls to the Math class methods. + function void main() { + var Array r; // Stores the test results; + let r = 8000; // Base address + + let r[0] = 2 * 3; // 6 + let r[1] = r[0] * (-30); // 6 * (-30) = -180 + let r[2] = r[1] * 100; // (-180) * 100 = -18000 + let r[3] = 1 * r[2]; // 1 * (-18000) = -18000 + let r[4] = r[3] * 0; // 0 + + let r[5] = 9 / 3; // 3 + let r[6] = (-18000) / 6; // -3000 + let r[7] = 32766 / (-32767); // (2^15 - 2) / (2^15 - 1) = 0 + + let r[8] = Math.sqrt(9); // 3 + let r[9] = Math.sqrt(32767); // 181 + + let r[10] = Math.min(345, 123); // 123 + let r[11] = Math.max(123, -345); // 123 + let r[12] = Math.abs(27); // 27 + let r[13] = Math.abs(-32767); // 32767 + + return; + } +} \ No newline at end of file diff --git a/12/MathTest/MathTest.tst b/12/MathTest/MathTest.tst new file mode 100644 index 0000000..127dbb4 --- /dev/null +++ b/12/MathTest/MathTest.tst @@ -0,0 +1,15 @@ +// 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/MathTest/MathTest.tst + +load, +output-file MathTest.out, +compare-to MathTest.cmp, +output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1 RAM[8004]%D2.6.1 RAM[8005]%D2.6.1 RAM[8006]%D2.6.1 RAM[8007]%D2.6.1 RAM[8008]%D2.6.1 RAM[8009]%D2.6.1 RAM[8010]%D2.6.1 RAM[8011]%D2.6.1 RAM[8012]%D2.6.1 RAM[8013]%D2.6.1; + +repeat 1000000 { + vmstep; +} + +output; diff --git a/12/Memory.jack b/12/Memory.jack new file mode 100644 index 0000000..8a853fa --- /dev/null +++ b/12/Memory.jack @@ -0,0 +1,33 @@ +// 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/Memory.jack +/** + * This library provides two services: direct access to the computer's main + * memory (RAM), and allocation and recycling of memory blocks. The Hack RAM + * consists of 32,768 words, each holding a 16-bit binary number. + */ +class Memory { + + /** Initializes the class. */ + function void init() { + } + + /** Returns the RAM value at the given address. */ + function int peek(int address) { + } + + /** Sets the RAM value at the given address to the given value. */ + function void poke(int address, int value) { + } + + /** Finds an available RAM block of the given size and returns + * a reference to its base address. */ + function int alloc(int size) { + } + + /** De-allocates the given object (cast as an array) by making + * it available for future allocations. */ + function void deAlloc(Array o) { + } +} diff --git a/12/MemoryTest/Main.jack b/12/MemoryTest/Main.jack new file mode 100644 index 0000000..a9817f4 --- /dev/null +++ b/12/MemoryTest/Main.jack @@ -0,0 +1,53 @@ +// 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/MemoryTest/Main.jack + +/** Test program for the OS Memory class. */ +class Main { + + /** Performs various memory manipulations. */ + function void main() { + var int temp, err; + var Array a, b, c; + + do Memory.poke(8000, 333); // RAM[8000] = 333 + let temp = Memory.peek(8000); + do Memory.poke(8001, temp + 1); // RAM[8001] = 334 + + let a = Array.new(3); // uses Memory.alloc + let a[2] = 222; + do Memory.poke(8002, a[2]); // RAM[8002] = 222 + + let err = 0; + let b = Array.new(3); + let b[1] = a[2] - 100; + if (b = a) { // Fail compare if b = a + let err = 1; } + do Memory.poke(8003, b[1] + err); // RAM[8003] = 122 + + let err = 0; + let c = Array.new(500); + let c[499] = a[2] - b[1]; + if (c = a) { // Fail compare if c = a + let err = 1; } + if (c = b) { // Fail compare if c = b + let err = err + 10; } + do Memory.poke(8004, c[499]+err); // RAM[8004] = 100 + + do a.dispose(); // uses Memory.deAlloc + do b.dispose(); + + let err = 0; + let b = Array.new(3); + let b[0] = c[499] - 90; + if (b = c) { // Fail compare if b = c + let err = 1; } + do Memory.poke(8005, b[0] + err); // RAM[8005] = 10 + + do c.dispose(); + do b.dispose(); + + return; + } +} diff --git a/12/MemoryTest/MemoryDiag/Main.jack b/12/MemoryTest/MemoryDiag/Main.jack new file mode 100644 index 0000000..de439d0 --- /dev/null +++ b/12/MemoryTest/MemoryDiag/Main.jack @@ -0,0 +1,183 @@ +// 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/MemoryTest/Main.jack + +/** Test program for the OS Memory class. */ +class Main { + + /** Test Memory.peek(), poke(), alloc() and deAlloc(). + * + * This test is also a diagnostic. RAM[17000] is incremented before and + * after every call so that the failure point can be accurately determined + * when using command line testing. Return values from all alloc() calls + * are also stored in the test results to aid debugging. + */ + function void main() { + var int temp; + var Array a, b, c, out; + + let out = 17000; // Address where test results will be stored. + + // Test poke() and peek(). + + let out[0] = 10; // poke test + do Memory.poke(out + 1, 333); // RAM[17001] = 333 + + let out[0] = 11; // peek test + let temp = Memory.peek(out + 1); + let out[2] = temp + 1; // RAM[17002] = 334 + let out[0] = 12; // peek/poke test complete + + // Allocate a memory block. + // Validate that the returned block is entirely within the heap, + // Test aborts if the block is not valid. + + let out[0] = 20; + let a = Memory.alloc(20); + let out[3] = a; // RAM[17003] = block address + + let out[0] = 21; + do Main.checkRange(a, 20); + let out[0] = 22; + + // Allocate a SMALLER memory block. + // Validate that the returned block is entirely within the heap, + // and that it does not overlap block 'a'. + // Test aborts if the block is not valid or overlaps. + // + // Common failure: first block was not removed from free list so space + // for this block was found within the first block. + + let out[0] = 30; + let b = Memory.alloc(3); + let out[4] = b; // RAM[17004] = block address + + let out[0] = 31; + do Main.checkRange(b, 3); + let out[0] = 32; + do Main.checkOverlap(b, 3, a, 3); + let out[0] = 33; + + // Allocate a memory block. + // Validate that the returned block is entirely within the heap, + // and that it does not overlap blocks 'a' or 'b'. + // Test aborts if the block is not valid or overlaps. + + let out[0] = 40; + let c = Memory.alloc(500); + let out[5] = c; // RAM[17005] = block address + + let out[0] = 41; + do Main.checkRange(c, 500); + let out[0] = 42; + do Main.checkOverlap(c, 500, a, 3); + let out[0] = 43; + do Main.checkOverlap(c, 500, b, 3); + let out[0] = 44; + + // Deallocate blocks 'a' and 'b', retaining 'c'. + // + // Common failure: free list corrupted by deAlloc(). + + let out[0] = 50; + do Memory.deAlloc(a); + + let out[0] = 51; + do Memory.deAlloc(b); + let out[0] = 52; + + // Allocate a memory block. + // Validate that the returned block is entirely within the heap, + // and that it does not overlap blocks 'c'. + // Test aborts if the block is not valid or overlaps. + // + // Common failure: free list corrupted by deAlloc(). + + let out[0] = 60; + let b = Memory.alloc(3); + let out[6] = b; // RAM[17006] = block address + + let out[0] = 61; + do Main.checkRange(b, 3); + let out[0] = 62; + do Main.checkOverlap(b, 3, c, 500); + let out[0] = 63; + + // Deallocate blocks 'b' and 'c'. + + let out[0] = 70; + do Memory.deAlloc(c); + + let out[0] = 71; + do Memory.deAlloc(b); + let out[0] = 72; + + // Test that deallocated blocks are placed on the free list and can + // be reused. + + let out[0] = 70; + let a = Memory.alloc(8000); + let out[7] = a; // RAM[17007] = block address + + let out[0] = 71; + do Main.checkRange(a, 8000); + + let out[0] = 72; + do Memory.deAlloc(a); + + let out[0] = 73; + let a = Memory.alloc(7000); + + let out[0] = 74; + do Main.checkRange(a, 7000); + + let out[0] = 75; + do Memory.deAlloc(a); + let out[8] = a; // RAM[17008] = block address + + // Test complete. + let out[0] = 100; + + // At this point all allocated blocks have been deallocated. + // + // You can inspect the free list and confirm that all of the heap is + // contained in the free segments. + // + // If you implemented defragmentation in dealloc(), the free list + // should contain only one segment, consisting of the entire heap. + + return; + } + + + /** Check that block a(a_len) is in the heap. + * + * If the block begins or ends outside of the heap, calls Sys.halt() + */ + function void checkRange(int a, int a_len) { + var int a_high; + let a_high = (a + a_len)-1; + if ((a < 2048) | ((a_high) > 16383)) { + // Block is not entirely within heap. + do Sys.halt(); + } + return; + } + + /** Check that block a(a_len) does not overlap block b(b_len). + * Assumes that both blocks have been range checked. + * + * If the blocks overlap, calls Sys.halt() + */ + function void checkOverlap(int a, int a_len, int b, int b_len) { + var int a_high, b_high; + let a_high = (a + a_len)-1; + let b_high = (b + b_len)-1; + if ( ~ ((a > b_high) | (a_high < b))) { + // Block overlaps excluded range. + do Sys.halt(); + } + return; + } +} diff --git a/12/MemoryTest/MemoryDiag/MemoryDiag.tst b/12/MemoryTest/MemoryDiag/MemoryDiag.tst new file mode 100644 index 0000000..94cd921 --- /dev/null +++ b/12/MemoryTest/MemoryDiag/MemoryDiag.tst @@ -0,0 +1,18 @@ +// 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/MemoryTest/MemoryDiag/MemoryDiag.tst + +echo "At the end of this test it is normal to see some pixels set on the screen"; +load, +output-file MemoryDiag.out, +compare-to MemoryDiag.cmp, +output-list RAM[17000]%D2.6.1 RAM[17001]%D2.6.1 RAM[17002]%D2.6.1 + RAM[17003]%D2.6.1 RAM[17004]%D2.6.1 RAM[17005]%D2.6.1 RAM[17006]%D2.6.1 + RAM[17007]%D2.6.1 RAM[17008]%D2.6.1; + +repeat 1000000 { + vmstep; +} + +output; diff --git a/12/MemoryTest/MemoryDiag/README.html b/12/MemoryTest/MemoryDiag/README.html new file mode 100644 index 0000000..587847e --- /dev/null +++ b/12/MemoryTest/MemoryDiag/README.html @@ -0,0 +1,55 @@ + +
+MemoryDiag tests the following: +
+At the end of this test it is normal to see some pixels set on the screen. This is because the results of the test are written to RAM[17000] – RAM[17008] which is in the Screen memory. MemoryDiag does not put its results in the first 16K of RAM because it must not interfere with the Memory.jack that is being tested. + + +
+When the test fails to compare, look at the MemoryDiag.out file and note the RAM[17000] value. This is the test step that failed. Look through the Main.jack code and find the corresponding
+ let out[0] = step;
+statement. The function immediately following this statement is where the failure occurred.
+
+For example, if RAM[17000] is 51, the
+ do Memory.deAlloc(b);
+call did not return. Either there was a simulation error like a bad address or deAlloc() got stuck in a loop.
+
+
+
+Supplied Memory.vm passes: +
+|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008| +| 100 | 333 | 334 | 2050 | 2072 | 2077 | 2050 | 2050 | 2050 | ++Memory.Jack using the Coursera implementation passes: +
+|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008| +| 100 | 333 | 334 | 16364 | 16359 | 15857 | 15852 | 7850 | 8850 | ++Broken Memory.jack fails (alloc() returns duplicate block address): +
+|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008| +| 32 | 333 | 334 | 2050 | 2050 | 0 | 0 | 0 | 0 | ++Broken Memory.jack fails (deAlloc() does not recycle memory blocks): +
+|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008| +| 73 | 333 | 334 | 16364 | 16359 | 15857 | 15852 | 7850 | 0 | ++ + +
\ No newline at end of file
diff --git a/12/MemoryTest/MemoryTest.tst b/12/MemoryTest/MemoryTest.tst
new file mode 100644
index 0000000..1da34fd
--- /dev/null
+++ b/12/MemoryTest/MemoryTest.tst
@@ -0,0 +1,15 @@
+// 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/MemoryTest/MemoryTest.tst
+
+load,
+output-file MemoryTest.out,
+compare-to MemoryTest.cmp,
+output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1 RAM[8004]%D2.6.1 RAM[8005]%D2.6.1;
+
+repeat 1000000 {
+ vmstep;
+}
+
+output;
diff --git a/12/MemoryTest/README.txt b/12/MemoryTest/README.txt
new file mode 100644
index 0000000..15ad0c8
--- /dev/null
+++ b/12/MemoryTest/README.txt
@@ -0,0 +1,9 @@
+There are some specific wrong values that indicate that your Memory.jack
+returned identical pointers to allocated segments. Look at Main.jack to
+see where the pointers a, b and c are used.
+
+RAM[8003] = 123 b = a
+RAM[8004] = 101 c = a
+RAM[8004] = 110 c = b
+RAM[8004] = 111 c = a and c = b
+RAM[8005] = 11 new b = c
diff --git a/12/Output.jack b/12/Output.jack
new file mode 100644
index 0000000..79534e5
--- /dev/null
+++ b/12/Output.jack
@@ -0,0 +1,202 @@
+// 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/Output.jack
+/**
+ * A library of functions for writing text on the screen.
+ * The Hack physical screen consists of 512 rows of 256 pixels each.
+ * The library uses a fixed font, in which each character is displayed
+ * within a frame which is 11 pixels high (including 1 pixel for inter-line
+ * spacing) and 8 pixels wide (including 2 pixels for inter-character spacing).
+ * The resulting grid accommodates 23 rows (indexed 0..22, top to bottom)
+ * of 64 characters each (indexed 0..63, left to right). The top left
+ * character position on the screen is indexed (0,0). A cursor, implemented
+ * as a small filled square, indicates where the next character will be displayed.
+ */
+class Output {
+
+ // Character map for displaying characters
+ static Array charMaps;
+
+ /** Initializes the screen, and locates the cursor at the screen's top-left. */
+ function void init() {
+ }
+
+ // Initializes the character map array
+ function void initMap() {
+ var int i;
+
+ let charMaps = Array.new(127);
+
+ // Black square, used for displaying non-printable characters.
+ do Output.create(0,63,63,63,63,63,63,63,63,63,0,0);
+
+ // Assigns the bitmap for each character in the charachter set.
+ // The first parameter is the character index, the next 11 numbers
+ // are the values of each row in the frame that represents this character.
+ do Output.create(32,0,0,0,0,0,0,0,0,0,0,0); //
+ do Output.create(33,12,30,30,30,12,12,0,12,12,0,0); // !
+ do Output.create(34,54,54,20,0,0,0,0,0,0,0,0); // "
+ do Output.create(35,0,18,18,63,18,18,63,18,18,0,0); // #
+ do Output.create(36,12,30,51,3,30,48,51,30,12,12,0); // $
+ do Output.create(37,0,0,35,51,24,12,6,51,49,0,0); // %
+ do Output.create(38,12,30,30,12,54,27,27,27,54,0,0); // &
+ do Output.create(39,12,12,6,0,0,0,0,0,0,0,0); // '
+ do Output.create(40,24,12,6,6,6,6,6,12,24,0,0); // (
+ do Output.create(41,6,12,24,24,24,24,24,12,6,0,0); // )
+ do Output.create(42,0,0,0,51,30,63,30,51,0,0,0); // *
+ do Output.create(43,0,0,0,12,12,63,12,12,0,0,0); // +
+ do Output.create(44,0,0,0,0,0,0,0,12,12,6,0); // ,
+ do Output.create(45,0,0,0,0,0,63,0,0,0,0,0); // -
+ do Output.create(46,0,0,0,0,0,0,0,12,12,0,0); // .
+ do Output.create(47,0,0,32,48,24,12,6,3,1,0,0); // /
+
+ do Output.create(48,12,30,51,51,51,51,51,30,12,0,0); // 0
+ do Output.create(49,12,14,15,12,12,12,12,12,63,0,0); // 1
+ do Output.create(50,30,51,48,24,12,6,3,51,63,0,0); // 2
+ do Output.create(51,30,51,48,48,28,48,48,51,30,0,0); // 3
+ do Output.create(52,16,24,28,26,25,63,24,24,60,0,0); // 4
+ do Output.create(53,63,3,3,31,48,48,48,51,30,0,0); // 5
+ do Output.create(54,28,6,3,3,31,51,51,51,30,0,0); // 6
+ do Output.create(55,63,49,48,48,24,12,12,12,12,0,0); // 7
+ do Output.create(56,30,51,51,51,30,51,51,51,30,0,0); // 8
+ do Output.create(57,30,51,51,51,62,48,48,24,14,0,0); // 9
+
+ do Output.create(58,0,0,12,12,0,0,12,12,0,0,0); // :
+ do Output.create(59,0,0,12,12,0,0,12,12,6,0,0); // ;
+ do Output.create(60,0,0,24,12,6,3,6,12,24,0,0); // <
+ do Output.create(61,0,0,0,63,0,0,63,0,0,0,0); // =
+ do Output.create(62,0,0,3,6,12,24,12,6,3,0,0); // >
+ do Output.create(64,30,51,51,59,59,59,27,3,30,0,0); // @
+ do Output.create(63,30,51,51,24,12,12,0,12,12,0,0); // ?
+
+ do Output.create(65,0,0,0,0,0,0,0,0,0,0,0); // A ** TO BE FILLED **
+ do Output.create(66,31,51,51,51,31,51,51,51,31,0,0); // B
+ do Output.create(67,28,54,35,3,3,3,35,54,28,0,0); // C
+ do Output.create(68,15,27,51,51,51,51,51,27,15,0,0); // D
+ do Output.create(69,63,51,35,11,15,11,35,51,63,0,0); // E
+ do Output.create(70,63,51,35,11,15,11,3,3,3,0,0); // F
+ do Output.create(71,28,54,35,3,59,51,51,54,44,0,0); // G
+ do Output.create(72,51,51,51,51,63,51,51,51,51,0,0); // H
+ do Output.create(73,30,12,12,12,12,12,12,12,30,0,0); // I
+ do Output.create(74,60,24,24,24,24,24,27,27,14,0,0); // J
+ do Output.create(75,51,51,51,27,15,27,51,51,51,0,0); // K
+ do Output.create(76,3,3,3,3,3,3,35,51,63,0,0); // L
+ do Output.create(77,33,51,63,63,51,51,51,51,51,0,0); // M
+ do Output.create(78,51,51,55,55,63,59,59,51,51,0,0); // N
+ do Output.create(79,30,51,51,51,51,51,51,51,30,0,0); // O
+ do Output.create(80,31,51,51,51,31,3,3,3,3,0,0); // P
+ do Output.create(81,30,51,51,51,51,51,63,59,30,48,0);// Q
+ do Output.create(82,31,51,51,51,31,27,51,51,51,0,0); // R
+ do Output.create(83,30,51,51,6,28,48,51,51,30,0,0); // S
+ do Output.create(84,63,63,45,12,12,12,12,12,30,0,0); // T
+ do Output.create(85,51,51,51,51,51,51,51,51,30,0,0); // U
+ do Output.create(86,51,51,51,51,51,30,30,12,12,0,0); // V
+ do Output.create(87,51,51,51,51,51,63,63,63,18,0,0); // W
+ do Output.create(88,51,51,30,30,12,30,30,51,51,0,0); // X
+ do Output.create(89,51,51,51,51,30,12,12,12,30,0,0); // Y
+ do Output.create(90,63,51,49,24,12,6,35,51,63,0,0); // Z
+
+ do Output.create(91,30,6,6,6,6,6,6,6,30,0,0); // [
+ do Output.create(92,0,0,1,3,6,12,24,48,32,0,0); // \
+ do Output.create(93,30,24,24,24,24,24,24,24,30,0,0); // ]
+ do Output.create(94,8,28,54,0,0,0,0,0,0,0,0); // ^
+ do Output.create(95,0,0,0,0,0,0,0,0,0,63,0); // _
+ do Output.create(96,6,12,24,0,0,0,0,0,0,0,0); // `
+
+ do Output.create(97,0,0,0,14,24,30,27,27,54,0,0); // a
+ do Output.create(98,3,3,3,15,27,51,51,51,30,0,0); // b
+ do Output.create(99,0,0,0,30,51,3,3,51,30,0,0); // c
+ do Output.create(100,48,48,48,60,54,51,51,51,30,0,0); // d
+ do Output.create(101,0,0,0,30,51,63,3,51,30,0,0); // e
+ do Output.create(102,28,54,38,6,15,6,6,6,15,0,0); // f
+ do Output.create(103,0,0,30,51,51,51,62,48,51,30,0); // g
+ do Output.create(104,3,3,3,27,55,51,51,51,51,0,0); // h
+ do Output.create(105,12,12,0,14,12,12,12,12,30,0,0); // i
+ do Output.create(106,48,48,0,56,48,48,48,48,51,30,0); // j
+ do Output.create(107,3,3,3,51,27,15,15,27,51,0,0); // k
+ do Output.create(108,14,12,12,12,12,12,12,12,30,0,0); // l
+ do Output.create(109,0,0,0,29,63,43,43,43,43,0,0); // m
+ do Output.create(110,0,0,0,29,51,51,51,51,51,0,0); // n
+ do Output.create(111,0,0,0,30,51,51,51,51,30,0,0); // o
+ do Output.create(112,0,0,0,30,51,51,51,31,3,3,0); // p
+ do Output.create(113,0,0,0,30,51,51,51,62,48,48,0); // q
+ do Output.create(114,0,0,0,29,55,51,3,3,7,0,0); // r
+ do Output.create(115,0,0,0,30,51,6,24,51,30,0,0); // s
+ do Output.create(116,4,6,6,15,6,6,6,54,28,0,0); // t
+ do Output.create(117,0,0,0,27,27,27,27,27,54,0,0); // u
+ do Output.create(118,0,0,0,51,51,51,51,30,12,0,0); // v
+ do Output.create(119,0,0,0,51,51,51,63,63,18,0,0); // w
+ do Output.create(120,0,0,0,51,30,12,12,30,51,0,0); // x
+ do Output.create(121,0,0,0,51,51,51,62,48,24,15,0); // y
+ do Output.create(122,0,0,0,63,27,12,6,51,63,0,0); // z
+
+ do Output.create(123,56,12,12,12,7,12,12,12,56,0,0); // {
+ do Output.create(124,12,12,12,12,12,12,12,12,12,0,0); // |
+ do Output.create(125,7,12,12,12,56,12,12,12,7,0,0); // }
+ do Output.create(126,38,45,25,0,0,0,0,0,0,0,0); // ~
+
+ return;
+ }
+
+ // Creates the character map array of the given character index, using the given values.
+ function void create(int index, int a, int b, int c, int d, int e,
+ int f, int g, int h, int i, int j, int k) {
+ var Array map;
+
+ let map = Array.new(11);
+ let charMaps[index] = map;
+
+ let map[0] = a;
+ let map[1] = b;
+ let map[2] = c;
+ let map[3] = d;
+ let map[4] = e;
+ let map[5] = f;
+ let map[6] = g;
+ let map[7] = h;
+ let map[8] = i;
+ let map[9] = j;
+ let map[10] = k;
+
+ return;
+ }
+
+ // Returns the character map (array of size 11) of the given character.
+ // If the given character is invalid or non-printable, returns the
+ // character map of a black square.
+ function Array getMap(char c) {
+ if ((c < 32) | (c > 126)) {
+ let c = 0;
+ }
+ return charMaps[c];
+ }
+
+ /** Moves the cursor to the j-th column of the i-th row,
+ * and erases the character displayed there. */
+ function void moveCursor(int i, int j) {
+ }
+
+ /** Displays the given character at the cursor location,
+ * and advances the cursor one column forward. */
+ function void printChar(char c) {
+ }
+
+ /** displays the given string starting at the cursor location,
+ * and advances the cursor appropriately. */
+ function void printString(String s) {
+ }
+
+ /** Displays the given integer starting at the cursor location,
+ * and advances the cursor appropriately. */
+ function void printInt(int i) {
+ }
+
+ /** Advances the cursor to the beginning of the next line. */
+ function void println() {
+ }
+
+ /** Moves the cursor one column back. */
+ function void backSpace() {
+ }
+}
diff --git a/12/OutputTest/Main.jack b/12/OutputTest/Main.jack
new file mode 100644
index 0000000..f243068
--- /dev/null
+++ b/12/OutputTest/Main.jack
@@ -0,0 +1,42 @@
+// 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/OutputTest/Main.jack
+
+/** Test program for the OS Output class. */
+class Main {
+
+ /** Outputs the entire character set to the screen using all the
+ * methods of the Output class. */
+ function void main() {
+ var String s;
+
+ let s = String.new(1);
+ do s.appendChar(String.doubleQuote());
+
+ do Output.moveCursor(0, 63);
+ do Output.printChar(66);
+ do Output.moveCursor(22, 0);
+ do Output.printChar(67);
+ do Output.moveCursor(22, 63);
+ do Output.printChar(68);
+ do Output.printChar(65);
+
+ do Output.moveCursor(2, 0);
+ do Output.printString("0123456789");
+ do Output.println();
+
+ do Output.printString("ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz");
+ do Output.println();
+
+ do Output.printString("!#$%&'()*+,-./:;<=>?@[\]^_`{|}~");
+ do Output.printString(s);
+ do Output.println();
+
+ do Output.printInt(-12345);
+ do Output.backSpace();
+ do Output.printInt(6789);
+
+ return;
+ }
+}
diff --git a/12/OutputTest/OutputTestOutput.gif b/12/OutputTest/OutputTestOutput.gif
new file mode 100644
index 0000000..b8ec2c0
Binary files /dev/null and b/12/OutputTest/OutputTestOutput.gif differ
diff --git a/12/Screen.jack b/12/Screen.jack
new file mode 100644
index 0000000..679b349
--- /dev/null
+++ b/12/Screen.jack
@@ -0,0 +1,42 @@
+// 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 {
+
+ /** Initializes the Screen. */
+ function void init() {
+ }
+
+ /** Erases the entire screen. */
+ function void clearScreen() {
+ }
+
+ /** 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) {
+ }
+
+ /** Draws the (x,y) pixel, using the current color. */
+ function void drawPixel(int x, int y) {
+ }
+
+ /** 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) {
+ }
+
+ /** 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) {
+ }
+
+ /** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
+ function void drawCircle(int x, int y, int r) {
+ }
+}
diff --git a/12/ScreenTest/Main.jack b/12/ScreenTest/Main.jack
new file mode 100644
index 0000000..00f36bd
--- /dev/null
+++ b/12/ScreenTest/Main.jack
@@ -0,0 +1,36 @@
+// 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/ScreenTest/Main.jack
+
+/** Test program for the OS Screen class. */
+class Main {
+
+ /** Draws a sample pictue on the screen using lines and circles. */
+ function void main() {
+
+ do Screen.drawLine(0,220,511,220); // base line
+ do Screen.drawRectangle(280,90,410,220); // house
+
+ do Screen.setColor(false);
+ do Screen.drawRectangle(350,120,390,219); // door
+ do Screen.drawRectangle(292,120,332,150); // window
+
+ do Screen.setColor(true);
+ do Screen.drawCircle(360,170,3); // door handle
+ do Screen.drawLine(280,90,345,35); // roof
+ do Screen.drawLine(345,35,410,90); // roof
+
+ do Screen.drawCircle(140,60,30); // sun
+ do Screen.drawLine(140,26, 140, 6);
+ do Screen.drawLine(163,35,178,20);
+ do Screen.drawLine(174,60,194,60);
+ do Screen.drawLine(163,85,178,100);
+ do Screen.drawLine(140,94,140,114);
+ do Screen.drawLine(117,85,102,100);
+ do Screen.drawLine(106,60,86,60);
+ do Screen.drawLine(117,35,102,20);
+
+ return;
+ }
+}
diff --git a/12/ScreenTest/ScreenTestOutput.gif b/12/ScreenTest/ScreenTestOutput.gif
new file mode 100644
index 0000000..f1742cc
Binary files /dev/null and b/12/ScreenTest/ScreenTestOutput.gif differ
diff --git a/12/String.jack b/12/String.jack
new file mode 100644
index 0000000..e829ec2
--- /dev/null
+++ b/12/String.jack
@@ -0,0 +1,63 @@
+// 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/String.jack
+/**
+ * Represents character strings. In addition for constructing and disposing
+ * strings, the class features methods for getting and setting individual
+ * characters of the string, for erasing the string's last character,
+ * for appending a character to the string's end, and more typical
+ * string-oriented operations.
+ */
+class String {
+
+ /** constructs a new empty string with a maximum length of maxLength
+ * and initial length of 0. */
+ constructor String new(int maxLength) {
+ }
+
+ /** Disposes this string. */
+ method void dispose() {
+ }
+
+ /** Returns the current length of this string. */
+ method int length() {
+ }
+
+ /** Returns the character at the j-th location of this string. */
+ method char charAt(int j) {
+ }
+
+ /** Sets the character at the j-th location of this string to c. */
+ method void setCharAt(int j, char c) {
+ }
+
+ /** Appends c to this string's end and returns this string. */
+ method String appendChar(char c) {
+ }
+
+ /** Erases the last character from this string. */
+ method void eraseLastChar() {
+ }
+
+ /** Returns the integer value of this string,
+ * until a non-digit character is detected. */
+ method int intValue() {
+ }
+
+ /** Sets this string to hold a representation of the given value. */
+ method void setInt(int val) {
+ }
+
+ /** Returns the new line character. */
+ function char newLine() {
+ }
+
+ /** Returns the backspace character. */
+ function char backSpace() {
+ }
+
+ /** Returns the double quote (") character. */
+ function char doubleQuote() {
+ }
+}
diff --git a/12/StringTest/Main.jack b/12/StringTest/Main.jack
new file mode 100644
index 0000000..2848548
--- /dev/null
+++ b/12/StringTest/Main.jack
@@ -0,0 +1,83 @@
+// 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/StringTest/Main.jack
+
+/** Test program for the OS String class. */
+class Main {
+
+ /** Performs various string manipulations and displays their results. */
+ function void main() {
+ var String s;
+ var String i;
+
+ let s = String.new(0); // a zero-capacity string should be supported
+ do s.dispose();
+
+ let s = String.new(6); // capacity 6, make sure that length 5 is displayed
+ let s = s.appendChar(97);
+ let s = s.appendChar(98);
+ let s = s.appendChar(99);
+ let s = s.appendChar(100);
+ let s = s.appendChar(101);
+ do Output.printString("new,appendChar: ");
+ do Output.printString(s); // new, appendChar: abcde
+ do Output.println();
+
+ let i = String.new(6);
+ do i.setInt(12345);
+ do Output.printString("setInt: ");
+ do Output.printString(i); // setInt: 12345
+ do Output.println();
+
+ do i.setInt(-32767);
+ do Output.printString("setInt: ");
+ do Output.printString(i); // setInt: -32767
+ do Output.println();
+
+ do Output.printString("length: ");
+ do Output.printInt(s.length()); // length: 5
+ do Output.println();
+
+ do Output.printString("charAt[2]: ");
+ do Output.printInt(s.charAt(2)); // charAt[2]: 99
+ do Output.println();
+
+ do s.setCharAt(2, 45);
+ do Output.printString("setCharAt(2,'-'): ");
+ do Output.printString(s); // setCharAt(2,'-'): ab-de
+ do Output.println();
+
+ do s.eraseLastChar();
+ do Output.printString("eraseLastChar: ");
+ do Output.printString(s); // eraseLastChar: ab-d
+ do Output.println();
+
+ let s = "456";
+ do Output.printString("intValue: ");
+ do Output.printInt(s.intValue()); // intValue: 456
+ do Output.println();
+
+ let s = "-32123";
+ do Output.printString("intValue: ");
+ do Output.printInt(s.intValue()); // intValue: -32123
+ do Output.println();
+
+ do Output.printString("backSpace: ");
+ do Output.printInt(String.backSpace()); // backSpace: 129
+ do Output.println();
+
+ do Output.printString("doubleQuote: ");
+ do Output.printInt(String.doubleQuote());// doubleQuote: 34
+ do Output.println();
+
+ do Output.printString("newLine: ");
+ do Output.printInt(String.newLine()); // newLine: 128
+ do Output.println();
+
+ do i.dispose();
+ do s.dispose();
+
+ return;
+ }
+}
diff --git a/12/StringTest/StringTestOutput.gif b/12/StringTest/StringTestOutput.gif
new file mode 100644
index 0000000..5c2932c
Binary files /dev/null and b/12/StringTest/StringTestOutput.gif differ
diff --git a/12/Sys.jack b/12/Sys.jack
new file mode 100644
index 0000000..bee6f67
--- /dev/null
+++ b/12/Sys.jack
@@ -0,0 +1,27 @@
+// 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/Sys.jack
+
+/**
+ * A library that supports various program execution services.
+ */
+class Sys {
+
+ /** Performs all the initializations required by the OS. */
+ function void init() {
+ }
+
+ /** Halts the program execution. */
+ function void halt() {
+ }
+
+ /** Waits approximately duration milliseconds and returns. */
+ function void wait(int duration) {
+ }
+
+ /** Displays the given error code in the form "ERR