Browse Source

Tabified

master
Stephen Downward 1 year ago
parent
commit
7a3a93d8cb
24 changed files with 740 additions and 738 deletions
  1. +12
    -12
      boot/32bit_print.asm
  2. +2
    -2
      boot/bootsect.asm
  3. +18
    -18
      boot/disk.asm
  4. +17
    -17
      boot/gdt.asm
  5. +22
    -22
      boot/print.asm
  6. +28
    -28
      boot/print_hex.asm
  7. +15
    -15
      boot/switch_pm.asm
  8. +9
    -9
      cpu/idt.c
  9. +12
    -12
      cpu/idt.h
  10. +143
    -143
      cpu/interrupt.asm
  11. +114
    -114
      cpu/isr.c
  12. +21
    -21
      cpu/ports.c
  13. +31
    -31
      cpu/timer.c
  14. +3
    -3
      cpu/types.h
  15. +26
    -26
      drivers/keyboard.c
  16. +14
    -14
      drivers/screen.c
  17. +35
    -35
      kernel/kernel.c
  18. +6
    -6
      libc/mem.c
  19. +33
    -33
      libc/string.c
  20. +14
    -14
      programs/texteditor.c
  21. +7
    -7
      util/bitmap.c
  22. +16
    -14
      util/commands.c
  23. +99
    -99
      util/font.c
  24. +43
    -43
      util/terminal.c

+ 12
- 12
boot/32bit_print.asm View File

@@ -5,22 +5,22 @@ VIDEO_MEMORY equ 0xb8000
WHITE_OB_BLACK equ 0x0f ; the color byte for each character

print_string_pm:
pusha
mov edx, VIDEO_MEMORY
pusha
mov edx, VIDEO_MEMORY

print_string_pm_loop:
mov al, [ebx] ; [ebx] is the address of our character
mov ah, WHITE_OB_BLACK
mov al, [ebx] ; [ebx] is the address of our character
mov ah, WHITE_OB_BLACK

cmp al, 0 ; check if end of string
je print_string_pm_done
cmp al, 0 ; check if end of string
je print_string_pm_done

mov [edx], ax ; store character + attribute in video memory
add ebx, 1 ; next char
add edx, 2 ; next video memory position
mov [edx], ax ; store character + attribute in video memory
add ebx, 1 ; next char
add edx, 2 ; next video memory position

jmp print_string_pm_loop
jmp print_string_pm_loop

print_string_pm_done:
popa
ret
popa
ret

+ 2
- 2
boot/bootsect.asm View File

@@ -30,8 +30,8 @@
%include "boot/print_hex.asm"

load_bootloader:
;mov dh, [SEC_COUNT]
;call print_hex
;mov dh, [SEC_COUNT]
;call print_hex
pusha
call disk_load


+ 18
- 18
boot/disk.asm View File

@@ -1,5 +1,5 @@
disk_load:
pusha
pusha

retry:
mov es, [CURRENT_REG_LOAD]
@@ -9,22 +9,22 @@ retry:
mov al, 1 ;Num sectors
mov ch, [CYL_COUNT] ;Cylinder number
mov dl, [BOOT_DRIVE]
mov ah, 0x02 ; ah <- int 0x13 function. 0x02 = 'read'
;mov cl, 0x02 ; cl <- sector (0x01 .. 0x11)
; 0x01 is our boot sector, 0x02 is the first 'available' sector
;mov ch, 0x00 ; ch <- cylinder (0x0 .. 0x3FF, upper 2 bits in 'cl')
; dl <- drive number. Our caller sets it as a parameter and gets it from BIOS
; (0 = floppy, 1 = floppy2, 0x80 = hdd, 0x81 = hdd2)
mov ah, 0x02 ; ah <- int 0x13 function. 0x02 = 'read'
;mov cl, 0x02 ; cl <- sector (0x01 .. 0x11)
; 0x01 is our boot sector, 0x02 is the first 'available' sector
;mov ch, 0x00 ; ch <- cylinder (0x0 .. 0x3FF, upper 2 bits in 'cl')
; dl <- drive number. Our caller sets it as a parameter and gets it from BIOS
; (0 = floppy, 1 = floppy2, 0x80 = hdd, 0x81 = hdd2)

; [es:bx] <- pointer to buffer where the data will be stored
; caller sets it up for us, and it is actually the standard location for int 13h
int 0x13 ; BIOS interrupt
jc disk_error ; if error (stored in the carry bit)
; [es:bx] <- pointer to buffer where the data will be stored
; caller sets it up for us, and it is actually the standard location for int 13h
int 0x13 ; BIOS interrupt
jc disk_error ; if error (stored in the carry bit)

cmp al, 1 ; BIOS also sets 'al' to the # of sectors read. Compare it.
jne sectors_error
popa
ret
cmp al, 1 ; BIOS also sets 'al' to the # of sectors read. Compare it.
jne sectors_error
popa
ret


disk_error:
@@ -37,11 +37,11 @@ disk_error:
jmp retry ;Try again. Forever.

sectors_error:
mov bx, SECTORS_ERROR
call print
mov bx, SECTORS_ERROR
call print

disk_loop:
jmp $
jmp $

DISK_ERROR: db "Disk read error", 0
SECTORS_ERROR: db "Incorrect number of sectors read", 0

+ 17
- 17
boot/gdt.asm View File

@@ -1,34 +1,34 @@
gdt_start: ; don't remove the labels, they're needed to compute sizes and jumps
; the GDT starts with a null 8-byte
dd 0x0 ; 4 byte
dd 0x0 ; 4 byte
; the GDT starts with a null 8-byte
dd 0x0 ; 4 byte
dd 0x0 ; 4 byte

; GDT for code segment. base = 0x00000000, length = 0xfffff
; for flags, refer to os-dev.pdf document, page 36
gdt_code:
dw 0xffff ; segment length, bits 0-15
dw 0x0 ; segment base, bits 0-15
db 0x0 ; segment base, bits 16-23
db 10011010b ; flags (8 bits)
db 11001111b ; flags (4 bits) + segment length, bits 16-19
db 0x0 ; segment base, bits 24-31
dw 0xffff ; segment length, bits 0-15
dw 0x0 ; segment base, bits 0-15
db 0x0 ; segment base, bits 16-23
db 10011010b ; flags (8 bits)
db 11001111b ; flags (4 bits) + segment length, bits 16-19
db 0x0 ; segment base, bits 24-31

; GDT for data segment. base and length identical to code segment
; some flags changed, again, refer to os-dev.pdf
gdt_data:
dw 0xffff
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
dw 0xffff
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0

gdt_end:

; GDT descriptor
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; size (16 bit), always one less of its true size
dd gdt_start ; address (32 bit)
dw gdt_end - gdt_start - 1 ; size (16 bit), always one less of its true size
dd gdt_start ; address (32 bit)

; define some constants for later use
CODE_SEG equ gdt_code - gdt_start


+ 22
- 22
boot/print.asm View File

@@ -1,37 +1,37 @@
print:
pusha
pusha

; keep this in mind:
; while (string[i] != 0) { print string[i]; i++ }

; the comparison for string end (null byte)
start:
mov al, [bx] ; 'bx' is the base address for the string
cmp al, 0
je done
mov al, [bx] ; 'bx' is the base address for the string
cmp al, 0
je done

