feat(vga): properly handle and multiple subsequent VGA.puts
+ 134
- 137
@@ -8,75 +8,74 @@ global show_cursor
 
 ; Inputs: rdi = row, rsi = col
 set_cursor_pos:
-    push    ebp
-    mov     ebp, esp
-
-    mov     eax, dword [ebp + 8]    ; eax = row
-    mov     ebx, 80
-    imul    eax, ebx                ; eax = row * 80
-    add     eax, dword [ebp + 12]   ; eax += col
-    mov     bx, ax                  ; bx = position (16-bit)
-
-    ; outb(0x3D4, 0x0E);
-    mov     dx, 0x3D4
-    mov     al, 0x0E
-    out     dx, al
-
-    ; outb(0x3D5, (position >> 8) & 0xFF);
-    mov     dx, 0x3D5
-    mov     al, bh
-    out     dx, al
-
-    ; outb(0x3D4, 0x0F);
-    mov     dx, 0x3D4
-    mov     al, 0x0F
-    out     dx, al
-
-    ; outb(0x3D5, position & 0xFF);
-    mov     dx, 0x3D5
-    mov     al, bl
-    out     dx, al
-
-    mov     esp, ebp
-    pop     ebp
-    ret
+  push    ebp
+  mov     ebp, esp
+
+  mov     eax, dword [ebp + 8]    ; eax = row
+  mov     ebx, 80
+  imul    eax, ebx                ; eax = row * 80
+  add     eax, dword [ebp + 12]   ; eax += col
+  mov     bx, ax                  ; bx = position (16-bit)
+
+  ; outb(0x3D4, 0x0E);
+  mov     dx, 0x3D4
+  mov     al, 0x0E
+  out     dx, al
+
+  ; outb(0x3D5, (position >> 8) & 0xFF);
+  mov     dx, 0x3D5
+  mov     al, bh
+  out     dx, al
+
+  ; outb(0x3D4, 0x0F);
+  mov     dx, 0x3D4
+  mov     al, 0x0F
+  out     dx, al
+
+  ; outb(0x3D5, position & 0xFF);
+  mov     dx, 0x3D5
+  mov     al, bl
+  out     dx, al
+
+  mov     esp, ebp
+  pop     ebp
+  ret
 
 ; void hide_cursor(void)
 hide_cursor:
-    ; Read: write index 0x0A, then write data with bit 5 set
-    ; For simplicity we don't read current value; we set start = 0x20 (disabled)
-    mov     dx, 0x3D4
-    mov     al, 0x0A
-    out     dx, al
+  ; Read: write index 0x0A, then write data with bit 5 set
+  ; For simplicity we don't read current value; we set start = 0x20 (disabled)
+  mov     dx, 0x3D4
+  mov     al, 0x0A
+  out     dx, al
 
-    mov     dx, 0x3D5
-    mov     al, 0x20    ; set bit 5 to disable cursor
-    out     dx, al
+  mov     dx, 0x3D5
+  mov     al, 0x20   ; set bit 5 to disable cursor
+  out     dx, al
 
-    ret
+  ret
 
 ; void show_cursor(void)
 show_cursor:
-    ; Restore a typical cursor shape: start = 0 (scanline start)
-    mov     dx, 0x3D4
-    mov     al, 0x0A
-    out     dx, al
+  ; Restore a typical cursor shape: start = 0 (scanline start)
+  mov     dx, 0x3D4
+  mov     al, 0x0A
+  out     dx, al
 
-    mov     dx, 0x3D5
-    mov     al, 0x00    ; cursor start = 0
-    out     dx, al
+  mov     dx, 0x3D5
+  mov     al, 0x00    ; cursor start = 0
+  out     dx, al
 
-    ; set cursor end (e.g., 15)
-    mov     dx, 0x3D4
-    mov     al, 0x0B
-    out     dx, al
+  ; set cursor end (e.g., 15)
+  mov     dx, 0x3D4
+  mov     al, 0x0B
+  out     dx, al
 
-    mov     dx, 0x3D5
-    mov     al, 0x0F    ; cursor end = 15 (typical)
-    out     dx, al
-
-    ret
+  mov     dx, 0x3D5
+  mov     al, 0x0F  ; cursor end = 15 (typical)
+  out     dx, al
 
+  ret
 
 section .entry
 

@@ -23,16 +23,17 @@ fun kmain
   VGA.init
 
   VGA.puts(
-    "[CrystalOS Kernel] Hello from Crystal.",
-    VGA::Colors::BLACK_ON_CYAN,
+    "[CrystalOS Kernel] Hello from Crystal.\n",
+    color: VGA::Colors::BLACK_ON_CYAN,
   )
-  VGA.puts("\n")
-  VGA.puts("Hello world!\n\nWorks maybe?\n", line: 1)
-  VGA.puts("Can print on multiple lines\n", line: 2, color: VGA::Colors::BLACK_ON_LIME)
-  VGA.puts("But because we don't have a Heap, we need to set lines number in puts call for now...\n", line: 3)
-  
-  VGA.set_cursor(5, 4)
-  VGA.hide_cursor
+  VGA.puts("weeeeeeee\n")
+
+  VGA.puts("Hello world!\n \nWorks maybe?\n")
+  VGA.puts("Can print on multiple lines\n", color: VGA::Colors::BLACK_ON_LIME)
+  VGA.puts("\n\nWe still don't have a heap, but now the puts stores the last row and col so it can call the putchar method with the right col / row instead of overlaying subsequent calls on-top one of another (this is super long line to test word wrap).\n")
+
+  # VGA.set_cursor(0, 5)
+  # VGA.hide_cursor
 
   while true
     asm (%(hlt))

