diff --git a/README.md b/README.md new file mode 100644 index 0000000..2ffb230 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# IdealOS +Component of ideal world + +### YouTube Overview + +[![IdealOS](https://img.youtube.com/vi/udBEQAI86ME/0.jpg)](https://youtube.com/watch?v=udBEQAI86ME) + + +[![IdealOS floppy](https://img.youtube.com/vi/Pk8kvccv47Q/0.jpg)](https://youtube.com/watch?v=Pk8kvccv47Q) diff --git a/build-FDD.bat b/build-FDD.bat new file mode 100644 index 0000000..221da65 --- /dev/null +++ b/build-FDD.bat @@ -0,0 +1,24 @@ +@mkdir "bin/components" +@mkdir "bin/components/programs" +@mkdir "bin/components/libraries" + +@nasm "components/IdealFS-FDD.asm" -o "bin/components/IdealFS" ^ + && nasm "components/kernel/main16.asm" -o "bin/components/kernel16" ^ + && tcc32 -w "-Icomponents/global" -nostdlib -c "components/kernel/main32.c" -o "bin/components/kernel32.elf" ^ + && load "bin/components/kernel16" | to ld > "bin/components/kernel16.ld" ^ + && ld -T kernel_script.ld -o "bin/components/kernel32.o" "bin/components/kernel32.elf" ^ + && objcopy -O binary -S "bin/components/kernel32.o" "bin/components/kernel" ^ + && build_program "libraries/graphics" ^ + && build_program "libraries/ps2" ^ + && build_program "programs/bootscreen" ^ + && build_program "programs/shell" ^ + && create.c.exe 144 > "bin/storage" ^ + && create.c.exe IdealFS "bin/storage" "bin/components/IdealFS" ^ + "bin/components/kernel" "kernel" ^ + "components/kernel/main32.c" "kernel.c" ^ + "bin/components/libraries/graphics" "graphics.com" ^ + "bin/components/libraries/ps2" "ps2.com" ^ + "bin/components/programs/bootscreen" "bootscreen.com" ^ + "bin/components/programs/shell" "shell.com" ^ + && qemu -usb -m 256 -no-reboot -fda "bin\storage" ^ + || pause \ No newline at end of file diff --git a/build-HDD.bat b/build-HDD.bat new file mode 100644 index 0000000..9667c45 --- /dev/null +++ b/build-HDD.bat @@ -0,0 +1,24 @@ +@mkdir "bin/components" +@mkdir "bin/components/programs" +@mkdir "bin/components/libraries" + +@nasm "components/IdealFS-HDD.asm" -o "bin/components/IdealFS" ^ + && nasm "components/kernel/main16.asm" -o "bin/components/kernel16" ^ + && tcc32 -w "-Icomponents/global" -nostdlib -c "components/kernel/main32.c" -o "bin/components/kernel32.elf" ^ + && load "bin/components/kernel16" | to ld > "bin/components/kernel16.ld" ^ + && ld -T kernel_script.ld -o "bin/components/kernel32.o" "bin/components/kernel32.elf" ^ + && objcopy -O binary -S "bin/components/kernel32.o" "bin/components/kernel" ^ + && build_program "libraries/graphics" ^ + && build_program "libraries/ps2" ^ + && build_program "programs/bootscreen" ^ + && build_program "programs/shell" ^ + && create.c.exe 144 > "bin/storage" ^ + && create.c.exe IdealFS "bin/storage" "bin/components/IdealFS" ^ + "bin/components/kernel" "kernel" ^ + "components/kernel/main32.c" "kernel.c" ^ + "bin/components/libraries/graphics" "graphics.com" ^ + "bin/components/libraries/ps2" "ps2.com" ^ + "bin/components/programs/bootscreen" "bootscreen.com" ^ + "bin/components/programs/shell" "shell.com" ^ + && qemu -usb -m 256 -no-reboot -hda "bin\storage" ^ + || pause \ No newline at end of file diff --git a/build_program.bat b/build_program.bat new file mode 100644 index 0000000..a68e9f8 --- /dev/null +++ b/build_program.bat @@ -0,0 +1,3 @@ +@tcc32 -w "-Icomponents/global" -nostdlib -c "components/%1/main.c" -o "bin/components/%1.elf" ^ + && ld -T program_script.ld -o "bin/components/%1.o" "bin/components/%1.elf" ^ + && objcopy -O binary -S "bin/components/%1.o" "bin/components/%1" \ No newline at end of file diff --git a/components/IdealFS-FDD.asm b/components/IdealFS-FDD.asm new file mode 100644 index 0000000..5efb0a9 --- /dev/null +++ b/components/IdealFS-FDD.asm @@ -0,0 +1,183 @@ +;global addresses +%define kernel_address 0x8000 +%define drive_number 0x7C00 - 1 + + +org 0x7C00 + +mov AX, CS +mov DS, AX +mov SS, AX +mov ES, AX +mov SP, drive_number + +mov [drive_number], DL +mov EBX, 0x500 + + +read_file: + call read_sector + cmp word [BX], 0 + je kernel_not_found + cmp word [BX], 1 + jne next_file + mov SI, 0x500 + 16 + mov DI, kernel_name + mov CX, 7 + rep cmpsb + je kernel_found +next_file: + mov EAX, [EBX + 4] + cmp EAX, 0 + je kernel_not_found + mov [start_sector], EAX + jmp read_file + + +kernel_found: + mov EAX, [EBX + 12] + cmp EAX, 0 + je end_fs_read_sector + mov [start_sector], EAX + mov DI, kernel_address + load_next_kernel_sector: + call read_sector + + mov SI, 0x500 + 12 + mov CX, 500 + rep movsb + + mov EAX, [EBX + 4] + cmp EAX, 0 + je end_fs_read_sector + mov [start_sector], EAX + jmp load_next_kernel_sector + end_fs_read_sector: + +push write_sector +push read_sector +push start_sector +jmp kernel_address + + +kernel_not_found: + mov SI, kernel_not_found_message + jmp handle_error + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;C H S LBA +;0 0 1 0 +;... +;0 0 18 17 +;0 1 1 18 +;... +;0 1 18 35 +;1 0 1 36 +;... +;1 0 18 53 +;1 1 1 54 +;... +;1 1 18 71 +;1 1 1 72 +;... + +;C = LBA / (2 * 18) +;H = (LBA / 18) % 2 +;S = (LBA % 18) + 1 + + +;CX = CH CL +;cylinder 7 6 5 4 3 2 1 0 9 8 +;sector 5 4 3 2 1 0 + +;DH = head + + +read_sector: + mov BX, 0x500 + + xor DX, DX + mov AX, [start_sector] + mov CX, 18 + div CX + mov CX, DX + inc CX + and CX, 0b00111111 ;sector + mov DX, AX + and DX, 1 + mov DH, DL ;head + shr AX, 1 + mov CH, AL ;cylinder low + shl AX, 6 + and AH, 0b11000000 + or CL, AH ;cylinder high + + mov DL, [drive_number] + + mov AX, 0x0201 + int 0x13 + jc read_error + ret + + +write_sector: + mov BX, 0x500 + + xor DX, DX + mov AX, [start_sector] + mov CX, 18 + div CX + mov CX, DX + inc CX + and CX, 0b00111111 ;sector + mov DX, AX + and DX, 1 + mov DH, DL ;head + shr AX, 1 + mov CH, AL ;cylinder low + shl AX, 6 + and AH, 0b11000000 + or CL, AH ;cylinder high + + mov DL, [drive_number] + + mov AX, 0x0301 + int 0x13 + jc read_error + ret + + +start_sector: dd 1 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +read_error: + mov SI, read_error_message +handle_error: + call print_string + + xor AX, AX + int 0x16 + int 0x19 + + +;in SI - printed string +print_string: + mov AH, 0x0E +print_next_string_char: + lodsb + cmp AL, 0 + je end_print_string + int 0x10 + jmp print_next_string_char +end_print_string: + ret + + +kernel_not_found_message: db "no " +kernel_name:db "kernel", 0 +read_error_message: db "read error", 0 \ No newline at end of file diff --git a/components/IdealFS-HDD.asm b/components/IdealFS-HDD.asm new file mode 100644 index 0000000..9ae9c6e --- /dev/null +++ b/components/IdealFS-HDD.asm @@ -0,0 +1,124 @@ +;global addresses +%define kernel_address 0x8000 +%define drive_number 0x7C00 - 1 + + +org 0x7C00 + +mov AX, CS +mov DS, AX +mov SS, AX +mov ES, AX +mov SP, drive_number + +mov [drive_number], DL +mov EBX, 0x500 + + +read_file: + call read_sector + cmp word [BX], 0 + je kernel_not_found + cmp word [BX], 1 + jne next_file + mov SI, 0x500 + 16 + mov DI, kernel_name + mov CX, 7 + rep cmpsb + je kernel_found +next_file: + mov EAX, [EBX + 4] + cmp EAX, 0 + je kernel_not_found + mov [start_sector], EAX + jmp read_file + + +kernel_found: + mov EAX, [EBX + 12] + cmp EAX, 0 + je end_fs_read_sector + mov [start_sector], EAX + mov DI, kernel_address + load_next_kernel_sector: + call read_sector + + mov SI, 0x500 + 12 + mov CX, 500 + rep movsb + + mov EAX, [EBX + 4] + cmp EAX, 0 + je end_fs_read_sector + mov [start_sector], EAX + jmp load_next_kernel_sector + end_fs_read_sector: + +push write_sector +push read_sector +push start_sector +jmp kernel_address + + +kernel_not_found: + mov SI, kernel_not_found_message + jmp handle_error + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +read_sector: + mov DL, [drive_number] + mov AH, 0x42 + mov SI, LBA_packet + int 0x13 + jc read_error + ret + + +write_sector: + mov DL, [drive_number] + mov AX, 0x4300 + mov SI, LBA_packet + int 0x13 + jc read_error + ret + + LBA_packet: + size db 16 + zero db 0 + number_of_sectors dw 1 + buffer_address_offset dw 0x500 + buffer_address_segment dw 0 + start_sector dq 1 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +read_error: + mov SI, read_error_message +handle_error: + call print_string + + xor AX, AX + int 0x16 + int 0x19 + + +;in SI - printed string +print_string: + mov AH, 0x0E +print_next_string_char: + lodsb + cmp AL, 0 + je end_print_string + int 0x10 + jmp print_next_string_char +end_print_string: + ret + + +kernel_not_found_message: db "no " +kernel_name:db "kernel", 0 +read_error_message: db "read error", 0 \ No newline at end of file diff --git a/components/global/IO.c b/components/global/IO.c new file mode 100644 index 0000000..bf211e3 --- /dev/null +++ b/components/global/IO.c @@ -0,0 +1,77 @@ +#ifndef IO_INCLUDED +#define IO_INCLUDED + + +Number8 in_8(Number16 port) +{ + Number8 data; + + asm volatile( + "inb %1, %0" + : "=a"(data) + : "Nd"(port) + ); + + return data; +} + + +void out_8(Number16 port, Number8 data) +{ + asm volatile( + "outb %0, %1" + : + : "a"(data), "Nd"(port) + ); +} + + +Number16 in_16(Number16 port) +{ + Number16 data; + + asm volatile( + "inw %1, %0" + : "=a"(data) + : "Nd"(port) + ); + + return data; +} + + +void out_16(Number16 port, Number16 data) +{ + asm volatile( + "outw %0, %1" + : + : "a"(data), "Nd"(port) + ); +} + + +Number32 in_32(Number16 port) +{ + Number32 data; + + asm volatile( + "inl %1, %0" + : "=a"(data) + : "Nd"(port) + ); + + return data; +} + + +void out_32(Number16 port, Number32 data) +{ + asm volatile( + "outl %0, %1" + : + : "a"(data), "Nd"(port) + ); +} + + +#endif//IO_INCLUDED \ No newline at end of file diff --git a/components/global/IdealOS.c b/components/global/IdealOS.c new file mode 100644 index 0000000..df0c75c --- /dev/null +++ b/components/global/IdealOS.c @@ -0,0 +1,38 @@ +#ifndef API_INCLUDED +#define API_INCLUDED + + +#include "types.c" + + +typedef struct { + struct Interface* next; + struct Interface* parent; + Byte name[32]; + Boolean is_folder; + void* data; +} +Interface; + + +#define MAX_NUMBER_OF_ARGUMENTS 256 + + +#include "interfaces/heap.c" +#include "interfaces/file.c" +#include "interfaces/process.c" + +#include "interfaces/graphics.c" +#include "interfaces/keyboard.c" + + +#define get_module_address_by_function(function) \ + Number module_address; \ + asm("call . + 5\n" "pop %0" : "=a"(module_address)); \ + module_address -= (Number)&(function) + 15; + +#define global(name) *(void**)((Byte*)&(name) + module_address) +#define global_ptr(name) ((Byte*)&(name) + module_address) + + +#endif//API_INCLUDED \ No newline at end of file diff --git a/components/global/interfaces/file.c b/components/global/interfaces/file.c new file mode 100644 index 0000000..898b476 --- /dev/null +++ b/components/global/interfaces/file.c @@ -0,0 +1,58 @@ +#ifndef FILE_INCLUDED +#define FILE_INCLUDED + + +typedef enum { + IdealFS_FILE = 1, + IdealFS_FOLDER = 2, + IdealFS_DATA = 4, +} +IdealFS_Node_Type; + + +typedef struct { + Number16 type; + Number16 size; + Number32 next; + Number32 prev; + Byte data[500]; +} +IdealFS_Node; + + +typedef struct { + Number16 type; + Number16 size; + Number32 next; + Number32 prev; + Number32 inner; + Byte name[496]; +} +IdealFS_File_Node; + + +typedef struct { + Number32 last_node_index; +} +IdealFS; + + +typedef struct { + Number32 file_node_index; + Number32 data_node; + IdealFS_File_Node file_node; +} +File; + + +typedef struct { + Boolean (*read) (File* file, Number32 file_node_index); + Boolean (*find) (File* file, Byte* path); + Boolean (*create) (File* file, Byte* name); + Signed_Number (*read_bytes) (File* file, Byte* bytes, Number number_of_bytes); + Signed_Number (*write_bytes) (File* file, Byte* bytes, Number number_of_bytes); +} +File_Interface; + + +#endif//FILE_INCLUDED \ No newline at end of file diff --git a/components/global/interfaces/graphics.c b/components/global/interfaces/graphics.c new file mode 100644 index 0000000..307fa55 --- /dev/null +++ b/components/global/interfaces/graphics.c @@ -0,0 +1,73 @@ +#define rgb(r, g, b) ((r << 16) | (g << 8) | (b)) + + +typedef struct { + Number scroll_x; + Number scroll_y; + Number width; + Number height; + Number32 buffer[]; +} +Frame; + + +typedef struct { + Frame* frame; + Number cursor_pos_x; + Number cursor_pos_y; + Number32 color; +} +Printer; + + +typedef struct { + Number16 attributes; + Number8 window_a; + Number8 window_b; + Number16 granularity; + Number16 window_size; + Number16 segment_a; + Number16 segment_b; + Number32 win_func_ptr; + Number16 pitch; + Number16 width; + Number16 height; + Number8 w_char; + Number8 y_char; + Number8 planes; + Number8 bpp; + Number8 banks; + Number8 memory_model; + Number8 bank_size; + Number8 image_pages; + Number8 reserved0; + + Number8 red_mask; + Number8 red_position; + Number8 green_mask; + Number8 green_position; + Number8 blue_mask; + Number8 blue_position; + Number8 reserved_mask; + Number8 reserved_position; + Number8 direct_color_attributes; + + Number32 framebuffer; + Number32 off_screen_mem_off; + Number16 off_screen_mem_size; + Number8 reserved1[206]; +} +VESA_Mode; + + +typedef struct { + Frame* (*create_frame) (Number width, Number height); + void (*clean_frame) (Frame* frame, Number32 color); + void (*draw_rectangle) (Frame* frame, Number x, Number y, Number width, Number height, Number32 color); + void (*draw_frame_in_frame) (Frame* destination_frame, Frame *source_frame, Number x, Number y); + void (*draw_frame) (Frame* frame, Number x, Number y); + + void (*draw_character) (Frame* frame, Number x, Number y, Number character, Number32 color); + void (*print) (Printer* printer, Byte* parameters, ...); +} +Graphics_Interface; \ No newline at end of file diff --git a/components/global/interfaces/heap.c b/components/global/interfaces/heap.c new file mode 100644 index 0000000..3894e2b --- /dev/null +++ b/components/global/interfaces/heap.c @@ -0,0 +1,13 @@ +#ifndef HEAP_INCLUDED +#define HEAP_INCLUDED + + +typedef struct { + void* (*allocate) (Number block_size, void(*on_free)(void* data)); + void (*free) (void* block); + Number (*get_free_size) (); +} +Heap_Interface; + + +#endif//HEAP_INCLUDED \ No newline at end of file diff --git a/components/global/interfaces/keyboard.c b/components/global/interfaces/keyboard.c new file mode 100644 index 0000000..2981a41 --- /dev/null +++ b/components/global/interfaces/keyboard.c @@ -0,0 +1,62 @@ +#ifndef KEYBOARD_INCLUDED +#define KEYBOARD_INCLUDED + + +typedef enum { + KEY_ESCAPE = 1, + + KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, + KEY_TAB, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, KEY_OPEN_SQUARE_BRACKET, KEY_CLOSE_SQUARE_BRACKET, KEY_ENTER, + KEY_LEFT_CONTROL, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_BACKTICK, + KEY_LEFT_SHIFT, KEY_BACKSLASH, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_RIGHT_SHIFT, + + KEY_NUMPAD_MUL, + KEY_LEFT_ALT, + KEY_SPACE, + + KEY_CAPSLOCK, + KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, + KEY_NUM_LOCK, KEY_SCROLL_LOCK, + + KEY_NUMPAD_7, KEY_NUMPAD_8, KEY_NUMPAD_9, KEY_NUMPAD_MINUS, + KEY_NUMPAD_4, KEY_NUMPAD_5, KEY_NUMPAD_6, KEY_NUMPAD_PLUS, + KEY_NUMPAD_1, KEY_NUMPAD_2, KEY_NUMPAD_3, + KEY_NUMPAD_0, KEY_NUMPAD_DOT, + + KEY_F11 = 87, + KEY_F12 = 88, + + + + + KEY_NUMPAD_ENTER = 156, + KEY_RIGHT_CONTROL = 157, + KEY_PRINT_SCREEN2 = 170, + KEY_NUMPAD_DIV = 181, + KEY_PRINT_SCREEN = 183, + KEY_RIGHT_ALT = 184, + + KEY_HOME = 199, + KEY_ARROW_UP = 200, + KEY_PAGE_UP = 201, + KEY_ARROW_LEFT = 203, + KEY_ARROW_RIGHT = 205, + KEY_END = 207, + KEY_ARROW_DOWN = 208, + KEY_PAGE_DOWN = 209, + KEY_INSERT = 210, + KEY_DELETE = 211, + + KEY_OS = 219, + KEY_CONTEXT_MENU = 221, +} +Key_Code; + + +typedef struct { + Number32 (*read_key_state) (); +} +Keyboard_Interface; + + +#endif//KEYBOARD_INCLUDED \ No newline at end of file diff --git a/components/global/interfaces/process.c b/components/global/interfaces/process.c new file mode 100644 index 0000000..411a6bf --- /dev/null +++ b/components/global/interfaces/process.c @@ -0,0 +1,68 @@ +#ifndef PROCESS_INCLUDED +#define PROCESS_INCLUDED + + +typedef enum { + PROCESS_LOADED, + PROCESS_WORKING, + PROCESS_WAITING, +} +Process_State; + + +typedef enum { + //0 - 255 interrupts + FILE_CHANGE_EVENT= 256, +} +Event; + + +typedef void(*Process_Start)(struct Process* process); + + +typedef struct { + void* (*get) (Byte* path); + void (*create) (Byte* path, void* data); + + Byte command[256]; + Number number_of_arguments; + Byte* arguments[MAX_NUMBER_OF_ARGUMENTS]; + + + Process_State state; + Event* wait_events; //null terminated + + + Process_Start start; + + struct Process* next; + + Number esp; + Number ebp; +} +Process; + + +#define get_module_address_by_function(function) \ + Number module_address; \ + asm("call . + 5\n" "pop %0" : "=a"(module_address)); \ + module_address -= (Number)&(function) + 15; + +#define global(name) *(void**)((Byte*)&name + module_address) +#define global_ptr(name) ((Byte*)&name + module_address) + + +typedef struct { + void (*create) (Process** process, Byte* command, Number* parsed_command_size, Process* previous_piping_process); + void (*switch_to) (Process* process); + void (*yield) (); + void (*wait) (Event event, ...); //null terminated + void (*stop) (Process* process, Number code); + void (*exit) (Number code); + Number (*execute) (Byte* command); + Process* (*get_list) (); +} +Process_Interface; + + +#endif//PROCESS_INCLUDED \ No newline at end of file diff --git a/components/global/memory.c b/components/global/memory.c new file mode 100644 index 0000000..b1481f0 --- /dev/null +++ b/components/global/memory.c @@ -0,0 +1,77 @@ +#ifndef MEMORY_INCLUDED +#define MEMORY_INCLUDED + + +void clean_bytes(Byte* bytes, Number size) +{ + Number system_size; + Number remind_size; + + system_size = size / sizeof(Number); + remind_size = size % sizeof(Number); + + while(system_size) { + *((Number*)bytes) = 0; + + --system_size; + bytes += sizeof(Number); + } + + while(remind_size) { + *bytes = 0; + + --remind_size; + ++bytes; + } +} + + + +void copy_bytes(Byte* destination, Byte* source, Number size) +{ + Number system_size; + Number remind; + + system_size = size / sizeof(Number); + remind = size % sizeof(Number); + + while(system_size) { + *((Number*)destination) = *((Number*)source); + + --system_size; + destination += sizeof(Number); + source += sizeof(Number); + } + + while(remind) { + *destination = *source; + + --remind; + ++destination; + ++source; + } +} + + +Signed_Number compare_bytes(Byte* bytes1, Number number_of_bytes1, Byte* bytes2, Number number_of_bytes2) +{ + Signed_Number difference; + + while(number_of_bytes1 && number_of_bytes2) { + difference = (Signed_Number)*bytes1 - (Signed_Number)*bytes2; + + if(difference) { + return difference; + } + + ++bytes1; + ++bytes2; + --number_of_bytes1; + --number_of_bytes2; + } + + return (Signed_Number)number_of_bytes1 - (Signed_Number)number_of_bytes2; +} + + +#endif//MEMORY_INCLUDED \ No newline at end of file diff --git a/components/global/string.c b/components/global/string.c new file mode 100644 index 0000000..544e36e --- /dev/null +++ b/components/global/string.c @@ -0,0 +1,47 @@ +#ifndef STRING_INCLUDED +#define STRING_INCLUDED + + +#include "types.c" + + +Byte to_upper_case(Byte c) +{ + if(c >= 'a' && c <= 'z') { + c = c + 'A' - 'a'; + } + + return c; +} + + +Byte to_lower_case(Byte c) +{ + if(c >= 'A' && c <= 'Z') { + c = c + 'a' - 'A'; + } + + return c; +} + + +Signed_Number compare_strings(Byte* string1, Byte* string2) +{ + Signed_Number difference; + + while(*string1 && *string2) { + difference = (Signed_Number)*string1 - (Signed_Number)*string2; + + if(difference) { + return difference; + } + + ++string1; + ++string2; + } + + return (Signed_Number)*string1 - (Signed_Number)*string2; +} + + +#endif//STRING_INCLUDED \ No newline at end of file diff --git a/components/global/types.c b/components/global/types.c new file mode 100644 index 0000000..c2d93d1 --- /dev/null +++ b/components/global/types.c @@ -0,0 +1,36 @@ +#ifndef TYPES_INCLUDED +#define TYPES_INCLUDED + + +// unsigned number +typedef unsigned char Number8; // [0, 255] +typedef unsigned short int Number16; // [0, 65 535] +typedef unsigned long int Number32; // [0, 4 294 967 296] +typedef unsigned long long int Number64; // [0, 18 446 744 073 709 551 616] +typedef Number32 Number; + +typedef char Signed_Number8; // [-127, 127] +typedef short int Signed_Number16; // [-32 767, 32 767] +typedef long int Signed_Number32; // [-2 147 483 648, 2 147 483 648] +typedef long long int Signed_Number64; // [-9 223 372 036 854 775 808, 9 223 372 036 854 775 808] +typedef Signed_Number32 Signed_Number; + +typedef float Real_Number32; +typedef double Real_Number64; +typedef long double Real_Number80; +typedef Real_Number32 Real_Number; + +typedef Number8 Byte; +typedef Number Boolean; + + +#define stdcall __attribute__((__stdcall__)) +#define cdecl __attribute__((__cdecl__)) +#define import __attribute__((dllimport)) +#define export __attribute__((dllexport)) + + +#pragma pack(push, 1) //no align for structs + + +#endif//TYPES_INCLUDED \ No newline at end of file diff --git a/components/global/writer.c b/components/global/writer.c new file mode 100644 index 0000000..65cfbb8 --- /dev/null +++ b/components/global/writer.c @@ -0,0 +1,262 @@ +#ifndef WRITER_INCLUDED +#define WRITER_INCLUDED + + +#include + + +typedef struct { + void* source; + Signed_Number (*write_bytes)(void* source, Byte* bytes, Number number_of_bytes); +} +Writer; + + +Signed_Number write_bytes(Writer* writer, Byte* bytes, Number number_of_bytes) +{ + return writer->write_bytes(writer->source, bytes, number_of_bytes); +} + + +Signed_Number write_Byte(Writer* writer, Byte byte) +{ + return writer->write_bytes(writer->source, &byte, sizeof(byte)); +} + + +Signed_Number write_string(Writer* writer, Byte* string) +{ + Signed_Number total_bytes_writed; + Signed_Number bytes_writed; + + total_bytes_writed = 0; + + for(; *string; ++string) { + bytes_writed = write_Byte(writer, *string); + + if(bytes_writed <= 0) { + break; + } + + total_bytes_writed += bytes_writed; + } + + return total_bytes_writed; +} + + +Signed_Number write_Number(Writer* writer, Number number) +{ + Signed_Number bytes_writed = 0; + + Number next; + Byte byte; + + next = number / 10; + + if(next) { + bytes_writed = write_Number(writer, next); + } + + bytes_writed += write_Byte(writer, number % 10 + '0'); + + return bytes_writed; +} + + +Signed_Number write_Number_triplets(Writer* writer, Number number, Number level) +{ + Signed_Number bytes_writed = 0; + + Number next; + + next = number / 10; + + if(next) { + bytes_writed = write_Number_triplets(writer, next, level + 1); + } + + bytes_writed += write_Byte(writer, number % 10 + '0'); + + if(level && !(level % 3)) { + bytes_writed += write_Byte(writer, ' '); + } + + return bytes_writed; +} + + +Signed_Number write_Signed_Number(Writer* writer, Signed_Number number) +{ + Signed_Number bytes_writed = 0; + + if(number < 0) { + bytes_writed = write_Byte(writer, '-'); + number = -number; + } + + bytes_writed += write_Number(writer, number); + + return bytes_writed; +} + +/* +Signed_Number write_Real_Number(Writer* writer, Real_Number number) +{ + Signed_Number bytes_writed = 0; + + Number integer_number; + Real_Number decimal; + + if(number < 0) { + bytes_writed += write_Byte(writer, '-'); + number = -number; + } + + integer_number = number; + bytes_writed += write_Number(writer, integer_number); + + decimal = number - integer_number; + + if(decimal > 0) { + bytes_writed += write_Byte(writer, '.'); + } + + while(decimal > 0) { + decimal *= 10; + bytes_writed += write_Byte(writer, (Number)decimal % 10 + '0'); + decimal = decimal - (Number)decimal; + } + + return bytes_writed; +}*/ + + +Signed_Number write_hex_character(Writer* writer, Byte character) +{ + Signed_Number bytes_writed = 0; + + if(character < 10) { + bytes_writed += write_Byte(writer, character + '0'); + } + else { + bytes_writed += write_Byte(writer, character - 10 + 'A'); + } + + return bytes_writed; +} + + +Signed_Number write_hex_Byte(Writer* writer, Byte byte) +{ + Signed_Number bytes_writed = 0; + + if(byte < 16) { + bytes_writed += write_Byte(writer, '0'); + bytes_writed += write_hex_character(writer, byte); + } + else { + bytes_writed += write_hex_character(writer, byte >> 4); + bytes_writed += write_hex_character(writer, byte & 0b00001111); + } + + return bytes_writed; +} + + +Signed_Number write(Writer* writer, Byte* format, Byte** values) +{ + Signed_Number bytes_writed; + Byte character; + + bytes_writed = 0; + + for(;;) { + character = *format; + + if(!character) { + break; + } + + ++format; + + if(character == '%') { + character = *format; + ++format; + + switch(character) { + case 'c': + bytes_writed += write_Byte(writer, *values); + ++values; + break; + + case 'x': + bytes_writed += write_hex_Byte(writer, *values); + ++values; + break; + + case 'u': + bytes_writed += write_Number(writer, *values); + ++values; + break; + + case 'd': + bytes_writed += write_Signed_Number(writer, *(Signed_Number32*)values); + ++values; + break; + + case 't': + bytes_writed += write_Number_triplets(writer, *values, 0); + ++values; + break; + + //case 'f': + // bytes_writed += write_Real_Number(writer, *(Real_Number*)values); + // ++values; + // break; + + case 's': + bytes_writed += write_string(writer, *values); + ++values; + break; + + default: + bytes_writed += write_Byte(writer, character); + } + } + else { + bytes_writed += write_Byte(writer, character); + } + } + + return bytes_writed; +} + + +Signed_Number write_bytes_in_string(Byte** string_pointer, Byte* bytes, Number number_of_bytes) +{ + Number i; + Byte* string; + + string = *string_pointer; + + for(i = 0; i < number_of_bytes; ++i) { + string[i] = bytes[i]; + } + + *string_pointer += number_of_bytes; + + return number_of_bytes; +} + + +Signed_Number print_in_string(Byte* string, Byte* format, ...) +{ + Writer string_writer = {&string, &write_bytes_in_string}; + + return write(&string_writer, format, &format + 1) + + write_Byte(&string_writer, '\0'); +} + + +#endif//WRITER_INCLUDED \ No newline at end of file diff --git a/components/kernel/interface.c b/components/kernel/interface.c new file mode 100644 index 0000000..2bf1be0 --- /dev/null +++ b/components/kernel/interface.c @@ -0,0 +1,173 @@ +Interface* interfaces_list = 0; + + +/* +void print_interfaces(Interface* interfaces_list) +{ + while(interfaces_list) { + print("%s\n", interfaces_list->name); + + interfaces_list = interfaces_list->next; + } +}*/ + + +Interface* open_interface(Interface* parent_interface, Byte* name) +{ + Interface* interface; + + if(parent_interface) { + interface = parent_interface->data; + } + else { + interface = interfaces_list; + } + + while(interface) { + if(!compare_strings(interface->name, name)) { + return interface; + } + + interface = interface->next; + } + + return 0; +} + + +void free_interface(Interface* interface) +{ + Interface** prev; + + if(interface->parent) { + prev = &((Interface*)interface->parent)->data; + } + else { + prev = &interfaces_list; + } + + while((*prev)->next && (*prev)->next != interface) { + prev = &(*prev)->next; + } + + *prev = interface->next; +} + + +Interface* create_interface(Interface* parent_interface, Byte* name, void* data, Boolean is_folder) +{ + Interface** interface_pointer; + + if(parent_interface) { + interface_pointer = &parent_interface->data; + } + else { + interface_pointer = &interfaces_list; + } + + while(*interface_pointer) { + interface_pointer = &(*interface_pointer)->next; + } + + *interface_pointer = allocate_memory(sizeof(Interface), &free_interface); //TODO: free_interface_folder + (*interface_pointer)->parent = parent_interface; + (*interface_pointer)->next = 0; + copy_bytes((*interface_pointer)->name, name, 32); + (*interface_pointer)->is_folder = is_folder; + (*interface_pointer)->data = data; + + return *interface_pointer; +} + + +/* +void delete_interface(Interface* parent_interface, Byte* name) +{ + +}*/ + + + + +Interface* get_interface(Byte* path) +{ + Interface* root; + Byte name[32]; + Number i; + + root = 0; + + while(*path) { + if(*path == '/') { + ++path; + } + + for(i = 0; i < sizeof(name) - 1 && *path && *path != '/'; ++i) { + name[i] = *path; + ++path; + } + name[i] = '\0'; + + root = open_interface(root, name); + + if(!root) { + return 0; + } + } + + return root; +} + + +Interface* create_interface_by_path(Byte* path, void* data) +{ + Interface* root; + Byte name[32]; + Number i; + + root = 0; + name[0] = '\0'; + + while(*path) { + if(*path == '/') { + ++path; + } + + for(i = 0; i < sizeof(name) - 1 && *path && *path != '/'; ++i) { + name[i] = *path; + ++path; + } + name[i] = '\0'; + + if(*path == '/') { + root = open_interface(root, name); + + if(!root) { + root = create_interface(root, name, 0, 1); + } + //TODO: maybe error for incompatible types + //else if(!root->is_folder) { + // + //} + } + else { + break; + } + } + + return create_interface(root, name, data, 0); +} + + +void* get_interface_data(Byte* path) +{ + Interface* interface; + + interface = get_interface(path); + + if(interface) { + return interface->data; + } + + return 0; +} \ No newline at end of file diff --git a/components/kernel/interfaces/file.c b/components/kernel/interfaces/file.c new file mode 100644 index 0000000..c2012c1 --- /dev/null +++ b/components/kernel/interfaces/file.c @@ -0,0 +1,295 @@ +IdealFS fs = {1}; + +/* +void print_IdealFS() +{ + IdealFS_Node* node; + Number32 node_index; + + node = 0x500; + node_index = 1; + + while(node_index) { + loader_api->read_sector(node_index); + + if(node->type != IdealFS_FILE && node->type != IdealFS_FOLDER) { //read error + return; + } + + print("%s\n", node->data + 4); + + node_index = node->next; + } +}*/ + + +Boolean read_file(File* file, Number32 file_node_index) +{ + IdealFS_Node* node; + + node = 0x500; + loader_api->read_sector(file_node_index); + + if(node->type != IdealFS_FILE && node->type != IdealFS_FOLDER) { //read error + return 0; + } + + copy_bytes(&file->file_node, node, sizeof(file->file_node)); + file->data_node = file->file_node.inner; + file->file_node_index = file_node_index; + + return 1; +} + + +Boolean find_file(File* file, Byte* path) +{ + IdealFS_Node* node; + + node = 0x500; + file->file_node_index = 1; + + while(file->file_node_index) { + loader_api->read_sector(file->file_node_index); + + if(node->type != IdealFS_FILE && node->type != IdealFS_FOLDER) { //read error + return 0; + } + + if(!compare_strings(path, node->data + 4)) { + copy_bytes(&file->file_node, node, sizeof(file->file_node)); + file->data_node = file->file_node.inner; + return 1; + } + + file->file_node_index = node->next; + } + + return 0; +} + + +Signed_Number read_bytes_from_file(File* file, Byte* bytes, Number number_of_bytes) +{ + Signed_Number bytes_readed; + IdealFS_Node* node; + + bytes_readed = 0; + node = 0x500; + + while(number_of_bytes >= 500 && file->data_node) { + loader_api->read_sector(file->data_node); + + if(node->type != IdealFS_DATA) { //read error + goto error; + } + + copy_bytes(bytes, node->data, 500); + + number_of_bytes -= 500; + bytes += 500; + bytes_readed += 500; + + file->data_node = node->next; + } + + if(file->data_node && number_of_bytes) { + loader_api->read_sector(file->data_node); + + if(node->type != IdealFS_DATA) { //read error + goto error; + } + + copy_bytes(bytes, node->data, 500); + + bytes_readed += number_of_bytes; + + file->data_node = node->next; + } + + return bytes_readed; + + error: { + return -1; + } +} + + +Number32 rewind_IdealFS_to_end() +{ + IdealFS_Node* node; + Number32 node_index; + + node = 0x500; + node_index = 1; + + for(;;) { + loader_api->read_sector(node_index); + + if(!node->type) { + goto error; + } + else { + if(!node->next) { + return node_index; + } + + node_index = node->next; + } + } + + error: { + return 0; + } +} + + +Number32 find_free_IdealFS_node() +{ + IdealFS_Node* node; + + node = 0x500; + + for(;;) { + loader_api->read_sector(fs.last_node_index); + + if(!node->type) { + break; + } + + ++fs.last_node_index; + } + + return fs.last_node_index; + + error: { + return 0; + } +} + + +Number32 allocate_IdealFS_node(Number32 prev_node_index, Number32 next_node_index, IdealFS_Node* new_node) +{ + Number32 new_node_index; + IdealFS_Node* prev_node; + IdealFS_Node* next_node; + + new_node_index = find_free_IdealFS_node(); + + if(!new_node_index) { + goto error; + } + + new_node->prev = prev_node_index; + new_node->next = next_node_index; + + copy_bytes(0x500, new_node, 512); + loader_api->write_sector(new_node_index); + + if(prev_node_index) { + prev_node = 0x500; + loader_api->read_sector(prev_node_index); + prev_node->next = new_node_index; + loader_api->write_sector(prev_node_index); + } + + if(next_node_index) { + next_node = 0x500; + loader_api->read_sector(next_node_index); + next_node->prev = new_node_index; + loader_api->write_sector(next_node_index); + } + + return new_node_index; + + error: { + return 0; + } +} + + +Number32 create_IdealFS_file(IdealFS_File_Node* file_node, Byte* name) +{ + Number32 file_node_index; + Number32 prev_node_index; + Number i; + + + clean_bytes(file_node, sizeof(IdealFS_File_Node)); + file_node->type = IdealFS_FILE; + file_node->inner = 0; + + for(i = 0; name[i] && i < sizeof(file_node->name) - 1; ++i) { + file_node->name[i] = name[i]; + } + file_node->name[i] = '\0'; + + + prev_node_index = rewind_IdealFS_to_end(); + file_node_index = allocate_IdealFS_node(prev_node_index, 0, file_node); + + + return file_node_index; + + error: { + return 0; + } +} + + +Boolean create_file(File* file, Byte* name) +{ + file->file_node_index = create_IdealFS_file(&file->file_node, name); + + if(!file->file_node_index) { + goto error; + } + + file->data_node = 0; + + return 1; + + error: { + return 0; + } +} + + +Signed_Number write_bytes_in_file(File* file, Byte* bytes, Number number_of_bytes) +{ + IdealFS_Node new_node; + Boolean is_empty; + + is_empty = !file->data_node; + + clean_bytes(&new_node, sizeof(new_node)); + new_node.type = IdealFS_DATA; + copy_bytes(new_node.data, bytes, number_of_bytes); + file->data_node = allocate_IdealFS_node(file->data_node, 0, &new_node); + + if(!file->data_node) { + goto error; + } + + if(is_empty) { + file->file_node.inner = file->data_node; + + copy_bytes(0x500, &file->file_node, 512); + loader_api->write_sector(file->file_node_index); + } + + return number_of_bytes; + + error: { + return -1; + } +} + + +File_Interface file_interface = { + .read = &read_file, + .find = &find_file, + .create = &create_file, + .read_bytes = &read_bytes_from_file, + .write_bytes = &write_bytes_in_file +}; \ No newline at end of file diff --git a/components/kernel/interfaces/heap.c b/components/kernel/interfaces/heap.c new file mode 100644 index 0000000..2b10843 --- /dev/null +++ b/components/kernel/interfaces/heap.c @@ -0,0 +1,108 @@ +typedef struct { + struct Memory_Chunk* previous_chunk; + Boolean is_busy; + void (*on_free)(void* data); + Process* owner; +} +Memory_Chunk; + + +extern Process* current_process; + + +Byte* heap_top; +Byte* max_heap_top; +Memory_Chunk* top_chunk = 0; + + +Boolean initialize_heap() +{ + Number i; + Memory_Region* region; + Memory_Region* largest_region; + + largest_region = 0; + + for(i = 0; i < loader_api->size_of_memory_regions; i += sizeof(Memory_Region)) { + region = (Byte*)loader_api->memory_regions + i; + + if(region->type != 1 || region->address_high) { + continue; + } + + if(!largest_region || region->size_low > largest_region->size_low) { + largest_region = region; + } + } + + if(!largest_region) { + return 0; + } + + heap_top = largest_region->address_low; + max_heap_top = heap_top + largest_region->size_low; + + return 1; +} + + +Byte* allocate_memory(Number size, void(*on_free)(void* data)) +{ + Memory_Chunk* new_chunk; + Byte* allocated_memory; + + if(size > max_heap_top - heap_top || size + sizeof(Memory_Chunk) > max_heap_top - heap_top) { + return 0; + } + + new_chunk = heap_top; + new_chunk->previous_chunk = top_chunk; + new_chunk->is_busy = 1; + new_chunk->on_free = on_free; + new_chunk->owner = current_process; + + heap_top += sizeof(Memory_Chunk); + allocated_memory = heap_top; + heap_top += size; + + top_chunk = new_chunk; + + return allocated_memory; +} + + +void free_memory(Byte* allocated_memory) +{ + Memory_Chunk* chunk; + + chunk = allocated_memory - sizeof(Memory_Chunk); + + if(chunk->owner != current_process) { + return; + } + + if(chunk->is_busy && chunk->on_free) { + chunk->on_free(allocated_memory); + } + + chunk->is_busy = 0; + + //defragmentation + while(!top_chunk->is_busy) { + heap_top = top_chunk; + top_chunk = top_chunk->previous_chunk; + } +} + + +Number get_free_memory_size() +{ + return max_heap_top - heap_top; +} + + +Heap_Interface heap_interface = { + .allocate = &allocate_memory, + .free = &free_memory, + .get_free_size = &get_free_memory_size +}; \ No newline at end of file diff --git a/components/kernel/interfaces/process.c b/components/kernel/interfaces/process.c new file mode 100644 index 0000000..ca0f356 --- /dev/null +++ b/components/kernel/interfaces/process.c @@ -0,0 +1,213 @@ +Process* processes_list = 0; +Process* current_process = 0; + + +Process* get_processes_list() +{ + return processes_list; +} + + +Process** get_last_process_pointer() +{ + Process** last_process_pointer; + + last_process_pointer = &processes_list; + + while(*last_process_pointer) { + last_process_pointer = &(*last_process_pointer)->next; + } + + return last_process_pointer; +} + + +Number esp; +Number ebp; + + +void switch_to_process(Process* process) +{ + //save current process context + if(current_process) { + asm("mov %%esp, %0":"=a"(current_process->esp)); + asm("mov %%ebp, %0":"=a"(current_process->ebp)); + //print("[save %s %d %d]\n", current_process->command, current_process->start, current_process->esp); + } + else { + asm("mov %%esp, %0":"=a"(esp)); + asm("mov %%ebp, %0":"=a"(ebp)); + } + + //switch to process + current_process = process; + + asm("mov %0, %%esp"::"a"(current_process->esp)); + asm("mov %0, %%ebp"::"a"(current_process->ebp)); + + //print("[switch %s %d %d]\n", current_process->command, current_process->start, current_process->esp); + + if(current_process->state == PROCESS_LOADED) { + //print("[start %s %d esp=%d]\n", current_process->command, current_process, current_process->esp); + current_process->state = PROCESS_WORKING; + current_process->start(current_process); + + asm("exit_address:"); + //print("[stop %s %d]\n", current_process->command, current_process); + + //free process + Process** process_pointer; + + process_pointer = &processes_list; + + while(*process_pointer != current_process) { + process_pointer = &(*process_pointer)->next; + } + + *process_pointer = current_process->next; + + + //get next process + Process* next_process; + + next_process = current_process->next; + + if(!next_process) { + next_process = processes_list; + } + + + //switch to next process + if(next_process) { + switch_to_process(next_process); + } + else { + //IdealOS end!!! + asm("mov %0, %%esp"::"a"(esp)); + asm("mov %0, %%ebp"::"a"(ebp)); + } + } +} + + +void exit_from_current_process(Number code) +{ + asm("jmp exit_address"); +} + + +void stop_process(Process* process, Number code) +{ + Process** process_pointer; + + process_pointer = &processes_list; + + while(*process_pointer != process) { + process_pointer = &(*process_pointer)->next; + } + + if(!*process_pointer) { + return; + } + + *process_pointer = (*process_pointer)->next; + + + //free process allocated memory + Memory_Chunk* current_chunk; + + current_chunk = top_chunk; + + while(current_chunk) { + if(current_chunk->owner == process) { + current_chunk->is_busy = 0; + } + + current_chunk = current_chunk->previous_chunk; + } + + //defragmentation + while(!top_chunk->is_busy) { + heap_top = top_chunk; + top_chunk = top_chunk->previous_chunk; + } +} + + +void initialize_process( + Process* process, + Byte* command, + Process_Start start, + Process* previous_piping_process, + Number stack_size +) +{ + process->next = 0; + process->state = PROCESS_LOADED; + process->wait_events = 0; + + process->get = &get_interface_data; + process->create = &create_interface_by_path; + + process->start = start; + + Number i; + for(i = 0; command[i]; ++i) { + process->command[i] = command[i]; + } + process->command[i] = '\0'; + + process->esp = allocate_memory(stack_size, 0) + stack_size;//process->start + file->file_size + 64 * 1024; + process->ebp = process->esp; + + *get_last_process_pointer() = process; +} + + +void yield() +{ + Process* next_process; + + next_process = current_process->next; + + while(next_process && next_process->state == PROCESS_WAITING) { + next_process = next_process->next; + } + + if(next_process) { + switch_to_process(next_process); + } + else { + switch_to_process(processes_list); + } +} + + +void wait_event(Event event, ...) { + current_process->wait_events = &event; + current_process->state = PROCESS_WAITING; + yield(); +} + + +void emit_event(Event event) +{ + Process* process = processes_list; + + while(process) { + if(process->state == PROCESS_WAITING) { + Event* e = process->wait_events; + + while(e && *e) { + if(*e == event) { + process->state = PROCESS_WORKING; + break; + } + + ++e; + } + } + + process = process->next; + } +} \ No newline at end of file diff --git a/components/kernel/main16.asm b/components/kernel/main16.asm new file mode 100644 index 0000000..0d39df4 --- /dev/null +++ b/components/kernel/main16.asm @@ -0,0 +1,691 @@ +org 0x8000 + +;push BP +mov BP, SP + +;start_sector [BP] +;read_sector [BP + 2] +;write_sector [BP + 4] + + +mov [old_SP], SP +mov [old_BP], BP + + +;enable A20 +in AL, 0x92 +or AL, 2 +out 0x92, AL + + +call setup_video + + +;get_memory_region +push ES + +xor DI, DI +xor EBX, EBX +next_memory_region: + mov AX, 0x2000 + mov ES, AX + mov ECX, 20 + mov EDX, 0x534D4150 ;'SMAP' + mov EAX, 0xE820 + int 0x15 + jc get_memory_region_error + cmp EAX, 0x534D4150 ;'SMAP' + jne get_memory_region_error + cmp CX, 20 + jne get_memory_region_error + add DI, 20 + cmp EBX, 0 + jne next_memory_region +get_memory_region_error: + +mov [size_of_memory_regions], DI +pop ES + + +lgdt [GDT_pointer] + + +call switch_to_32_bit +use32 +mov ESP, 0x80000 +mov EBP, ESP + + +push 0x20000 +push dword [size_of_memory_regions] +push VESA_Mode +push write_sector +push read_sector +push interrupt_queue +call kernel_main + + +call switch_to_16_bit +use16 +mov SP, [old_SP] + +mov AX, 0x0003 +int 0x10 + +mov BX, no_actions_message +call print_string + +no_actions: + xor AX, AX + int 16h + int 19h + +no_actions_message: db 10, 13, "IdealOS ended. Press any key to reboot.", 0 + + +size_of_memory_regions: dd 0 + + + + + + +use16 + + +VESA: times 512 db 0 +%define VESA__video_modes 14 + +VESA_Mode: times 256 db 0 +%define VESA_Mode__pitch 16 +%define VESA_Mode__width 18 +%define VESA_Mode__height 20 +%define VESA_Mode__bpp 25 + +VESA_CRTC: times 512 db 0 + + +setup_video: + mov AX, 0x4F00 + mov DI, VESA + int 0x10 + cmp AX, 0x004F + jne setup_VGA + + mov SI, VESA + mov EBX, [SI + VESA__video_modes] + +test_VESA_Mode: + mov AX, 0x4F01 + mov CX, [EBX] + cmp CX, 0xFFFF + je VESA_Mode_not_found + mov DI, VESA_Mode + int 0x10 + + ;push CX + + ;mov AX, [DI + VESA_Mode__width] + ;call print_number + ;mov AL, 'x' + ;call print_char + + ;mov AX, [DI + VESA_Mode__height] + ;call print_number + ;mov AL, 'x' + ;call print_char + + ;xor AX, AX + ;mov AL, [DI + VESA_Mode__bpp] + ;call print_number + ;mov AL, 10 + ;call print_char + ;mov AL, 13 + ;call print_char + + ;pop CX + + + cmp word [DI + VESA_Mode__width], 640 + jne next_VESA_Mode + cmp word [DI + VESA_Mode__height], 480 + jne next_VESA_Mode + cmp byte [DI + VESA_Mode__bpp], 24 + jl next_VESA_Mode + + + mov AX, 0x4F02 + mov DI, VESA_CRTC + mov BX, CX + ;or BX, 0x4000 + int 0x10 + + ret + +next_VESA_Mode: + add EBX, 2 + jmp test_VESA_Mode + + ret + +VESA_Mode_not_found: + ;call print_string + ;jmp $ + jmp setup_VGA + +setup_VGA: + mov AX, 0x0012 ;640x480x16 + int 0x10 + ret + + +;in AL - char code +print_char: + mov AH, 0x0E + int 0x10 + ret + + +;in BX - printed null terminated string +print_string: + mov AL, [BX] + cmp AL, 0 + je end_print_string + call print_char + inc BX + jmp print_string + + end_print_string: + ret + + +;in AX - printed number +print_number: + mov CX, 10 + mov DX, 0 + div CX + push DX + cmp AX, 0 + je skip_print_number + call print_number +skip_print_number: + pop DX + add DX, '0' + mov AL, DL + mov AH, 0x0E + int 0x10 + ret + + + + + + +use32 + + +old_SP: dw 0 +old_BP: dw 0 +old_ESP: dd 0 +old_EBP: dd 0 +sector_number: dd 0 + + +read_sector: + mov EAX, [ESP + 4] + mov [sector_number], EAX + + mov [old_ESP], ESP + mov [old_EBP], EBP + call switch_to_16_bit + use16 + mov SP, [old_SP] + mov BP, [old_BP] + + mov EAX, [sector_number] + xor EBX, EBX + mov BX, [BP] + mov [EBX], EAX + mov AX, [BP + 2] + call AX + + call switch_to_32_bit + use32 + mov ESP, [old_ESP] + mov EBP, [old_EBP] + + ret + + +write_sector: + mov EAX, [ESP + 4] + mov [sector_number], EAX + + mov [old_ESP], ESP + mov [old_EBP], EBP + call switch_to_16_bit + use16 + mov SP, [old_SP] + mov BP, [old_BP] + + mov EAX, [sector_number] + xor EBX, EBX + mov BX, [BP] + mov [EBX], EAX + mov AX, [BP + 4] + call AX + + call switch_to_32_bit + use32 + mov ESP, [old_ESP] + mov EBP, [old_EBP] + + ret + + + + + + + +%macro out_8 2 + mov AL, %2 + out %1, AL +%endmacro + + +;BX - PIC setting, 0x0870 for 16 bit, 0x2028 for 32 +use16 +reset_pic: + out_8 0x20, 0x11 + out_8 0x21, BH + out_8 0x21, 0x04 + out_8 0x21, 0x01 + out_8 0x21, 0x00 + + out_8 0xA0, 0x11 + out_8 0xA1, BL + out_8 0xA1, 0x02 + out_8 0xA1, 0x01 + out_8 0xA1, 0x00 + + ret + + +return_EIP: dd 0 + +use16 +switch_to_32_bit: + cli + + pop word[return_EIP] + + mov BX, 0x2028 + call reset_pic + + lidt [IDT_pointer] + + mov EAX, CR0 + or EAX, 1 + mov CR0, EAX + + jmp 8:switch_to_32_bit_1 + + use32 +switch_to_32_bit_1: + mov EAX, 16 + mov DS, EAX + mov SS, EAX + mov ES, EAX + mov FS, EAX + mov GS, EAX + + sti + + mov EAX, [return_EIP] + jmp EAX + + +align 4 +idtr_16: + dw 0x3FF + dd 0 + +use32 +switch_to_16_bit: + cli + + pop dword[return_EIP] + + lidt [idtr_16] + + mov AX, 32 + mov DS, AX + mov SS, AX + mov ES, AX + mov FS, AX + mov GS, AX + + jmp 24:switch_to_16_bit_1 + + align 16 + use16 +switch_to_16_bit_1: + + mov EAX, CR0 + and EAX, 0xFFFFFFFE + mov CR0, EAX + + jmp 0:switch_to_16_bit_2 + +switch_to_16_bit_2: + mov AX, CS + mov DS, AX + mov SS, AX + mov ES, AX + mov FS, AX + mov GS, AX + + mov BX, 0x0870 + call reset_pic + + sti + + mov AX, [return_EIP] + jmp AX + + + + + + +%define INTERRUPT_QUEUE_SIZE 256 + +interrupt_queue: +interrupt_queue_start: dd 0 +interrupt_queue_end: dd 0 + +interrupt_queue_data: + times INTERRUPT_QUEUE_SIZE db 0 + +%macro interrupt_handler 1 + interrupt_handler_%1: + push EAX + mov AL, %1 + jmp interrupt_handler_main +%endmacro + +%macro interrupt_handler_pic1 1 + interrupt_handler_%1: + push EAX + mov AL, %1 + jmp interrupt_handler_pic1_main +%endmacro + +%macro interrupt_handler_pic2 1 + interrupt_handler_%1: + push EAX + mov AL, %1 + jmp interrupt_handler_pic2_main +%endmacro + +use32 + +;%assign i 0 +;%rep 256 +;interrupt_handler i +;%assign i i+1 +;%endrep + +%assign i 0 +%rep 32 +interrupt_handler i +%assign i i+1 +%endrep + +%assign i 32 +%rep 8 +interrupt_handler_pic1 i +%assign i i+1 +%endrep + +%assign i 40 +%rep 8 +interrupt_handler_pic2 i +%assign i i+1 +%endrep + +%assign i 48 +%rep 208 +interrupt_handler i +%assign i i+1 +%endrep + +interrupt_handler_main: + push EBX + push ECX + + mov EBX, [interrupt_queue_end] + mov ECX, EBX + + inc ECX + cmp ECX, INTERRUPT_QUEUE_SIZE + jne skip_rewind_to_queue_start + xor ECX, ECX + skip_rewind_to_queue_start: + cmp ECX, [interrupt_queue_start] + je interrupt_queue_filled_error_handler + + add EBX, interrupt_queue_data + mov [EBX], AL + + mov [interrupt_queue_end], ECX + + pop ECX + pop EBX + pop EAX + + iret + +interrupt_handler_pic1_main: + push EBX + push ECX + + mov EBX, [interrupt_queue_end] + mov ECX, EBX + + inc ECX + cmp ECX, INTERRUPT_QUEUE_SIZE + jne skip_rewind_to_queue_start1 + xor ECX, ECX +skip_rewind_to_queue_start1: + cmp ECX, [interrupt_queue_start] + je interrupt_queue_filled_error_handler + + add EBX, interrupt_queue_data + mov [EBX], AL + + mov [interrupt_queue_end], ECX + + mov AL, 0x20 + out 0x20, AL + + pop ECX + pop EBX + pop EAX + + iret + + +interrupt_handler_pic2_main: + push EBX + push ECX + + mov EBX, [interrupt_queue_end] + mov ECX, EBX + + inc ECX + cmp ECX, INTERRUPT_QUEUE_SIZE + jne skip_rewind_to_queue_start2 + xor ECX, ECX +skip_rewind_to_queue_start2: + cmp ECX, [interrupt_queue_start] + je interrupt_queue_filled_error_handler + + add EBX, interrupt_queue_data + mov [EBX], AL + + mov [interrupt_queue_end], ECX + + mov AL, 0x20 + out 0x20, AL + out 0xA0, AL + + pop ECX + pop EBX + pop EAX + + iret + + +interrupt_queue_filled_error_handler: + call switch_to_16_bit + use16 + mov SP, [old_SP] + mov BP, [old_BP] + + mov AX, 0x0003 + int 0x10 + + xor BX, BX +print_next_interrupt: + xor AX, AX + mov AL, [BX + interrupt_queue_data] + call print_number + mov AL, ' ' + call print_char + + inc BX + cmp BX, INTERRUPT_QUEUE_SIZE + jne print_next_interrupt + + mov BX, interrupt_queue_filled_message + call print_string + + jmp no_actions + +interrupt_queue_filled_message: db "ERROR: interrupt queue filled", 10, 0 + + + + + + +align 16 +GDT: + ; dummy + dq 0 + + ; CODE (CS register = 8) + dw 0xFFFF ; размер сегмента + dw 0 ; базовый адрес + db 0 ; базовый адрес + db 0b10011010 ; 1 сегмент правильный(должно быть 1) + ; 00 уровень привилегий(меньше - больше привилегий) + ; 1 если сегмент в памяти то 1 + ; 1 сегмент исполняемый + ; 0 направление для сегмента данных либо возможность перехода с низких привилегий на высокие для сегмента кода(1 - разрешено, 0 - запрещено) + ; 1 разрешение на чтение для сегмента кода, разрешение на запись для сегмента данных + ; 0 бит доступа к сегменту, устанавливается процессором(рекомендуется 0) + db 0b11001111 ; 1 гранулярность(если 0, то размер адреса равен размеру сегмента кода, если 1 то размеру сегмента кода * 4096) + ; 1 размер, если 0 и 64 битный режим(следующий бит) = 0, то селектор определяет 16 битный режим, если 1 - 32 битный. Если 64 битный режим равен 1, то должен быть равен 0(значение 1 зарезервировано, будет генерировать исключение) + ; 0 64 битный режим + ; 0 зарезервировано + ; 1111 размер сегмента + db 0 ; базовый адрес + + ; DATA (DS register = 16) + dw 0xffff ; размер сегмента + dw 0 ; базовый адрес + db 0 ; базовый адрес + db 0b10010010 ; 1 сегмент правильный(должно быть 1) + ; 00 уровень привилегий(меньше - больше привилегий) + ; 1 если сегмент в памяти то 1 + ; 0 сегмент исполняемый + ; 0 направление для сегмента данных либо возможность перехода с низких привилегий на высокие для сегмента кода + ; 1 разрешение на чтение для сегмента кода, разрешение на запись для сегмента данных + ; 0 бит доступа к сегменту, устанавливается процессором(рекомендуется 0) + db 0b11001111 ; 1 гранулярность(если 0, то размер адреса равен размеру сегмента кода, если 1 то размеру сегмента кода * 4096) + ; 1 размер, если 0 и 64 битный режим(следующий бит) = 0, то селектор определяет 16 битный режим, если 1 - 32 битный. Если 64 битный режим равен 1, то должен быть равен 0(значение 1 зарезервировано, будет генерировать исключение) + ; 0 64 битный режим + ; 0 зарезервировано + ; 1111 размер сегмента + db 0 ; базовый адрес + + ; CODE16 (CS register = 24) + dw 0xFFFF ; размер сегмента + dw 0 ; базовый адрес + db 0 ; базовый адрес + db 0b10011010 ; 1 сегмент правильный(должно быть 1) + ; 00 уровень привилегий(меньше - больше привилегий) + ; 1 0 - системный, 1 - код или данные + ; 1 сегмент исполняемый + ; 1 направление для сегмента данных либо возможность перехода с низких привилегий на высокие для сегмента кода(1 - разрешено, 0 - запрещено) + ; 1 разрешение на чтение для сегмента кода, разрешение на запись для сегмента данных + ; 0 бит доступа к сегменту, устанавливается процессором(рекомендуется 0) + db 0b00001111 ; 0 гранулярность(если 0, то размер адреса равен размеру сегмента кода, если 1 то размеру сегмента кода * 4096) + ; 0 размер, если 0 и 64 битный режим(следующий бит) = 0, то селектор определяет 16 битный режим, если 1 - 32 битный. Если 64 битный режим равен 1, то должен быть равен 0(значение 1 зарезервировано, будет генерировать исключение) + ; 0 64 битный режим + ; 0 зарезервировано + ; 1111 размер сегмента + db 0 ; базовый адрес + + ; DATA16 (DS register = 32) + dw 0xFFFF ; размер сегмента + dw 0 ; базовый адрес + db 0 ; базовый адрес + db 0b10010010 ; 1 сегмент правильный(должно быть 1) + ; 00 уровень привилегий(меньше - больше привилегий) + ; 1 0 - системный, 1 - код или данные + ; 0 сегмент исполняемый + ; 0 направление для сегмента данных либо возможность перехода с низких привилегий на высокие для сегмента кода + ; 1 разрешение на чтение для сегмента кода, разрешение на запись для сегмента данных + ; 0 бит доступа к сегменту, устанавливается процессором(рекомендуется 0) + db 0b00001111 ; 0 гранулярность(если 0, то размер адреса равен размеру сегмента кода, если 1 то размеру сегмента кода * 4096) + ; 0 размер, если 0 и 64 битный режим(следующий бит) = 0, то селектор определяет 16 битный режим, если 1 - 32 битный. Если 64 битный режим равен 1, то должен быть равен 0(значение 1 зарезервировано, будет генерировать исключение) + ; 0 64 битный режим + ; 0 зарезервировано + ; 1111 размер сегмента + db 0 ; базовый адрес + +GDT_pointer: + dw $ - GDT ;размер + dd GDT ;адрес + + + + +%macro interrupt_descriptor 3 + dw %1 ; handler_address_low + dw %2 ; selector + db 0 ; zero + db %3 ; attributes + dw 0 ; handler_address_high +%endmacro + +align 16 +IDT: + %assign i 0 + %rep 256 + interrupt_descriptor interrupt_handler_%[i], 8, 0x8E + %assign i i+1 + %endrep + + +IDT_pointer: + dw $ - IDT ;размер + dd IDT ;адрес + + +align 32 +kernel_main: \ No newline at end of file diff --git a/components/kernel/main32.c b/components/kernel/main32.c new file mode 100644 index 0000000..4997909 --- /dev/null +++ b/components/kernel/main32.c @@ -0,0 +1,166 @@ +#include + + +#define INTERRUPT_QUEUE_SIZE 256 + +typedef struct { + Number start; + Number end; + Byte data[INTERRUPT_QUEUE_SIZE]; +} +Interrupt_Queue; + + +typedef struct { + Number32 address_low; + Number32 address_high; + Number32 size_low; + Number32 size_high; + Number32 type; //1 - normal, 2 - reserved, other - not used +} +Memory_Region; + + +typedef struct { + Interrupt_Queue* interrupt_queue; + + //sector address is 0x500 + void (*read_sector)(Number32 sector_number); + void (*write_sector)(Number32 sector_number); + + //VGA_Interface VGA; + VESA_Mode* VESA; + Number32 size_of_memory_regions; + Memory_Region* memory_regions; + void* t; +} +Loader_Api; + + +Loader_Api* loader_api; + + +void main(); + + +void _start(Loader_Api api) +{ + loader_api = &api; + main(); +} + + +#include +#include +#include + +#include "interfaces/heap.c" +#include "interface.c" +#include "interfaces/file.c" +#include "interfaces/process.c" + +#include "shell.c" + + +void interrupt_handler(Process* process) +{ + Interrupt_Queue* interrupt_queue; + Number start_index; + Number interrupt_number; + Process* next_process; + + interrupt_queue = loader_api->interrupt_queue; + + for(;;) { + for(;;) { + start_index = interrupt_queue->start; + + if(start_index == interrupt_queue->end) { + break; + } + + interrupt_number = interrupt_queue->data[start_index]; + + emit_event(interrupt_number); + + ++start_index; + + if(start_index >= INTERRUPT_QUEUE_SIZE) { + start_index = 0; + } + + interrupt_queue->start = start_index; + } + + + next_process = process->next; + + if(!next_process) { + break; + } + + while(next_process && next_process->state == PROCESS_WAITING) { + next_process = next_process->next; + } + + if(next_process) { + switch_to_process(next_process); + } + else { + asm("hlt"); + } + } +} + + +void init(Process* process) +{ + execute_command("graphics"); + + + Process* bootscreen_process; + + if(create_program_process(&bootscreen_process, "bootscreen", 0, 0)) { + return; + } + + //switch_to_process(bootscreen_process); + + execute_command("ps2"); + + + Number i; + + for(i = 0; i < 18 * 4; ++i) { + wait_event(32, 0); + } + + + stop_process(bootscreen_process, 0); + + + execute_command("shell"); +} + + +void main() +{ + if(!initialize_heap()) { + return; + } + + + create_interface_by_path("VESA", loader_api->VESA); + create_interface_by_path("file", &file_interface); + create_interface_by_path("heap", &heap_interface); + create_interface_by_path("process", &process_interface); + + + Process interrupt_handler_process; + Process init_process; + + initialize_process(&interrupt_handler_process, "interrupt_handler", &interrupt_handler, 0, 1024); + initialize_process(&init_process, "init", &init, 0, 65536); + + switch_to_process(&interrupt_handler_process); +} \ No newline at end of file diff --git a/components/kernel/shell.c b/components/kernel/shell.c new file mode 100644 index 0000000..cf62f5f --- /dev/null +++ b/components/kernel/shell.c @@ -0,0 +1,225 @@ +Number get_program_name_extension_index(Byte program_name[64], Number program_name_size) +{ + Number extension_index; + + for(extension_index = program_name_size; extension_index; --extension_index) { + if(program_name[extension_index - 1] == '.') { + break; + } + } + + return extension_index; +} + + +Number parse_program_name(Byte* command, Byte program_name[64]) +{ + Number i; + + for( + i = 0; + i < 63 && + command[i] && + command[i] != ' ' && + command[i] != '|'; + ++i + ) { + program_name[i] = command[i]; + } + + program_name[i] = '\0'; + + return i; +} + + +Number parse_arguments(Byte* command, Byte** arguments, Number* number_of_arguments) +{ + Number arguments_size; + + arguments_size = 0; + *number_of_arguments = 0; + + while(command[arguments_size] && *number_of_arguments < MAX_NUMBER_OF_ARGUMENTS && command[arguments_size] != '|') { + arguments[*number_of_arguments] = command + arguments_size; + ++*number_of_arguments; + + while(command[arguments_size] && command[arguments_size] != ' ' && command[arguments_size] != '|') { + ++arguments_size; + } + + + if(command[arguments_size] == ' ') { + command[arguments_size] = '\0'; + ++arguments_size; + } + else if(command[arguments_size] == '|') { + Number i; + for(i = 255; i > arguments_size; --i) { + command[i] = command[i - 1]; + } + + command[arguments_size] = '\0'; + ++arguments_size; + } + + + while(command[arguments_size] && command[arguments_size] == ' ') { + ++arguments_size; + } + } + + return arguments_size; +} + + +Boolean load_COM_program(Process* process, File* file) +{ + Byte* program; + + program = allocate_memory(500, 0); + process->start = program; + + Memory_Chunk* chunk = (Byte*)process - sizeof(Memory_Chunk); + chunk->owner = process; + + while(read_bytes_from_file(file, program, 500) > 0) { + //program = allocate_memory(500); + program = heap_top; + heap_top += 500; + } + + //free_memory(program); + heap_top -= 500; + + return 1; +} + + +Number load_program(Process* process, Byte* command) +{ + Byte program_name[64]; + Number program_name_size; + Number extension_index; + File file; + + program_name_size = parse_program_name(command, program_name); + extension_index = get_program_name_extension_index(program_name, program_name_size); + + if(!extension_index) { + if(program_name_size >= 64 - 5) { + goto not_found_error; + } + + program_name[program_name_size++] = '.'; + extension_index = program_name_size; + program_name[program_name_size++] = 'c'; + program_name[program_name_size++] = 'o'; + program_name[program_name_size++] = 'm'; + program_name[program_name_size] = '\0'; + } + + if(find_file(&file, program_name)) { + if(!load_COM_program(process, &file)) { + goto execution_error; + } + + return 0; + } + else { + goto not_found_error; + } + + not_found_error: { + //print( + // "%s not found.\n" + // "Enter \"load dir\" for show all commands", + // program_name + //); + + return 1; + } + + execution_error: { + //print( + // "%s not executed.", + // program_name + //); + + return 2; + } +} + + +Number create_program_process(Process** process, Byte* command, Number* parsed_command_size, Process* previous_piping_process) +{ + Number load_program_status; + + *process = allocate_memory(sizeof(Process), 0); + + load_program_status = load_program(*process, command); + + if(load_program_status) { + free_memory(*process); + return load_program_status; + } + + initialize_process(*process, command, (*process)->start, previous_piping_process, 65536); + + if(!parsed_command_size) { + parsed_command_size = &load_program_status; + } + + *parsed_command_size = parse_arguments( + (*process)->command, + &(*process)->arguments, + &(*process)->number_of_arguments + ); + + return 0; +} + + +Number execute_command(Byte* command) +{ + Process* process; + Process* previous_piping_process; + Number parsed_command_size; + Number create_programm_process_status; + + previous_piping_process = 0; + + for(;;) { + create_programm_process_status = create_program_process(&process, command, &parsed_command_size, previous_piping_process); + + if(create_programm_process_status) { + return create_programm_process_status; + } + + if(command[parsed_command_size] != '|') { + break; + } + + command += parsed_command_size + 1; + + while(*command == ' ') { + ++command; + } + } + + switch_to_process(process); + + return 0; +} + + +Process_Interface process_interface = { + .create = &create_program_process, + .switch_to = &switch_to_process, + .yield = &yield, + .wait = &wait_event, + .stop = &stop_process, + .exit = &exit_from_current_process, + .execute = &execute_command, + .get_list = &get_processes_list +}; \ No newline at end of file diff --git a/components/libraries/graphics/font.c b/components/libraries/graphics/font.c new file mode 100644 index 0000000..227ed87 --- /dev/null +++ b/components/libraries/graphics/font.c @@ -0,0 +1,97 @@ +Byte glyphs_8_16[95][128]= { + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,231,0,0,0,0,0,0,203,231,0,0,0,0,0,0,203,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,231,0,0,0,0,0,0,203,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,174,95,255,174,0,0,95,255,138,95,255,138,0,0,0,255,138,0,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,174,0,203,174,0,0,0,174,174,0,203,174,0,0,0,203,174,0,231,138,0,138,255,255,255,255,255,255,255,0,0,231,138,0,255,95,0,0,0,255,95,95,255,0,0,203,255,255,255,255,255,255,174,0,95,255,0,138,231,0,0,0,95,231,0,138,231,0,0,0,138,231,0,174,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,138,0,0,0,0,203,255,255,255,231,0,0,231,203,0,255,95,0,0,95,255,138,0,255,0,0,0,0,255,231,95,231,0,0,0,0,95,255,255,231,0,0,0,0,0,0,174,255,255,203,0,0,0,0,203,174,138,255,138,0,0,0,203,138,0,255,138,0,0,0,231,95,174,255,95,95,255,255,255,255,255,0,0,0,0,95,231,0,0,0,0,0,0,138,231,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,255,231,0,0,174,231,203,174,0,255,138,95,255,0,203,174,0,255,95,231,138,0,95,255,255,203,174,203,0,0,0,0,0,95,255,0,0,0,0,0,0,231,138,0,0,0,0,0,174,203,138,255,255,174,0,95,255,0,231,138,95,255,0,231,138,0,231,138,95,255,203,203,0,0,138,255,255,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,255,174,0,0,0,203,203,0,95,255,95,0,0,203,174,0,95,255,95,0,0,174,255,0,231,203,0,0,0,0,231,255,174,0,0,0,0,255,203,255,203,0,231,174,174,231,0,95,255,174,231,138,174,203,0,0,174,255,255,0,138,255,95,0,0,255,255,0,0,174,255,255,255,138,231,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,0,0,0,0,0,0,174,255,0,0,0,0,0,0,174,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,95,0,0,0,0,0,231,203,0,0,0,0,0,174,231,0,0,0,0,0,0,255,138,0,0,0,0,0,138,231,0,0,0,0,0,0,203,203,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,203,203,0,0,0,0,0,0,138,255,0,0,0,0,0,0,0,255,138,0,0,0,0,0,0,174,255,0,0,0,0,0,0,0,231,203,0,0,0,0,0,0,0,231,95,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,95,0,0,0,0,0,0,138,255,0,0,0,0,0,0,0,203,231,0,0,0,0,0,0,0,255,138,0,0,0,0,0,0,203,203,0,0,0,0,0,0,138,231,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,231,0,0,0,0,0,0,203,203,0,0,0,0,0,0,255,138,0,0,0,0,0,203,203,0,0,0,0,0,138,255,0,0,0,0,0,0,231,95,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,174,0,0,0,0,203,174,138,174,95,231,0,0,0,174,255,255,231,0,0,0,0,174,255,255,203,0,0,0,203,174,138,174,138,231,0,0,0,0,138,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,138,255,255,255,255,255,255,203,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,203,255,174,0,0,0,0,0,138,255,138,0,0,0,0,0,231,255,0,0,0,0,138,255,231,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,95,0,0,0,0,0,255,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,0,0,0,0,0,0,203,174,0,0,0,0,0,95,255,95,0,0,0,0,0,174,203,0,0,0,0,0,0,255,138,0,0,0,0,0,138,231,0,0,0,0,0,0,231,138,0,0,0,0,0,95,255,0,0,0,0,0,0,203,174,0,0,0,0,0,0,255,95,0,0,0,0,0,174,203,0,0,0,0,0,0,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,0,0,0,174,231,0,0,203,231,0,0,255,138,0,0,95,255,138,138,255,0,0,0,203,255,174,138,231,0,0,255,174,203,203,138,231,138,255,95,0,203,174,138,255,231,0,0,0,231,174,0,255,138,0,0,0,255,95,0,203,255,0,0,203,231,0,0,0,203,255,255,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,95,0,0,0,95,255,174,255,95,0,0,0,231,0,138,255,95,0,0,0,0,0,138,255,95,0,0,0,0,0,138,255,95,0,0,0,0,0,138,255,95,0,0,0,0,0,138,255,95,0,0,0,0,0,138,255,95,0,0,0,0,0,138,255,95,0,0,0,203,255,255,255,255,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,203,0,0,0,203,138,0,0,255,174,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,255,174,0,0,0,0,0,203,255,0,0,0,0,0,203,255,95,0,0,0,0,174,255,95,0,0,0,0,138,255,138,0,0,0,0,0,255,255,255,255,255,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,255,255,231,0,0,0,0,0,0,0,231,174,0,0,0,0,0,0,203,203,0,0,0,0,0,0,255,138,0,0,0,203,255,255,174,0,0,0,0,0,0,0,203,231,0,0,0,0,0,0,95,255,95,0,0,0,0,0,95,255,0,0,0,0,0,0,231,203,0,0,231,255,255,255,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,95,0,0,0,0,174,231,255,95,0,0,0,0,255,95,255,95,0,0,0,203,203,0,255,95,0,0,95,255,0,0,255,95,0,0,231,174,0,0,255,95,0,138,231,0,0,0,255,95,0,203,255,255,255,255,255,255,231,0,0,0,0,0,255,95,0,0,0,0,0,0,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,255,255,255,203,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,255,255,255,255,0,0,0,0,0,0,0,203,255,0,0,0,0,0,0,95,255,95,0,0,0,0,0,138,255,95,0,0,0,0,0,255,203,0,0,203,255,255,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,231,0,0,0,255,203,0,0,0,0,0,174,203,0,0,0,0,0,0,231,138,0,0,0,0,0,0,255,138,255,255,255,138,0,0,255,231,0,0,138,255,95,0,255,95,0,0,0,231,174,0,231,138,0,0,0,231,138,0,174,231,0,0,138,255,0,0,0,203,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,255,255,255,255,255,138,0,0,0,0,0,95,255,95,0,0,0,0,0,203,203,0,0,0,0,0,95,255,138,0,0,0,0,0,174,231,0,0,0,0,0,0,255,138,0,0,0,0,0,174,231,0,0,0,0,0,0,255,174,0,0,0,0,0,138,255,0,0,0,0,0,0,255,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,255,255,138,0,0,231,174,0,0,138,255,95,0,255,138,0,0,95,255,95,0,174,255,138,0,231,203,0,0,0,95,255,255,174,0,0,0,138,255,138,95,255,231,0,0,255,174,0,0,95,255,138,95,255,138,0,0,0,255,138,0,231,203,0,0,174,255,95,0,0,255,255,255,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,255,231,0,0,0,231,203,0,0,203,203,0,95,255,95,0,0,95,255,95,95,255,0,0,0,0,255,138,0,255,174,0,0,174,255,138,0,95,255,255,255,174,255,138,0,0,0,0,0,95,255,95,0,0,0,0,0,174,231,0,0,0,0,0,174,255,95,0,0,203,255,255,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,0,0,0,0,0,0,231,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,0,0,0,0,0,0,231,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,0,0,0,0,0,0,231,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,95,0,0,0,0,0,203,255,174,0,0,0,0,0,138,255,174,0,0,0,0,0,203,255,0,0,0,0,95,255,255,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,203,0,0,0,0,0,231,231,0,0,0,0,95,255,203,0,0,0,0,138,255,138,0,0,0,0,0,231,255,138,0,0,0,0,0,0,95,255,203,0,0,0,0,0,0,0,231,231,0,0,0,0,0,0,0,203,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,138,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,0,0,0,0,0,0,0,174,255,95,0,0,0,0,0,0,138,255,174,0,0,0,0,0,0,95,255,203,0,0,0,0,0,0,255,255,95,0,0,0,138,255,174,0,0,0,0,174,255,95,0,0,0,0,138,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,231,0,0,0,0,0,0,0,203,255,95,0,0,0,0,0,0,231,203,0,0,0,0,0,0,174,231,0,0,0,0,0,0,231,203,0,0,0,0,255,255,231,0,0,0,0,0,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,174,0,0,0,0,0,138,255,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,174,0,0,95,255,138,0,0,255,138,0,231,138,0,0,0,138,231,138,231,0,0,0,0,0,255,174,174,0,231,255,255,95,231,231,95,174,203,0,255,0,231,231,0,231,138,95,231,0,231,255,0,255,95,138,231,0,255,231,0,255,95,203,203,138,203,231,95,203,255,174,255,255,95,174,174,0,0,0,0,0,0,95,255,138,0,0,174,95,0,0,95,255,255,255,203,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,95,0,0,0,0,95,231,203,174,0,0,0,0,174,174,138,231,0,0,0,0,231,138,95,255,95,0,0,95,255,0,0,231,174,0,0,174,203,0,0,174,231,0,0,231,174,0,0,138,255,0,95,255,255,255,255,255,255,138,174,231,0,0,0,0,203,203,203,174,0,0,0,0,138,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,255,255,255,95,0,0,231,174,0,0,174,255,0,0,231,174,0,0,95,255,0,0,231,174,0,0,203,203,0,0,231,255,255,255,255,0,0,0,231,174,0,0,174,255,0,0,231,174,0,0,0,231,138,0,231,174,0,0,0,255,138,0,231,174,0,0,174,255,0,0,231,255,255,255,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,255,255,203,0,0,95,255,174,0,0,138,138,0,231,203,0,0,0,0,0,95,255,95,0,0,0,0,0,138,255,95,0,0,0,0,0,138,255,95,0,0,0,0,0,95,255,95,0,0,0,0,0,0,255,174,0,0,0,0,0,0,174,255,138,0,0,138,138,0,0,138,255,255,255,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,255,255,255,203,0,0,95,255,95,0,0,231,231,0,95,255,95,0,0,0,255,174,95,255,95,0,0,0,203,203,95,255,95,0,0,0,203,231,95,255,95,0,0,0,203,231,95,255,95,0,0,0,231,203,95,255,95,0,0,95,255,138,95,255,95,0,0,255,203,0,95,255,255,255,255,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,255,255,255,255,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,255,255,255,255,231,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,255,255,255,231,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,255,255,255,255,203,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,255,255,203,0,0,138,255,138,0,0,138,138,0,255,174,0,0,0,0,0,138,255,0,0,0,0,0,0,174,255,0,0,0,0,0,0,174,255,0,0,231,255,255,138,138,255,0,0,0,0,231,138,95,255,138,0,0,0,231,138,0,174,255,95,0,0,231,138,0,0,174,255,255,255,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,255,255,255,255,255,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,255,255,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,203,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,255,255,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,174,0,0,138,255,0,0,0,95,255,255,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,138,0,0,138,255,138,0,231,138,0,95,255,138,0,0,231,138,0,231,174,0,0,0,231,138,174,231,0,0,0,0,231,174,255,0,0,0,0,0,231,255,255,0,0,0,0,0,231,138,174,231,0,0,0,0,231,138,0,231,203,0,0,0,231,138,0,0,255,174,0,0,231,138,0,0,138,255,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,255,255,255,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,174,0,0,138,255,174,95,255,231,0,0,174,255,174,138,231,231,95,0,231,174,203,138,203,174,138,95,203,174,203,138,203,95,203,174,138,174,203,174,203,0,231,231,0,174,203,174,203,0,174,203,0,174,231,174,203,0,0,0,0,138,231,174,203,0,0,0,0,138,231,203,203,0,0,0,0,138,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,231,0,0,0,231,138,95,255,231,95,0,0,231,138,95,255,174,203,0,0,231,138,95,255,95,255,0,0,231,138,95,255,95,174,138,0,231,138,95,255,95,95,231,0,231,138,95,255,95,0,231,95,231,138,95,255,95,0,138,174,231,138,95,255,95,0,0,231,231,138,95,255,95,0,0,174,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,95,0,0,203,231,0,0,174,255,95,95,255,95,0,0,0,231,174,174,231,0,0,0,0,174,231,174,203,0,0,0,0,174,231,174,203,0,0,0,0,174,231,174,231,0,0,0,0,174,203,95,255,95,0,0,0,231,174,0,231,231,0,0,174,255,0,0,0,231,255,255,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,255,255,255,95,0,0,231,174,0,0,174,255,95,0,231,174,0,0,0,231,174,0,231,174,0,0,0,255,174,0,231,174,0,0,174,255,0,0,231,255,255,255,231,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,95,0,0,203,231,0,0,174,255,95,95,255,95,0,0,0,231,174,174,255,0,0,0,0,203,231,174,231,0,0,0,0,174,231,174,231,0,0,0,0,174,231,174,255,0,0,0,0,203,231,95,255,95,0,0,0,231,174,0,231,231,0,0,174,255,0,0,0,231,255,255,255,0,0,0,0,0,174,231,0,0,0,0,0,0,95,255,95,0,203,0,0,0,0,138,255,255,231}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,255,255,255,0,0,0,231,174,0,0,203,231,0,0,231,174,0,0,138,255,0,0,231,174,0,0,231,203,0,0,231,255,255,255,203,0,0,0,231,174,0,203,203,0,0,0,231,174,0,95,255,0,0,0,231,174,0,0,203,174,0,0,231,174,0,0,138,255,0,0,231,174,0,0,0,231,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,203,0,0,231,231,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,231,0,0,0,0,0,0,95,255,255,231,0,0,0,0,0,0,95,255,255,174,0,0,0,0,0,0,138,255,95,0,0,0,0,0,0,255,138,0,0,0,0,0,174,255,0,95,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,255,255,255,255,255,203,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,174,95,255,95,0,0,0,231,138,0,231,203,0,0,174,255,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,203,0,0,0,0,138,255,174,255,0,0,0,0,203,203,95,255,138,0,0,0,255,138,0,231,174,0,0,95,255,0,0,174,231,0,0,174,231,0,0,95,255,95,0,231,174,0,0,0,231,174,95,255,95,0,0,0,203,231,174,231,0,0,0,0,138,255,255,174,0,0,0,0,0,255,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,203,0,0,0,0,138,231,203,203,0,0,0,0,138,231,174,203,0,0,0,0,138,231,174,231,0,174,203,0,138,203,138,231,0,203,255,0,174,203,138,231,0,231,203,138,174,203,95,255,95,203,174,174,174,174,95,255,174,138,95,231,203,174,95,255,255,95,0,231,255,138,0,255,231,0,0,203,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,95,0,0,0,255,203,0,203,231,0,0,203,231,0,0,95,255,138,95,255,138,0,0,0,174,231,231,203,0,0,0,0,0,231,255,95,0,0,0,0,95,255,255,95,0,0,0,0,203,231,203,231,0,0,0,138,255,138,95,255,174,0,0,255,203,0,0,174,255,95,203,255,0,0,0,0,231,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,231,0,0,0,0,174,255,95,255,138,0,0,0,255,138,0,174,255,0,0,174,231,0,0,0,255,174,95,255,138,0,0,0,138,255,203,203,0,0,0,0,0,231,255,95,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,95,0,0,0,0,0,174,203,0,0,0,0,0,95,255,95,0,0,0,0,0,203,174,0,0,0,0,0,95,255,0,0,0,0,0,0,231,174,0,0,0,0,0,138,231,0,0,0,0,0,0,255,138,0,0,0,0,0,174,203,0,0,0,0,0,0,255,255,255,255,255,255,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,255,255,95,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,255,255,255,95,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,203,0,0,0,0,0,0,95,255,0,0,0,0,0,0,0,231,174,0,0,0,0,0,0,138,231,0,0,0,0,0,0,0,231,138,0,0,0,0,0,0,174,203,0,0,0,0,0,0,0,255,95,0,0,0,0,0,0,203,174,0,0,0,0,0,0,95,255,0,0,0,0,0,0,0,231,138,0,0,0,0,0,0,138,231,0,0,0,0,0,0,0,255,138,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,255,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,231,255,255,231,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,231,0,0,0,0,0,138,231,203,174,0,0,0,0,231,138,95,255,0,0,0,138,231,0,0,203,174,0,0,255,138,0,0,95,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,203,0,0,0,0,0,0,0,231,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,138,0,0,138,138,0,0,174,255,0,0,0,0,0,0,95,255,95,0,0,255,255,255,255,255,95,0,231,203,0,0,95,255,95,0,255,174,0,0,231,255,95,0,138,255,255,255,138,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,231,255,255,174,0,0,231,255,138,0,138,255,95,0,231,174,0,0,0,231,138,0,231,174,0,0,0,231,174,0,231,174,0,0,0,255,138,0,231,174,0,0,174,255,0,0,203,255,255,255,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,255,255,255,0,0,95,255,138,0,0,0,0,0,203,203,0,0,0,0,0,0,231,174,0,0,0,0,0,0,203,203,0,0,0,0,0,0,138,255,138,0,0,0,0,0,0,138,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,203,255,255,255,255,0,0,203,231,0,0,138,255,0,0,255,95,0,0,138,255,0,95,255,95,0,0,138,255,0,95,255,95,0,0,138,255,0,0,231,174,0,138,255,255,0,0,95,255,255,255,95,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,0,0,0,203,231,0,0,174,255,0,0,255,95,0,0,0,255,138,95,255,255,255,255,255,255,138,0,255,95,0,0,0,0,0,0,203,231,0,0,0,0,0,0,0,203,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,203,0,0,0,231,203,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,138,255,255,255,255,255,255,95,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,255,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,255,255,255,203,0,203,231,0,0,203,203,0,0,231,138,0,0,138,231,0,0,203,231,0,0,231,203,0,0,203,255,255,255,231,0,0,0,255,95,0,0,0,0,0,0,174,255,255,255,255,255,0,95,255,95,0,0,0,231,203,138,255,95,0,0,0,255,174,0,174,255,255,255,255,174,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,231,255,255,138,0,0,231,255,138,0,174,255,0,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,0,0,0,0,0,0,203,255,0,0,0,0,0,0,0,0,0,0,0,0,174,255,255,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,231,255,255,255,255,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,95,0,0,0,0,0,174,255,95,0,0,0,0,0,0,0,0,0,0,231,255,255,255,255,95,0,0,0,0,0,95,255,95,0,0,0,0,0,95,255,95,0,0,0,0,0,95,255,95,0,0,0,0,0,95,255,95,0,0,0,0,0,95,255,95,0,0,0,0,0,95,255,95,0,0,0,0,0,95,255,95,0,0,174,0,0,203,231,0,0,0,174,255,255,231,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,203,0,0,0,0,0,0,203,203,0,0,0,0,0,0,203,203,0,0,0,0,0,0,203,203,0,0,203,255,138,0,203,203,0,203,231,0,0,0,203,203,231,231,0,0,0,0,203,255,255,138,0,0,0,0,203,203,95,255,138,0,0,0,203,203,0,138,255,138,0,0,203,203,0,0,174,255,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,255,255,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,231,255,255,255,255,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,231,203,255,174,231,255,138,138,255,174,174,255,138,203,203,138,255,0,174,231,0,174,203,138,255,0,174,231,0,174,203,138,255,0,174,231,0,174,203,138,255,0,174,231,0,174,203,138,255,0,174,231,0,174,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,138,231,255,255,138,0,0,231,255,138,0,174,255,0,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,255,255,95,0,0,231,203,0,0,138,255,95,95,255,95,0,0,0,231,174,138,255,0,0,0,0,203,203,95,255,95,0,0,0,231,174,0,231,203,0,0,174,255,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,138,231,255,255,174,0,0,231,255,138,0,138,255,95,0,231,174,0,0,0,231,138,0,231,174,0,0,0,231,174,0,231,174,0,0,0,255,138,0,231,174,0,0,174,255,0,0,231,255,255,255,231,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,255,0,0,203,231,0,0,138,255,0,0,255,95,0,0,138,255,0,95,255,95,0,0,138,255,0,95,255,95,0,0,138,255,0,0,231,174,0,138,255,255,0,0,95,255,255,255,95,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0,0,0,0,0,0,138,255,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,203,138,255,255,203,0,0,174,255,255,0,0,255,138,0,174,255,0,0,0,231,174,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,174,0,0,174,231,0,0,0,0,0,0,174,255,95,0,0,0,0,0,0,174,255,255,255,0,0,0,0,0,0,0,203,231,0,0,0,0,0,0,174,231,0,0,203,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,174,255,255,255,255,255,255,95,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,174,231,0,0,0,0,0,0,138,255,95,0,0,0,0,0,0,203,255,255,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,231,174,0,0,95,255,95,0,203,203,0,0,255,255,95,0,95,255,255,255,95,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,95,0,0,0,231,203,0,231,174,0,0,95,255,95,0,174,231,0,0,174,203,0,0,0,255,95,0,231,138,0,0,0,203,174,95,231,0,0,0,0,95,231,174,174,0,0,0,0,0,231,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,203,0,0,0,0,138,231,174,203,0,0,0,0,174,203,138,231,0,174,203,0,174,203,95,255,0,231,231,0,203,174,0,255,95,203,174,138,231,138,0,231,203,138,95,203,231,95,0,203,255,0,0,231,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,255,203,0,0,95,255,174,0,95,255,138,0,255,174,0,0,0,138,255,203,203,0,0,0,0,0,203,255,0,0,0,0,0,174,231,174,231,0,0,0,138,255,95,0,231,203,0,138,255,174,0,0,95,255,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,95,0,0,0,231,174,0,231,174,0,0,138,255,0,0,174,231,0,0,203,203,0,0,0,255,95,0,255,95,0,0,0,203,174,138,203,0,0,0,0,95,255,231,95,0,0,0,0,0,231,231,0,0,0,0,0,0,231,174,0,0,0,0,0,174,231,0,0,0,0,203,255,255,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,255,255,255,231,0,0,0,0,0,0,255,95,0,0,0,0,0,231,138,0,0,0,0,0,174,203,0,0,0,0,0,95,231,0,0,0,0,0,0,255,95,0,0,0,0,0,203,255,255,255,255,255,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,255,174,0,0,0,0,174,231,0,0,0,0,0,0,203,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,255,95,0,0,0,0,231,255,0,0,0,0,0,0,0,0,255,95,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,231,174,0,0,0,0,0,0,203,174,0,0,0,0,0,0,174,231,0,0,0,0,0,0,0,231,255,174,0}, + {0,0,0,0,0,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0,0,0,0,174,203,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,138,255,255,95,0,0,0,0,0,0,174,231,0,0,0,0,0,0,95,255,0,0,0,0,0,0,95,255,0,0,0,0,0,0,95,255,0,0,0,0,0,0,0,255,138,0,0,0,0,0,0,0,203,255,0,0,0,0,0,255,138,0,0,0,0,0,95,255,0,0,0,0,0,0,95,255,0,0,0,0,0,0,95,255,0,0,0,0,0,0,95,255,0,0,0,0,0,0,174,231,0,0,0,0,138,255,255,95,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,255,231,0,0,138,231,138,231,0,174,231,0,174,203,174,203,0,0,174,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} +}; \ No newline at end of file diff --git a/components/libraries/graphics/main.c b/components/libraries/graphics/main.c new file mode 100644 index 0000000..c40af89 --- /dev/null +++ b/components/libraries/graphics/main.c @@ -0,0 +1,290 @@ +#include + + +typedef struct { + VESA_Mode* VESA; + Heap_Interface* heap; + Process_Interface* process; +} +Module; + +Module _module = {0}; + + +void main(Process* process); + + +void start(Process* process) +{ + get_module_address_by_function(start); + Module* module = global_ptr(_module); + + module->VESA = process->get(global_ptr("VESA")); + module->heap = process->get(global_ptr("heap")); + module->process = process->get(global_ptr("process")); + + main(process); +} + + +Frame* create_frame(Number width, Number height) +{ + get_module_address_by_function(create_frame); + Module* module = global_ptr(_module); + + + Frame* frame; + + frame = module->heap->allocate(sizeof(Frame) + width * height * sizeof(frame->buffer[0]), 0); + + frame->scroll_x = 0; + frame->scroll_y = 0; + frame->width = width; + frame->height = height; + + return frame; +} + + +void clean_frame(Frame* frame, Number32 color) +{ + Number x; + Number y; + Number32* line; + + line = frame->buffer; + + for(y = 0; y < frame->height; ++y) { + for(x = 0; x < frame->width; ++x) { + line[x] = color; + } + + line += frame->width; + } +} + + +void draw_rectangle(Frame* frame, Number x, Number y, Number width, Number height, Number32 color) +{ + Number i; + Number j; + Number32* line; + + if(x >= frame->width || y >= frame->height) { + return; + } + + if(x + width >= frame->width) { + width = frame->width - x; + } + + if(y + height >= frame->height) { + height = frame->height - y; + } + + line = frame->buffer + y * frame->width + x; + + for(i = 0; i < height; ++i) { + for(j = 0; j < width; ++j) { + line[j] = color; + } + + line += frame->width; + } +} + + +void draw_frame_in_frame(Frame* destination_frame, Frame *source_frame, Number x, Number y) +{ + Number i; + Number j; + Number32* source_line; + Number32* destination_line; + + Number width; + Number height; + + if(x >= destination_frame->width || y >= destination_frame->height) { + return; + } + + width = source_frame->width; + height = source_frame->height; + + if(x + width >= destination_frame->width) { + width = destination_frame->width - x; + } + + if(y + height >= destination_frame->height) { + height = destination_frame->height - y; + } + + source_line = source_frame->buffer; + destination_line = destination_frame->buffer + y * destination_frame->width + x; + + for(i = 0; i < height; ++i) { + for(j = 0; j < width; ++j) { + destination_line[j] = source_line[j]; + } + + destination_line += destination_frame->width; + source_line += source_frame->width; + } +} + + +void draw_frame(Frame* frame, Number x, Number y) +{ + get_module_address_by_function(draw_frame); + Module* module = global_ptr(_module); + + + Number i; + Number j; + Number32* source_line; + + Number width; + Number height; + + if(x >= 640 || y >= 480) { + return; + } + + width = frame->width; + height = frame->height; + + if(x + width >= 640) { + width = 640 - x; + } + + if(y + height >= 480) { + height = 480 - y; + } + + source_line = frame->buffer; + + if(module->VESA->bpp == 24) { + Byte* destination_line; + + destination_line = module->VESA->framebuffer + y * module->VESA->pitch + x * 3; + + for(i = 0; i < height; ++i) { + for(j = 0; j < width; ++j) { + *(Number32*)(destination_line + j * 3) = source_line[j]; + } + + source_line += frame->width; + destination_line += module->VESA->pitch; + } + } + else if(module->VESA->bpp == 32) { + Byte* destination_line; + + destination_line = module->VESA->framebuffer + y * module->VESA->pitch + x * 4; + + for(i = 0; i < height; ++i) { + for(j = 0; j < width; ++j) { + *(Number32*)(destination_line + j * 4) = source_line[j]; + } + + source_line += frame->width; + destination_line += module->VESA->pitch; + } + } +} + + +#include "font.c" + + +void draw_character(Frame* frame, Number x, Number y, Number character, Number32 color) +{ + get_module_address_by_function(draw_character); + + + Number i; + Number j; + Byte* glyph; + Byte glyph_color; + Number r; + Number g; + Number b; + + Number32* line; + Number width; + Number height; + + if(x >= frame->width || y >= frame->height) { + return; + } + + width = 8; + + if(x + width >= frame->width) { + width = frame->width - x; + } + + height = 16; + + if(y + height >= frame->height) { + height = frame->height - y; + } + + b = ((color >> 0) & 0xFF) + 1; + g = ((color >> 8) & 0xFF) + 1; + r = ((color >> 16) & 0xFF) + 1; + + //Byte(*glyphs)[95][128] = global_ptr(glyphs_8_16); + //glyph = (*glyphs)[character - ' ']; + glyph = (*(Byte(*)[95][128])global_ptr(glyphs_8_16))[character - ' ']; + + line = frame->buffer + y * frame->width + x; + + for(i = 0; i < height; ++i) { + for(j = 0; j < width; ++j) { + glyph_color = glyph[i * 8 + j]; + //line[j] = rgb(glyph_color, glyph_color, glyph_color);//rgb(glyph_color * r, glyph_color * g, glyph_color * b); + if(glyph_color) { + line[j] = rgb((glyph_color * r) / 256, (glyph_color * g) / 256, (glyph_color * b) / 256); + } + } + + line += frame->width; + } +} + + +#include "text-display.c" + + +Graphics_Interface _interface; + + +void main(Process* process) +{ + get_module_address_by_function(main); + Module* module = global_ptr(_module); + + + //if(process->get(global_ptr("graphics"))) { + // return; + //} + + + Graphics_Interface* interface = global_ptr(_interface); + + + interface->create_frame = global_ptr(create_frame); + interface->clean_frame = global_ptr(clean_frame); + interface->draw_frame = global_ptr(draw_frame); + interface->draw_frame_in_frame = global_ptr(draw_frame_in_frame); + interface->draw_rectangle = global_ptr(draw_rectangle); + interface->draw_character = global_ptr(draw_character); + interface->print = global_ptr(print); + + process->create(global_ptr("graphics"), interface); + + for(;;) { + module->process->wait(0); + } +} \ No newline at end of file diff --git a/components/libraries/graphics/text-display.c b/components/libraries/graphics/text-display.c new file mode 100644 index 0000000..1961ebc --- /dev/null +++ b/components/libraries/graphics/text-display.c @@ -0,0 +1,98 @@ +#include + + +void scroll_down(Frame* frame) +{ + Number x; + Number y; + Number32* line1; + Number32* line2; + + line1 = frame->buffer + y * frame->width; + line2 = frame->buffer + (y + 16) * frame->width; + + for(y = 0; y < frame->height - 16; ++y) { + for(x = 0; x < frame->width; ++x) { + line1[x] = line2[x]; + } + + line1 += frame->width; + line2 += frame->width; + } + + for(; y < frame->height; ++y) { + for(x = 0; x < frame->width; ++x) { + line1[x] = 0x000000; + } + + line1 += frame->width; + } +} + + +void print_character(Printer* printer, Number character) +{ + switch(character) { + case '\n': { + printer->cursor_pos_x = 0; + ++printer->cursor_pos_y; + break; + } + + case '\r': { + printer->cursor_pos_x = 0; + break; + } + + case '\t': { + print_character(printer, ' '); + print_character(printer, ' '); + print_character(printer, ' '); + print_character(printer, ' '); + break; + } + + default: { + draw_character(printer->frame, printer->cursor_pos_x * 8, printer->cursor_pos_y * 16, character, printer->color); + ++printer->cursor_pos_x; + } + } + + if(printer->cursor_pos_x >= printer->frame->width / 8) { + printer->cursor_pos_x = 0; + ++printer->cursor_pos_y; + } + + if(printer->cursor_pos_y >= printer->frame->height / 16) { + --printer->cursor_pos_y; + + scroll_down(printer->frame); + } +} + +Signed_Number print_characters(Printer* printer, Byte* characters, Number number_of_characters) +{ + Number i; + + for(i = 0; i < number_of_characters; ++i) { + print_character(printer, characters[i]); + } + + return number_of_characters; +} + + +void print(Printer* printer, Byte* parameters, ...) +{ + get_module_address_by_function(print); + + + Writer writer = { + .source = printer, + .write_bytes = global_ptr(print_characters) + }; + + write(&writer, parameters, ¶meters + 1); + + //draw_frame(printer->frame, 0, 0); +} \ No newline at end of file diff --git a/components/libraries/ps2/main.c b/components/libraries/ps2/main.c new file mode 100644 index 0000000..452c800 --- /dev/null +++ b/components/libraries/ps2/main.c @@ -0,0 +1,201 @@ +#include + + +typedef struct { + Process_Interface* process; +} +Module; + +Module _module = {0}; + + +void main(Process* process); + + +void start(Process* process) +{ + get_module_address_by_function(start); + Module* module = global_ptr(_module); + + module->process = process->get(global_ptr("process")); + + main(process); +} + + +typedef enum { + PS2_OUTPUT_BUFFER_FULL = 0b00000001, + PS2_INPUT_BUFFER_FULL = 0b00000010, + PS2_INITIALIZED = 0b00000100, + PS2_A2_STATE = 0b00001000, + PS2_KEYBOARD_CONNECTED = 0b00010000, + PS2_MOUSE_OUTPUT_BUFFER_FULL = 0b00100000, + PS2_TIMEOUT_ERROR = 0b01000000, + PS2_PARITY_ERROR = 0b10000000 +} +PS2_State; + + +typedef enum { + PS2_READ_COMMAND_BYTE = 0x20, + PS2_WRITE_COMMAND_BYTE = 0x60, + PS2_DISABLE_MOUSE_INTERFACE = 0xA7, + PS2_ENABLE_MOUSE_INTERFACE = 0xA8, + PS2_MOUSE_INTERFACE_TEST = 0xA9, + PS2_KEYBOARD_INTERFACE_TEST = 0xAB, + PS2_DISABLE_KEYBOARD_INTERFACE = 0xAD, + PS2_ENABLE_KEYBOARD_INTERFACE = 0xAE, + PS2_WRITE_IN_MOUSE_DEVICE = 0xD4, +} +PS2_Command; + + +typedef enum { + PS2_ENABLE_INPUT_BUFFER_FULL_INTERRUPT = 0b00000001, //IRQ1 + PS2_ENABLE_MOUSE_INPUT_BUFFER_FULL_INTERRUPT = 0b00000010, //IRQ12 + PS2_DISABLE_MOUSE = 0b00100000, +} +PS2_Command_Byte; + + +typedef enum { + PS2_MOUSE_ENABLE_STREAMING = 0xF4, + PS2_MOUSE_DISABLE_STREAMING = 0xF5, + PS2_MOUSE_SET_DEFAULTS = 0xF6, +} +PS2_Mouse_Device_Command; + + +#include + +/* +Byte read_data_from_ps2() +{ + Number tries_count; + + //wait while input buffer not full + tries_count = 0; + while(!(in_8(0x64) & PS2_MOUSE_OUTPUT_BUFFER_FULL)) { + ++tries_count; + + if(tries_count > 1000) { + return 0; + } + } + + return in_8(0x60); +}*/ + + +Byte read_data_from_ps2() +{ + Number tries_count; + + //wait while input buffer not full + tries_count = 0; + while(!(in_8(0x64) & PS2_OUTPUT_BUFFER_FULL)) { + ++tries_count; + + if(tries_count > 1000) { + return 0; + } + } + + return in_8(0x60); +} + + +Boolean write_data_in_ps2(Byte data) +{ + Number tries_count; + + //wait while output buffer not empty + tries_count = 0; + while(in_8(0x64) & PS2_OUTPUT_BUFFER_FULL) { + ++tries_count; + + if(tries_count > 1000) { + return 0; + } + } + + out_8(0x60, data); + + return 1; +} + +/* +Boolean ps2_mouse_acknowledge() +{ + return read_data_from_ps2() == 0xFA; +}*/ + + +Number32 read_key_state() +{ + Byte ps2_key_state; + Number32 key_state; + + if(!(in_8(0x64) & PS2_OUTPUT_BUFFER_FULL)) { + return 0; + } + + ps2_key_state = in_8(0x60); + + if(ps2_key_state == 0xE0) { + ps2_key_state = in_8(0x60); + key_state = (ps2_key_state & 0b1111111) + 128; + } + else { + key_state = ps2_key_state & 0b1111111; + } + + if(ps2_key_state & 0b10000000) { + key_state |= 0x80000000; + } + + return key_state; +} + + +Keyboard_Interface _interface; + + +void main(Process* process) +{ + get_module_address_by_function(main); + Module* module = global_ptr(_module); + + +/* + out_8(0x64, PS2_DISABLE_KEYBOARD_INTERFACE); + out_8(0x64, PS2_DISABLE_MOUSE_INTERFACE); + + + //test for present ps2 + Byte old_config = in_8(0x64); + out_8(0x64, 0xAA); + + if(read_data_from_ps2() != 0x55) { + return; + } + + out_8(0x64, old_config); + + + out_8(0x64, PS2_ENABLE_KEYBOARD_INTERFACE); + out_8(0x64, PS2_ENABLE_MOUSE_INTERFACE); +*/ + + + Keyboard_Interface* interface = global_ptr(_interface); + + interface->read_key_state = global_ptr(read_key_state); + + process->create(global_ptr("keyboard"), interface); + + + for(;;) { + module->process->wait(0); + } +} \ No newline at end of file diff --git a/components/programs/bootscreen/main.c b/components/programs/bootscreen/main.c new file mode 100644 index 0000000..35fd35f --- /dev/null +++ b/components/programs/bootscreen/main.c @@ -0,0 +1,56 @@ +#include + + +void start(Process* process) +{ + get_module_address_by_function(start); + + + Graphics_Interface* graphics = process->get(global_ptr("graphics")); + Process_Interface* process_interface = process->get(global_ptr("process")); + + + Frame* frame; + + Byte p1 = 16 * 8; + Byte p2 = 8 * 8; + Byte p3 = 0 * 8; + + Number t; + + frame = graphics->create_frame(50, 64); + + for(t = 0; ; ++t) { + graphics->clean_frame(frame, 0x000000); + + if((t + 16) % 32 < 16) { + p1 += 8; + } + else { + p1 -= 8; + } + + if((t + 8) % 32 < 16) { + p2 += 8; + } + else { + p2 -= 8; + } + + if((t + 0) % 32 < 16) { + p3 += 8; + } + else { + p3 -= 8; + } + + graphics->draw_rectangle(frame, 0, 32 - (8 + p1 / 8), 10, (8 + p1 / 8) * 2, 0xFFFFFF); + graphics->draw_rectangle(frame, 20, 32 - (8 + p2 / 8), 10, (8 + p2 / 8) * 2, 0xFFFFFF); + graphics->draw_rectangle(frame, 40, 32 - (8 + p3 / 8), 10, (8 + p3 / 8) * 2, 0xFFFFFF); + + graphics->draw_frame(frame, 320 - frame->width / 2, 240 - frame->height / 2); + + + process_interface->wait(32, 0); + } +} \ No newline at end of file diff --git a/components/programs/shell/main.c b/components/programs/shell/main.c new file mode 100644 index 0000000..10dcf39 --- /dev/null +++ b/components/programs/shell/main.c @@ -0,0 +1,288 @@ +#include + + +typedef struct { + struct File_Node* next; + File file; +} +File_Node; + + +typedef struct { + Graphics_Interface* graphics; + File_Interface* file; + Heap_Interface* heap; + Keyboard_Interface* keyboard; + Process_Interface* process; + + File_Node* files_list; + Number number_of_files; + Byte sector[500]; + + Number number_of_processes; +} +Module; + +Module _module = {0}; + + +void main(Process* process); + + +void start(Process* process) +{ + get_module_address_by_function(start); + Module* module = global_ptr(_module); + + + module->graphics = process->get(global_ptr("graphics")); + module->file = process->get(global_ptr("file")); + module->heap = process->get(global_ptr("heap")); + module->keyboard = process->get(global_ptr("keyboard")); + module->process = process->get(global_ptr("process")); + + main(process); +} + + +#include + + +void update_files_list() +{ + get_module_address_by_function(update_files_list); + Module* module = global_ptr(_module); + + + Number32 f_index; + File_Node** f_pointer; + File_Node* f; + + f = module->files_list; + + while(f) { + File_Node* next = f->next; + module->heap->free(f); + f = next; + } + + f_index = 1; + f_pointer = &module->files_list; + module->number_of_files = 0; + + while(f_index) { + *f_pointer = module->heap->allocate(sizeof(File_Node), 0); + (*f_pointer)->next = 0; + + if(!module->file->read(&(*f_pointer)->file, f_index)) { + module->heap->free(*f_pointer); + *f_pointer = 0; + break; + } + + f_index = (*f_pointer)->file.file_node.next; + f_pointer = &(*f_pointer)->next; + ++module->number_of_files; + } +} + + +void redraw(Frame* frame, Number cursor_pos_y) +{ + get_module_address_by_function(redraw); + Module* module = global_ptr(_module); + + + Printer printer = { + .frame = frame, + .cursor_pos_x = 0, + .cursor_pos_y = 0, + .color = 0xFFFFFF//0xAAAAAA//0x22CC22 + }; + + + module->graphics->clean_frame(frame, 0x002244); + module->graphics->draw_rectangle(frame, 0, cursor_pos_y * 16, 640, 16, 0x888888); + + + File_Node* f; + + f = module->files_list; + + while(f) { + module->graphics->print(&printer, global_ptr("%s\n"), f->file.file_node.name); + + f = f->next; + } + + + Process* current_process = module->process->get_list(); + + module->number_of_processes = 0; + module->graphics->print(&printer, global_ptr("\n\n")); + + while(current_process) { + module->graphics->print(&printer, global_ptr("%x%x%x%x[%d] state:%d %s\n"), + (Number)current_process->start >> 24, + (Number)current_process->start >> 16, + (Number)current_process->start >> 8, + current_process->start, + current_process->esp, + current_process->state, + current_process->command + ); + + ++module->number_of_processes; + current_process = current_process->next; + } + + + module->graphics->print(&printer, global_ptr("\n\n%t bytes free\n\n"), module->heap->get_free_size()); + + + module->graphics->draw_frame(frame, 0, 0); +} + + +void main(Process* process) +{ + get_module_address_by_function(main); + Module* module = global_ptr(_module); + + + Frame* frame; + Frame* text_frame; + Number cursor_pos_y; + + cursor_pos_y = 0; + + frame = module->graphics->create_frame(640, 480); + //module->graphics->clean_frame(frame, 0x002244); + + text_frame = module->graphics->create_frame(320, 480); + module->graphics->clean_frame(text_frame, 0x000000); + + + update_files_list(); + redraw(frame, cursor_pos_y); + + + for(;;) { + Number32 key_state; + Byte key_code; + + key_state = module->keyboard->read_key_state(); + key_code = key_state & 0xFF; + + if(!(key_state & 0x80000000)) { + switch(key_code) { + case KEY_ARROW_DOWN: + case KEY_NUMPAD_2: { + if(module->number_of_files && cursor_pos_y < module->number_of_files - 1) { + ++cursor_pos_y; + redraw(frame, cursor_pos_y); + } + else if(cursor_pos_y == module->number_of_files - 1) { + cursor_pos_y = module->number_of_files - 1 + 3; + redraw(frame, cursor_pos_y); + } + else if(cursor_pos_y - 1 - module->number_of_files < module->number_of_processes) { + ++cursor_pos_y; + redraw(frame, cursor_pos_y); + } + break; + } + + case KEY_ARROW_UP: + case KEY_NUMPAD_8: { + if(cursor_pos_y) { + if(cursor_pos_y == module->number_of_files - 1 + 3) { + if(module->number_of_files) { + cursor_pos_y = module->number_of_files - 1; + } + } + else { + --cursor_pos_y; + } + + redraw(frame, cursor_pos_y); + } + break; + } + + case KEY_DELETE: + case KEY_NUMPAD_DOT: { + if(cursor_pos_y < module->number_of_files) { + + } + else { + Number i; + Number process_number = cursor_pos_y - 2 - module->number_of_files; + Process* target_process = module->process->get_list(); + + for(i = 0; i < process_number; ++i) { + target_process = target_process->next; + } + + module->process->stop(target_process, 0); + + redraw(frame, cursor_pos_y); + } + + break; + } + + case KEY_ENTER: { + if(cursor_pos_y < module->number_of_files) { + Number i; + File_Node* target_file = module->files_list; + + for(i = 0; i < cursor_pos_y; ++i) { + target_file = target_file->next; + } + + module->process->execute(target_file->file.file_node.name); + + redraw(frame, cursor_pos_y); + } + + break; + } + + /*case KEY_ENTER: { + Printer printer = { + .frame = text_frame, + .cursor_pos_x = 0, + .cursor_pos_y = 0, + .color = 0xFFFFFF//0xAAAAAA//0x22CC22 + }; + + + Number i; + File_Node* target_file = module->files_list; + + for(i = 0; i < cursor_pos_y; ++i) { + target_file = target_file->next; + } + + File f; + + copy_bytes(&f, &target_file->file, sizeof(File)); + + module->file->read_bytes(&f, module->sector, 500); + module->graphics->clean_frame(text_frame, 0x000000); + + for(i = 0; i < 500 && printer.cursor_pos_y < 30; ++i) { + module->graphics->print(&printer, global_ptr("%c"), module->sector[i]); + } + + module->graphics->draw_frame(text_frame, 320, 0); + + break; + }*/ + } + } + + module->process->wait(32, 33, 0); + } +} \ No newline at end of file diff --git a/kernel_script.ld b/kernel_script.ld new file mode 100644 index 0000000..a69bb86 --- /dev/null +++ b/kernel_script.ld @@ -0,0 +1,12 @@ +SECTIONS +{ + . = 0x8000; + . = ALIGN(4); + .text : { + INCLUDE "bin/components/kernel16.ld"; + * (.text); + } + .data : { + * (.data); + } +} \ No newline at end of file diff --git a/program_script.ld b/program_script.ld new file mode 100644 index 0000000..424c4bf --- /dev/null +++ b/program_script.ld @@ -0,0 +1,11 @@ +SECTIONS +{ + . = 0; + . = ALIGN(4); + .text : { + * (.text); + } + .data : { + * (.data); + } +} \ No newline at end of file diff --git a/utils/create.c.exe b/utils/create.c.exe new file mode 100644 index 0000000..5954fa8 Binary files /dev/null and b/utils/create.c.exe differ diff --git a/utils/load.exe b/utils/load.exe new file mode 100644 index 0000000..11442fb Binary files /dev/null and b/utils/load.exe differ diff --git a/utils/to.exe b/utils/to.exe new file mode 100644 index 0000000..3eb54a2 Binary files /dev/null and b/utils/to.exe differ