; the part where we print with the BIOS help
mov ah, 0x0e
int 0x10 ; 'al' already contains the char
; the part where we print with the BIOS help
mov ah, 0x0e
int 0x10 ; 'al' already contains the char

; increment pointer and do next loop
add bx, 1
jmp start
; increment pointer and do next loop
add bx, 1
jmp start

done:
popa
ret
popa
ret



print_nl:
pusha
mov ah, 0x0e
mov al, 0x0a ; newline char
int 0x10
mov al, 0x0d ; carriage return
int 0x10
popa
ret
pusha
mov ah, 0x0e
mov al, 0x0a ; newline char
int 0x10
mov al, 0x0d ; carriage return
int 0x10
popa
ret

+ 28
- 28
boot/print_hex.asm View File

@@ -1,46 +1,46 @@
; receiving the data in 'dx'
; For the examples we'll assume that we're called with dx=0x1234
print_hex:
pusha
pusha

mov cx, 0 ; our index variable
mov cx, 0 ; our index variable

; Strategy: get the last char of 'dx', then convert to ASCII
; Numeric ASCII values: '0' (ASCII 0x30) to '9' (0x39), so just add 0x30 to byte N.
; For alphabetic characters A-F: 'A' (ASCII 0x41) to 'F' (0x46) we'll add 0x40
; Then, move the ASCII byte to the correct position on the resulting string
hex_loop:
cmp cx, 4 ; loop 4 times
je end
; 1. convert last char of 'dx' to ascii
mov ax, dx ; we will use 'ax' as our working register
and ax, 0x000f ; 0x1234 -> 0x0004 by masking first three to zeros
add al, 0x30 ; add 0x30 to N to convert it to ASCII "N"
cmp al, 0x39 ; if > 9, add extra 8 to represent 'A' to 'F'
jle step2
add al, 7 ; 'A' is ASCII 65 instead of 58, so 65-58=7
cmp cx, 4 ; loop 4 times
je end
; 1. convert last char of 'dx' to ascii
mov ax, dx ; we will use 'ax' as our working register
and ax, 0x000f ; 0x1234 -> 0x0004 by masking first three to zeros
add al, 0x30 ; add 0x30 to N to convert it to ASCII "N"
cmp al, 0x39 ; if > 9, add extra 8 to represent 'A' to 'F'
jle step2
add al, 7 ; 'A' is ASCII 65 instead of 58, so 65-58=7

step2:
; 2. get the correct position of the string to place our ASCII char
; bx <- base address + string length - index of char
mov bx, HEX_OUT + 5 ; base + length
sub bx, cx ; our index variable
mov [bx], al ; copy the ASCII char on 'al' to the position pointed by 'bx'
ror dx, 4 ; 0x1234 -> 0x4123 -> 0x3412 -> 0x2341 -> 0x1234
; 2. get the correct position of the string to place our ASCII char
; bx <- base address + string length - index of char
mov bx, HEX_OUT + 5 ; base + length
sub bx, cx ; our index variable
mov [bx], al ; copy the ASCII char on 'al' to the position pointed by 'bx'
ror dx, 4 ; 0x1234 -> 0x4123 -> 0x3412 -> 0x2341 -> 0x1234

; increment index and loop
add cx, 1
jmp hex_loop
; increment index and loop
add cx, 1
jmp hex_loop

end:
; prepare the parameter and call the function
; remember that print receives parameters in 'bx'
mov bx, HEX_OUT
call print
; prepare the parameter and call the function
; remember that print receives parameters in 'bx'
mov bx, HEX_OUT
call print

popa
ret
popa
ret

HEX_OUT:
db '0x0000',0 ; reserve memory for our new string
db '0x0000',0 ; reserve memory for our new string

+ 15
- 15
boot/switch_pm.asm View File

@@ -1,22 +1,22 @@
[bits 16]
switch_to_pm:
cli ; 1. disable interrupts
lgdt [gdt_descriptor] ; 2. load the GDT descriptor
mov eax, cr0
or eax, 0x1 ; 3. set 32-bit mode bit in cr0
mov cr0, eax
jmp CODE_SEG:init_pm ; 4. far jump by using a different segment
cli ; 1. disable interrupts
lgdt [gdt_descriptor] ; 2. load the GDT descriptor
mov eax, cr0
or eax, 0x1 ; 3. set 32-bit mode bit in cr0
mov cr0, eax
jmp CODE_SEG:init_pm ; 4. far jump by using a different segment

[bits 32]
init_pm: ; we are now using 32-bit instructions
mov ax, DATA_SEG ; 5. update the segment registers
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, DATA_SEG ; 5. update the segment registers
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax

mov ebp, 0x90000 ; 6. update the stack right at the top of the free space
mov esp, ebp
mov ebp, 0x90000 ; 6. update the stack right at the top of the free space
mov esp, ebp

call BEGIN_PM ; 7. Call a well-known label with useful code
call BEGIN_PM ; 7. Call a well-known label with useful code

+ 9
- 9
cpu/idt.c View File

@@ -1,16 +1,16 @@
#include "idt.h"

void set_idt_gate(int n, u32 handler) {
idt[n].low_offset = low_16(handler);
idt[n].sel = KERNEL_CS;
idt[n].always0 = 0;
idt[n].flags = 0x8E;
idt[n].high_offset = high_16(handler);
idt[n].low_offset = low_16(handler);
idt[n].sel = KERNEL_CS;
idt[n].always0 = 0;
idt[n].flags = 0x8E;
idt[n].high_offset = high_16(handler);
}

void set_idt() {
idt_reg.base = (u32) &idt;
idt_reg.limit = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
/* Don't make the mistake of loading &idt -- always load &idt_reg */
__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
idt_reg.base = (u32) &idt;
idt_reg.limit = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
/* Don't make the mistake of loading &idt -- always load &idt_reg */
__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
}

+ 12
- 12
cpu/idt.h View File

@@ -8,23 +8,23 @@

/* How every interrupt gate (handler) is defined */
typedef struct {
u16 low_offset; /* Lower 16 bits of handler function address */
u16 sel; /* Kernel segment selector */
u8 always0;
/* First byte
* Bit 7: "Interrupt is present"
* Bits 6-5: Privilege level of caller (0=kernel..3=user)
* Bit 4: Set to 0 for interrupt gates
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
u8 flags;
u16 high_offset; /* Higher 16 bits of handler function address */
u16 low_offset; /* Lower 16 bits of handler function address */
u16 sel; /* Kernel segment selector */
u8 always0;
/* First byte
* Bit 7: "Interrupt is present"
* Bits 6-5: Privilege level of caller (0=kernel..3=user)
* Bit 4: Set to 0 for interrupt gates
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
u8 flags;
u16 high_offset; /* Higher 16 bits of handler function address */
} __attribute__((packed)) idt_gate_t ;

/* A pointer to the array of interrupt handlers.
* Assembly instruction 'lidt' will read it */
typedef struct {
u16 limit;
u32 base;
u16 limit;
u32 base;
} __attribute__((packed)) idt_register_t;

#define IDT_ENTRIES 256


+ 143
- 143
cpu/interrupt.asm View File

@@ -4,7 +4,7 @@

