~src/kernel/kernel.cr
.cr
Crystal
(text/x-crystal)
require "./vga.cr"
require "./tiny_alloc_i386.cr"
require "./irq.cr"
require "./timer.cr"
# require "./pmm.cr"

CRYSTAL_OS_MAGIC = "123113371338".to_unsafe

lib KernelShim
  @[Packed]
  struct StartInfo
    multiboot_ptr : UInt32
    end_of_kernel : UInt32
  end
  
  fun crystalOSMagic   : UInt8
  fun crystalOSVersion : UInt8
  
  fun kernelBssBlockStart : UInt64
  fun kernelBssBlockEnd   : UInt64
end

fun kearly(info_ptr: KernelShim::StartInfo*)
  VGA.init

  # Get the startup info
  info = info_ptr.value
  
  # VGA.debug_print info
end

fun kmain
  # todo: troubelshoot Pointer compare
  # magic = KernelShim.crystalOSMagic.value
  # if magic != CRYSTAL_OS_MAGIC.value
  #   while (1)
  #   end
  #   return
  # end
  
  # Zeroes the BSS block
  # kernel_bss_block_size = (KernelShim.kernelBssBlockEnd.to_u64 - KernelShim.kernelBssBlockStart.to_u64).to_u32
  # ptr = Pointer(UInt8).new(KernelShim.kernelBssBlockStart)
  # i = 0
  # while i < kernel_bss_block_size
  #   ptr[i] = 0_u8
  #   i += 1
  # end

  # Init VGA (+ module demo)
  VGA.puts(
    "[CrystalOS Kernel] Hello from Crystal.\n",
    color: VGA::Colors::BLACK_ON_LIME,
  )
  # puts KernelShim.crystalOSVersion
  # PMM.init # Physical Memory Init
  TinyAllocI386.init
  IRQ.init
  Timer.init
  # Net.init
  # PS2.init
  # Audio.init
  # Display.init
  # WM.init

  puts("weeeeeeee\n")
  VGA.puts("Can print on multiple lines\n", color: VGA::Colors::BLACK_ON_LIME)
  VGA.puts("\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 \x1b[32mright\x1b[0m col / row instead of overlaying subsequent calls on-top one of another (this is super long line to test word wrap).\n")
  VGA.puts "\nFeatures:\n"
  VGA.puts("\tIt supports \\t char at start\taswell as in text.\n\tIt supports \\n char at end aswell as in text.\n")
  VGA.puts "\t"
  VGA.puts "It support writing on same line"
  VGA.puts " "
  VGA.puts "(YAY)", VGA::Colors::GREEN_ON_WHITE
  VGA.puts "\n"
  VGA.puts("\tCan use custom colors", VGA::Colors::RED_ON_BLACK)
  VGA.puts("\tCan use another custom color\n", VGA::Colors::GREEN_ON_BLACK)
  VGA.puts("\tCan use lot of custom color\n", VGA::Colors::CYAN_ON_BLACK)
  
  puts "\nPress [enter] to boot into graphical mode\n\n"
  
  IRQ.register(0, ->(data : UInt8) {
    puts "timer handler called ...\n"
    Timer.irq_handler(data)
    return
  })
  
  IRQ.register(1, ->(scan_code : UInt8) {
    puts "keyboard handler called ...\n"
    if scan_code == 0x1C
      puts "Enter\n"
    end
    return
  })

  # VGA.set_cursor(0, 5)
  # VGA.hide_cursor
  
  # asm (%(sti))

  while true
    asm (%(hlt))
  end
end