@@ -1,5 +1,5 @@
+# Definitions from kernel/entry.asm
 lib KernelShim
-  # Definition in kernel/entry.asm
   fun hide_cursor()
   fun show_cursor()
   fun set_cursor_pos(

...
@@ -9,33 +9,11 @@ lib KernelShim
 end
 
 struct VGACursor
-  col : Int32 = 0
-  row : Int32 = 0
+  @col : Int32 = 0
+  property col
   
-  def initialize
-    @col = 0
-    @row = 0
-  end
-  
-  def col : Int32
-    @col
-  end
-  def col=(c : Int32)
-    @col = c
-  end
-  def col_incr(c : Int32)
-    @col += c
-  end
-  
-  def row : Int32
-    @row
-  end
-  def row=(r : Int32)
-    @row = r
-  end
-  def row_incr(r : Int32)
-    @row += r
-  end
+  @row : Int32 = 0
+  property row
 end
 
 module VGA

...
@@ -73,8 +51,8 @@ module VGA
       (VGA_BUFFER + (i * 2) + 1).value = Colors::DEFAULT
       i += 1
     end
-    VGA_CURSOR.col = 0
-    VGA_CURSOR.row = 0
+    col = 0
+    row = 0
   end
   
   # Hide cursor

...
@@ -90,60 +68,79 @@ module VGA
   # Set typing cursor position
   def self.set_cursor(
     col : Int32,
-    row : Int32
+    next_row : Int32
   ) : Nil
     KernelShim
-      .set_cursor_pos(row.to_u32, col.to_u32)
+      .set_cursor_pos(next_row.to_u32, col.to_u32)
+    @@row = next_row
   end
   
+  @@puts_count = 0
+  property puts_count
+  
+  @@col = 0
+  class_property col
+  
+  @@row = 0
+  class_property row
+  
   # Write a single character to the current cursor position
   def self.putchar(
-      ch : UInt8,
-      i : Int32? = 0,
-      line : Int32? = 0,
-      color : UInt8? = Colors::DEFAULT
+    ch : UInt8,
+    i : Int32? = 0,
+    line : Int32? = 0,
+    color : UInt8? = Colors::DEFAULT
   ) : Nil
-      VGA_CURSOR.col = i
-      VGA_CURSOR.row = line
-  
-      if ch == 0x0A_u8 # \n (not working...)
-       # VGA_CURSOR.col = 0
-        VGA_CURSOR.row += 1
-        if VGA_CURSOR.row >= VGA_HEIGHT
-          VGA_CURSOR.row = VGA_HEIGHT - 1
-        end
-        ch = " ".to_unsafe.value
+    @@col ||= i || 0
+    @@row ||= line || 0
+
+    # somehow doesn't work...
+    if ch == 0x0A_u8 # \n handler
+      @@col = 0
+      @@row += 1
+      if @@row >= VGA_HEIGHT
+        @@row = VGA_HEIGHT - 1
       end
-  
-      offset = (VGA_CURSOR.row * VGA_WIDTH + VGA_CURSOR.col) * 2
-  
-      (VGA_BUFFER + offset).value = ch
-      (VGA_BUFFER + offset + 1).value = color
-  
-      VGA_CURSOR.col += 1
-  
-      #  Wrap around if past screen
-      if VGA_CURSOR.col >= VGA_WIDTH
-        VGA_CURSOR.col = 0
-        VGA_CURSOR.row += 1
-        if VGA_CURSOR.row >= VGA_HEIGHT
-          VGA_CURSOR.row = VGA_HEIGHT - 1
-        end
+    end
+
+    offset = (@@row * VGA_WIDTH + @@col) * 2
+
+    (VGA_BUFFER + offset).value = ch
+    (VGA_BUFFER + offset + 1).value = color
+
+    @@col += 1
+
+    #  Wrap around if past screen
+    if @@col >= VGA_WIDTH
+      @@col = 0
+      @@row += 1
+      if @@row >= VGA_HEIGHT
+        @@row = VGA_HEIGHT - 1
       end
     end
-  
-    # Write a string to VGA
-    def self.puts(
-      str : String,
-      color : UInt8? = Colors::DEFAULT,
-      line : Int32? = 0,
-    ) : Nil
-      i = 0
-      while i < str.size - 1
-        ch = (str.to_unsafe + i).value
-        putchar(ch, i, line, color)
+  end
+
+  # Write a string to VGA
+  def self.puts(
+    str : String,
+    color : UInt8? = Colors::DEFAULT,
+    line : Int32? = nil,
+  ) : Nil
+    i = 0
+    @@row ||= (line || 0)
+    while i < str.size
+      ch = (str.to_unsafe + i).value
+      if ch == 0x0A_u8
+        @@row += 1
+        @@col = 0
         i += 1
+        next
       end
+      putchar(ch, i, @@row, color)
+      i += 1
     end
+    
+    VGA.set_cursor(0, @@row)
+  end
 
 end