Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
|
start [2025/12/06 09:45] jango |
start [2025/12/10 10:09] (aktuell) jango |
||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | < | ||
| - | #include " | ||
| - | #include " | ||
| - | #include " | ||
| - | #include " | ||
| - | |||
| - | // Keyboard I/O | ||
| - | #define KBD_DATA | ||
| - | #define KBD_STATUS 0x64 | ||
| - | |||
| - | // Cursor ports | ||
| - | #define VGA_CRTC_INDEX 0x3D4 | ||
| - | #define VGA_CRTC_DATA | ||
| - | |||
| - | #define VGA_W 80 | ||
| - | #define VGA_H (BUFSIZE / VGA_W) | ||
| - | |||
| - | uint32 vga_index; | ||
| - | static uint32 next_line_index = 1; | ||
| - | uint8 g_fore_color = WHITE, g_back_color = BLUE; | ||
| - | |||
| - | char str[128] = {0}; | ||
| - | int strc = 0; | ||
| - | |||
| - | uint8 inb(uint16 port) | ||
| - | { | ||
| - | uint8 ret; | ||
| - | asm volatile(" | ||
| - | return ret; | ||
| - | } | ||
| - | |||
| - | void outb(uint16 port, uint8 data) | ||
| - | { | ||
| - | asm volatile(" | ||
| - | } | ||
| - | |||
| - | static inline uint8 kbd_has_data(void) | ||
| - | { | ||
| - | return (inb(KBD_STATUS) & 0x01); | ||
| - | } | ||
| - | |||
| - | static inline uint8 kbd_read_data(void) | ||
| - | { | ||
| - | return inb(KBD_DATA); | ||
| - | } | ||
| - | |||
| - | // ---- tiny I/O wait (optional but useful) ---- | ||
| - | static inline void io_wait(void) | ||
| - | { | ||
| - | // klassischer "I/O wait" port | ||
| - | asm volatile ("outb %0, %1" : : " | ||
| - | } | ||
| - | |||
| - | // --- repeat filter state --- | ||
| - | static uint8 key_down[128] = {0}; | ||
| - | static uint8 e0_prefix = 0; | ||
| - | |||
| - | // returns 1 if a NEW key press (make) should be processed, else 0 | ||
| - | int get_keycode_once(uint8 *out_scancode) | ||
| - | { | ||
| - | if (!kbd_has_data()) return 0; | ||
| - | |||
| - | uint8 sc = kbd_read_data(); | ||
| - | |||
| - | // Extended prefix | ||
| - | if (sc == 0xE0) { e0_prefix = 1; return 0; } | ||
| - | |||
| - | // If we currently don't support E0 keys: discard next byte cleanly | ||
| - | if (e0_prefix) { e0_prefix = 0; return 0; } | ||
| - | |||
| - | // Break (release) | ||
| - | if (sc & 0x80) { | ||
| - | uint8 make = sc & 0x7F; | ||
| - | if (make < 128) key_down[make] = 0; | ||
| - | return 0; | ||
| - | } | ||
| - | |||
| - | // Make (press) - suppress repeats | ||
| - | if (sc < 128) { | ||
| - | if (key_down[sc]) return 0; // typematic repeat ignore | ||
| - | key_down[sc] = 1; | ||
| - | } | ||
| - | |||
| - | *out_scancode = sc; | ||
| - | return 1; | ||
| - | } | ||
| - | |||
| - | static inline void vga_set_cursor(uint16 pos) | ||
| - | { | ||
| - | outb(VGA_CRTC_INDEX, | ||
| - | outb(VGA_CRTC_DATA, | ||
| - | outb(VGA_CRTC_INDEX, | ||
| - | outb(VGA_CRTC_DATA, | ||
| - | } | ||
| - | |||
| - | uint16 vga_entry(unsigned char ch, uint8 fore_color, uint8 back_color) | ||
| - | { | ||
| - | uint16 ax = 0; | ||
| - | uint8 attr = (back_color << 4) | (fore_color & 0x0F); | ||
| - | ax = ((uint16)attr << 8) | (uint16)ch; | ||
| - | return ax; | ||
| - | } | ||
| - | |||
| - | void clear_vga_buffer(uint16 **buffer, uint8 fore_color, uint8 back_color) | ||
| - | { | ||
| - | for (uint32 i = 0; i < BUFSIZE; i++) | ||
| - | (*buffer)[i] = vga_entry(' | ||
| - | |||
| - | next_line_index = 1; | ||
| - | vga_index = 0; | ||
| - | vga_set_cursor((uint16)vga_index); | ||
| - | } | ||
| - | |||
| - | void init_vga(uint8 fore_color, uint8 back_color) | ||
| - | { | ||
| - | vga_buffer = (uint16*)VGA_ADDRESS; | ||
| - | clear_vga_buffer(& | ||
| - | g_fore_color = fore_color; | ||
| - | g_back_color = back_color; | ||
| - | } | ||
| - | |||
| - | // ---- SCROLL statt komplettes Löschen ---- | ||
| - | static void vga_scroll_if_needed(void) | ||
| - | { | ||
| - | if (vga_index < BUFSIZE) return; | ||
| - | |||
| - | // scroll um 1 Zeile nach oben | ||
| - | for (uint32 i = 0; i < (VGA_H - 1) * VGA_W; i++) | ||
| - | vga_buffer[i] = vga_buffer[i + VGA_W]; | ||
| - | |||
| - | // letzte Zeile leeren | ||
| - | for (uint32 i = (VGA_H - 1) * VGA_W; i < VGA_H * VGA_W; i++) | ||
| - | vga_buffer[i] = vga_entry(' | ||
| - | |||
| - | vga_index = (VGA_H - 1) * VGA_W; | ||
| - | } | ||
| - | |||
| - | void print_new_line(void) | ||
| - | { | ||
| - | // auf Zeilenanfang springen | ||
| - | vga_index += VGA_W - (vga_index % VGA_W); | ||
| - | vga_scroll_if_needed(); | ||
| - | vga_set_cursor((uint16)vga_index); | ||
| - | |||
| - | // next_line_index ist jetzt eigentlich optional, aber falls du ihn weiter nutzt: | ||
| - | next_line_index = (vga_index / VGA_W) + 1; | ||
| - | } | ||
| - | |||
| - | void print_char(char ch) | ||
| - | { | ||
| - | if (ch == ' | ||
| - | |||
| - | vga_buffer[vga_index] = vga_entry(ch, | ||
| - | vga_index++; | ||
| - | |||
| - | vga_scroll_if_needed(); | ||
| - | vga_set_cursor((uint16)vga_index); | ||
| - | } | ||
| - | |||
| - | void print_string(char *s) | ||
| - | { | ||
| - | for (uint32 i = 0; s[i]; i++) | ||
| - | print_char(s[i]); | ||
| - | } | ||
| - | |||
| - | // ---- FIX: wait_for_io Underflow bug ---- | ||
| - | void wait_for_io(uint32 timer_count) | ||
| - | { | ||
| - | while (timer_count--) { | ||
| - | asm volatile(" | ||
| - | } | ||
| - | } | ||
| - | |||
| - | void sleep(uint32 timer_count) | ||
| - | { | ||
| - | wait_for_io(timer_count); | ||
| - | } | ||
| - | |||
| - | // ---- kleiner case-insensitive Vergleich ---- | ||
| - | static int streq_ci(const char *a, const char *b) | ||
| - | { | ||
| - | while (*a && *b) { | ||
| - | char ca = *a, cb = *b; | ||
| - | if (ca >= ' | ||
| - | if (cb >= ' | ||
| - | if (ca != cb) return 0; | ||
| - | a++; b++; | ||
| - | } | ||
| - | return (*a == 0 && *b == 0); | ||
| - | } | ||
| - | |||
| - | static void reset_input_line(void) | ||
| - | { | ||
| - | strc = 0; | ||
| - | str[0] = 0; | ||
| - | } | ||
| - | |||
| - | static void append_char(char ch) | ||
| - | { | ||
| - | if (strc >= (int)sizeof(str) - 1) return; // bounds check | ||
| - | str[strc++] = ch; | ||
| - | str[strc] = 0; | ||
| - | print_char(ch); | ||
| - | } | ||
| - | |||
| - | void loop(void) | ||
| - | { | ||
| - | uint8 keycode; | ||
| - | |||
| - | while (1) { | ||
| - | |||
| - | if (!get_keycode_once(& | ||
| - | // CPU nicht verheizen: schlafen. | ||
| - | // Achtung: hlt braucht Interrupts; falls die bei dir noch nicht an sind, | ||
| - | // kannst du statt hlt ein kleines wait_for_io() nutzen. | ||
| - | asm volatile(" | ||
| - | continue; | ||
| - | } | ||
| - | |||
| - | if (keycode == KEY_ENTER) { | ||
| - | print_new_line(); | ||
| - | |||
| - | // Command ausführen | ||
| - | if (strc > 0) { | ||
| - | if (streq_ci(str, | ||
| - | print_string(" | ||
| - | print_new_line(); | ||
| - | print_string(" | ||
| - | print_new_line(); | ||
| - | } | ||
| - | // hier später weitere Commands... | ||
| - | } | ||
| - | |||
| - | // neues Prompt | ||
| - | print_string("> | ||
| - | reset_input_line(); | ||
| - | continue; | ||
| - | } | ||
| - | |||
| - | if (keycode == KEY_BACKSPACE) { | ||
| - | // nur löschen, wenn wir nach dem Prompt sind und auch was im Buffer ist | ||
| - | if (strc > 0 && vga_index > 0) { | ||
| - | // optional: Schutz, dass du nicht ins Prompt reinlöschst | ||
| - | uint32 prompt_start = (vga_index / VGA_W) * VGA_W + 2; // "> " = 2 chars | ||
| - | if (vga_index > prompt_start) { | ||
| - | vga_index--; | ||
| - | strc--; | ||
| - | str[strc] = 0; | ||
| - | vga_buffer[vga_index] = vga_entry(' | ||
| - | vga_set_cursor((uint16)vga_index); | ||
| - | } | ||
| - | } | ||
| - | continue; | ||
| - | } | ||
| - | |||
| - | if (keycode == KEY_SPACE) { | ||
| - | append_char(' | ||
| - | continue; | ||
| - | } | ||
| - | |||
| - | char ch = get_ascii_char(keycode); | ||
| - | |||
| - | // Erlaubte Zeichen: A-Z, 0-9, ' | ||
| - | if (ch == ' | ||
| - | (ch >= ' | ||
| - | (ch >= ' | ||
| - | append_char(ch); | ||
| - | } | ||
| - | |||
| - | // kein riesiger busy-sleep mehr nötig | ||
| - | io_wait(); | ||
| - | } | ||
| - | } | ||
| - | |||
| - | void kernel_entry(void) | ||
| - | { | ||
| - | init_vga(WHITE, | ||
| - | print_string(" | ||
| - | print_new_line(); | ||
| - | print_string(" | ||
| - | print_new_line(); | ||
| - | print_string(" | ||
| - | print_new_line(); | ||
| - | print_string("> | ||
| - | reset_input_line(); | ||
| - | loop(); | ||
| - | } | ||
| - | </ | ||
| Hallo Besucher! Willkommen in diesem kleinen Wiki rund um IT. Vieles ist noch **unvollständig, | Hallo Besucher! Willkommen in diesem kleinen Wiki rund um IT. Vieles ist noch **unvollständig, | ||