; Common ISR code
isr_common_stub:
; 1. Save CPU state
; 1. Save CPU state
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov ax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor
@@ -14,10 +14,10 @@ isr_common_stub:
mov fs, ax
mov gs, ax
; 2. Call C handler
; 2. Call C handler
call isr_handler
; 3. Restore state
; 3. Restore state
pop eax
mov ds, ax
mov es, ax
@@ -31,24 +31,24 @@ isr_common_stub:
; Common IRQ code. Identical to ISR code except for the 'call'
; and the 'pop ebx'
irq_common_stub:
pusha
mov ax, ds
push eax
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call irq_handler ; Different than the ISR code
pop ebx ; Different than the ISR code
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
popa
add esp, 8
sti
iret
pusha
mov ax, ds
push eax
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call irq_handler ; Different than the ISR code
pop ebx ; Different than the ISR code
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
popa
add esp, 8
sti
iret
; We don't get information about which interrupt was caller
; when the handler is run, so we will need to have a different handler
@@ -110,221 +110,221 @@ global irq15

; 0: Divide By Zero Exception
isr0:
cli
push byte 0
push byte 0
jmp isr_common_stub
cli
push byte 0
push byte 0
jmp isr_common_stub

; 1: Debug Exception
isr1:
cli
push byte 0
push byte 1
jmp isr_common_stub
cli
push byte 0
push byte 1
jmp isr_common_stub

; 2: Non Maskable Interrupt Exception
isr2:
cli
push byte 0
push byte 2
jmp isr_common_stub
cli
push byte 0
push byte 2
jmp isr_common_stub

; 3: Int 3 Exception
isr3:
cli
push byte 0
push byte 3
jmp isr_common_stub
cli
push byte 0
push byte 3
jmp isr_common_stub

; 4: INTO Exception
isr4:
cli
push byte 0
push byte 4
jmp isr_common_stub
cli
push byte 0
push byte 4
jmp isr_common_stub

; 5: Out of Bounds Exception
isr5:
cli
push byte 0
push byte 5
jmp isr_common_stub
cli
push byte 0
push byte 5
jmp isr_common_stub

; 6: Invalid Opcode Exception
isr6:
cli
push byte 0
push byte 6
jmp isr_common_stub
cli
push byte 0
push byte 6
jmp isr_common_stub

; 7: Coprocessor Not Available Exception
isr7:
cli
push byte 0
push byte 7
jmp isr_common_stub
cli
push byte 0
push byte 7
jmp isr_common_stub

; 8: Double Fault Exception (With Error Code!)
isr8:
cli
push byte 8
jmp isr_common_stub
cli
push byte 8
jmp isr_common_stub

; 9: Coprocessor Segment Overrun Exception
isr9:
cli
push byte 0
push byte 9
jmp isr_common_stub
cli
push byte 0
push byte 9
jmp isr_common_stub

; 10: Bad TSS Exception (With Error Code!)
isr10:
cli
push byte 10
jmp isr_common_stub
cli
push byte 10
jmp isr_common_stub

; 11: Segment Not Present Exception (With Error Code!)
isr11:
cli
push byte 11
jmp isr_common_stub
cli
push byte 11
jmp isr_common_stub

; 12: Stack Fault Exception (With Error Code!)
isr12:
cli
push byte 12
jmp isr_common_stub
cli
push byte 12
jmp isr_common_stub

; 13: General Protection Fault Exception (With Error Code!)
isr13:
cli
push byte 13
jmp isr_common_stub
cli
push byte 13
jmp isr_common_stub

; 14: Page Fault Exception (With Error Code!)
isr14:
cli
push byte 14
jmp isr_common_stub
cli
push byte 14
jmp isr_common_stub

; 15: Reserved Exception
isr15:
cli
push byte 0
push byte 15
jmp isr_common_stub
cli
push byte 0
push byte 15
jmp isr_common_stub

; 16: Floating Point Exception
isr16:
cli
push byte 0
push byte 16
jmp isr_common_stub
cli
push byte 0
push byte 16
jmp isr_common_stub

; 17: Alignment Check Exception
isr17:
cli
push byte 0
push byte 17
jmp isr_common_stub
cli
push byte 0
push byte 17
jmp isr_common_stub

; 18: Machine Check Exception
isr18:
cli
push byte 0
push byte 18
jmp isr_common_stub
cli
push byte 0
push byte 18
jmp isr_common_stub

; 19: Reserved
isr19:
cli
push byte 0
push byte 19
jmp isr_common_stub
cli
push byte 0
push byte 19
jmp isr_common_stub

; 20: Reserved
isr20:
cli
push byte 0
push byte 20
jmp isr_common_stub
cli
push byte 0
push byte 20
jmp isr_common_stub

; 21: Reserved
isr21:
cli
push byte 0
push byte 21
jmp isr_common_stub
cli
push byte 0
push byte 21
jmp isr_common_stub

; 22: Reserved
isr22:
cli
push byte 0
push byte 22
jmp isr_common_stub
cli
push byte 0
push byte 22
jmp isr_common_stub

; 23: Reserved
isr23:
cli
push byte 0
push byte 23
jmp isr_common_stub
cli
push byte 0
push byte 23
jmp isr_common_stub

; 24: Reserved
isr24:
cli
push byte 0
push byte 24
jmp isr_common_stub
cli
push byte 0
push byte 24
jmp isr_common_stub

; 25: Reserved
isr25:
cli
push byte 0
push byte 25
jmp isr_common_stub
cli
push byte 0
push byte 25
jmp isr_common_stub

; 26: Reserved
isr26:
cli
push byte 0
push byte 26
jmp isr_common_stub
cli
push byte 0
push byte 26
jmp isr_common_stub

; 27: Reserved
isr27:
cli
push byte 0
push byte 27
jmp isr_common_stub
cli
push byte 0
push byte 27
jmp isr_common_stub

; 28: Reserved
isr28:
cli
push byte 0
push byte 28
jmp isr_common_stub
cli
push byte 0
push byte 28
jmp isr_common_stub

; 29: Reserved
isr29:
cli
push byte 0
push byte 29
jmp isr_common_stub
cli
push byte 0
push byte 29
jmp isr_common_stub

; 30: Reserved
isr30:
cli
push byte 0
push byte 30
jmp isr_common_stub
cli
push byte 0
push byte 30
jmp isr_common_stub

; 31: Reserved
isr31:
cli
push byte 0
push byte 31
jmp isr_common_stub
cli
push byte 0
push byte 31
jmp isr_common_stub

; IRQ handlers
irq0:


+ 114
- 114
cpu/isr.c View File

