This commit is contained in:
QkoSad
2025-07-16 13:00:37 +03:00
commit 7894b48931
806 changed files with 162532 additions and 0 deletions
+29
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){
do Sys.error(7);
}
return Memory.alloc(size);
}
/** Disposes this array. */
method void dispose() {
do Memory.deAlloc(this);
return;
}
}
+102
View File
@@ -0,0 +1,102 @@
// 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 {
static Array mem;
/** Initializes the keyboard. */
function void init() {
let mem = 0;
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() {
return mem[24576];
}
/**
* 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 a, b;
do Output.printChar(0);
while ((b = 0) | (a > 0)){
let a = Keyboard.keyPressed();
if (a > 0){
let b = a;
}
}
do Output.printChar(String.backSpace());
do Output.printChar(b);
return b;
}
/**
* 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, b;
var char c;
let s = String.new(100);
do Output.printString(message);
while (true){
let c = Keyboard.readChar();
if (c = 128){
return s;
}
else{
if (c = 129){
do s.eraseLastChar();
}
else{
do s.appendChar(c);
}
}
}
return s;
}
/**
* 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 starting a;
var int b;
let a = Keyboard.readLine(message);
let b = String.intValue(a);
do String.dispose(a);
return b;
}
}
+83
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: ");
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;
}
}
+143
View File
@@ -0,0 +1,143 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/12/Math.jack
/**
* A library of commonly used mathematical functions.
* Note: Jack compilers implement multiplication and division using OS method calls.
*/
class Math {
static Array st;
static int division_tmp, f;
/** Initializes the library. */
function void init() {
var int a;
let st = Array.new(16);
let st[0] = 1;
while (a < 15){
let a = a + 1;
let st[a] = st[a - 1] + st[a - 1];
}
return;
}
/** Returns the absolute value of x. */
function int abs(int x) {
if (x > 0){
return 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, temp, y_comp, i, neg;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (x < y){
let temp = x;
let x = y;
let y = temp;
}
if (y = 1){
if(neg){
return -x;
}
return x;
}
while((y_comp - 1) < (y - 1)){
if ((st[i] & y) > 0) {
let sum = sum + x;
let y_comp = y_comp + st[i];
}
let x = x + x;
let i = i + 1;
}
if(neg){
let sum = -sum;
}
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, neg;
if (f = 0){
let division_tmp = 0;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (y = 0){
do Sys.error(3);
}
let f = 1;
}
if ((y > x) | (y < 0)){
return 0;
}
let q = Math.divide(x, y + y);
let f = 0;
let q = Math.abs(q);
if ((q & 1) = 1){
let division_tmp = division_tmp + y + y;
}
if (x - division_tmp < y){
if (neg){
return -(q + q);
}
return q + q;
}
else{
if (neg){
return -(q + q + 1);
}
return q + q + 1;
}
}
/** Returns the integer part of the square root of x. */
function int sqrt(int x) {
var int j, b, d, y;
if (x < 0){
do Sys.error(4);
}
let j = 7;
while (j > -1){
let d = y + st[j];
let b = d * d;
if ((~(b > x)) & (b > 0)){
let y = d;
}
let j = j - 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;
}
}
+63
View File
@@ -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/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 mem;
/** Initializes the class. */
function void init() {
let mem = 0;
let mem[2048] = 14334;
let mem[2049] = -1;
return;
}
/** Returns the RAM value at the given address. */
function int peek(int address) {
return mem[address];
}
/** Sets the RAM value at the given address to the given value. */
function void poke(int address, int value) {
let mem[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 current_block;
var int tmp;
let current_block = 2048;
if (size < 0){
do Sys.error(5);
}
if (size = 0){
let size = 1;
}
while (current_block[0] < (size + 2)) {
let current_block = current_block[1];
}
let current_block[0] = current_block[0] - size - 2;
let current_block = current_block + current_block[0] + 2;
let current_block[0] = size;
return current_block + 2;
}
/** De-allocates the given object (cast as an array) by making
* it available for future allocations. */
function void deAlloc(Array o) {
var Array current_block;
let current_block = 2048;
let o[1]= current_block[1];
let current_block[1] = o;
return;
}
}
+299
View File
@@ -0,0 +1,299 @@
// 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 address;
static bool half;
/** Initializes the screen, and locates the cursor at the screen's top-left. */
function void init() {
do Output.initMap();
do Output.moveCursor(0, 0);
return;
}
// 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 ** 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) {
var int co,display;
var Array r,ch;
if (j = 0){
let half = true;
}
else{
let half = (j / 2) * 2 = j; // chetno true, 1vaa chast
}
let address = (352 * i) + (j / 2) + 16384;
let ch = Output.getMap(32);
while (co < 11){
if (half){
let display = r[address] & (-256);
let r[address] = ch[co] | display;
}
else{
let display = r[address] & 255;
let r[address] = (ch[co]*256) | display;
}
let co = co + 1;
let address = address + 32;
}
let address = address - 352;
return;
}
/** Displays the given character at the cursor location,
* and advances the cursor one column forward. */
function void printChar(char c) {
var Array ch;
var Array r;
var int co;
var int ds;
let ch = Output.getMap(c);
while (co < 11){
if (half){
let ds = r[address] & (-256);
let r[address] = ch[co] | ds;
}
else{
let ds = r[address] & 255;
let r[address] = (ch[co]*256) | ds;
}
let co = co + 1;
let address = address + 32;
}
if (half){
let address = address - 352;
let half = false;
}
else{
if (address > 24480){
let address = 16384;
let half = true;
}
else{
let address = address - 351;
let half = true;
}
}
return;
}
/** displays the given string starting at the cursor location,
* and advances the cursor appropriately. */
function void printString(String s) {
var int i, length;
let length = s.length();
while (i < length){
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 String s;
let s = String.new(6);
do s.setInt(i);
do Output.printString(s);
return;
}
/** Advances the cursor to the beginning of the next line. */
function void println() {
var int row;
let row = (((address - 16384) / 32)/11) + 1;
if (row > 32){
let row = 0;
}
do Output.moveCursor(row, 0);
return;
}
/** Moves the cursor one column back. */
function void backSpace() {
if (address = 16384){
let address = 24191;
let half = true;
return;
}
if (half){
let address = address - 1;
let half = false;
}
else{
let half = true;
}
return;
}
}
+206
View File
@@ -0,0 +1,206 @@
// 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 256 rows (indexed 0..255, top to bottom)
* of 512 pixels each (indexed 0..511, left to right). The top left pixel on
* the screen is indexed (0,0).
*/
class Screen {
static Array mem;
static Array st;
static boolean color;
/** Initializes the Screen. */
function void init() {
var int a;
let st = Array.new(16);
let st[0] = 1;
while (a < 15){
let a = a + 1;
let st[a] = st[a - 1] + st[a - 1];
}
let color = true;
return;
}
/** Erases the entire screen. */
function void clearScreen() {
var int a;
let a = 16384;
while (a < 24575){
let mem[a] = 0;
let a = a + 1;
}
return;
}
/** Sets the current color, to be used for all subsequent drawXXX commands.
* Black is represented by true, white by false. */
function void setColor(boolean b) {
let color = b;
return;
}
/** Draws the (x,y) pixel, using the current color. */
function void drawPixel(int x, int y) {
var int value, address, bit, mem_block;
if ((x > 511) | (x < 0) | (y > 255) | (y < 0)){
do Sys.error(7);
}
let mem_block = x / 16;
let address = (32 * y) + mem_block + 16384;
let value = mem[address];
let bit = x - (mem_block * 16);
if (color){
let mem[address] = st[bit] | value;
}
else{
let mem[address] = (~st[bit])& 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 diff, dx, dy, a, b;
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
do Sys.error(8);
}
let dx = x2 - x1;
let dy = y2 - y1;
if (dx = 0){
if (dy > 0){
while(~(b > dy)){
do Screen.drawPixel(x1, y1 + b);
let b = b + 1;
}
return;
}
else{
while(~(b < dy)){
do Screen.drawPixel(x1, y1 + b);
let b = b - 1;
}
return;
}
}
if (dy = 0){
if (dx > 0){
while(~(a > dx)){
do Screen.drawPixel(x1 + a, y1);
let a = a + 1;
}
return;
}
else{
while(~(a < dx)){
do Screen.drawPixel(x1 + a, y1);
let a = a - 1;
}
return;
}
}
if (dx < 0){
if (dy < 0){
while ((~(a < dx)) & (~(b < dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a - 1;
let diff = diff - dy;
}
else{
let b = b - 1;
let diff = diff + dx;
}
}
}
else{
while ((~(a < dx)) & (~(b > dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a - 1;
let diff = diff + dy;
}
else{
let b = b + 1;
let diff = diff + dx;
}
}
}
}
else{
if (dy < 0){
while ((~(a > dx)) & (~(b < dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a + 1;
let diff = diff - dy;
}
else{
let b = b - 1;
let diff = diff - dx;
}
}
}
else{
while ((~(a > dx)) & (~(b > dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a + 1;
let diff = diff + dy;
}
else{
let b = b + 1;
let diff = diff - dx;
}
}
}
}
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 a, tmp;
if (x1 > x2){
let tmp = x1;
let x1 = x2;
let x2 = tmp;
}
if (y1 > y2){
let tmp = y1;
let y1 = y2;
let y2 = tmp;
}
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
do Sys.error(8);
}
let tmp = y2 - y1;
while(a < tmp){
do Screen.drawLine(x1, y1 + a, x2, y1 + a);
let a = a + 1;
}
return;
}
/** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
function void drawCircle(int x, int y, int r) {
var int dy, dx, tmp;
if(r > 181){
do Sys.error(7);
}
let dy = - r;
while (dy < r){
let tmp = Math.sqrt((r * r) - (dy * dy));
do Screen.drawLine(x - tmp, y + dy, x + tmp, y + dy);
let dy = dy + 1;
}
return;
}
}
+154
View File
@@ -0,0 +1,154 @@
// 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 Array str;
field int length;
field int strLength;
/** constructs a new empty string with a mavalimum length of mavalLength
* and initial length of 0. */
constructor String new(int mavalLength) {
if (mavalLength > 0){
let str = Array.new(mavalLength);
}
let strLength = mavalLength;
let length = 0;
return this;
}
/** Disposes this string. */
method void dispose() {
if(length > 0){
do str.dispose();
}
do Memory.deAlloc(this);
return;
}
/** Returns the current length of this string. */
method int length() {
return length;
}
/** Returns the character at the j-th location of this string. */
method char charAt(int j) {
if(j > length){
do Sys.error(7);
}
return str[j];
}
/** Sets the character at the j-th location of this string to c. */
method void setCharAt(int j, char c) {
if(j > length){
do Sys.error(7);
}
let str[j] = c;
return;
}
/** Appends c to this string's end and returns this string. */
method String appendChar(char c) {
if(strLength = length){
do Sys.error(7);
}
let str[length] = c;
let length = length + 1;
return this;
}
/** Erases the last character from this string. */
method void eraseLastChar() {
if (length = 0){
do Sys.error(7);
}
let str[length] = 0;
let length = length - 1;
return;
}
/** Returns the integer value of this string,
* until a non-digit character is detected. */
method int intValue() {
var int d, sum, i;
var bool f;
while(i < length){
let d = str[i];
if ((d > 47) & (d < 58)){
let sum = (sum * 10) + (d - 48);
}
else{
if((i = 0) & (d = 45)){
let f = true;
}
else{
let i = length;
}
}
let i = i + 1;
}
if (f){
return -sum;
}
return sum;
}
/** Sets this string to hold a representation of the given value. */
method void setInt(int val) {
var Array c;
var int d, b, a;
let c = Array.new(6);
if (val < 0){
let d = ~0;
let val = -val;
}
let b = val;
while(b > 0){
let b = val / 10;
let c[a] = 48 + val - (b * 10);
let a = a + 1;
let val = b;
}
if (d){
let c[a] = 45;
let a = a + 1;
}
if (a = 0){
let str[0] = 48;
let length = 1;
}
else{
let length = 0;
while (length < a){
let str[length] = c[a - 1 - length];
let length = length + 1;
}
}
do Array.dispose(c);
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;
}
}
+53
View File
@@ -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/Sys.jack
/**
* A library that supports various program execution services.
*/
class Sys {
/** Performs all the initializations required by the OS. */
function void init() {
do Memory.init();
do Math.init();
do Output.init();
do Screen.init();
do Keyboard.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;
while (duration > 0){
let i = 100;
while(i > 0){
let i = i -1;
}
let duration = duration - 1;
}
return;
}
/** Displays the given error code in the form "ERR<errorCode>",
* and halts the program's execution. */
function void error(int errorCode) {
var String s;
let s = String.new(3);
do s.setInt(errorCode);
do Output.printString("ERR");
do Output.printString(s);
return;
}
}