179 lines
4.7 KiB
Plaintext
179 lines
4.7 KiB
Plaintext
// 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;
|
|
}
|
|
}
|