Add solutions for part 1

This commit is contained in:
2020-11-15 13:57:48 -05:00
parent e4f9fd2682
commit 742db6d102
479 changed files with 202980 additions and 13 deletions

23
projects/12/Array.jack Normal file
View File

@@ -0,0 +1,23 @@
// 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() {
}
}

View File

@@ -0,0 +1,29 @@
// 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) {
if (size > 0) {
return Memory.alloc(size);
} else {
return 0;
}
}
/** Disposes this array. */
method void dispose() {
do Memory.deAlloc(this);
return;
}
}

View File

@@ -0,0 +1,2 @@
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|
| 222 | 122 | 100 | 10 |

View File

@@ -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;

View File

@@ -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;
}
}

62
projects/12/Keyboard.jack Normal file
View File

@@ -0,0 +1,62 @@
// 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) {
}
}

View File

@@ -0,0 +1,196 @@
// 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() {
return;
}
/**
* 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() {
var char value;
let value = Memory.peek(24576);
if (value = 128) {
return String.newLine();
}
if (value = 129) {
return String.backSpace();
}
return value;
}
/**
* 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() {
var char key, result;
while (Keyboard.keyPressed() = 0) {}
let key = Keyboard.keyPressed();
while (~(Keyboard.keyPressed() = 0)) {}
if (key = String.newLine()) {
return key;
}
if (key = String.backSpace()) {
return key;
}
do Output.printChar(key);
return key;
}
/**
* 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) {
var String s;
var char key, newline, backspace;
var int i;
let newline = String.newLine();
let backspace = String.backSpace();
let s = String.new(128);
let key = 0;
do Output.printString(message);
let i = 0;
while (~(key = newline)) {
let key = Keyboard.readChar();
if (key = newline) {
do Output.println();
return s;
} else {
if (key = backspace) {
if (i > 0) {
do s.eraseLastChar();
do Output.backSpace();
let i = i - 1;
}
} else {
do s.appendChar(key);
let i = i + 1;
}
}
// Prevent out of bound error.
if (i = 128) {
return s;
}
}
return s;
}
function int textToInt(String s) {
var int result, i, length, multiplier;
var char c;
var boolean isNegative, continue;
let isNegative = false;
let length = s.length();
let i = 0;
let result = 0;
let multiplier = 1;
if (length = 0) {
return 0;
}
if (s.charAt(0) = 45) {
let isNegative = true;
}
let i = length;
while (true) {
let i = i - 1;
let c = s.charAt(i);
if ((s.charAt(i) > 47) & (s.charAt(i) < 58)) {
let result = result + ((s.charAt(i) - 48) * multiplier);
let multiplier = multiplier * 10;
} else {
// could raise exception here;
}
if (isNegative) {
if (i = 1) {
return -result;
}
} else {
if (i = 0) {
return result;
}
}
}
return 0;
}
/**
* 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) {
var String s;
var char key, newline, backspace;
var int i;
let newline = String.newLine();
let backspace = String.backSpace();
let s = String.new(128);
let key = 0;
do Output.printString(message);
let i = 0;
while (~(key = newline)) {
let key = Keyboard.readChar();
if (key = newline) {
do Output.println();
} else {
if (key = backspace) {
if (i > 0) {
do s.eraseLastChar();
do Output.backSpace();
let i = i - 1;
}
} else {
do s.appendChar(key);
let i = i + 1;
}
}
// Prevent out of bound error.
if (i = 128) {
return s;
}
}
let i = Keyboard.textToInt(s);
do s.dispose();
return i;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -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 'Page Down' key");
while (key = 0) {
let key = Keyboard.keyPressed();
}
let c = key;
while (~(key = 0)) {
let key = Keyboard.keyPressed();
}
do Output.println();
if (c = 137) {
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;
}
}

47
projects/12/Math.jack Normal file
View File

@@ -0,0 +1,47 @@
// 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 {
/** Initializes the library. */
function void init() {
}
/** Returns the absolute value of x. */
function int abs(int 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) {
}
/** 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) {
}
/** Returns the integer part of the square root of x. */
function int sqrt(int x) {
}
/** Returns the greater number. */
function int max(int a, int b) {
}
/** Returns the smaller number. */
function int min(int a, int b) {
}
}

View File

