mirror of
https://github.com/usatiuk/nand2tetris.git
synced 2025-10-29 00:27:49 +01:00
163 lines
4.7 KiB
Plaintext
163 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 Array twoToThe;
|
|
static boolean color;
|
|
|
|
/** Initializes the Screen. */
|
|
function void init() {
|
|
let color = true;
|
|
let twoToThe = Array.new(16);
|
|
let twoToThe[0] = 1;
|
|
let twoToThe[1] = 2;
|
|
let twoToThe[2] = 4;
|
|
let twoToThe[3] = 8;
|
|
let twoToThe[4] = 16;
|
|
let twoToThe[5] = 32;
|
|
let twoToThe[6] = 64;
|
|
let twoToThe[7] = 128;
|
|
let twoToThe[8] = 256;
|
|
let twoToThe[9] = 512;
|
|
let twoToThe[10] = 1024;
|
|
let twoToThe[11] = 2048;
|
|
let twoToThe[12] = 4096;
|
|
let twoToThe[13] = 8192;
|
|
let twoToThe[14] = 16384;
|
|
let twoToThe[15] = 16384 + 16384;
|
|
return;
|
|
}
|
|
|
|
/** Erases the entire screen. */
|
|
function void clearScreen() {
|
|
var int x, y;
|
|
var boolean prevColor;
|
|
let x = 0;
|
|
let y = 0;
|
|
let prevColor = color;
|
|
let color = false;
|
|
while (x < 256) {
|
|
while (y < 512) {
|
|
do Screen.drawPixel(x, y);
|
|
let y = y + 1;
|
|
}
|
|
let x = x + 1;
|
|
}
|
|
let color = prevColor;
|
|
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 Array address, value;
|
|
let address = (32 * y) + (x/16);
|
|
let value = Memory.peek(16384 + address);
|
|
if(color) {
|
|
let value = value | twoToThe[x & 15];
|
|
} else {
|
|
let value = value & (~(twoToThe[x & 15]));
|
|
}
|
|
do Memory.poke(16384 + 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 dx, dy, a, b, diff;
|
|
let dx = x2-x1;
|
|
let dy = y2-y1;
|
|
let a = 0;
|
|
let b = 0;
|
|
let diff = 0;
|
|
if(dx = 0) {
|
|
while(~(dy = 0)) {
|
|
do Screen.drawPixel(x1, y1 + dy);
|
|
if(dy > 0) {
|
|
let dy = dy - 1;
|
|
} else {
|
|
let dy = dy + 1;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
if(dy = 0) {
|
|
while(~(dx = 0)) {
|
|
do Screen.drawPixel(x1 + dx, y1);
|
|
if (dx > 0) {
|
|
let dx = dx - 1;
|
|
} else {
|
|
let dx = dx + 1;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
while((~(Math.abs(a) > Math.abs(dx))) & (~(Math.abs(b) > Math.abs(dy)))) {
|
|
do Screen.drawPixel(x1 + a, y1 + b);
|
|
if(diff < 0) {
|
|
if(dx > 0) {
|
|
let a = a + 1;
|
|
}
|
|
if(dx < 0) {
|
|
let a = a - 1;
|
|
}
|
|
let diff = diff + Math.abs(dy);
|
|
} else {
|
|
if(dy > 0) {
|
|
let b = b + 1;
|
|
}
|
|
if(dy < 0) {
|
|
let b = b - 1;
|
|
}
|
|
let diff = diff - Math.abs(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 dy;
|
|
let dy = y2 - y1;
|
|
while(~(Math.abs(dy) = 0)) {
|
|
if (dy > 0) {
|
|
do Screen.drawLine(x1, y1 + dy, x2, y1 + dy);
|
|
let dy = dy - 1;
|
|
} else {
|
|
do Screen.drawLine(x1, y1 + dy, x2, y1 + dy);
|
|
let dy = dy + 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;
|
|
let dy = -r;
|
|
if (r > 181) {
|
|
return;
|
|
}
|
|
while(dy < (r + 1)) {
|
|
do Screen.drawLine(x-Math.sqrt((r*r)-(dy*dy)),y + dy,x+Math.sqrt((r*r)-(dy*dy)),y + dy);
|
|
let dy = dy + 1;
|
|
}
|
|
return;
|
|
}
|
|
}
|