@@ -11,141 +11,141 @@ isr_t interrupt_handlers[256];
/* Can't do this with a loop because we need the address
* of the function names */
void isr_install() {
set_idt_gate(0, (u32)isr0);
set_idt_gate(1, (u32)isr1);
set_idt_gate(2, (u32)isr2);
set_idt_gate(3, (u32)isr3);
set_idt_gate(4, (u32)isr4);
set_idt_gate(5, (u32)isr5);
set_idt_gate(6, (u32)isr6);
set_idt_gate(7, (u32)isr7);
set_idt_gate(8, (u32)isr8);
set_idt_gate(9, (u32)isr9);
set_idt_gate(10, (u32)isr10);
set_idt_gate(11, (u32)isr11);
set_idt_gate(12, (u32)isr12);
set_idt_gate(13, (u32)isr13);
set_idt_gate(14, (u32)isr14);
set_idt_gate(15, (u32)isr15);
set_idt_gate(16, (u32)isr16);
set_idt_gate(17, (u32)isr17);
set_idt_gate(18, (u32)isr18);
set_idt_gate(19, (u32)isr19);
set_idt_gate(20, (u32)isr20);
set_idt_gate(21, (u32)isr21);
set_idt_gate(22, (u32)isr22);
set_idt_gate(23, (u32)isr23);
set_idt_gate(24, (u32)isr24);
set_idt_gate(25, (u32)isr25);
set_idt_gate(26, (u32)isr26);
set_idt_gate(27, (u32)isr27);
set_idt_gate(28, (u32)isr28);
set_idt_gate(29, (u32)isr29);
set_idt_gate(30, (u32)isr30);
set_idt_gate(31, (u32)isr31);
set_idt_gate(0, (u32)isr0);
set_idt_gate(1, (u32)isr1);
set_idt_gate(2, (u32)isr2);
set_idt_gate(3, (u32)isr3);
set_idt_gate(4, (u32)isr4);
set_idt_gate(5, (u32)isr5);
set_idt_gate(6, (u32)isr6);
set_idt_gate(7, (u32)isr7);
set_idt_gate(8, (u32)isr8);
set_idt_gate(9, (u32)isr9);
set_idt_gate(10, (u32)isr10);
set_idt_gate(11, (u32)isr11);
set_idt_gate(12, (u32)isr12);
set_idt_gate(13, (u32)isr13);
set_idt_gate(14, (u32)isr14);
set_idt_gate(15, (u32)isr15);
set_idt_gate(16, (u32)isr16);
set_idt_gate(17, (u32)isr17);
set_idt_gate(18, (u32)isr18);
set_idt_gate(19, (u32)isr19);
set_idt_gate(20, (u32)isr20);
set_idt_gate(21, (u32)isr21);
set_idt_gate(22, (u32)isr22);
set_idt_gate(23, (u32)isr23);
set_idt_gate(24, (u32)isr24);
set_idt_gate(25, (u32)isr25);
set_idt_gate(26, (u32)isr26);
set_idt_gate(27, (u32)isr27);
set_idt_gate(28, (u32)isr28);
set_idt_gate(29, (u32)isr29);
set_idt_gate(30, (u32)isr30);
set_idt_gate(31, (u32)isr31);

// Remap the PIC
port_byte_out(0x20, 0x11);
port_byte_out(0xA0, 0x11);
port_byte_out(0x21, 0x20);
port_byte_out(0xA1, 0x28);
port_byte_out(0x21, 0x04);
port_byte_out(0xA1, 0x02);
port_byte_out(0x21, 0x01);
port_byte_out(0xA1, 0x01);
port_byte_out(0x21, 0x0);
port_byte_out(0xA1, 0x0);
// Remap the PIC
port_byte_out(0x20, 0x11);
port_byte_out(0xA0, 0x11);
port_byte_out(0x21, 0x20);
port_byte_out(0xA1, 0x28);
port_byte_out(0x21, 0x04);
port_byte_out(0xA1, 0x02);
port_byte_out(0x21, 0x01);
port_byte_out(0xA1, 0x01);
port_byte_out(0x21, 0x0);
port_byte_out(0xA1, 0x0);

// Install the IRQs
set_idt_gate(32, (u32)irq0);
set_idt_gate(33, (u32)irq1);
set_idt_gate(34, (u32)irq2);
set_idt_gate(35, (u32)irq3);
set_idt_gate(36, (u32)irq4);
set_idt_gate(37, (u32)irq5);
set_idt_gate(38, (u32)irq6);
set_idt_gate(39, (u32)irq7);
set_idt_gate(40, (u32)irq8);
set_idt_gate(41, (u32)irq9);
set_idt_gate(42, (u32)irq10);
set_idt_gate(43, (u32)irq11);
set_idt_gate(44, (u32)irq12);
set_idt_gate(45, (u32)irq13);
set_idt_gate(46, (u32)irq14);
set_idt_gate(47, (u32)irq15);
// Install the IRQs
set_idt_gate(32, (u32)irq0);
set_idt_gate(33, (u32)irq1);
set_idt_gate(34, (u32)irq2);
set_idt_gate(35, (u32)irq3);
set_idt_gate(36, (u32)irq4);
set_idt_gate(37, (u32)irq5);
set_idt_gate(38, (u32)irq6);
set_idt_gate(39, (u32)irq7);
set_idt_gate(40, (u32)irq8);
set_idt_gate(41, (u32)irq9);
set_idt_gate(42, (u32)irq10);
set_idt_gate(43, (u32)irq11);
set_idt_gate(44, (u32)irq12);
set_idt_gate(45, (u32)irq13);
set_idt_gate(46, (u32)irq14);
set_idt_gate(47, (u32)irq15);

set_idt(); // Load with ASM
set_idt(); // Load with ASM
}