@@ -0,0 +1,35 @@
// 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
/** Test program for 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;
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); // 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;
}
}

View File

@@ -0,0 +1,133 @@
// 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 {
/** Initializes the library. */
function void init() {
return;
}
/** Returns the absolute value of x. */
function int abs(int x) {
if (x < 0) {
let x = -x;
}
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 sum;
var int i;
var int mask;
var int xShifted;
let sum = 0;
let i = 0;
let mask = 1;
let xShifted = x;
if (x = 1) {
return y;
}
if (y = 1) {
return x;
}
while (i < 16) { // 16 because we got a 16 bit architecture
if (y & mask) {
let sum = sum + xShifted;
}
let xShifted = xShifted + xShifted; // xShifted << 2;
let mask = mask + mask; // mask << 2;
let i = i + 1;
}
return sum;
}
/** 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 q;
var int sign;
let sign = 1;
if (x < 0) {
let x = -x;
let sign = -sign;
}
if (y < 0) {
let y = -y;
let sign = -sign;
}
if (y > x) {
return 0;
}
let q = x / (y + y);
if ((x - (2 * q * y)) < y) {
return (q + q) * sign;
} else {
return (q + q + 1) * sign;
}
}
/** Returns the integer part of the square root of x. */
function int sqrt(int x) {
var int y;
var int p;
var int s;
var int s2;
let y = 0;
let p = 128; // 2^7
while (p > 0) {
let s = y + p;
let s2 = s * s;
if ((s2 - 1) < x) {
if (s2 > 0) {
let y = s;
}
}
let p = p / 2; // p >> 1;
}
return y;
}
/** Returns the greater number. */
function int max(int a, int b) {
if (a > b) {
return a;
}
return b;
}
/** Returns the smaller number. */
function int min(int a, int b) {
if (a < b) {
return a;
}
return b;
}
}

View File

@@ -0,0 +1,2 @@
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|RAM[8006]|RAM[8007]|RAM[8008]|RAM[8009]|RAM[8010]|RAM[8011]|RAM[8012]|RAM[8013]|
| 6 | -180 | -18000 | -18000 | 0 | 3 | -3000 | 0 | 3 | 181 | 123 | 123 | 27 | 32767 |

View File

@@ -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;

34
projects/12/Memory.jack Normal file
View File

@@ -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/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) {
}
}

View File

@@ -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/MemoryTest/Main.jack
/** Test program for the OS Memory class. */
class Main {
/** Performs various memory manipulations. */
function void main() {
var int temp;
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 b = Array.new(3);
let b[1] = a[2] - 100;
do Memory.poke(8003, b[1]); // RAM[8003] = 122
let c = Array.new(500);
let c[499] = a[2] - b[1];
do Memory.poke(8004, c[499]); // RAM[8004] = 100
do a.dispose(); // uses Memory.deAlloc
do b.dispose();
let b = Array.new(3);
let b[0] = c[499] - 90;
do Memory.poke(8005, b[0]); // RAM[8005] = 10
do c.dispose();
do b.dispose();
return;
}
}

View File

@@ -0,0 +1,120 @@
// 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 {
static Array ram;
static Array heap;
static Array freeList;
/** Initializes the class. */
function void init() {
let ram = 0;
let heap = 2048;
let freeList = heap;
let freeList[0] = 0; // next
let freeList[1] = 14334; // length
return;
}
/** Returns the RAM value at the given address. */
function int peek(int address) {
return ram[address];
}
/** Sets the RAM value at the given address to the given value. */
function void poke(int address, int value) {
let ram[address] = value;
return;
}
/** Finds an available RAM block of the given size and returns
* a reference to its base address. */
function int alloc(int size) {
var Array previousBlock;
var Array currentBlock;
var Array resultBlock;
var int currentBlockSize;
var int remainingSize;
var int currentBlockNext;
if (freeList = 0) {
return 0;
}
// XXX: I am not happy with having the whole code duplicated just because
// we have the "special case" that we select the first block.
// Using the first block is a special case, because we have to
// update freeList instead of simply taking the block out of the list
// by doing `let previousBlock.next = currentBlock.next`.
let currentBlockSize = freeList[1];
if (currentBlockSize > size) {
let remainingSize = currentBlockSize - size;
let resultBlock = freeList;
if (remainingSize < 4) {
// If remainingSize is smaller than 4 it does not make sense to split
// the block. Just return it as a whole.
let freeList = freeList[0]; // point to freeList.next
} else {
// If remainingSize is big enough we split the block. In that case
// we have to update the size of the block we return as well as
// the block (aka the remainder of the current block).
let resultBlock[1] = size;
let freeList = resultBlock + 2 + size;
let freeList[0] = resultBlock[0];
let freeList[1] = currentBlockSize - size - 2;
}
return resultBlock + 2;
}
let previousBlock = freeList;
// The following excludes the first block which is what we want
// because we handled it separately before.
while (~(previousBlock[0] = 0)) {
let currentBlock = previousBlock[0];
let currentBlockSize = currentBlock[1];
if (currentBlockSize > size) {
let resultBlock = currentBlock;
let remainingSize = currentBlockSize - size;
if (remainingSize < 4) {
let previousBlock[0] = resultBlock[0];
} else {
let resultBlock[1] = size;
let currentBlock = resultBlock + 2 + size;
let currentBlock[0] = resultBlock[0];
let currentBlock[1] = currentBlockSize - size - 2;
let previousBlock[0] = currentBlock;
}
return resultBlock;
} else {
let previousBlock = currentBlock;
}
}
// Not enough heap available. Call defragment and try again.
return 0;
}
/** De-allocates the given object (cast as an array) by making
* it available for future allocations. */
function void deAlloc(Array o) {
var Array currentBlock;
if (freeList = 0) {
let freeList = o - 2;
}
let currentBlock = freeList;
while (~(currentBlock[0] = 0)) {
let currentBlock = currentBlock[0];
}
let currentBlock[0] = o - 2;
return;
}
}

