Screen.jack implementation!

This took me a while!

This took me a while!

// 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). */ // Screen starts at 16384 // 8K screen memory map // 512 x 256 // each class Screen { static Array screen; static boolean isBlack; static Array bitArray; /** Initializes the Screen. */ function void init() { let bitArray = Array.new(16); let bitArray[0] = 1; // 0000000000000001 let bitArray[1] = 2; // 0000000000000010 let bitArray[2] = 4; // 0000000000000100 let bitArray[3] = 8; // 0000000000001000 let bitArray[4] = 16; // 0000000000010000 let bitArray[5] = 32; // 0000000000100000 let bitArray[6] = 64; // 0000000001000000 let bitArray[7] = 128; // 0000000010000000 let bitArray[8] = 256; // 0000000100000000 let bitArray[9] = 512; // 0000001000000000 let bitArray[10] = 1024; // 0000010000000000 let bitArray[11] = 2048; // 0000100000000000 let bitArray[12] = 4096; // 0001000000000000 let bitArray[13] = 8192; // 0010000000000000 let bitArray[14] = 16384; // 0100000000000000 let bitArray[15] = 16384 + 16384; // 1000000000000000 let screen = 16384; let isBlack = true; return; } /** Erases the entire screen. */ function void clearScreen() { var int i; let i = 0; while (i < 8192) { let screen[i] = false; let i = i + 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 isBlack = b; return; } /** Draws the (x,y) pixel, using the current color. */ function void drawPixel(int x, int y) { var int address, value, modulo, pattern; let address = (32 * y) + (x / 16); let value = Memory.peek(16384 + address); let modulo = x - (x / 16 * 16); // a % b can be done as a-(a/b*b) let pattern = bitArray[modulo]; if (isBlack) { let value = value | pattern; } else { let pattern = ~pattern; let value = value & pattern; } do Memory.poke((16384 + address), value); return; } /** Draws a line from (x1, y1) to (x2, y2). */ function void drawLine(int x1, int y1, int x2, int y2) { var int dx, dy, a, b, diff; if (y1 = y2) { do Screen.drawHLine(x1, x2, y1); return; } if (x1 = x2) { do Screen.drawVLine(x1, y1, y2); return; } let dx = x2 - x1; let dy = y2 - y1; let a = 0; let b = 0; let diff = 0; if (dx > 0 & 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; } } } if (dx < 0 & 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; } } } if (dx > 0 & 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; } } } if (dx < 0 & 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; } } } return; } //draw horizontal line function void drawHLine(int x1, int x2, int y) { var int temp; var int diff; if (x1 > x2) { let temp = x1; let x1 = x2; let x2 = temp; } let diff = x2 - x1; while (diff > -1) { do Screen.drawPixel((x1 + diff), y); let diff = diff - 1; } return; } //draw vertical line function void drawVLine(int x, int y1, int y2) { var int temp; var int diff; if (y1 > y2) { let temp = y1; let y1 = y2; let y2 = temp; } let diff = y2 - y1; while (diff > -1) { do Screen.drawPixel(x, y1 + diff); let diff = diff - 1; } return; } /** Draws a filled rectangle where the top left corner * is (x1, y1) and the bottom right corner is (x2, y2). */ function void drawRectangle(int x1, int y1, int x2, int y2) { while(~(y1 > y2)) { do Screen.drawHLine(x1, x2, y1); let y1 = y1 + 1; } return; } /** Draws a filled circle of radius r around (cx, cy). */ function void drawCircle(int cx, int cy, int r) { var int dx, dy; var int r_squared; let dy = -r; let r_squared = r*r; while( ~(dy > r) ) { let dx = Math.sqrt(r_squared-(dy*dy)); do Screen.drawHLine( cx-dx, cx+dx, cy+dy ); let dy = dy + 1; } return; } }