/* To print the message which defines every exception */
char *exception_messages[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",

"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",

"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",

"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};

void isr_handler(registers_t r) {
println("received interrupt: ");
char s[3];
int_to_ascii(r.int_no, s);
println(s);
println(exception_messages[r.int_no]);
println("received interrupt: ");
char s[3];
int_to_ascii(r.int_no, s);
println(s);
println(exception_messages[r.int_no]);
}

void register_interrupt_handler(u8 n, isr_t handler) {
interrupt_handlers[n] = handler;
interrupt_handlers[n] = handler;
}

void irq_handler(registers_t r) {
/* After every interrupt we need to send an EOI to the PICs
* or they will not send another interrupt again */
if (r.int_no >= 40) port_byte_out(0xA0, 0x20); /* slave */
port_byte_out(0x20, 0x20); /* master */
/* After every interrupt we need to send an EOI to the PICs
* or they will not send another interrupt again */
if (r.int_no >= 40) port_byte_out(0xA0, 0x20); /* slave */
port_byte_out(0x20, 0x20); /* master */

/* Handle the interrupt in a more modular way */
if (interrupt_handlers[r.int_no] != 0) {
isr_t handler = interrupt_handlers[r.int_no];
handler(r);
}
/* Handle the interrupt in a more modular way */
if (interrupt_handlers[r.int_no] != 0) {
isr_t handler = interrupt_handlers[r.int_no];
handler(r);
}
}

void irq_install() {
/* Enable interruptions */
asm volatile("sti");
/* IRQ0: timer */
init_timer(50);
/* IRQ1: keyboard */
init_keyboard();
/* Enable interruptions */
asm volatile("sti");
/* IRQ0: timer */
init_timer(50);
/* IRQ1: keyboard */
init_keyboard();
}

+ 21
- 21
cpu/ports.c View File

@@ -4,34 +4,34 @@
* Read a byte from the specified port
*/
u8 port_byte_in (u16 port) {
u8 result;
/* Inline assembler syntax
* !! Notice how the source and destination registers are switched from NASM !!
*
* '"=a" (result)'; set '=' the C variable '(result)' to the value of register e'a'x
* '"d" (port)': map the C variable '(port)' into e'd'x register
*
* Inputs and outputs are separated by colons
*/
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
return result;
u8 result;
/* Inline assembler syntax
* !! Notice how the source and destination registers are switched from NASM !!
*
* '"=a" (result)'; set '=' the C variable '(result)' to the value of register e'a'x
* '"d" (port)': map the C variable '(port)' into e'd'x register
*
* Inputs and outputs are separated by colons
*/
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
return result;
}

void port_byte_out (u16 port, u8 data) {
/* Notice how here both registers are mapped to C variables and
* nothing is returned, thus, no equals '=' in the asm syntax
* However we see a comma since there are two variables in the input area
* and none in the 'return' area
*/
__asm__ __volatile__("out %%al, %%dx" : : "a" (data), "d" (port));
/* Notice how here both registers are mapped to C variables and
* nothing is returned, thus, no equals '=' in the asm syntax
* However we see a comma since there are two variables in the input area
* and none in the 'return' area
*/
__asm__ __volatile__("out %%al, %%dx" : : "a" (data), "d" (port));
}

u16 port_word_in (u16 port) {
u16 result;
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
return result;
u16 result;
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
return result;
}

void port_word_out (u16 port, u16 data) {
__asm__ __volatile__("out %%ax, %%dx" : : "a" (data), "d" (port));
__asm__ __volatile__("out %%ax, %%dx" : : "a" (data), "d" (port));
}

+ 31
- 31
cpu/timer.c View File

@@ -9,42 +9,42 @@ volatile u8 done = 0;
u32 countdown = 0;

static void timer_callback(registers_t regs) {
tick++;
if (!done && countdown) countdown--;
if (countdown == 0) done = 1;
UNUSED(regs);
tick++;
if (!done && countdown) countdown--;
if (countdown == 0) done = 1;
UNUSED(regs);
}

void init_timer(u32 freq) {
cl_freq = freq;
/* Install the function we just wrote */
register_interrupt_handler(IRQ0, timer_callback);
cl_freq = freq;
/* Install the function we just wrote */
register_interrupt_handler(IRQ0, timer_callback);

/* Get the PIT value: hardware clock at 1193180 Hz */
u32 divisor = 1193180 / freq;
u8 low = (u8)(divisor & 0xFF);
u8 high = (u8)( (divisor >> 8) & 0xFF);
/* Send the command */
port_byte_out(0x43, 0x36); /* Command port */
port_byte_out(0x40, low);
port_byte_out(0x40, high);
/* Get the PIT value: hardware clock at 1193180 Hz */
u32 divisor = 1193180 / freq;
u8 low = (u8)(divisor & 0xFF);
u8 high = (u8)( (divisor >> 8) & 0xFF);
/* Send the command */
port_byte_out(0x43, 0x36); /* Command port */
port_byte_out(0x40, low);
port_byte_out(0x40, high);
}

void delay(u32 ms) {
if (cl_freq == 0) return; //Timer isn't initialized, so don't delay
done = 0;
countdown = ms * cl_freq / 1000;
while (!done) { //TODO: Lower CPU clock speed to save some power
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
}
return;
if (cl_freq == 0) return; //Timer isn't initialized, so don't delay
done = 0;
countdown = ms * cl_freq / 1000;
while (!done) { //TODO: Lower CPU clock speed to save some power
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
__asm__("nop");
}
return;
}

+ 3
- 3
cpu/types.h View File

@@ -4,11 +4,11 @@
/* Instead of using 'chars' to allocate non-character bytes,
* we will use these new type with no semantic meaning */
typedef unsigned int u32;
typedef int s32;
typedef int s32;
typedef unsigned short u16;
typedef short s16;
typedef short s16;
typedef unsigned char u8;
typedef char s8;
typedef char s8;

#define low_16(address) (u16)((address) & 0xFFFF)
#define high_16(address) (u16)(((address) >> 16) & 0xFFFF)


+ 26
- 26
drivers/keyboard.c View File

@@ -11,24 +11,24 @@ static u8 uppercase = 0;

#define SC_MAX 57
const char *sc_name[] = { "ERROR", "Esc", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0", "-", "=", "Backspace", "Tab", "Q", "W", "E",
"R", "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Lctrl",
"A", "S", "D", "F", "G", "H", "J", "K", "L", ";", "'", "`",
"LShift", "\\", "Z", "X", "C", "V", "B", "N", "M", ",", ".",
"/", "RShift", "Keypad *", "LAlt", "Spacebar"};
"7", "8", "9", "0", "-", "=", "Backspace", "Tab", "Q", "W", "E",
"R", "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Lctrl",
"A", "S", "D", "F", "G", "H", "J", "K", "L", ";", "'", "`",
"LShift", "\\", "Z", "X", "C", "V", "B", "N", "M", ",", ".",
"/", "RShift", "Keypad *", "LAlt", "Spacebar"};
const char sc_ascii[] = { '?', '?', '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', '?', '?', 'Q', 'W', 'E', 'R', 'T', 'Y',
'U', 'I', 'O', 'P', '[', ']', '?', '?', 'A', 'S', 'D', 'F', 'G',
'H', 'J', 'K', 'L', ';', '\'', '`', '?', '\\', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', ',', '.', '/', '?', '*', '?', ' '};
'7', '8', '9', '0', '-', '=', '?', '?', 'Q', 'W', 'E', 'R', 'T', 'Y',
'U', 'I', 'O', 'P', '[', ']', '?', '?', 'A', 'S', 'D', 'F', 'G',
'H', 'J', 'K', 'L', ';', '\'', '`', '?', '\\', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', ',', '.', '/', '?', '*', '?', ' '};

const char sc_shift_below[] = { '?', '?', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '?', '?'};
const char sc_shift_middle[] = { ':', '"', '~', '?', '|'}; //0x27 to 0x2B
const char sc_shift_above[] = { '<', '>', '?', '?', '*', '?', ' '}; //0x33 to 0x39

static void keyboard_callback(registers_t regs) {
/* The PIC leaves us the scancode in port 0x60 */
u8 scancode = port_byte_in(0x60);
/* The PIC leaves us the scancode in port 0x60 */
u8 scancode = port_byte_in(0x60);
u8 special = 1;

if (scancode > SC_MAX)
@@ -38,36 +38,36 @@ static void keyboard_callback(registers_t regs) {
{
uppercase = 0;
}
}
else {
if (scancode == LSHIFT || scancode == RSHIFT)
}
else {
if (scancode == LSHIFT || scancode == RSHIFT)
{
uppercase = 1;
}
else
{
char letter = sc_ascii[(int)scancode];
char letter = sc_ascii[(int)scancode];
if (letter >= 65 && letter <= 90) {
letter += 32 * !uppercase; //Remove 32 from letter(make it lower case) if uppercase is false
special = 0;
}
else if (uppercase)
}
else if (uppercase)
{
if (scancode < 0x10)
if (scancode < 0x10)
{
special = 0;
letter = sc_shift_below[scancode];
}
letter = sc_shift_below[scancode];
}
else if (scancode >= 0x27 && scancode <= 0x2B)
{
special = 0;
letter = sc_shift_middle[scancode - 0x27];
}
letter = sc_shift_middle[scancode - 0x27];
}
else if (scancode >= 0x33 && scancode <= 0x39)
{
special = 0;
letter = sc_shift_above[scancode - 0x33];
}
letter = sc_shift_above[scancode - 0x33];
}
}
else if ((scancode >= 0x02 && scancode <= 0x0D) || (scancode >= 0x27 && scancode <= 0x29) ||
(scancode >= 0x33 && scancode <= 0x35) || scancode == 0x2B || scancode == 0x39) {
@@ -83,8 +83,8 @@ static void keyboard_callback(registers_t regs) {
keyboard_handler(letter);
}
}
}
UNUSED(regs);
}
UNUSED(regs);
}