View File

@@ -0,0 +1,2 @@
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|
| 333 | 334 | 222 | 122 | 100 | 10 |

View File

@@ -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;

203
projects/12/Output.jack Normal file
View File

@@ -0,0 +1,203 @@
// 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() {
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,317 @@
// 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;
static int currentColumn;
static int currentRow;
/** Initializes the screen, and locates the cursor at the screen's top-left. */
function void init() {
do Screen.clearScreen();
do Output.initMap();
let currentColumn = 0;
let currentRow = 0;
return;
}
function int modulo(int a, int b) {
var int d;
let d = a / b;
return a - (d * b);
}
// 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,12,30,51,51,63,51,51,51,51,0,0); // A
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) {
let currentRow = i;
let currentColumn = j;
do Output.printChar(32);
let currentRow = i;
let currentColumn = j;
return;
}
/** Displays the given character at the cursor location,
* and advances the cursor one column forward. */
function void printChar(char c) {
var Array m;
var int i, address, value, currentCharRow, higherByte;
let m = Output.getMap(c);
let address = 16384 + (32 * currentRow * 11) + ((currentColumn * 8) / 16);
let higherByte = Output.modulo(currentColumn, 2);
let i = 0;
while (i < 11) {
let value = Memory.peek(address);
let currentCharRow = m[i];
if (higherByte = 1) {
let currentCharRow = currentCharRow * 256; // x << 8;
let value = currentCharRow | (value & 255); // 255 = 0x00ff
} else {
let value = (value & (-256)) | (currentCharRow); // -256 = 0xff00
}
do Memory.poke(address, value);
let address = address + 32;
let i = i + 1;
}
if (currentColumn = 63) {
if (currentRow = 22) {
let currentRow = 0;
let currentColumn = 0;
} else {
let currentColumn = 0;
let currentRow = currentRow + 1;
}
} else {
let currentColumn = currentColumn + 1;
}
return;
}
/** displays the given string starting at the cursor location,
* and advances the cursor appropriately. */
function void printString(String s) {
var int stringLength, i;
let stringLength = s.length();
let i = 0;
while (i < stringLength) {
do Output.printChar(s.charAt(i));
let i = i + 1;
}
return;
}
/** Displays the given integer starting at the cursor location,
* and advances the cursor appropriately. */
function void printInt(int i) {
var int digit, divisor;
var boolean firstDigitPrinted;
let divisor = 10000;
let firstDigitPrinted = false;
if (i = 0) {
do Output.printChar(48 + 0);
return;
}
if (i < 0) {
do Output.printChar(45); // 45 = '-'
let i = (~i) + 1;
}
while (~(divisor = 0)) {
let digit = i / divisor;
if (digit = 0) {
if (firstDigitPrinted) {
do Output.printChar(48 + 0);
}
} else {
do Output.printChar(48 + digit);
let firstDigitPrinted = true;
}
let i = i - (digit * divisor);
let divisor = divisor / 10;
}
return;
}
/** Advances the cursor to the beginning of the next line. */
function void println() {
if (currentRow = 22) {
let currentRow = 0;
} else {
let currentRow = currentRow + 1;
}
let currentColumn = 0;
return;
}
/** Moves the cursor one column back. */
function void backSpace() {
var int newRow, newColumn;
if (currentColumn = 0) {
if (currentRow = 0) {
let newRow = 22;
let newColumn = 63;
} else {
let newRow = currentRow - 1;
let newColumn = 63;
}
} else {
let newRow = currentRow;
let newColumn = currentColumn - 1;
}
do Output.moveCursor(newRow, newColumn);
return;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

43
projects/12/Screen.jack Normal file
View File

@@ -0,0 +1,43 @@
// 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) {
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,178 @@
// 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 boolean color;
/** Initializes the Screen. */
function void init() {
let color = true;
return;
}
/** Erases the entire screen. */
function void clearScreen() {
var int i;
var Array a;
let i = 0;
let a = 16384;
while (i < 8192) {
let a[i] = 0;
let i = i + 1;
}
return;
}
function int modulo(int a, int b) {
var int d;
let d = a / b;
return a - (d * b);
}
/** 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 address;
var int value;
var int i;
var int mask;
var int inverseMask;
var int pixel;
let pixel = Screen.modulo(x, 16);
let i = 0;
let mask = 1;
while (~(i = pixel)) {
let mask = mask + mask;
let i = i + 1;
}
let inverseMask = ~mask;
let address = 16384 + (32 * y) + (x / 16);
let value = Memory.peek(address);
if (color) {
let value = ((value & inverseMask) | ((-1) & mask)); // pixel gets set to 1
} else {
let value = (value & inverseMask); // pixel gets set to 0
}
do Memory.poke(address, value);
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 a, b, diff, dx, dy, xinc, yinc;
var boolean continue;
let a = 0;
let b = 0;
let diff = 0;
let dx = Math.abs(x2 - x1);
let dy = Math.abs(y2 - y1);
let continue = true;
if (x2 > x1) {
let xinc = 1; // going from left to right;
} else {
let xinc = -1; // going from right to left;
}
if (y2 > y1) {
let yinc = 1; // going from top to bottom
} else {
let yinc = -1; // going from bottom to top
}
// vertical line
if (dx = 0) {
while (~(y1 = y2)) {
do Screen.drawPixel(x1, y1);
let y1 = y1 + yinc;
}
return;
}
// horizontal line
if (dy = 0) {
while (~(x1 = x2)) {
do Screen.drawPixel(x1, y1);
let x1 = x1 + xinc;
}
return;
}
while (continue) {
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0) {
let a = a + xinc;
let diff = diff + dy;
} else {
let b = b + yinc;
let diff = diff - dx;
}
if ((x1 + a) = x2) {
if ((y1 + b) = y2) {
let continue = false;
}
}
}
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 yinc;
if (y2 > y1) {
let yinc = 1;
} else {
let yinc = -1;
}
while (~(y1 = y2)) {
do Screen.drawLine(x1, y1, x2, y1);
let y1 = y1 + yinc;
}
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 dy;
var int halfSegment;
let dy = -r;
if (r > 181) {
return;
}
while (dy < (r + 1)) {
let halfSegment = Math.sqrt((r * r) - (dy * dy));
do Screen.drawLine(x - halfSegment, y + dy, x + halfSegment, y + dy);
let dy = dy + 1;
}
return;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

64
projects/12/String.jack Normal file
View File

@@ -0,0 +1,64 @@
// 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() {
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,203 @@
// 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 {
field int maxLength;
field int length;
field Array s;
/** constructs a new empty string with a maximum length of maxLength
* and initial length of 0. */
constructor String new(int maxStringLength) {
let maxLength = maxStringLength;
let length = 0;
// Only allocate memory for positive length.
if (maxLength > 0) {
let s = Array.new(maxLength);
} else {
let s = 0;
}
return this;
}
/** Disposes this string. */
method void dispose() {
// Only deAlloc for positive length. We do not alloc memory in constructor
// if length is not positive.
if (~(s = 0)) {
do s.dispose();
}
return;
}
/** Returns the current length of this string. */
method int length() {
return length;
}
/** Sets all fields to null and resets length. */
method void clear() {
var int i;
let i = 0;
while (i < maxLength) {
let s[i] = 0;
let i = i + 1;
}
let length = 0;
return;
}
/** Returns the character at the j-th location of this string. */
method char charAt(int j) {
if (j < maxLength) {
return s[j];
}
return 0; // Out-of-bounds access. Consider raising an error.
}
/** Sets the character at the j-th location of this string to c. */
method void setCharAt(int j, char c) {
if (j < maxLength) {
let s[j] = c;
} else {
// Out-of-bounds access. Consider raising an error.
}
return;
}
/** Appends c to this string's end and returns this string. */
method String appendChar(char c) {
if (length < maxLength) {
let s[length] = c;
let length = length + 1;
}
return this;
}
/** Erases the last character from this string. */
method void eraseLastChar() {
if (length > 0) {
let length = length - 1;
let s[length] = 0;
}
return;
}
/** Returns the integer value of this string,
* until a non-digit character is detected. */
method int intValue() {
var int i, result, multiplier;
var boolean isNegative, continue;
var char c;
let i = 0;
let isNegative = false;
if (charAt(0) = 45) {
let isNegative = true;
let i = i + 1;
}
// First iterate up to the highest numerical character.
let continue = true;
while (continue) {
let c = charAt(i);
if ((c > 47) & (c < 58)) {
let i = i + 1;
} else {
let continue = false;
}
if (~(i < maxLength)) {
let continue = false;
}
}
// Then iterate backwards and add the values to result.
// Checking if we are within the range allows us to not
// worry about a potential negative sign.
let continue = true;
let multiplier = 1;
let i = i - 1;
while (continue) {
let c = charAt(i);
if ((c > 47) & (c < 58)) {
let result = result + ((c - 48) * multiplier);
let multiplier = multiplier * 10;
} else {
let continue = false;
}
if (i = 0) {
let continue = false;
}
let i = i - 1;
}
if (isNegative) {
let result = -result;
}
return result;
}
/** Sets this string to hold a representation of the given value. */
method void setInt(int val) {
var int digit, divisor;
var boolean firstDigitPrinted;
let divisor = 10000;
let firstDigitPrinted = false;
do clear();
if (val = 0) {
do appendChar(48); // 0
return;
}
if (val < 0) {
do appendChar(45); // 45 = '-'
let val = (~val) + 1;
}
while (~(divisor = 0)) {
let digit = val / divisor;
if (digit = 0) {
if (firstDigitPrinted) {
do appendChar(48 + 0);
}
} else {
do appendChar(48 + digit);
let firstDigitPrinted = true;
}
let val = val - (digit * divisor);
let divisor = divisor / 10;
}
return;
}
/** Returns the new line character. */
function char newLine() {
return 128;
}
/** Returns the backspace character. */
function char backSpace() {
return 129;
}
/** Returns the double quote (") character. */
function char doubleQuote() {
return 34;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

27
projects/12/Sys.jack Normal file
View File

@@ -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<errorCode>",
* and halts the program's execution. */
function void error(int errorCode) {
}
}

View File

@@ -0,0 +1,31 @@
// 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/SysTest/Main.jack
/** Test program for the OS Sys class. */
class Main {
/** Tests the wait method of the Sys class. */
function void main() {
var char key;
do Output.printString("Wait test:");
do Output.println();
do Output.printString("Press any key. After 2 seconds, another message will be printed:");
while (key = 0) {
let key = Keyboard.keyPressed();
}
while (~(key = 0)) {
let key = Keyboard.keyPressed();
}
do Sys.wait(2000);
do Output.println();
do Output.printString("Time is up. Make sure that 2 seconds elapsed.");
return;
}
}

View File

@@ -0,0 +1,52 @@
// 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() {
do Math.init();
do Memory.init();
do Screen.init();
do Keyboard.init();
do Output.init();
do Main.main();
do Sys.halt();
return;
}
/** Halts the program execution. */
function void halt() {
while (true) {}
return;
}
/** Waits approximately duration milliseconds and returns. */
function void wait(int duration) {
var int i, j;
let i = 0;
while (i < duration) {
let i = i + 1;
let j = 0;
while (j < 50) {
let j = j + 1;
}
}
return;
}
/** Displays the given error code in the form "ERR<errorCode>",
* and halts the program's execution. */
function void error(int errorCode) {
do Output.printString("ERR<");
do Output.printInt(errorCode);
do Output.printString(">");
do Sys.halt();
return;
}
}