summaryrefslogblamecommitdiff
path: root/jackos/Screen.jack
blob: a370ab976467ace1bc33068f57fd9379ddeb6e69 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                                 


                           


                                   









                                      
                          
                



                                     


                           
                                                 

                       




                                                                                

                       



                                                           










                                                                      
                                                                                

                



                                                                                      
                                          

                    
                                   


























                                         
                                       
          
                




                                                                       
                   




                                     

                                              

                



                                                                                         

                            

                                                              





                                                
                                                                


                             

      
// 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 Array screen;
    static boolean color;

    /** Initializes the Screen. */
    function void init() {
        var int i, x;
        let x = 1;
        let i = 0;
        let twoToThe = Array.new(16);
        while (i < 16){
            let twoToThe[i] = x;
            let x = x + x;
            let i = i + 1;
        }
        let screen = 16384;
        let color = true;
        return;
    }

    /** Erases the entire screen. */
    function void clearScreen() {
        var boolean c;
        let c = color;
        let color = false;
        do Screen.drawRectangle(0, 0, 511, 255);
        let color = c;
        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 addr, t;
        if ((x < 0) | (y < 0) | (x > 511) | (y > 255)) {
            //String.println("drawPixel: coordinates out of range!");
            //Sys.error(2);
            return;
        }
        let t = x / 16;
        let addr = 32 * y + t;
        if (color) {
            let screen[addr] = screen[addr] | twoToThe[x - (t * 16)];
        } else {
            let screen[addr] = screen[addr] & (- (twoToThe[x - (t * 16)] + 1));
        }
        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, x, y, a, b, diff;
        let x = x1;
        let y = y1;
        do Screen.drawPixel(x, y);
        if (x1 = x2) {
            if (y1 = y2) {
                return;
            } else {
                let diff = 1;
            }
        } else {
            if (y1 = y2) {
                let diff = -1;
            } else {
                let diff = 0;
            }
        }
        let dx = x2 - x1;
        let dy = y2 - y1;
        let a = Math.sign(dx);
        let b = Math.sign(dy);
        let dx = Math.abs(dx);
        let dy = Math.abs(dy);
        while (~((x = x2) & (y = y2))) {
            if (diff < 0){
                let x = x + a;
                let diff = diff + dy;
            } else {
                let y = y + b;
                let diff = diff - dx;
            }
            do Screen.drawPixel(x, y);
        }
        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 x;
        if ((x1 > x2) | (y1 > y2)) {
            return;
        }
        let x = x1;
        while (~(x > x2)) {
            do Screen.drawLine(x, y1, x, y2);
            let x = x + 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, r2;
        if (r > 181) {
            do String.println("drawCircle: radius too big!");
            do Sys.error(2);
            return;
        }
        let dy = -r;
        let r2 = r * r;
        while (~(dy > r)) {
            let dx = Math.sqrt(r2 - (dy * dy));
            do Screen.drawLine(x - dx, y + dy, x + dx, y + dy);
            let dy = dy + 1;
        }
        return;
    }
}