void init_keyboard() {


+ 14
- 14
drivers/screen.c View File

@@ -18,12 +18,12 @@ int get_offset_row(int offset);
int get_offset_col(int offset);

/**********************************************************
* Public Kernel API functions *
* Public Kernel API functions *
**********************************************************/

void putpixel(int x, int y, u32 fg) {
unsigned where = x*COLOR_BITS/8 + y*SCN_PITCH; //TODO: Should come from above function
u8 *screen = (u8*) VIDEO_ADDRESS;
unsigned where = x*COLOR_BITS/8 + y*SCN_PITCH; //TODO: Should come from above function
u8 *screen = (u8*) VIDEO_ADDRESS;

//TODO: Is there a way to set these all at once?
for (int j = 0; j < COLOR_BITS/8; j++) {
@@ -32,23 +32,23 @@ void putpixel(int x, int y, u32 fg) {
}

void fillrect(int x, int y, u32 fg, int w, int h) {
unsigned where = x*COLOR_BITS/8 + y*SCN_PITCH;
u8 *screen = (u8*) VIDEO_ADDRESS;
int i, j;
unsigned where = x*COLOR_BITS/8 + y*SCN_PITCH;
u8 *screen = (u8*) VIDEO_ADDRESS;
int i, j;

for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
//TODO: Is there a way to set these all at once?
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
//TODO: Is there a way to set these all at once?
for (int k = 0; k < COLOR_BITS/8; k++) {
screen[where + (int)(j*COLOR_BITS/8) + k] = (fg >> k*8) & 255;
}
}
where += SCN_PITCH;
}
}
where += SCN_PITCH;
}
}

void scroll_up(u8 lines) { //NOTE: Does not clear the bottom lines!
memory_copy((u8 *)(VIDEO_ADDRESS + lines * SCN_PITCH), (u8 *)VIDEO_ADDRESS, (SCN_HEIGHT - lines) * SCN_PITCH);
memory_copy((u8 *)(VIDEO_ADDRESS + lines * SCN_PITCH), (u8 *)VIDEO_ADDRESS, (SCN_HEIGHT - lines) * SCN_PITCH);
}

u32 color_to_pixel(Color_t color)
@@ -66,7 +66,7 @@ u32 color_to_pixel(Color_t color)
}

/**********************************************************
* Private kernel functions *
* Private kernel functions *
**********************************************************/




+ 35
- 35
kernel/kernel.c View File

@@ -12,54 +12,54 @@
void generate_fractal(u16 x, u16 y, u16 w, u16 h);

void main() {
isr_install();
irq_install();
isr_install();
irq_install();

setup_video();
setup_video();

set_background(0, 100, 100);
clear_screen();
set_background(0, 100, 100);
clear_screen();

print_centered(SCN_WIDTH, 8, "_______ _________ _______ _______ _______ _______ ");
print_centered(SCN_WIDTH, 16,"( ____ \\\\__ __/( ____ \\|\\ /|( ____ \\( ___ )( ____ \\");
print_centered(SCN_WIDTH, 24,"| ( \\/ ) ( | ( \\/| ) ( || ( \\/| ( ) || ( \\/");
print_centered(SCN_WIDTH, 32, "| (_____ | | | (__ | | | || (__ | | | || (_____ ");
print_centered(SCN_WIDTH, 40, "(_____ ) | | | __) ( ( ) )| __) | | | |(_____ )");
print_centered(SCN_WIDTH, 48, " ) | | | | ( \\ \\_/ / | ( | | | | ) |");
print_centered(SCN_WIDTH, 56, "/\\____) | | | | (____/\\ \\ / | (____/\\| (___) |/\\____) |");
print_centered(SCN_WIDTH, 64, "\\_______) )_( (_______/ \\_/ (_______/(_______)\\_______)");
set_offset(0, 80);
print_centered(SCN_WIDTH, 8, "_______ _________ _______ _______ _______ _______ ");
print_centered(SCN_WIDTH, 16,"( ____ \\\\__ __/( ____ \\|\\ /|( ____ \\( ___ )( ____ \\");
print_centered(SCN_WIDTH, 24,"| ( \\/ ) ( | ( \\/| ) ( || ( \\/| ( ) || ( \\/");
print_centered(SCN_WIDTH, 32, "| (_____ | | | (__ | | | || (__ | | | || (_____ ");
print_centered(SCN_WIDTH, 40, "(_____ ) | | | __) ( ( ) )| __) | | | |(_____ )");
print_centered(SCN_WIDTH, 48, " ) | | | | ( \\ \\_/ / | ( | | | | ) |");
print_centered(SCN_WIDTH, 56, "/\\____) | | | | (____/\\ \\ / | (____/\\| (___) |/\\____) |");
print_centered(SCN_WIDTH, 64, "\\_______) )_( (_______/ \\_/ (_______/(_______)\\_______)");
set_offset(0, 80);

generate_fractal(SCN_WIDTH - 64 - 8, 8, 64, 64);
generate_fractal(SCN_WIDTH - 64 - 8, 8, 64, 64);

// if (!init_floppy()) {
// println("WARNING: This type of floppy drive is not supported by the system.");
//}
// if (!init_floppy()) {
// println("WARNING: This type of floppy drive is not supported by the system.");
//}

println("STEVEOS V0.0.2");
println("WRITTEN BY STEPHEN DOWNWARD");
println("TYPE \"HELP\" FOR HELP.");
print("> ");
println("STEVEOS V0.0.2");
println("WRITTEN BY STEPHEN DOWNWARD");
println("TYPE \"HELP\" FOR HELP.");
print("> ");

register_commands();
register_commands();
}

