From a094f510d3738e84aaae4ef8162e4301bd218c5c Mon Sep 17 00:00:00 2001 From: Nigel Barink Date: Sun, 16 May 2021 15:53:14 +0100 Subject: [PATCH 1/9] More work on interrupt handling, Started timer interrupt implementation, PIC remapped hopefully successfull --- Makefile | 11 +- README.md | 3 + screenshots/WIP_interruptHandling.png | Bin 0 -> 16282 bytes src/kernel/arch/i386/boot.s | 426 +++++++++++++++--------- src/kernel/{ => arch/i386/gdt}/gdtc.cpp | 0 src/kernel/{ => arch/i386/gdt}/gdtc.h | 0 src/kernel/{ => arch/i386/idt}/idt.cpp | 111 +++--- src/kernel/arch/i386/idt/idt.h | 81 +++++ src/kernel/arch/i386/pic/pic.cpp | 62 ++++ src/kernel/arch/i386/pic/pic.h | 57 ++++ src/kernel/idt.h | 93 ------ src/kernel/kernel.cpp | 46 +-- src/kernel/kernel.h | 4 +- src/kernel/timer.cpp | 27 ++ src/kernel/timer.h | 6 + 15 files changed, 577 insertions(+), 350 deletions(-) create mode 100644 screenshots/WIP_interruptHandling.png rename src/kernel/{ => arch/i386/gdt}/gdtc.cpp (100%) rename src/kernel/{ => arch/i386/gdt}/gdtc.h (100%) rename src/kernel/{ => arch/i386/idt}/idt.cpp (51%) create mode 100644 src/kernel/arch/i386/idt/idt.h create mode 100644 src/kernel/arch/i386/pic/pic.cpp create mode 100644 src/kernel/arch/i386/pic/pic.h delete mode 100644 src/kernel/idt.h create mode 100644 src/kernel/timer.cpp create mode 100644 src/kernel/timer.h diff --git a/Makefile b/Makefile index 3aec044..aa43673 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CC = ${HOME}/opt/cross/bin/i686-elf-gcc CPP = ${HOME}/opt/cross/bin/i686-elf-g++ CFLAGS = -ffreestanding -O2 -Wall -Wextra -OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/io.o $(BUILD_DIR)/MMU.o $(BUILD_DIR)/idt.o +OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/io.o $(BUILD_DIR)/MMU.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o SRC_DIR = src BUILD_DIR = build @@ -24,7 +24,7 @@ all: clean build build: build_kernel run run: - $(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std + $(EMULATOR) -d int -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std build_kernel: $(OBJ_LINK_LIST) @@ -55,7 +55,12 @@ $(BUILD_DIR)/crtn.o: $(BUILD_DIR)/io.o: $(CPP) -c $(SRC_DIR)/kernel/io.cpp -o $(BUILD_DIR)/io.o $(CFLAGS) -fno-exceptions -fno-rtti + $(BUILD_DIR)/MMU.o: $(CPP) -c $(SRC_DIR)/kernel/MMU.cpp -o $(BUILD_DIR)/MMU.o $(CFLAGS) -fno-exceptions -fno-rtti + $(BUILD_DIR)/idt.o: - $(CPP) -c $(SRC_DIR)/kernel/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti \ No newline at end of file + $(CPP) -c $(SRC_DIR)/kernel/arch/i386/idt/idt.cpp -o $(BUILD_DIR)/idt.o $(CFLAGS) -fno-exceptions -fno-rtti + +$(BUILD_DIR)/pic.o: + $(CPP) -c $(SRC_DIR)/kernel/arch/i386/pic/pic.cpp -o $(BUILD_DIR)/pic.o $(CFLAGS) -fno-exceptions -fno-rtti diff --git a/README.md b/README.md index cf263a6..eefdecd 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ ________________________ The first scrolling boot screen. 😲 + +W.I.P - Working on interrupt handling + ________________________ ### The goal diff --git a/screenshots/WIP_interruptHandling.png b/screenshots/WIP_interruptHandling.png new file mode 100644 index 0000000000000000000000000000000000000000..cc9c89ed85437e6a10451f6fc4bb91c6af6cc3be GIT binary patch literal 16282 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 Zino= 8) + outb(PIC2_COMMAND, PIC_EOI); + outb(PIC1_COMMAND, PIC_EOI); +} + +/* Helper func */ +static uint16_t __pic_get_irq_reg(int ocw3) +{ + /* OCW3 to PIC CMD to get the register values. PIC2 is chained, and + * represents IRQs 8-15. PIC1 is IRQs 0-7, with 2 being the chain */ + outb(PIC1_COMMAND, ocw3); + outb(PIC2_COMMAND, ocw3); + return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND); +} + +/* Returns the combined value of the cascaded PICs irq request register */ +uint16_t pic_get_irr(void) +{ + return __pic_get_irq_reg(PIC_READ_IRR); +} + +/* Returns the combined value of the cascaded PICs in-service register */ +uint16_t pic_get_isr(void) +{ + return __pic_get_irq_reg(PIC_READ_ISR); +} + + +void PIC_remap (int offset1, int offset2 ){ + unsigned char a1, a2; + + a1 = inb(PIC1_DATA); + a2 = inb(PIC2_DATA); + + + // Start initialization + + outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); + io_wait(); + outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); + io_wait(); + outb(PIC1_DATA, offset1); + io_wait(); + outb(PIC2_DATA, offset2); + io_wait(); + outb(PIC1_DATA, 4); + io_wait(); + outb(PIC2_DATA, 2); + io_wait(); + + outb(PIC1_DATA, ICW4_8086); + io_wait(); + outb(PIC2_DATA, ICW4_8086); + io_wait(); + + outb(PIC1_DATA, a1); + outb(PIC2_DATA, a2); + +} \ No newline at end of file diff --git a/src/kernel/arch/i386/pic/pic.h b/src/kernel/arch/i386/pic/pic.h new file mode 100644 index 0000000..5358f5a --- /dev/null +++ b/src/kernel/arch/i386/pic/pic.h @@ -0,0 +1,57 @@ +#pragma once +#include "../../../io.h" + +#define PIC1 0x20 /* IO base address for master PIC */ +#define PIC2 0xA0 /* IO base address for slave PIC */ +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1+1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2+1) + + +#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ + +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ + +#define PIC_EOI 0x20 +#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */ +#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */ + +extern "C"{ + +extern void irq0 (); +extern void irq1 (); +extern void irq2 (); +extern void irq3 (); +extern void irq4 (); +extern void irq5 (); +extern void irq6 (); +extern void irq7 (); +extern void irq8 (); +extern void irq9 (); +extern void irq10 (); +extern void irq11 (); +extern void irq12 (); +extern void irq13 (); +extern void irq14 (); +extern void irq15 (); + +void PIC_sendEOI (unsigned char irq); + +} + + +static uint16_t __pic_get_irq_reg(int ocw3); +uint16_t pic_get_irr(void); +uint16_t pic_get_isr(void); + + +void PIC_remap (int offset1, int offset2 ); \ No newline at end of file diff --git a/src/kernel/idt.h b/src/kernel/idt.h deleted file mode 100644 index 07c7440..0000000 --- a/src/kernel/idt.h +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once -#include "stdint.h" -#include "stddef.h" -#include "arch/i386/vga/colors.h" - -#define AS_KERNEL() ( kterm_writestring("[KERNEL]:")) - -extern "C" void kterm_writestring(const char* data ); -extern "C" void kterm_putat(char, uint8_t, size_t, size_t); -extern "C" void kterm_put(char); - - -extern "C" { - struct __attribute__((__packed__)) IDT_entry { - uint16_t offset_1; - uint16_t selector; - uint8_t zero; - uint8_t type_attr; - uint16_t offset_2; - }; - - struct __attribute__((__packed__)) IDT_ptr { - unsigned short length; - unsigned long base; - }; - - struct registers { - uint32_t ds; // Data segment selector - uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha. - uint32_t int_no, err_code; // Interrupt number and error code (if applicable) - uint32_t eip, cs, eflags, useresp, ss; - }; - - - extern void idt_flush(uint32_t); - void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags); - void init_idt(); - - void irq_handler (registers regs); - - extern void irq0 (); - extern void irq1 (); - extern void irq2 (); - extern void irq3 (); - extern void irq4 (); - extern void irq5 (); - extern void irq6 (); - extern void irq7 (); - extern void irq8 (); - extern void irq9 (); - extern void irq10 (); - extern void irq11 (); - extern void irq12 (); - extern void irq13 (); - extern void irq14 (); - extern void irq15 (); - extern void irq16 (); - extern void irq17 (); - extern void irq18 (); - extern void irq19 (); - extern void irq20 (); - extern void irq21 (); - extern void irq22 (); - extern void irq23 (); - extern void irq24 (); - extern void irq25 (); - extern void irq26 (); - extern void irq27 (); - extern void irq28 (); - extern void irq29 (); - extern void irq30 (); - extern void irq31 (); -/* - extern void irq0 (); - extern void irq1 (); - extern void irq2 (); - extern void irq3 (); - extern void irq4 (); - extern void irq5 (); - extern void irq6 (); - extern void irq7 (); - extern void irq8 (); - extern void irq9 (); - extern void irq10 (); - extern void irq11 (); - extern void irq12 (); - extern void irq13 (); - extern void irq14 (); - extern void irq15 ();*/ - - - -} diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index 2530c7a..edd7f22 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -9,10 +9,6 @@ void delay(int t){ asm("NOP"); } - - - - class Test { public: Test(); @@ -20,7 +16,6 @@ class Test { ~Test(); }; - Test::Test(){ kterm_writestring("Create a test object\n"); }; @@ -56,7 +51,6 @@ static int init_serial() { return 0; } - int is_transmit_empty() { return inb(PORT + 5) & 0x20; } @@ -77,7 +71,6 @@ char read_serial() { return inb(PORT); } - void print_serial(const char* string ){ for(size_t i = 0; i < strlen(string); i ++){ write_serial(string[i]); @@ -102,31 +95,13 @@ void test_serial(){ kterm_writestring("\n"); } - - extern "C" { void early_main(){ init_serial(); print_serial("\033[31;42mEarly main called!\n"); - - print_serial("Remapping PIC\n"); - // remap the PIC IRQ table - /*outb(0x20, 0x11); - outb(0xA0, 0x11); - outb(0x21, 0x20); - outb(0xA1, 0x28); - outb(0x21, 0x04); - outb(0xA1, 0x02); - outb(0x21, 0x01); - outb(0xA1, 0x01); - outb(0x21, 0x0); - outb(0xA1, 0x0);*/ - - - print_serial("done... \n"); - + } void kernel_main (void) { @@ -162,24 +137,7 @@ extern "C" { auto testObject = Test(); testObject.printMe(); - /*IRQ_set_mask(0); - IRQ_set_mask(1); - IRQ_set_mask(2); - IRQ_set_mask(3); - IRQ_set_mask(4); - IRQ_set_mask(5); - IRQ_set_mask(6); - IRQ_set_mask(7); - IRQ_set_mask(8); - IRQ_set_mask(9); - IRQ_set_mask(10); - IRQ_set_mask(11); - IRQ_set_mask(12); - IRQ_set_mask(13); - IRQ_set_mask(14); - IRQ_set_mask(15); - */ - + /** test interrupt handlers **/ asm volatile ("int $0x03"); diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h index 3b1b0bc..ced720a 100644 --- a/src/kernel/kernel.h +++ b/src/kernel/kernel.h @@ -3,7 +3,7 @@ extern "C" { #include "../libc/include/string.h" #include "arch/i386/tty/kterm.h" } + +#include "arch/i386/idt/idt.h" #include "MMU.h" #include "io.h" -#include "idt.h" -//#include "pic.h" \ No newline at end of file diff --git a/src/kernel/timer.cpp b/src/kernel/timer.cpp new file mode 100644 index 0000000..35a8a4a --- /dev/null +++ b/src/kernel/timer.cpp @@ -0,0 +1,27 @@ +#include "timer.h" + +uint32_t tick = 0; + + +static void timer_callback (registers_t regs ){ + tick ++ ; + kterm_writestring ("tick passed!"); +} + +void init_timer (uint32_t frequency){ + // register timer callback + + uint32_t divisor = 1193180 / frequency; + + // Send the commmand byte + outb(0x43, 0x36); + + // Divisor has to be sent byt-wise , so will send lower then upper bytes + uint8_t low = (uint8_t) (divisor & 0xFF); + uint8_t high = (uint8_t) ((divisor >> 8) & 0xFF); + + outb(0x40, low); + outb(0x40, high); + + +} \ No newline at end of file diff --git a/src/kernel/timer.h b/src/kernel/timer.h new file mode 100644 index 0000000..db8be78 --- /dev/null +++ b/src/kernel/timer.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include + +void init_timer (uint32_t frequency); \ No newline at end of file From 63ea825e2e2a5dfc123c266a49b7967b4e82bed5 Mon Sep 17 00:00:00 2001 From: Nigel Date: Tue, 18 May 2021 21:11:48 +0100 Subject: [PATCH 2/9] Added CMOS time read function, Added cariage return support to kterm --- src/kernel/arch/i386/tty/kterm.c | 105 ++++++++++++++++++++- src/kernel/arch/i386/tty/kterm.h | 10 +- src/kernel/time.h | 151 +++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+), 5 deletions(-) create mode 100644 src/kernel/time.h diff --git a/src/kernel/arch/i386/tty/kterm.c b/src/kernel/arch/i386/tty/kterm.c index 6dab47f..7ec9ae1 100644 --- a/src/kernel/arch/i386/tty/kterm.c +++ b/src/kernel/arch/i386/tty/kterm.c @@ -62,15 +62,17 @@ void kterm_scrollup(){ } void kterm_put (char c) { - if(++kterm_column == VGA_WIDTH || c == '\n' ) { kterm_column = 0; - if(kterm_row == VGA_HEIGHT-1) { + if(kterm_row == VGA_HEIGHT-1 ) { kterm_scrollup(); } else { kterm_row ++; } - + } + if ( c == '\r'){ + kterm_column = 0; + return; } if(c == '\n') return; @@ -89,3 +91,100 @@ void kterm_writestring(const char* data ){ AS_KERNEL(); kterm_write(data, strlen(data)); } + + +static void itoa (char *buf, int base, int d) { + char *p = buf; + char *p1, *p2; + unsigned long ud = d; + int divisor = 10; + if ( base == 'd' && d < 0){ + *p++ = '-'; + buf++; + ud = -d; + } else if (base == 'x'){ + divisor = 16; + } + + do { + int remainder = ud % divisor; + + *p++ = (remainder < 10 ) ? remainder + '0' : remainder + 'a' -10; + } while(ud /= divisor); + + /*terminate buf*/ + *p =0; + p1 = buf; + p2 = p -1; + + while (p1 < p2) + { + char tmp = *p1; + *p1 = *p2; + *p2 = tmp; + p1++; + p2--; + + } + +} + +void printf ( const char *format, ...) { + + char **arg = (char **)&format; + int c; + char buf[20]; + + arg++; + + while ((c = *format++) != 0){ + if( c != '%') + kterm_put(c); + else{ + char *p, *p2; + int pad0 = 0, pad = 0; + + c = *format++; + if(c =='0'){ + pad0 = 1; + c = *format++; + } + + if ( c >= '0' && c <= '9'){ + pad = c - '0'; + c = *format++; + } + + switch (c) + { + case 'd': + + case 'u': + case 'x': + itoa(buf, c, *((int *) arg++)); + + p = buf; + goto string; + break; + + case 's': + p = *arg++; + if(!p) + p = "(null)"; + + string: + for (p2 = p; *p2; p2++); + for (; p2 < p + pad; p2++) + kterm_put(pad0 ? '0': ' '); + while (*p) + kterm_put(*p++); + break; + + + default: + kterm_put(*((int *)arg++)); + break; + } + } + } +} \ No newline at end of file diff --git a/src/kernel/arch/i386/tty/kterm.h b/src/kernel/arch/i386/tty/kterm.h index f1570c6..d9f704f 100644 --- a/src/kernel/arch/i386/tty/kterm.h +++ b/src/kernel/arch/i386/tty/kterm.h @@ -15,10 +15,16 @@ void kterm_putat(char, uint8_t, size_t, size_t); void kterm_put(char); void kterm_write(const char*, size_t); void kterm_writestring(const char*); - void kterm_scrollup(); + +void printf ( const char *format, ...); + +static void itoa (char *buf, int base, int d); + #define KernelTag "[Kernel]: " #define AS_KERNEL() ( kterm_setcolor(VGA_COLOR_LIGHT_BLUE),\ kterm_write(KernelTag, 10 ), \ - kterm_resetcolor()) \ No newline at end of file + kterm_resetcolor()) + + diff --git a/src/kernel/time.h b/src/kernel/time.h new file mode 100644 index 0000000..6a098b7 --- /dev/null +++ b/src/kernel/time.h @@ -0,0 +1,151 @@ +#define CURRENT_YEAR 2021 // Change this each year! + +int century_register = 0x00; // Set by ACPI table parsing code if possible + +unsigned char second; +unsigned char minute; +unsigned char hour; +unsigned char day; +unsigned char month; +unsigned int year; + + + +enum { + cmos_address = 0x70, + cmos_data = 0x71 +}; + +int get_update_in_progress_flag() { + outb(cmos_address, 0x0A); + return (inb(cmos_data) & 0x80); +} + +unsigned char get_RTC_register(int reg) { + outb(cmos_address, reg); + return inb(cmos_data); +} + +void read_rtc() { + unsigned char century; + unsigned char last_second; + unsigned char last_minute; + unsigned char last_hour; + unsigned char last_day; + unsigned char last_month; + unsigned char last_year; + unsigned char last_century; + unsigned char registerB; + + // Note: This uses the "read registers until you get the same values twice in a row" technique + // to avoid getting dodgy/inconsistent values due to RTC updates + + while (get_update_in_progress_flag()); // Make sure an update isn't in progress + second = get_RTC_register(0x00); + minute = get_RTC_register(0x02); + hour = get_RTC_register(0x04); + day = get_RTC_register(0x07); + month = get_RTC_register(0x08); + year = get_RTC_register(0x09); + if(century_register != 0) { + century = get_RTC_register(century_register); + } + + do { + last_second = second; + last_minute = minute; + last_hour = hour; + last_day = day; + last_month = month; + last_year = year; + last_century = century; + + while (get_update_in_progress_flag()); // Make sure an update isn't in progress + second = get_RTC_register(0x00); + minute = get_RTC_register(0x02); + hour = get_RTC_register(0x04); + day = get_RTC_register(0x07); + month = get_RTC_register(0x08); + year = get_RTC_register(0x09); + if(century_register != 0) { + century = get_RTC_register(century_register); + } + } while( (last_second != second) || (last_minute != minute) || (last_hour != hour) || + (last_day != day) || (last_month != month) || (last_year != year) || + (last_century != century) ); + + registerB = get_RTC_register(0x0B); + + // Convert BCD to binary values if necessary + + if (!(registerB & 0x04)) { + second = (second & 0x0F) + ((second / 16) * 10); + minute = (minute & 0x0F) + ((minute / 16) * 10); + hour = ( (hour & 0x0F) + (((hour & 0x70) / 16) * 10) ) | (hour & 0x80); + day = (day & 0x0F) + ((day / 16) * 10); + month = (month & 0x0F) + ((month / 16) * 10); + year = (year & 0x0F) + ((year / 16) * 10); + if(century_register != 0) { + century = (century & 0x0F) + ((century / 16) * 10); + } + } + + // Convert 12 hour clock to 24 hour clock if necessary + + if (!(registerB & 0x02) && (hour & 0x80)) { + hour = ((hour & 0x7F) + 12) % 24; + } + + // Calculate the full (4-digit) year + + if(century_register != 0) { + year += century * 100; + } else { + year += (CURRENT_YEAR / 100) * 100; + if(year < CURRENT_YEAR) year += 100; + } +} + + +/* +void ReadFromCMOS(unsigned char array[]) +{ + unsigned char tvalue, index; + + for (index = 0; index < 128; index++) + { + asm( + "cli\n\t" // Disable interrupts + "mov al, index\n\t" // Move index address + // since the 0x80 bit of al is not set, NMI is active + "out 0x70,al\n\t" // Copy address to CMOS register + // some kind of real delay here is probably best + "in al,0x71\n\t" // Fetch 1 byte to al + "sti\n\t" // Enable interrupts + "mov tvalue,al\n\t"); + + array[index] = tvalue; + } +} +*/ + +/* +void WriteTOCMOS(unsigned char array[]) +{ + unsigned char index; + + for(index = 0; index < 128; index++) + { + unsigned char tvalue = array[index]; + + asm("cli\n\t" // Clear interrupts + "mov al,index\n\t" // move index address + "out 0x70,al\n\t" // copy address to CMOS register + /* some kind of real delay here is probably best + "mov al,tvalue\n\t" // move value to al + "out 0x71,al\n\t" // write 1 byte to CMOS + "sti\n\\t" ); // Enable interrupts + + } +} +*/ \ No newline at end of file From f71a3a8ed66266a913bae5de88060e5476d4f308 Mon Sep 17 00:00:00 2001 From: Nigel Date: Tue, 18 May 2021 21:13:14 +0100 Subject: [PATCH 3/9] Removed itoa and printf from idt --- src/kernel/arch/i386/idt/idt.cpp | 97 -------------------------------- src/kernel/arch/i386/idt/idt.h | 9 ++- 2 files changed, 4 insertions(+), 102 deletions(-) diff --git a/src/kernel/arch/i386/idt/idt.cpp b/src/kernel/arch/i386/idt/idt.cpp index d515272..165e7a8 100644 --- a/src/kernel/arch/i386/idt/idt.cpp +++ b/src/kernel/arch/i386/idt/idt.cpp @@ -1,102 +1,5 @@ #include "idt.h" -static void itoa (char *buf, int base, int d) { - char *p = buf; - char *p1, *p2; - unsigned long ud = d; - int divisor = 10; - if ( base == 'd' && d < 0){ - *p++ = '-'; - buf++; - ud = -d; - } else if (base == 'x'){ - divisor = 16; - } - - do { - int remainder = ud % divisor; - - *p++ = (remainder < 10 ) ? remainder + '0' : remainder + 'a' -10; - } while(ud /= divisor); - - /*terminate buf*/ - *p =0; - p1 = buf; - p2 = p -1; - - while (p1 < p2) - { - char tmp = *p1; - *p1 = *p2; - *p2 = tmp; - p1++; - p2--; - - } - -} - -void printf ( const char *format, ...) { - - AS_KERNEL(); - char **arg = (char **)&format; - int c; - char buf[20]; - - arg++; - - while ((c = *format++) != 0){ - if( c != '%') - kterm_put(c); - else{ - char *p, *p2; - int pad0 = 0, pad = 0; - - c = *format++; - if(c =='0'){ - pad0 = 1; - c = *format++; - } - - if ( c >= '0' && c <= '9'){ - pad = c - '0'; - c = *format++; - } - - switch (c) - { - case 'd': - - case 'u': - case 'x': - itoa(buf, c, *((int *) arg++)); - - p = buf; - goto string; - break; - - case 's': - p = *arg++; - if(!p) - p = "(null)"; - - string: - for (p2 = p; *p2; p2++); - for (; p2 < p + pad; p2++) - kterm_put(pad0 ? '0': ' '); - while (*p) - kterm_put(*p++); - break; - - - default: - kterm_put(*((int *)arg++)); - break; - } - } - } -} - IDT_entry idt_table[256]; IDT_ptr idt_ptr; diff --git a/src/kernel/arch/i386/idt/idt.h b/src/kernel/arch/i386/idt/idt.h index 7281fa9..b616b85 100644 --- a/src/kernel/arch/i386/idt/idt.h +++ b/src/kernel/arch/i386/idt/idt.h @@ -3,14 +3,13 @@ #include "stdint.h" #include "stddef.h" #include "../vga/colors.h" -#include "../pic/pic.h"; +#include "../pic/pic.h" +extern "C"{ + #include "../tty/kterm.h" +} #define AS_KERNEL() ( kterm_writestring("[KERNEL]:")) -extern "C" void kterm_writestring(const char* data ); -extern "C" void kterm_putat(char, uint8_t, size_t, size_t); -extern "C" void kterm_put(char); - extern "C" { struct __attribute__((__packed__)) IDT_entry { From e84d196b002bb97ddf164796d14c6397de6e2017 Mon Sep 17 00:00:00 2001 From: Nigel Date: Tue, 18 May 2021 21:14:26 +0100 Subject: [PATCH 4/9] Kernel now enter continuous time telling mode --- src/kernel/kernel.cpp | 9 +++++++++ src/kernel/kernel.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index edd7f22..1b87e9f 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -144,6 +144,15 @@ extern "C" { asm volatile ("int $4"); + + + while (true){ + // Read time indefinetely + read_rtc(); + printf( "(YY-MM-DD h:mm:ss): %2d-%2d-%2d %2d:%2d:%2d\r" ,year, month, day, hour, minute, second); + delay(1000); + } + /** Lets start using the serial port for debugging .. **/ // Hopefully once we go into realmode or do something that // cause the screen to go black.. this serial comms part will give diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h index ced720a..eed09c0 100644 --- a/src/kernel/kernel.h +++ b/src/kernel/kernel.h @@ -7,3 +7,4 @@ extern "C" { #include "arch/i386/idt/idt.h" #include "MMU.h" #include "io.h" +#include "time.h" From 595a7d51635835fc626d2025a68af039153527f8 Mon Sep 17 00:00:00 2001 From: Nigel Date: Sat, 22 May 2021 19:24:29 +0100 Subject: [PATCH 5/9] Nicer time print --- src/kernel/kernel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index 1b87e9f..d27944d 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -149,7 +149,7 @@ extern "C" { while (true){ // Read time indefinetely read_rtc(); - printf( "(YY-MM-DD h:mm:ss): %2d-%2d-%2d %2d:%2d:%2d\r" ,year, month, day, hour, minute, second); + printf( "UTC time: %2d-%2d-%2d %2d:%2d:%2d : (YY-MM-DD h:mm:ss)\r" ,year, month, day, hour, minute, second); delay(1000); } From 5f50f8c01322124b80b498277949a8b60882724d Mon Sep 17 00:00:00 2001 From: Nigel Date: Fri, 28 May 2021 22:18:50 +0100 Subject: [PATCH 6/9] Fix up wrong interrupt handler numbers in boot.s --- src/kernel/arch/i386/boot.s | 88 +++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 32 deletions(-) diff --git a/src/kernel/arch/i386/boot.s b/src/kernel/arch/i386/boot.s index 17432e4..2de2f8d 100644 --- a/src/kernel/arch/i386/boot.s +++ b/src/kernel/arch/i386/boot.s @@ -273,116 +273,140 @@ irs31: irq0: cli push $0 - push $32 - jmp irs_common + push $0 + jmp irq_common .globl irq1 irq1: cli push $0 - push $33 - jmp irs_common + push $1 + jmp irq_common .globl irq2 irq2: cli push $0 - push $34 - jmp irs_common + push $2 + jmp irq_common .globl irq3 irq3: cli push $0 - push $35 - jmp irs_common + push $3 + jmp irq_common .globl irq4 irq4: cli push $0 - push $36 - jmp irs_common + push $4 + jmp irq_common .globl irq5 irq5: cli push $0 - push $37 - jmp irs_common + push $5 + jmp irq_common .globl irq6 irq6: cli push $0 - push $38 - jmp irs_common + push $6 + jmp irq_common .globl irq7 irq7: cli push $0 - push $39 - jmp irs_common + push $7 + jmp irq_common .globl irq8 irq8: cli push $0 - push $40 - jmp irs_common + push $8 + jmp irq_common .globl irq9 irq9: cli push $0 - push $41 - jmp irs_common + push $9 + jmp irq_common .globl irq10 irq10: cli push $0 - push $42 - jmp irs_common + push $10 + jmp irq_common .globl irq11 irq11: cli push $0 - push $43 - jmp irs_common + push $11 + jmp irq_common .globl irq12 irq12: cli push $0 - push $44 - jmp irs_common + push $12 + jmp irq_common .globl irq13 irq13: cli push $0 - push $45 - jmp irs_common + push $13 + jmp irq_common .globl irq14 irq14: cli push $0 - push $46 - jmp irs_common + push $14 + jmp irq_common .globl irq15 irq15: cli push $0 - push $47 - jmp irs_common + push $15 + jmp irq_common +irq_common: + pusha + mov %ds, %ax + push %eax + + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + call irq_handler + + pop %eax + + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + popa + add $8, %esp # cleans push error and irs code + sti + iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP irs_common: From 59bcc17668dc7ec9b053b6b18c46a19f55767014 Mon Sep 17 00:00:00 2001 From: Nigel Date: Fri, 28 May 2021 22:20:13 +0100 Subject: [PATCH 7/9] Kernel now responding to keyboard interrupts --- src/kernel/arch/i386/idt/idt.cpp | 52 ++++++++++++++++++++++++++++++-- src/kernel/kernel.cpp | 9 +++--- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/kernel/arch/i386/idt/idt.cpp b/src/kernel/arch/i386/idt/idt.cpp index 165e7a8..b81ace6 100644 --- a/src/kernel/arch/i386/idt/idt.cpp +++ b/src/kernel/arch/i386/idt/idt.cpp @@ -1,5 +1,5 @@ #include "idt.h" - +#include "Scancodes.h" IDT_entry idt_table[256]; IDT_ptr idt_ptr; @@ -17,7 +17,7 @@ void set_id_entry (uint8_t num , uint32_t base, uint16_t sel, uint8_t flags){ void irs_handler (registers regs) { kterm_writestring("received interrupt!\n"); - printf(" Interrupt number: %d \n", regs.int_no); + printf("(IRS) Interrupt number: %d \n", regs.int_no); if( regs.int_no == 13){ printf(" Error code: %d \n", regs.err_code); @@ -28,6 +28,52 @@ void irs_handler (registers regs) { +void irq_handler (registers regs) { + + + if ( regs.int_no != 0) { + kterm_writestring("received interrupt!\n"); + printf("(IRQ) Interrupt number: %d \n", regs.int_no); + + } + + if ( regs.int_no == 1 ){ + // Keyboard interrupt !! + + int scan; + register int i; + + // Read scancode + + scan = inb(0x60); + + // Send ack message! + i = inb(0x61); + outb(0x61, i|0x80); + outb(0x61, i); + kterm_writestring("A key was pressed/released\n"); + printf( "Scancode: %x\n", scan); + + + } + + + + outb(0x20, 0x20); // send end of interrupt to master + + if ( regs.int_no > 8 && regs.int_no <= 15) { + outb(0xA0, 0x20); // send end of interrupt to slave + } + + + if( regs.int_no == 13){ + printf(" Error code: %d \n", regs.err_code); + + } + +} + + @@ -39,7 +85,7 @@ void init_idt(){ // TODO: Set everything to zero first - set_id_entry(0, (uint32_t) irs0 , 0x08, 0x8E); + set_id_entry(0, (uint32_t) irs0 , 0x08, 0x8F); set_id_entry(1, (uint32_t) irs1 , 0x08, 0x8E); set_id_entry(2, (uint32_t) irs2 , 0x08, 0x8E); set_id_entry(3, (uint32_t) irs3 , 0x08, 0x8E); diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index d27944d..6764040 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -140,18 +140,17 @@ extern "C" { /** test interrupt handlers **/ - asm volatile ("int $0x03"); + //asm volatile ("int $0x03"); - asm volatile ("int $4"); + //asm volatile ("int $0x04"); - - while (true){ - // Read time indefinetely + //Read time indefinetely read_rtc(); printf( "UTC time: %2d-%2d-%2d %2d:%2d:%2d : (YY-MM-DD h:mm:ss)\r" ,year, month, day, hour, minute, second); delay(1000); } + /** Lets start using the serial port for debugging .. **/ // Hopefully once we go into realmode or do something that From 9dc7a05da14ba40a09c0c138268b10688b52809f Mon Sep 17 00:00:00 2001 From: Nigel Date: Wed, 21 Jul 2021 21:31:57 +0100 Subject: [PATCH 8/9] Basic keyboard input --- .../Screenshot from 2021-06-21 14-26-39.png | 3 + src/kernel/arch/i386/idt/idt.cpp | 2 +- src/kernel/arch/i386/idt/scancodes/set1.h | 184 ++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 screenshots/Screenshot from 2021-06-21 14-26-39.png create mode 100644 src/kernel/arch/i386/idt/scancodes/set1.h diff --git a/screenshots/Screenshot from 2021-06-21 14-26-39.png b/screenshots/Screenshot from 2021-06-21 14-26-39.png new file mode 100644 index 0000000..30c104f --- /dev/null +++ b/screenshots/Screenshot from 2021-06-21 14-26-39.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73b9d3ed540e1bc0b6d55114a00f9aa688006b38a542c1bf048d90b791a748ce +size 141605 diff --git a/src/kernel/arch/i386/idt/idt.cpp b/src/kernel/arch/i386/idt/idt.cpp index b81ace6..4722109 100644 --- a/src/kernel/arch/i386/idt/idt.cpp +++ b/src/kernel/arch/i386/idt/idt.cpp @@ -1,5 +1,5 @@ #include "idt.h" -#include "Scancodes.h" +//#include "scancodes/set1.h" IDT_entry idt_table[256]; IDT_ptr idt_ptr; diff --git a/src/kernel/arch/i386/idt/scancodes/set1.h b/src/kernel/arch/i386/idt/scancodes/set1.h new file mode 100644 index 0000000..2fe6b17 --- /dev/null +++ b/src/kernel/arch/i386/idt/scancodes/set1.h @@ -0,0 +1,184 @@ +#pragma once + + + + + + +// ScanCode set 1 +int ScanCodeToKeyCode [0xD8]; + +/* key pressed scancode */ +ScanCodeToKeyCode[0x01] = 4017; // escape pressed +ScanCodeToKeyCode[0x02] = 4018; // 1 pressed +ScanCodeToKeyCode[0x03] = 4019; // 2 pressed +ScanCodeToKeyCode[0x04] = 4020; // 3 pressed +ScanCodeToKeyCode[0x05] ="" // 4 pressed +ScanCodeToKeyCode[0x06] ="" // 5 pressed +ScanCodeToKeyCode[0x07] ="" // 6 pressed +ScanCodeToKeyCode[0x08] ="" // 7 pressed +ScanCodeToKeyCode[0x09] ="" // 8 pressed +ScanCodeToKeyCode[0x0A] ="" // 9 pressed +ScanCodeToKeyCode[0x0B] ="" // 0 (zero) pressed +ScanCodeToKeyCode[0x0C] ="" // - pressed +ScanCodeToKeyCode[0x0D] ="" // = pressed +ScanCodeToKeyCode[0x0E] ="" // backspace pressed +ScanCodeToKeyCode[0x0F] ="" // tab pressed +ScanCodeToKeyCode[0x10] ="" // Q pressed +ScanCodeToKeyCode[0x11] ="" // W pressed +ScanCodeToKeyCode[0x12] ="" // E pressed +ScanCodeToKeyCode[0x13] ="" // R pressed +ScanCodeToKeyCode[0x14] ="" // T pressed +ScanCodeToKeyCode[0x15] ="" // Y pressed +ScanCodeToKeyCode[0x16] ="" // U pressed +ScanCodeToKeyCode[0x17] ="" // I pressed +ScanCodeToKeyCode[0x18] ="" // O pressed +ScanCodeToKeyCode[0x19] ="" // P pressed +ScanCodeToKeyCode[0x1A] ="" // [ pressed +ScanCodeToKeyCode[0x1B] ="" // ] pressed +ScanCodeToKeyCode[0x1C] ="" // enter pressed +ScanCodeToKeyCode[0x1D] ="" // left control pressed +ScanCodeToKeyCode[0x1E] ="" // A pressed +ScanCodeToKeyCode[0x1F] ="" // S pressed +ScanCodeToKeyCode[0x20] ="" // D pressed +ScanCodeToKeyCode[0x21] ="" // F pressed +ScanCodeToKeyCode[0x22] ="" // G pressed +ScanCodeToKeyCode[0x23] ="" // H pressed +ScanCodeToKeyCode[0x24] ="" // J pressed +ScanCodeToKeyCode[0x25] ="" // K pressed +ScanCodeToKeyCode[0x26] ="" // L pressed +ScanCodeToKeyCode[0x27] ="" // ; pressed +ScanCodeToKeyCode[0x28] ="" // ' (single quote) pressed +ScanCodeToKeyCode[0x29] ="" // ` (back tick) pressed +ScanCodeToKeyCode[0x2A] ="" // left shift pressed +ScanCodeToKeyCode[0x2B] ="" // \ pressed +ScanCodeToKeyCode[0x2C] ="" // Z pressed +ScanCodeToKeyCode[0x2D] ="" // X pressed +ScanCodeToKeyCode[0x2E] ="" // C pressed +ScanCodeToKeyCode[0x2F] ="" // V pressed +ScanCodeToKeyCode[0x30] ="" // B pressed +ScanCodeToKeyCode[0x31] ="" // N pressed +ScanCodeToKeyCode[0x32] ="" // M pressed +ScanCodeToKeyCode[0x33] ="" // , pressed +ScanCodeToKeyCode[0x34] ="" // . pressed +ScanCodeToKeyCode[0x35] ="" // / pressed +ScanCodeToKeyCode[0x36] ="" // right shift pressed +ScanCodeToKeyCode[0x37] ="" // (keypad) * pressed +ScanCodeToKeyCode[0x38] ="" // left alt pressed +ScanCodeToKeyCode[0x39] ="" // space pressed +ScanCodeToKeyCode[0x3A] ="" // CapsLock pressed +ScanCodeToKeyCode[0x3B] ="" // F1 pressed +ScanCodeToKeyCode[0x3C] ="" // F2 pressed +ScanCodeToKeyCode[0x3D] ="" // F3 pressed +ScanCodeToKeyCode[0x3E] ="" // F4 pressed +ScanCodeToKeyCode[0x3F] ="" // F5 pressed +ScanCodeToKeyCode[0x40] ="" // F6 pressed +ScanCodeToKeyCode[0x41] ="" // F7 pressed +ScanCodeToKeyCode[0x42] ="" // F8 pressed +ScanCodeToKeyCode[0x43] ="" // F9 pressed +ScanCodeToKeyCode[0x44] ="" // F10 pressed +ScanCodeToKeyCode[0x45] ="" // NumberLock pressed +ScanCodeToKeyCode[0x46] ="" // ScrollLock pressed +ScanCodeToKeyCode[0x47] ="" // (keypad) 7 pressed +ScanCodeToKeyCode[0x48] ="" // (keypad) 8 pressed +ScanCodeToKeyCode[0x49] ="" // (keypad) 9 pressed +ScanCodeToKeyCode[0x4A] ="" // (keypad) - pressed +ScanCodeToKeyCode[0x4B] ="" // (keypad) 4 pressed +ScanCodeToKeyCode[0x4C] ="" // (keypad) 5 pressed +ScanCodeToKeyCode[0x4D] ="" // (keypad) 6 pressed +ScanCodeToKeyCode[0x4E] ="" // (keypad) + pressed +ScanCodeToKeyCode[0x4F] ="" // (keypad) 1 pressed +ScanCodeToKeyCode[0x50] ="" // (keypad) 2 pressed +ScanCodeToKeyCode[0x51] ="" // (keypad) 3 pressed +ScanCodeToKeyCode[0x52] ="" // (keypad) 0 pressed +ScanCodeToKeyCode[0x53] ="" // (keypad) . pressed +ScanCodeToKeyCode[0x57] ="" // F11 pressed +ScanCodeToKeyCode[0x58] ="" // F12 pressed + + +/* key released scanCode.""*/ +ScanCodeToKeyCode[0x81] ="" // escape released +ScanCodeToKeyCode[0x82] ="" // 1 released +ScanCodeToKeyCode[0x83] ="" // 2 released +ScanCodeToKeyCode[0x84] ="" // 3 released +ScanCodeToKeyCode[0x85] ="" // 4 released +ScanCodeToKeyCode[0x86] ="" // 5 released +ScanCodeToKeyCode[0x87] ="" // 6 released +ScanCodeToKeyCode[0x88] ="" // 7 released +ScanCodeToKeyCode[0x89] ="" // 8 released +ScanCodeToKeyCode[0x8A] ="" // 9 released +ScanCodeToKeyCode[0x8B] ="" // 0 (zero) released +ScanCodeToKeyCode[0x8C] ="" // - released +ScanCodeToKeyCode[0x8D] ="" // = released +ScanCodeToKeyCode[0x8E] ="" // backspace released +ScanCodeToKeyCode[0x8F] ="" // tab released +ScanCodeToKeyCode[0x90] ="" // Q released +ScanCodeToKeyCode[0x91] ="" // W released +ScanCodeToKeyCode[0x92] ="" // E released +ScanCodeToKeyCode[0x93] ="" // R released +ScanCodeToKeyCode[0x94] ="" // T released +ScanCodeToKeyCode[0x95] ="" // Y released +ScanCodeToKeyCode[0x96] ="" // U released +ScanCodeToKeyCode[0x97] ="" // I released +ScanCodeToKeyCode[0x98] ="" // O released +ScanCodeToKeyCode[0x99] ="" // P released +ScanCodeToKeyCode[0x9A] ="" // [ released +ScanCodeToKeyCode[0x9B] ="" // ] released +ScanCodeToKeyCode[0x9C] ="" // enter released +ScanCodeToKeyCode[0x9D] ="" // left control released +ScanCodeToKeyCode[0x9E] ="" // A released +ScanCodeToKeyCode[0x9F] ="" // S released +ScanCodeToKeyCode[0xA0] ="" // D released +ScanCodeToKeyCode[0xA1] ="" // F released +ScanCodeToKeyCode[0xA2] ="" // G released +ScanCodeToKeyCode[0xA3] ="" // H released +ScanCodeToKeyCode[0xA4] ="" // J released +ScanCodeToKeyCode[0xA5] ="" // K released +ScanCodeToKeyCode[0xA6] ="" // L released +ScanCodeToKeyCode[0xA7] ="" // ; released +ScanCodeToKeyCode[0xA8] ="" // ' (single quote) released +ScanCodeToKeyCode[0xA9] ="" // ` (back tick) released +ScanCodeToKeyCode[0xAA] ="" // left shift released +ScanCodeToKeyCode[0xAB] ="" // \ released +ScanCodeToKeyCode[0xAC] ="" // Z released +ScanCodeToKeyCode[0xAD] ="" // X released +ScanCodeToKeyCode[0xAE] ="" // C released +ScanCodeToKeyCode[0xAF] ="" // V released +ScanCodeToKeyCode[0xB0] ="" // B released +ScanCodeToKeyCode[0xB1] ="" // N released +ScanCodeToKeyCode[0xB2] ="" // M released +ScanCodeToKeyCode[0xB3] ="" // , released +ScanCodeToKeyCode[0xB4] ="" // . released +ScanCodeToKeyCode[0xB5] ="" // / released +ScanCodeToKeyCode[0xB6] ="" // right shift released +ScanCodeToKeyCode[0xB7] ="" // (keypad) * released +ScanCodeToKeyCode[0xB8] ="" // left alt released +ScanCodeToKeyCode[0xB9] ="" // space released +ScanCodeToKeyCode[0xBA] ="" // CapsLock released +ScanCodeToKeyCode[0xBB] ="" // F1 released +ScanCodeToKeyCode[0xBC] ="" // F2 released +ScanCodeToKeyCode[0xBD] ="" // F3 released +ScanCodeToKeyCode[0xBE] ="" // F4 released +ScanCodeToKeyCode[0xBF] ="" // F5 released +ScanCodeToKeyCode[0xC0] ="" // F6 released +ScanCodeToKeyCode[0xC1] ="" // F7 released +ScanCodeToKeyCode[0xC2] ="" // F8 released +ScanCodeToKeyCode[0xC3] ="" // F9 released +ScanCodeToKeyCode[0xC4] ="" // F10 released +ScanCodeToKeyCode[0xC5] ="" // NumberLock released +ScanCodeToKeyCode[0xC6] ="" // ScrollLock released +ScanCodeToKeyCode[0xC7] ="" // (keypad) 7 released +ScanCodeToKeyCode[0xC8] ="" // (keypad) 8 released +ScanCodeToKeyCode[0xC9] ="" // (keypad) 9 released +ScanCodeToKeyCode[0xCA] ="" // (keypad) - released +ScanCodeToKeyCode[0xCB] ="" // (keypad) 4 released +ScanCodeToKeyCode[0xCC] ="" // (keypad) 5 released +ScanCodeToKeyCode[0xCD] ="" // (keypad) 6 released +ScanCodeToKeyCode[0xCE] ="" // (keypad) + released +ScanCodeToKeyCode[0xCF] ="" // (keypad) 1 released +ScanCodeToKeyCode[0xD0] ="" // (keypad) 2 released +ScanCodeToKeyCode[0xD1] ="" // (keypad) 3 released +ScanCodeToKeyCode[0xD2] ="" // (keypad) 0 released +ScanCodeToKeyCode[0xD3] ="" // (keypad) . released +ScanCodeToKeyCode[0xD7] ="" // F11 released +ScanCodeToKeyCode[0xD8] ="" // F12 released \ No newline at end of file From d455735ea28bd9ecf0c48f5168e00d2a92f4df7a Mon Sep 17 00:00:00 2001 From: Nigel Date: Tue, 2 Nov 2021 21:44:50 +0100 Subject: [PATCH 9/9] Modified screenshot?? --- screenshots/WIP_interruptHandling.png | Bin 16282 -> 130 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/screenshots/WIP_interruptHandling.png b/screenshots/WIP_interruptHandling.png index cc9c89ed85437e6a10451f6fc4bb91c6af6cc3be..6c22b50cae707ad433fbe054584cc07bd5240685 100644 GIT binary patch literal 130 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 Zino