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);