//Mandelbrot Generator
void generate_fractal(u16 x, u16 y, u16 w, u16 h) {
for(int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
double Zr = 0;
double Zrt = 0; //Temp
double Zi = 0;
for(int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
double Zr = 0;
double Zrt = 0; //Temp
double Zi = 0;

double Cr = ((double)i/w)*3 - 2;
double Ci = ((double)j/h)*3 - 1.5;
double Cr = ((double)i/w)*3 - 2;
double Ci = ((double)j/h)*3 - 1.5;

int numIterations = 0;
u8 painted = 0;
while (numIterations < 255) {
numIterations++;
Zrt = Zr * Zr + Cr - (Zi * Zi);
int numIterations = 0;
u8 painted = 0;
while (numIterations < 255) {
numIterations++;
Zrt = Zr * Zr + Cr - (Zi * Zi);
Zi = 2 * Zi * Zr + Ci;
Zr = Zrt;


+ 6
- 6
libc/mem.c View File

@@ -1,13 +1,13 @@
#include "mem.h"

void memory_copy(u8 *source, u8 *dest, int nbytes) {
int i;
for (i = 0; i < nbytes; i++) {
*(dest + i) = *(source + i);
}
int i;
for (i = 0; i < nbytes; i++) {
*(dest + i) = *(source + i);
}
}

void memory_set(u8 *dest, u8 val, u32 len) {
u8 *temp = (u8 *)dest;
for ( ; len != 0; len--) *temp++ = val;
u8 *temp = (u8 *)dest;
for ( ; len != 0; len--) *temp++ = val;
}

+ 33
- 33
libc/string.c View File

@@ -4,76 +4,76 @@
* K&R implementation
*/
void int_to_ascii(int n, char str[]) {
int i, sign;
if ((sign = n) < 0) n = -n;
i = 0;
do {
str[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
int i, sign;
if ((sign = n) < 0) n = -n;
i = 0;
do {
str[i++] = n % 10 + '0';
} while ((n /= 10) > 0);

if (sign < 0) str[i++] = '-';
str[i] = '\0';
if (sign < 0) str[i++] = '-';
str[i] = '\0';

reverse(str);
reverse(str);
}

/* K&R */
void reverse(char s[]) {
int c, i, j;
for (i = 0, j = strlen(s)-1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
int c, i, j;
for (i = 0, j = strlen(s)-1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}

/* K&R */
int strlen(char s[]) {
int i = 0;
while (s[i] != '\0') ++i;
return i;
int i = 0;
while (s[i] != '\0') ++i;
return i;
}

void append(char s[], char n) {
int len = strlen(s);
s[len] = n;
s[len+1] = '\0';
int len = strlen(s);
s[len] = n;
s[len+1] = '\0';
}

void backspace(char s[]) {
int len = strlen(s);
s[len-1] = '\0';
int len = strlen(s);
s[len-1] = '\0';
}

/* K&R
* Returns <0 if s1<s2, 0 if s1==s2, >0 if s1>s2 */
int strcmp(char s1[], char s2[]) {
int i;
for (i = 0; s1[i] == s2[i]; i++) {
if (s1[i] == '\0') return 0;
}
return s1[i] - s2[i];
int i;
for (i = 0; s1[i] == s2[i]; i++) {
if (s1[i] == '\0') return 0;
}
return s1[i] - s2[i];
}

//New stuff

//Splits a string into 2 at a separator
void strsplit(char *orig, char separator, char *a, char *b) {
int found = 0;
for(int i = 0; i < strlen(orig); i++) {
int found = 0;
for(int i = 0; i < strlen(orig); i++) {
if (orig[i] == separator && found == 0) found = i + 1; //+1 for the seperator char
if (found > 0) {
b[i - found] = orig[i];
} else {
a[i] = orig[i];
}
}
}
}

void tolowercase(char *in) {
for(int i = 0; i < strlen(in); i++) {
for(int i = 0; i < strlen(in); i++) {
if(in[i] >= 65 && in[i] <= 90) {
in[i] += 32;
}
}
}
}

+ 14
- 14
programs/texteditor.c View File

@@ -4,28 +4,28 @@
#include "../drivers/screen.h"

void gen_padding(char *menu) {
print("=");
for(u8 i = 0; i < strlen(menu); i++) {
if (menu[i] != '|')
print("=");
else
print("|");
}
println("=");
print("=");
for(u8 i = 0; i < strlen(menu); i++) {
if (menu[i] != '|')
print("=");
else
print("|");
}
println("=");
}

void gen_menu() {
//Top bar
//Top bar
Color_t red;
red.r = 255;
fillrect(0, 0, color_to_pixel(red), SCN_WIDTH, 9);
print("File Edit Exit");
print("File Edit Exit");
}

void editor() {
//Clear screen
clear_screen();
//Clear screen
clear_screen();

//Menu setup
gen_menu();
//Menu setup
gen_menu();
}

+ 7
- 7
util/bitmap.c View File

@@ -1,14 +1,14 @@
#include "bitmap.h"

struct bitmap {
int height;
int width;
char *R, *B, *G;
int height;
int width;
char *R, *B, *G;
};

/*bitmap get_Tux() {
struct bitmap tux;
tux.height = 860;
tux.width = 712;
*tux.R = ;
struct bitmap tux;
tux.height = 860;
tux.width = 712;
*tux.R = ;
}*/

+ 16
- 14
util/commands.c View File

@@ -3,29 +3,30 @@
#include "../drivers/screen.h"
#include "../libc/function.h"
#include "../libc/string.h"
#include "../programs/texteditor.h"

void help(char *args) {
UNUSED(args);
println("Not implemented yet :( you have to pester stephen");
UNUSED(args);
println("Not implemented yet :( you have to pester stephen");
}

void echo(char *args) {
println(args);
println(args);
}

void clear(char *args) {
UNUSED(args);
clear_screen();
UNUSED(args);
clear_screen();
}

void change_bg (char *args) {
set_background((args[0] - '0' ) * 28, (args[1] - '0') * 28, (args[2] - '0') * 28);
set_background((args[0] - '0' ) * 28, (args[1] - '0') * 28, (args[2] - '0') * 28);
}

void halt_cpu(char *args) {
UNUSED(args);
println("Shutting down the CPU. Goodbye.");
__asm__ __volatile__("hlt");
UNUSED(args);
println("Shutting down the CPU. Goodbye.");
__asm__ __volatile__("hlt");
}

void video_debug(char *args) {
@@ -81,10 +82,11 @@ void video_debug(char *args) {
}

void register_commands() {
register_command("help", help);
register_command("echo", echo);
register_command("clear", clear);
register_command("bgc", change_bg);
register_command("halt", halt_cpu);
register_command("help", help);
register_command("echo", echo);
register_command("clear", clear);
register_command("bgc", change_bg);
register_command("halt", halt_cpu);
register_command("vinfo", video_debug);
register_command("edit", editor);
}

+ 99
- 99
util/font.c View File

@@ -4,125 +4,125 @@
#include "../util/types.h"

u16 characters[26 * 8 + 31 * 8 + 16*8] = {
24,24,0,24,60,60,126,126,
0,0,0,0,108,108,108,108,
108,254,254,108,108,254,254,108,
16,124,124,16,8,124,124,16,
198,206,28,56,112,224,198,6,
16,124,64,124,64,64,124,16,
0,0,0,0,6,6,6,6,
24,30,14,6,6,14,30,24,
6,30,28,24,24,28,30,6,
146,84,56,254,56,84,146,16,
0,24,24,126,126,24,24,0,
28,56,48,0,0,0,0,0,
0,0,0,252,252,0,0,0,
14,14,14,0,0,0,0,0,
6,14,28,56,112,224,192,0,
254,254,206,222,246,230,254,254,
254,254,48,48,48,62,60,56,
254,254,28,56,118,230,254,254,
254,254,192,254,254,192,254,254,
48,48,48,254,254,54,54,54,
254,254,198,192,254,6,254,254,
254,254,198,254,254,6,254,254,
48,48,48,48,48,48,62,62,
124,238,198,254,124,198,238,124,
192,192,254,254,198,198,254,254,
24,24,0,0,0,0,24,24,
12,28,56,48,0,0,48,48,
48,56,28,14,14,28,56,48,
0,0,254,254,0,254,254,0,
24,56,112,224,224,112,56,24,
24,24,0,120,120,96,120,120,
254,254,6,246,246,198,254,254,
198,198,254,254,198,238,124,56,
62,126,102,126,126,102,126,62,
126,126,6,6,6,6,126,126,
62,126,230,198,198,230,126,62,
254,254,6,30,30,6,254,254,
6,6,126,126,6,6,254,254,
254,254,198,246,246,6,254,254,
198,198,198,254,254,198,198,198,
126,126,24,24,24,24,126,126,
62,62,54,54,48,48,48,48,
102,118,62,30,30,62,118,102,
62,62,6,6,6,6,6,6,
198,198,198,214,254,254,238,198,
198,198,246,246,222,222,198,198,
254,254,198,198,198,198,254,254,
6,6,62,126,102,102,126,62,
62,126,246,246,198,198,254,254,
230,118,62,126,102,102,126,62,
126,126,112,56,28,14,126,126,
24,24,24,24,24,24,126,126,
254,254,198,198,198,198,198,198,
24,60,126,102,102,102,102,102,
198,238,254,254,214,198,198,198,
198,238,124,56,56,124,238,198,
24,24,24,24,60,126,102,102,
126,126,12,28,56,48,126,126,
30,30,6,6,6,6,30,30,
192,224,112,56,28,14,6,0,
30,30,24,24,24,24,30,30,
0,0,0,132,204,252,120,48,
254,254,0,0,0,0,0,0,
0,0,0,0,0,12,14,6,
192,254,254,198,198,254,254,192,
62,126,102,102,126,62,6,6,
62,62,6,62,62,0,0,0,
254,254,246,254,254,192,192,192,
254,254,6,246,246,198,254,254,
24,126,126,24,216,216,248,248,
126,64,126,126,102,102,126,126,
102,102,126,126,6,6,6,6,
6,6,6,6,6,0,6,6
24,24,0,24,60,60,126,126,
0,0,0,0,108,108,108,108,
108,254,254,108,108,254,254,108,
16,124,124,16,8,124,124,16,
198,206,28,56,112,224,198,6,
16,124,64,124,64,64,124,16,
0,0,0,0,6,6,6,6,
24,30,14,6,6,14,30,24,
6,30,28,24,24,28,30,6,
146,84,56,254,56,84,146,16,
0,24,24,126,126,24,24,0,
28,56,48,0,0,0,0,0,
0,0,0,252,252,0,0,0,
14,14,14,0,0,0,0,0,
6,14,28,56,112,224,192,0,
254,254,206,222,246,230,254,254,
254,254,48,48,48,62,60,56,
254,254,28,56,118,230,254,254,
254,254,192,254,254,192,254,254,
48,48,48,254,254,54,54,54,
254,254,198,192,254,6,254,254,
254,254,198,254,254,6,254,254,
48,48,48,48,48,48,62,62,
124,238,198,254,124,198,238,124,
192,192,254,254,198,198,254,254,
24,24,0,0,0,0,24,24,
12,28,56,48,0,0,48,48,
48,56,28,14,14,28,56,48,
0,0,254,254,0,254,254,0,
24,56,112,224,224,112,56,24,
24,24,0,120,120,96,120,120,
254,254,6,246,246,198,254,254,
198,198,254,254,198,238,124,56,
62,126,102,126,126,102,126,62,
126,126,6,6,6,6,126,126,
62,126,230,198,198,230,126,62,
254,254,6,30,30,6,254,254,
6,6,126,126,6,6,254,254,
254,254,198,246,246,6,254,254,
198,198,198,254,254,198,198,198,
126,126,24,24,24,24,126,126,
62,62,54,54,48,48,48,48,
102,118,62,30,30,62,118,102,
62,62,6,6,6,6,6,6,
198,198,198,214,254,254,238,198,
198,198,246,246,222,222,198,198,
254,254,198,198,198,198,254,254,
6,6,62,126,102,102,126,62,
62,126,246,246,198,198,254,254,
230,118,62,126,102,102,126,62,
126,126,112,56,28,14,126,126,
24,24,24,24,24,24,126,126,
254,254,198,198,198,198,198,198,
24,60,126,102,102,102,102,102,
198,238,254,254,214,198,198,198,
198,238,124,56,56,124,238,198,
24,24,24,24,60,126,102,102,
126,126,12,28,56,48,126,126,
30,30,6,6,6,6,30,30,
192,224,112,56,28,14,6,0,
30,30,24,24,24,24,30,30,
0,0,0,132,204,252,120,48,
254,254,0,0,0,0,0,0,
0,0,0,0,0,12,14,6,
192,254,254,198,198,254,254,192,
62,126,102,102,126,62,6,6,
62,62,6,62,62,0,0,0,
254,254,246,254,254,192,192,192,
254,254,6,246,246,198,254,254,
24,126,126,24,216,216,248,248,
126,64,126,126,102,102,126,126,
102,102,126,126,6,6,6,6,
6,6,6,6,6,0,6,6
};

void draw_char(int x, int y, char c, u32 fg) {
unsigned where = x*COLOR_BITS/8 + y*SCN_PITCH;
u8 *screen = (u8 *) VIDEO_ADDRESS;
if (c == 124) { //Custom code for |
for(int r = 0; r < 8; r++) {//Rows
putpixel(x + 3, y - r, fg); //TODO: CHANGE THIS
putpixel(x + 4, y - r, fg); //TODO: CHANGE THIS
}
}
else {
if (c >= 106) {
c -= 32;
}
//We now know c is a letter we have. Subtract 65 to get a number we can use in the above array.
c -= 33;
for(int r = 0; r < 8; r++) {//Rows
uint16 row = characters[c * 8 + r];
for (int i = 0; i < 8; i++) {
if (row&(1 << i)) {
if (c == 124) { //Custom code for |
for(int r = 0; r < 8; r++) {//Rows
putpixel(x + 3, y - r, fg); //TODO: CHANGE THIS
putpixel(x + 4, y - r, fg); //TODO: CHANGE THIS
}
}
else {
if (c >= 106) {
c -= 32;
}
//We now know c is a letter we have. Subtract 65 to get a number we can use in the above array.
c -= 33;
for(int r = 0; r < 8; r++) {//Rows
uint16 row = characters[c * 8 + r];
for (int i = 0; i < 8; i++) {
if (row&(1 << i)) {
//TODO: Is there a way to set these all at once?
for (int j = 0; j < COLOR_BITS/8; j++) {
screen[where + (int)(i*COLOR_BITS/8) + j] = (fg >> j*8) & 255;
}
}
}
}
where -= SCN_PITCH;
}
}
}
}
}

void print_at(int x, int y, char *c, u32 fg) {
int i = 0;
while (c[i] != 0) {
draw_char(x + i * 8, y, c[i], fg);
i++;
}
int i = 0;
while (c[i] != 0) {
draw_char(x + i * 8, y, c[i], fg);
i++;
}
}

//X is where the middle character goes
void print_centered(int scn_width, int y, char *c) {
int x_left = (scn_width - (strlen(c) * 8)) / 2;
int x_left = (scn_width - (strlen(c) * 8)) / 2;
Color_t fg;
fg.r = 255;
fg.g = 0;
fg.b = 0;
print_at(x_left, y, c, color_to_pixel(fg));
print_at(x_left, y, c, color_to_pixel(fg));
}

+ 43
- 43
util/terminal.c View File

@@ -11,52 +11,52 @@ u32 bg;
u32 fg;

void newline() {
offset_x = 0;
offset_y += char_height;
if (offset_y >= SCN_HEIGHT) {
scroll_up(char_height);
fillrect(0, SCN_HEIGHT - char_height, bg, SCN_WIDTH, char_height); //Clear last line
offset_y -= char_height;
}
offset_x = 0;
offset_y += char_height;
if (offset_y >= SCN_HEIGHT) {
scroll_up(char_height);
fillrect(0, SCN_HEIGHT - char_height, bg, SCN_WIDTH, char_height); //Clear last line
offset_y -= char_height;
}
}

void print(char *c) {
int i = 0;
while (c[i] != 0) {
if (c[i] >= 97 && c[i] <= 122) { //UPPERCASE because my lowercase font sucks
c[i] -= 32;
}
if (c[i] == '\n') {
newline();
} else {
if (offset_x + 8 > SCN_WIDTH) {
newline();
}