-
Notifications
You must be signed in to change notification settings - Fork 0
/
Screen.jack
143 lines (132 loc) · 3.44 KB
/
Screen.jack
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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/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 int baseMem, rowTotal, colTotal;
static boolean color;
static Array twoToThe;
/** Initializes the Screen. */
function void init() {
var int i, twoToI;
let twoToThe = Array.new(16);
let i = 0;
let twoToI = 1;
while (i < 16) {
let twoToThe[i] = twoToI;
let twoToI = twoToI + twoToI;
let i = i + 1;
}
let baseMem = 16384;
let rowTotal = 256;
let colTotal = 512;
let color = true;
do Screen.clearScreen();
return;
}
/** Erases the entire screen. */
function void clearScreen() {
var int i, j;
let i = 0;
let j = 0;
while (i < 256) {
let j = 0;
while (j < 32) {
do Memory.poke(baseMem + (32 * i) + j, 0);
let j = j + 1;
}
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 color = b;
return;
}
/** Draws the (x,y) pixel, using the current color. */
function void drawPixel(int x, int y) {
var int rel, cur;
let rel = y * 32 + (x / 16);
let cur = Memory.peek(baseMem + rel);
if (color) {
do Memory.poke(baseMem + rel, cur | twoToThe[x - ((x / 16) * 16)]);
} else {
do Memory.poke(baseMem + rel, cur & ~(twoToThe[x - ((x / 16) * 16)]));
}
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, dx, dy, adyMinusbdx, da, db;
let a = 0;
let b = 0;
let dx = x2 - x1;
let dy = y2 - y1;
let adyMinusbdx = 0;
if (dx > 0) {
let da = 1;
} else {
let da = -1;
}
if (dy > 0) {
let db = 1;
} else {
let db = -1;
}
if (dx = 0) { // Draw a vertical line
while (Math.abs(b) < (Math.abs(dy) + 1)) {
do Screen.drawPixel(x1, y1 + b);
let b = b + db;
}
return;
}
if (dy = 0) { // Draw a horizontal line
while (Math.abs(a) < (Math.abs(dx) + 1)) {
do Screen.drawPixel(x1 + a, y1);
let a = a + da;
}
return;
}
while ((Math.abs(a) < (Math.abs(dx) + 1)) & (Math.abs(b) < (Math.abs(dy) + 1))) {
do Screen.drawPixel(x1 + a, y1 + b);
if (adyMinusbdx < 0) {
let a = a + da;
let adyMinusbdx = adyMinusbdx + Math.abs(dy);
} else {
let b = b + db;
let adyMinusbdx = adyMinusbdx - 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 b;
let b = y1;
while (b < (y2 + 1)) {
do Screen.drawLine(x1, b, x2, b);
let b = b + 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 dx, dy;
let dy = -r;
while (dy < (r + 1)) {
let dx = Math.sqrt((r * r) - (dy * dy));
do Screen.drawLine(x - dx, y + dy, x + dx, y + dy);
let dy = dy + 1;
}
return;
}
}