3#include "../../lib/base/generic.h" 
    4#include "../../lib/base/memory.h" 
    5#include "../../lib/base/syscall.h" 
    7#include "../kernel/interruption_tables.h" 
   12#define REG_SCREEN_CTRL 0x3d4 
   13#define REG_SCREEN_DATA 0x3d5 
   15#define VIDEO_MEMORY 0xb8000 
   30static u_dword get_cursor_offset() {
 
   31    port_byte_out(REG_SCREEN_CTRL, 14);
 
   32    u_dword offset = (u_dword) ((port_byte_in(REG_SCREEN_DATA) << 8) & 0xff00);
 
   33    port_byte_out(REG_SCREEN_CTRL, 15);
 
   34    offset += (u_dword) (port_byte_in(REG_SCREEN_DATA) & 0x00ff);
 
   38static void set_cursor_offset(u_dword offset) {
 
   40    port_byte_out(REG_SCREEN_CTRL, 14);
 
   41    port_byte_out(REG_SCREEN_DATA, (
byte) ((offset & 0xff00) >> 8));
 
   42    port_byte_out(REG_SCREEN_CTRL, 15);
 
   43    port_byte_out(REG_SCREEN_DATA, (
byte) (offset & 0x00ff));
 
   47    u_dword offset = get_cursor_offset();
 
   48    return (
screen_coords) {offset % COLS_NUM + 1, offset / COLS_NUM};
 
   52    set_cursor_offset(coords.row * COLS_NUM + coords.column);
 
   57static u_dword scroll (u_dword cursor_offset) {
 
   58    if (cursor_offset < COLS_NUM * ROWS_NUM * 2) 
return cursor_offset;
 
   60    for (
int i = 1; i < ROWS_NUM; ++i) {
 
   61        byte* curr_row = (
byte*) VIDEO_MEMORY + (i * COLS_NUM * 2);
 
   62        byte* prev_row = (
byte*) VIDEO_MEMORY + ((i - 1) * COLS_NUM * 2);
 
   63        memory_copy(curr_row, prev_row, COLS_NUM * 2);
 
   66    byte* last = (
byte*) VIDEO_MEMORY + ((ROWS_NUM - 1) * COLS_NUM * 2);
 
   67    u_word sample = (BLACK << 12u) + (LIGHT_GRAY << 8u) + 
' ';
 
   68    memory_fill(last, (
byte *) &sample, 2, COLS_NUM);
 
   69    cursor_offset -= COLS_NUM * 2;
 
   76void print_char_color (
char c, 
byte text_color, 
byte back_color) {
 
   77    byte attributes = (back_color << 4u) + text_color;
 
   78    byte* vm = (
byte*) VIDEO_MEMORY;
 
   79    u_dword mem_offset = get_cursor_offset() * 2;
 
   82        u_dword rows = (mem_offset / 2) / COLS_NUM + 1;
 
   83        mem_offset = 2 * COLS_NUM * rows - 2;
 
   84    } 
else if (c == 
'\b') {
 
   87        vm[mem_offset + 1] = attributes;
 
   89    } 
else if (c == 
'\t') {
 
   90        for (
int i = 0; i < 4; ++i) {
 
   91            vm[mem_offset + (2 * i)] = 
' ';
 
   92            vm[mem_offset + (2 * i) + 1] = attributes;
 
   97        vm[mem_offset + 1] = attributes;
 
  101    mem_offset = scroll(mem_offset);
 
  102    set_cursor_offset(mem_offset / 2);
 
  106    byte* vm = (
byte*) VIDEO_MEMORY;
 
  107    return vm[coords.row * coords.column];
 
  112extern void print_string_color(
string str, 
byte text_color, 
byte back_color, u_dword length) {
 
  113    if (length == 0) 
for (
int i = 0; str[i] != 0; ++i) print_char_color(str[i], text_color, back_color);
 
  114    else for (
int i = 0; i < length; ++i) print_char_color(str[i], text_color, back_color);
 
  120    u_word sample = (BLACK << 12) + (LIGHT_GRAY << 8) + 
' ';
 
  121    memory_fill((
byte*) VIDEO_MEMORY, (
byte *) &sample, 2, COLS_NUM * ROWS_NUM);
 
  128    GET_CHAR = 0, SET_CHAR = 1, SET_CHARS = 2, GET_CURSOR = 3, SET_CURSOR = 4, CLEAR_SCREEN = 5
 
  131static void screen_callback(
registers* regs) {
 
  132    u_dword call_type, ret_value = 0;
 
  133    system_get_arg(regs->ebp, 0, call_type)
 
  140            u_dword character, front_color, back_color;
 
  141            system_get_arg(regs->ebp, 1, character)
 
  142            system_get_arg(regs->ebp, 2, front_color)
 
  143            system_get_arg(regs->ebp, 3, back_color)
 
  144            print_char_color(character, front_color, back_color);
 
  148            u_dword str, front_color, back_color, length;
 
  149            system_get_arg(regs->ebp, 1, str)
 
  150            system_get_arg(regs->ebp, 2, front_color)
 
  151            system_get_arg(regs->ebp, 3, back_color)
 
  152            system_get_arg(regs->ebp, 4, length)
 
  153            print_string_color((mod_string) str, front_color, back_color, length);
 
  156            ret_value = get_cursor_offset();
 
  161            system_get_arg(regs->ebp, 1, offset)
 
  162            set_cursor_offset(offset);
 
  171    system_push(regs->ebp, ret_value)
 
  176void init_screen_io() {
 
  177    set_interrupt_handler(48, screen_callback);