diff --git a/12/Keyboard.jack b/12/Keyboard.jack index 9141b5f..4d5f310 100644 --- a/12/Keyboard.jack +++ b/12/Keyboard.jack @@ -10,7 +10,7 @@ class Keyboard { /** Initializes the keyboard. */ function void init() { return; - } + } /** * Returns the character of the currently pressed key on the keyboard; @@ -37,35 +37,30 @@ class Keyboard { } /** Waits until a key is pressed on the keyboard and released, - * then echoes the key to the screen, and returns the character + * then echoes the key to the screen, and returns the character * of the pressed key. */ function char readChar() { var char key; - + // Wait for key press while (Keyboard.keyPressed() = 0) {} - + let key = Keyboard.keyPressed(); - + // Wait for release while (~(Keyboard.keyPressed() = 0)) {} - + // Echo (except backspace) if (key < 129) { // Handle newline specially for cleaner output? - // Output.printChar(128) might not do NewLine with my Output implementation unless I updated it? - // My Output implementation (Step 240) does NOT check for 128. - // So I should call println() if 128. if (key = 128) { do Output.println(); } else { do Output.printChar(key); } } - // If key > 129 (arrows etc), printChar might print garbage or square. - // Spec usually implies echoing everything or being selective. - // I'll stick to echoing only standard chars + newline. - + // If key > 129 (arrows etc), printChar might print garbage or square. + return key; } @@ -75,24 +70,24 @@ class Keyboard { function String readLine(String message) { var String s; var char c; - + do Output.printString(message); let s = String.new(64); // Assume max line 64 - + while (true) { let c = Keyboard.readChar(); - + if (c = 128) { // Newline do Output.println(); return s; } - + if (c = 129) { // Backspace if (s.length() > 0) { do s.eraseLastChar(); do Output.backSpace(); // Erase not supported by Output, so we print space and back up again? - // But printChar sends cursor forward. + // But printChar sends cursor forward. // To visually erase: Backspace (move left), Print Space (overwrite, move right), Backspace (move left). // My output implementation doesn't support 'erasing' naturally. // But this trick works. @@ -104,7 +99,7 @@ class Keyboard { } } return s; - } + } /** Displays the message on the screen, reads from the keyboard the entered * text until a newline character is detected, echoes the text to the screen, @@ -113,11 +108,11 @@ class Keyboard { function int readInt(String message) { var String s; var int val; - + let s = Keyboard.readLine(message); let val = s.intValue(); do s.dispose(); - + return val; } } diff --git a/12/Output.jack b/12/Output.jack index 83c8251..745ebcc 100644 --- a/12/Output.jack +++ b/12/Output.jack @@ -5,18 +5,18 @@ /** * A library of functions for writing text on the screen. * The Hack physical screen consists of 512 rows of 256 pixels each. - * The library uses a fixed font, in which each character is displayed - * within a frame which is 11 pixels high (including 1 pixel for inter-line + * The library uses a fixed font, in which each character is displayed + * within a frame which is 11 pixels high (including 1 pixel for inter-line * spacing) and 8 pixels wide (including 2 pixels for inter-character spacing). * The resulting grid accommodates 23 rows (indexed 0..22, top to bottom) - * of 64 characters each (indexed 0..63, left to right). The top left + * of 64 characters each (indexed 0..63, left to right). The top left * character position on the screen is indexed (0,0). A cursor, implemented * as a small filled square, indicates where the next character will be displayed. */ class Output { // Character map for displaying characters - static Array charMaps; + static Array charMaps; static int cursorRow, cursorCol; /** Initializes the screen, and locates the cursor at the screen's top-left. */ @@ -29,9 +29,9 @@ class Output { // Initializes the character map array function void initMap() { var int i; - + let charMaps = Array.new(127); - + // Black square, used for displaying non-printable characters. do Output.create(0,63,63,63,63,63,63,63,63,63,0,0); @@ -52,9 +52,9 @@ class Output { do Output.create(43,0,0,0,12,12,63,12,12,0,0,0); // + do Output.create(44,0,0,0,0,0,0,0,12,12,6,0); // , do Output.create(45,0,0,0,0,0,63,0,0,0,0,0); // - - do Output.create(46,0,0,0,0,0,0,0,12,12,0,0); // . + do Output.create(46,0,0,0,0,0,0,0,12,12,0,0); // . do Output.create(47,0,0,32,48,24,12,6,3,1,0,0); // / - + do Output.create(48,12,30,51,51,51,51,51,30,12,0,0); // 0 do Output.create(49,12,14,15,12,12,12,12,12,63,0,0); // 1 do Output.create(50,30,51,48,24,12,6,3,51,63,0,0); // 2 @@ -65,7 +65,7 @@ class Output { do Output.create(55,63,49,48,48,24,12,12,12,12,0,0); // 7 do Output.create(56,30,51,51,51,30,51,51,51,30,0,0); // 8 do Output.create(57,30,51,51,51,62,48,48,24,14,0,0); // 9 - + do Output.create(58,0,0,12,12,0,0,12,12,0,0,0); // : do Output.create(59,0,0,12,12,0,0,12,12,6,0,0); // ; do Output.create(60,0,0,24,12,6,3,6,12,24,0,0); // < @@ -132,7 +132,7 @@ class Output { do Output.create(120,0,0,0,51,30,12,12,30,51,0,0); // x do Output.create(121,0,0,0,51,51,51,62,48,24,15,0); // y do Output.create(122,0,0,0,63,27,12,6,51,63,0,0); // z - + do Output.create(123,56,12,12,12,7,12,12,12,56,0,0); // { do Output.create(124,12,12,12,12,12,12,12,12,12,0,0); // | do Output.create(125,7,12,12,12,56,12,12,12,7,0,0); // } @@ -163,7 +163,7 @@ class Output { return; } - + // Returns the character map (array of size 11) of the given character. // If the given character is invalid or non-printable, returns the // character map of a black square. @@ -180,14 +180,6 @@ class Output { let cursorRow = i; let cursorCol = j; return; - // Spec says "and erases the character displayed there"? - // Usually moveCursor just moves it. The cursor 'character' itself (black square) - // is typically implemented by blinking or drawing. - // Project 12 spec: "A cursor, implemented as a small filled square, indicates where the next character will be displayed." - // And "erases the character displayed there"? Maybe erases the *cursor* from old location? - // Or erases the *content*? "Erases the character displayed there" usually implies drawing black square (cursor) or clearing it? - // Wait, standard implementation usually just updates coordinates. - // I will assume simple update. } /** Displays the given character at the cursor location, @@ -195,18 +187,18 @@ class Output { function void printChar(char c) { var Array map; var int i, val, address; - + let map = Output.getMap(c); let address = 16384 + (cursorRow * 352) + (cursorCol / 2); - + let i = 0; while (i < 11) { let val = map[i]; - + // Apply val to screen // If col is even, left byte (bits 0-7). If odd, right byte (8-15). // LSB is left. - + if ((cursorCol & 1) = 0) { // Even col // Mask out low byte (0x00FF), keep high byte // Keep high byte: value & -256 (0xFF00) @@ -218,12 +210,12 @@ class Output { // Set high byte: val << 8 let val = (Memory.peek(address + (i * 32)) & 255) | (val * 256); } - + do Memory.poke(address + (i * 32), val); - + let i = i + 1; } - + // Advance cursor let cursorCol = cursorCol + 1; if (cursorCol > 63) { @@ -233,7 +225,7 @@ class Output { let cursorRow = 0; // Wrap to top? } } - + return; } diff --git a/12/Screen.jack b/12/Screen.jack index 4516e08..1b7f3eb 100644 --- a/12/Screen.jack +++ b/12/Screen.jack @@ -5,13 +5,13 @@ /** * 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 + * 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; static Array powersOfTwo; // Helper for bit manipulation - + /** Initializes the Screen. */ function void init() { let color = true; // Default black @@ -57,20 +57,19 @@ class Screen { function void drawPixel(int x, int y) { var int address, value; var int mask; - + let address = 16384 + (y * 32) + (x / 16); let value = Memory.peek(address); - - // Calculate 2^(x%16) logic inline or helper? + // x & 15 is x % 16 - let mask = powersOfTwo[x & 15]; - + let mask = powersOfTwo[x & 15]; + if (color) { let value = value | mask; } else { let value = value & ~mask; } - + do Memory.poke(address, value); return; } @@ -81,7 +80,7 @@ class Screen { var int a, b; var int diff; var int temp; - + if (x1 > x2) { let temp = x1; let x1 = x2; @@ -90,13 +89,13 @@ class Screen { let y1 = y2; let y2 = temp; } - + let dx = x2 - x1; let dy = y2 - y1; let a = 0; let b = 0; let diff = 0; - + // Vertical line if (dx = 0) { if (y1 > y2) { @@ -110,7 +109,7 @@ class Screen { } return; } - + // Horizontal line if (dy = 0) { while (~(x1 > x2)) { @@ -119,7 +118,7 @@ class Screen { } return; } - + // Diagonal if (dy > 0) { while ((~(a > dx)) & (~(b > dy))) { @@ -144,7 +143,7 @@ class Screen { } } } - + return; } @@ -165,14 +164,14 @@ class Screen { var int dy; var int r2; var int halfWidth; - + if (r > 181) { return; // overflow check } - + let dy = -r; let r2 = r*r; - + while (~(dy > r)) { let halfWidth = Math.sqrt(r2 - (dy*dy)); do Screen.drawLine(x - halfWidth, y + dy, x + halfWidth, y + dy); diff --git a/12/String.jack b/12/String.jack index 9e6b2c7..77181c4 100644 --- a/12/String.jack +++ b/12/String.jack @@ -19,10 +19,6 @@ class String { constructor String new(int maxLength) { if (maxLength = 0) { let maxLength = 1; // min length 1 for alloc safety? - // Actually spec says allocation of 0 size might happen. - // My Array.new -> Memory.alloc handles 0 size by returning a 1 word block (header-1?? No). - // Let's alloc 0 if needed. - // If maxLength is 0, we can't really store anything. } if (maxLength > 0) { let buffer = Array.new(maxLength); @@ -74,23 +70,23 @@ class String { return; } - /** Returns the integer value of this string, + /** Returns the integer value of this string, * until a non-digit character is detected. */ method int intValue() { var int val, i, d; var boolean neg; - + let val = 0; let i = 0; let neg = false; - + if (length > 0) { if (buffer[0] = 45) { // '-' let neg = true; let i = 1; } } - + while (i < length) { let d = buffer[i] - 48; // '0' is 48 if ((d > -1) & (d < 10)) { @@ -100,7 +96,7 @@ class String { let i = length; // break } } - + if (neg) { return -val; } @@ -110,24 +106,24 @@ class String { /** Sets this string to hold a representation of the given value. */ method void setInt(int val) { let length = 0; // Clear string - + if (val < 0) { let val = -val; do appendChar(45); // '-' } - + do int2String(val); return; } - + // Helper for recursive int printing method void int2String(int val) { var int lastDigit; var int c; - + let lastDigit = val - ((val / 10) * 10); // val % 10 let c = lastDigit + 48; - + if (val < 10) { do appendChar(c); } else { diff --git a/12/Sys.jack b/12/Sys.jack index 675997e..e2c3ba8 100644 --- a/12/Sys.jack +++ b/12/Sys.jack @@ -10,8 +10,11 @@ class Sys { /** Performs all the initializations required by the OS. */ function void init() { + // do Memory.poke(8000, 1); // Start do Memory.init(); + // do Memory.poke(8000, 2); // Mem init done do Math.init(); + // do Memory.poke(8000, 3); // Math init done do Screen.init(); do Output.init(); do Keyboard.init(); @@ -35,10 +38,8 @@ class Sys { let j = 0; // Calibration: loop count determines delay. // On typical VM emulator settings (Fast), ~50-100 loops might be 1ms? - // User requested 2 seconds wait in test. // "WaitWithInput" sample in Snake used loop for waiting. - // Standard N2T value is roughly 50-100. while (j < 50) { let j = j + 1; }