From 913e65b8569bb37d93e9ccd5f7a681576a1d0159 Mon Sep 17 00:00:00 2001 From: Tiberiu Chibici Date: Tue, 14 Sep 2021 18:48:57 +0300 Subject: [PATCH] [GOOD] BUILD 0.1.0.450 DATE 8/29/2011 AT 10:30 AM ==================================================== + Changed 'align 0x4' line above multiboot header in loader.asm to 'align 4' + Removed -e option for echo in build.sh + Modified build.sh for linux + Fixed triple fault when enabling paging + Fixed page faults at memory manager initialization + Fixed 'mem' console function + Added more info about page fault at crash screen + Added Panic() macro + Added verbose mode for memory manager [ BAD] BUILD 0.1.0.390 DATE 8/27/2011 AT 10:54 PM ==================================================== + Added stdlib routines, separated in different files + Rewritten physical memory manager + Added virtual mem manager + Added memory allocation/freeing + Added memory library + Added temporary allocation (at end of kernel), until paging is started - Removed functionality from debug console function 'mem' - Removed system.h, the one remaining function now in stdio.h --- #RESOURCES/Text Mode Color Table.png | Bin 17969 -> 0 bytes #RESOURCES/kb.txt | 635 ------------ #RESOURCES/kbgiud11.zip | Bin 21464 -> 0 bytes #RESOURCES/vfd21-080206.zip | Bin 143704 -> 0 bytes .cproject | 60 ++ .directory | 4 + .project | 78 ++ .settings/org.eclipse.cdt.codan.core.prefs | 66 ++ .../org.eclipse.ltk.core.refactoring.prefs | 3 + Build/bootload.bin | Bin 512 -> 0 bytes Build/lib-conio.o | Bin 7944 -> 0 bytes Build/lib-ctype.o | Bin 1080 -> 0 bytes Build/loader.o | Bin 152 -> 1472 bytes Build/main.o | Bin 1488 -> 1208 bytes Build/mmngr-asm.o | Bin 202 -> 0 bytes Build/mmngr-lib-pde.o | Bin 1054 -> 0 bytes Build/mmngr-lib-pte.o | Bin 934 -> 0 bytes Build/mmngr-phys.o | Bin 3848 -> 0 bytes Build/mmngr-virt.o | Bin 3000 -> 0 bytes Build/stage2.cta | Bin 1805 -> 0 bytes FONT.TXT | 955 ------------------ Kernel/debug/commands.c | 255 +++++ Kernel/debug/commands.c~ | 255 +++++ Kernel/debug/console-base.c | 131 +++ Kernel/debug/console-in.c | 162 +++ Kernel/debug/console-out.c | 155 +++ Kernel/debug/console.c | 93 ++ Kernel/drivers/cmos/cmos.c | 63 ++ Kernel/drivers/cmos/cmos.h | 12 + Kernel/drivers/dma/dma.c | 111 ++ Kernel/drivers/dma/dma.h | 80 ++ Kernel/drivers/drivers.c | 34 + Kernel/drivers/drivers.h | 6 + Kernel/drivers/floppy/floppy.c | 384 +++++++ Kernel/drivers/floppy/floppy.h | 86 ++ Kernel/drivers/pit/pit.c | 13 + Kernel/drivers/pit/pit.h | 7 + Kernel/hal/clock/clock.c | 19 + Kernel/hal/clock/clock.h | 9 + .../gdt/gdt.asm => Kernel/hal/cpu/gdt-asm.asm | 13 +- .../drivers/cpu/gdt => Kernel/hal/cpu}/gdt.c | 24 +- .../drivers/cpu/gdt => Kernel/hal/cpu}/gdt.h | 8 +- .../idt/idt.asm => Kernel/hal/cpu/idt-asm.asm | 8 +- .../drivers/cpu/idt => Kernel/hal/cpu}/idt.c | 12 +- .../drivers/cpu/idt => Kernel/hal/cpu}/idt.h | 6 +- .../irq/irq.asm => Kernel/hal/cpu/irq-asm.asm | 70 +- Kernel/hal/cpu/irq.c | 91 ++ Kernel/hal/cpu/irq.h | 10 + .../isrs.asm => Kernel/hal/cpu/isrs-asm.asm | 132 +-- Kernel/hal/cpu/isrs.c | 114 +++ Kernel/hal/cpu/isrs.h | 10 + .../drivers/cpu/irq => Kernel/hal/cpu}/pic.c | 4 +- Kernel/hal/cpu/pic.h | 6 + Kernel/hal/crash.c | 96 ++ Kernel/hal/crash.c~ | 97 ++ Kernel/hal/hal.c | 35 + Kernel/hal/hal.h | 6 + Kernel/hal/keyboard/keyboard.c | 327 ++++++ Kernel/hal/keyboard/keyboard.h | 52 + Kernel/hal/mouse/mouse.c | 116 +++ Kernel/hal/mouse/mouse.h | 36 + Kernel/hal/sysinfo.c | 27 + Kernel/hal/vfs.c | 40 + {SysCore => Kernel}/include/ctype.h | 2 +- Kernel/include/debugio.h | 88 ++ Kernel/include/fileio.h | 70 ++ Kernel/include/memory-add.h | 97 ++ Kernel/include/memory-add.h~ | 96 ++ Kernel/include/memory.h | 29 + Kernel/include/memory.h~ | 29 + Kernel/include/multiboot.h | 119 +++ Kernel/include/settings.h | 38 + Kernel/include/settings.h~ | 37 + {SysCore => Kernel}/include/stdarg.h | 12 +- Kernel/include/stdio.h | 29 + Kernel/include/stdlib.h | 69 ++ Kernel/include/stdlib.h~ | 69 ++ Kernel/include/storage.h | 65 ++ Kernel/include/time.h | 37 + Kernel/include/types.h | 267 +++++ Kernel/include/va_list.h | 17 + Kernel/include/version.h | 1 + Kernel/include/version.h~ | 1 + {SysCore/lib => Kernel/library}/ctype.c | 0 Kernel/library/memory/memory_alloc.c | 84 ++ Kernel/library/memory/memory_alloc.c~ | 87 ++ Kernel/library/memory/memory_free.c | 20 + Kernel/library/memory/memory_info.c | 48 + Kernel/library/memory/memory_info.c~ | 48 + Kernel/library/memory/memory_init.c | 88 ++ Kernel/library/memory/memory_init.c~ | 92 ++ Kernel/library/stdio.c | 44 + Kernel/library/stdlib/convert_ops.c | 100 ++ Kernel/library/stdlib/mem_ops.c | 42 + Kernel/library/stdlib/num_ops.c | 39 + Kernel/library/stdlib/ord_arr.c | 112 ++ Kernel/library/stdlib/str_ops.c | 39 + Kernel/library/storage.c | 18 + Kernel/library/time.c | 98 ++ Kernel/loader.asm | 98 ++ Kernel/loader.asm~ | 99 ++ Kernel/main.c | 27 + Kernel/main.c~ | 27 + Kernel/memory/mem-heap.c | 304 ++++++ Kernel/memory/mem-paging.c | 74 ++ Kernel/memory/mem-paging.c~ | 75 ++ Kernel/memory/mem-phys.c | 108 ++ Kernel/memory/mem-phys.c~ | 109 ++ Makefile | 270 ----- SysBoot/makeall.bat | 16 - SysBoot/stage1/BOOTLOAD.BIN | Bin 512 -> 0 bytes SysBoot/stage1/bootload.asm | 314 ------ SysBoot/stage1/make.bat | 23 - SysBoot/stage2/MAKE.BAT | 24 - SysBoot/stage2/STAGE2.CTA | Bin 1784 -> 0 bytes SysBoot/stage2/a20.inc | 60 -- SysBoot/stage2/bootinfo.inc | 39 - SysBoot/stage2/common.inc | 24 - SysBoot/stage2/fat12.inc | 245 ----- SysBoot/stage2/floppy16.inc | 120 --- SysBoot/stage2/gdt.inc | 68 -- SysBoot/stage2/getdata.inc | 98 -- SysBoot/stage2/memory.inc | 174 ---- SysBoot/stage2/paging.inc | 83 -- SysBoot/stage2/stage2.asm | 264 ----- SysBoot/stage2/stdio.inc | 296 ------ SysCore/compile.bat | 20 - SysCore/debug/BIOS-bochs-latest | Bin 131072 -> 0 bytes SysCore/debug/OSDev.log | 195 ---- SysCore/debug/VGABIOS-lgpl-latest | Bin 40448 -> 0 bytes SysCore/debug/bochs_config.bxrc | 17 - SysCore/debug/ctaos.img | Bin 1474560 -> 0 bytes SysCore/drivers/BSOD.c | 85 -- SysCore/drivers/clock/clock.h | 20 - SysCore/drivers/clock/pit.c | 120 --- SysCore/drivers/compile.bat | 43 - SysCore/drivers/cpu/compile.bat | 18 - SysCore/drivers/cpu/cpu.c | 40 - SysCore/drivers/cpu/cpu.h | 17 - SysCore/drivers/cpu/irq/irq.c | 99 -- SysCore/drivers/cpu/irq/irq.h | 10 - SysCore/drivers/cpu/irq/pic.h | 6 - SysCore/drivers/cpu/isrs/isrs.c | 115 --- SysCore/drivers/cpu/isrs/isrs.h | 8 - SysCore/drivers/drivers.c | 55 - SysCore/drivers/drivers.h | 9 - SysCore/drivers/filesys/fat.c | 34 - SysCore/drivers/filesys/fat.h | 91 -- SysCore/drivers/filesys/vfs.c | 98 -- SysCore/drivers/filesys/vfs.h | 57 -- SysCore/drivers/floppy/dma.c | 137 --- SysCore/drivers/floppy/dma.h | 42 - SysCore/drivers/floppy/floppy.c | 494 --------- SysCore/drivers/floppy/floppy.h | 26 - SysCore/drivers/floppy/storage.h | 14 - SysCore/drivers/keyboard/compile.bat | 16 - SysCore/drivers/keyboard/key_list.txt | 135 --- SysCore/drivers/keyboard/keyboard.c | 306 ------ .../drivers/keyboard/keyboard.deprecated.h | 135 --- .../drivers/keyboard/keyboard.h.deprecated | 135 --- SysCore/drivers/makeall.bat | 158 --- SysCore/filelist.txt | 82 -- SysCore/include/_null.h | 30 - SysCore/include/bootinfo.h | 192 ---- SysCore/include/cctype | 9 - SysCore/include/conio.h | 104 -- SysCore/include/crtdefs.h | 50 - SysCore/include/cstdarg | 7 - SysCore/include/cstdint | 9 - SysCore/include/cstring | 9 - SysCore/include/drivers/floppy.h | 26 - SysCore/include/drivers/keyboard.h | 173 ---- SysCore/include/hal.h | 167 --- SysCore/include/regs.h | 100 -- SysCore/include/size_t.h | 23 - SysCore/include/stdint.h | 163 --- SysCore/include/stdlib.h | 93 -- SysCore/include/string.h | 46 - SysCore/include/sys/declarat.h | 21 - SysCore/include/system.h | 40 - SysCore/include/time.h | 25 - SysCore/include/va_list.h | 52 - SysCore/lib/compile.bat | 51 - SysCore/lib/conio.c | 695 ------------- SysCore/lib/stdlib.c | 286 ------ SysCore/lib/string.c | 23 - SysCore/lib/system.c | 44 - SysCore/lib/time.c | 78 -- SysCore/link.ld | 60 -- SysCore/loader.asm | 25 - SysCore/main.c | 73 -- SysCore/makeall.bat | 76 -- SysCore/makeallh.bat | 76 -- SysCore/memory/compile.bat | 35 - SysCore/memory/lib/pde.c | 36 - SysCore/memory/lib/pde.h | 30 - SysCore/memory/lib/pte.c | 45 - SysCore/memory/lib/pte.h | 29 - SysCore/memory/mmngr.asm | 38 - SysCore/memory/mmngr_ph.c | 352 ------- SysCore/memory/mmngr_ph.h | 47 - SysCore/memory/mmngr_vi.c | 193 ---- SysCore/memory/mmngr_vi.h | 26 - SysCore/objects/CONIO.O | Bin 8431 -> 0 bytes SysCore/objects/CTYPE.O | Bin 672 -> 0 bytes SysCore/objects/LOADER.O | Bin 148 -> 0 bytes SysCore/objects/MAIN.O | Bin 1118 -> 0 bytes SysCore/objects/MMNGR.O | Bin 202 -> 0 bytes SysCore/objects/MMNGR_PH.O | Bin 4349 -> 0 bytes SysCore/objects/SHELL.O | Bin 8752 -> 0 bytes SysCore/objects/STDLIB.O | Bin 2845 -> 0 bytes SysCore/objects/STRING.O | Bin 414 -> 0 bytes SysCore/objects/SYSTEM.O | Bin 649 -> 0 bytes SysCore/objects/TIME.O | Bin 1160 -> 0 bytes SysCore/objects/compile.bat | 16 - SysCore/objects/drivers/BSOD.o | Bin 1556 -> 0 bytes SysCore/objects/drivers/cpu.o | Bin 854 -> 0 bytes SysCore/objects/drivers/dma.o | Bin 1332 -> 0 bytes SysCore/objects/drivers/drivers.o | Bin 1191 -> 0 bytes SysCore/objects/drivers/fat.o | Bin 379 -> 0 bytes SysCore/objects/drivers/fat12.o | Bin 2324 -> 0 bytes SysCore/objects/drivers/floppy.o | Bin 9373 -> 0 bytes SysCore/objects/drivers/gdt.o | Bin 920 -> 0 bytes SysCore/objects/drivers/gdt_asm.o | Bin 145 -> 0 bytes SysCore/objects/drivers/idt.o | Bin 725 -> 0 bytes SysCore/objects/drivers/idt_asm.o | Bin 95 -> 0 bytes SysCore/objects/drivers/irq.o | Bin 2053 -> 0 bytes SysCore/objects/drivers/irq_asm.o | Bin 614 -> 0 bytes SysCore/objects/drivers/isrs.o | Bin 3547 -> 0 bytes SysCore/objects/drivers/isrs_asm.o | Bin 1120 -> 0 bytes SysCore/objects/drivers/keyboard.o | Bin 5046 -> 0 bytes SysCore/objects/drivers/pic.o | Bin 378 -> 0 bytes SysCore/objects/drivers/pit.o | Bin 3386 -> 0 bytes SysCore/objects/mmngr_de.o | Bin 744 -> 0 bytes SysCore/objects/mmngr_te.o | Bin 611 -> 0 bytes SysCore/objects/mmngr_vi.o | Bin 2814 -> 0 bytes SysCore/objects/video/VGA03H.O | Bin 1057 -> 0 bytes SysCore/shell/apps.h | 207 ---- SysCore/shell/compile.bat | 26 - SysCore/shell/shell.c | 62 -- SysCore/video/color/color.c | 165 --- SysCore/video/color/color.h | 66 -- SysCore/video/compile.bat | 24 - SysCore/video/vga.h | 37 - SysCore/video/vga03h.c | 30 - SysCore/video/vga03h.h | 7 - VIDEO.CPP | 476 --------- Video.exe | Bin 46776 -> 0 bytes WPROOT~1.SF | Bin 312 -> 0 bytes _play/fat16.img.gz | Bin 1673 -> 0 bytes _play/stage1.asm | 105 -- _play/stage2/MAKE.BAT | 24 - _play/stage2/STAGE2.CTA | Bin 1213 -> 0 bytes _play/stage2/stage2.asm | 201 ---- _play/stage2/stdio.inc | 386 ------- bochs/.bochsrc | 9 + bochs/.bochsrc~ | 10 + bochs/bochs_run.log | 206 ++++ bochs/bochsrc.bxrc | 9 + build.sh | 79 ++ build.sh~ | 78 ++ build/clock.o | Bin 0 -> 936 bytes build/cmos.o | Bin 0 -> 2616 bytes build/console-base.o | Bin 0 -> 2520 bytes build/console-in.o | Bin 0 -> 2720 bytes build/console-out.o | Bin 0 -> 2572 bytes build/console.o | Bin 0 -> 8964 bytes build/convert_ops.o | Bin 0 -> 1736 bytes build/crash.o | Bin 0 -> 4120 bytes build/ctype.o | Bin 0 -> 1108 bytes build/dma.o | Bin 0 -> 1852 bytes build/drivers.o | Bin 0 -> 1476 bytes build/floppy.o | Bin 0 -> 6496 bytes build/gdt-asm.o | Bin 0 -> 544 bytes build/gdt.o | Bin 0 -> 1364 bytes build/hal.o | Bin 0 -> 2008 bytes build/idt-asm.o | Bin 0 -> 512 bytes build/idt.o | Bin 0 -> 1088 bytes build/irq-asm.o | Bin 0 -> 1024 bytes build/irq.o | Bin 0 -> 2256 bytes build/isrs-asm.o | Bin 0 -> 1872 bytes build/isrs.o | Bin 0 -> 3792 bytes build/keyboard.o | Bin 0 -> 4844 bytes build/mem-heap.o | Bin 0 -> 3168 bytes build/mem-paging.o | Bin 0 -> 2048 bytes build/mem-phys.o | Bin 0 -> 2396 bytes build/mem_ops.o | Bin 0 -> 876 bytes build/memory_alloc.o | Bin 0 -> 2468 bytes build/memory_free.o | Bin 0 -> 1260 bytes build/memory_info.o | Bin 0 -> 1168 bytes build/memory_init.o | Bin 0 -> 2284 bytes build/mouse.o | Bin 0 -> 2564 bytes build/num_ops.o | Bin 0 -> 806 bytes build/ord_arr.o | Bin 0 -> 1796 bytes build/pic.o | Bin 0 -> 724 bytes build/pit.o | Bin 0 -> 828 bytes build/stdio.o | Bin 0 -> 1324 bytes build/storage.o | Bin 0 -> 763 bytes build/str_ops.o | Bin 0 -> 852 bytes build/sysinfo.o | Bin 0 -> 940 bytes build/time.o | Bin 0 -> 2240 bytes buildOS.bat | 41 - change.log | 28 + change.log~ | 24 + filelistAsm.txt | 15 + filelistC.txt | 111 ++ floppy/floppy_mount.sh | 15 + .../fat16.img => floppy/grub_aux.img | Bin 1474560 -> 1474560 bytes floppy/original.img | Bin 0 -> 1474560 bytes kernel.bin | Bin 0 -> 48534 bytes link.ld | 45 + luxos.img | Bin 0 -> 1474560 bytes preview/booting.png | Bin 37633 -> 0 bytes preview/floppy.png | Bin 26829 -> 0 bytes preview/help&input.png | Bin 14085 -> 0 bytes preview/help.png | Bin 10770 -> 0 bytes preview/memory.png | Bin 12706 -> 0 bytes preview/pageFault.png | Bin 14753 -> 0 bytes scripts/build.bat | 6 + scripts/format | 3 - scripts/pack.bat | 6 + scripts/pack.sh | 13 + scripts/run.bat | 6 + scripts/stage1d | 2 - scripts/version.txt | 1 + vidbackup.zip | Bin 24469 -> 0 bytes 326 files changed, 6990 insertions(+), 12229 deletions(-) delete mode 100644 #RESOURCES/Text Mode Color Table.png delete mode 100644 #RESOURCES/kb.txt delete mode 100644 #RESOURCES/kbgiud11.zip delete mode 100644 #RESOURCES/vfd21-080206.zip create mode 100644 .cproject create mode 100644 .directory create mode 100644 .project create mode 100644 .settings/org.eclipse.cdt.codan.core.prefs create mode 100644 .settings/org.eclipse.ltk.core.refactoring.prefs delete mode 100644 Build/bootload.bin delete mode 100644 Build/lib-conio.o delete mode 100644 Build/lib-ctype.o delete mode 100644 Build/mmngr-asm.o delete mode 100644 Build/mmngr-lib-pde.o delete mode 100644 Build/mmngr-lib-pte.o delete mode 100644 Build/mmngr-phys.o delete mode 100644 Build/mmngr-virt.o delete mode 100644 Build/stage2.cta delete mode 100644 FONT.TXT create mode 100644 Kernel/debug/commands.c create mode 100644 Kernel/debug/commands.c~ create mode 100644 Kernel/debug/console-base.c create mode 100644 Kernel/debug/console-in.c create mode 100644 Kernel/debug/console-out.c create mode 100644 Kernel/debug/console.c create mode 100644 Kernel/drivers/cmos/cmos.c create mode 100644 Kernel/drivers/cmos/cmos.h create mode 100644 Kernel/drivers/dma/dma.c create mode 100644 Kernel/drivers/dma/dma.h create mode 100644 Kernel/drivers/drivers.c create mode 100644 Kernel/drivers/drivers.h create mode 100644 Kernel/drivers/floppy/floppy.c create mode 100644 Kernel/drivers/floppy/floppy.h create mode 100644 Kernel/drivers/pit/pit.c create mode 100644 Kernel/drivers/pit/pit.h create mode 100644 Kernel/hal/clock/clock.c create mode 100644 Kernel/hal/clock/clock.h rename SysCore/drivers/cpu/gdt/gdt.asm => Kernel/hal/cpu/gdt-asm.asm (64%) rename {SysCore/drivers/cpu/gdt => Kernel/hal/cpu}/gdt.c (81%) rename {SysCore/drivers/cpu/gdt => Kernel/hal/cpu}/gdt.h (81%) rename SysCore/drivers/cpu/idt/idt.asm => Kernel/hal/cpu/idt-asm.asm (51%) rename {SysCore/drivers/cpu/idt => Kernel/hal/cpu}/idt.c (83%) rename {SysCore/drivers/cpu/idt => Kernel/hal/cpu}/idt.h (76%) rename SysCore/drivers/cpu/irq/irq.asm => Kernel/hal/cpu/irq-asm.asm (76%) create mode 100644 Kernel/hal/cpu/irq.c create mode 100644 Kernel/hal/cpu/irq.h rename SysCore/drivers/cpu/isrs/isrs.asm => Kernel/hal/cpu/isrs-asm.asm (68%) create mode 100644 Kernel/hal/cpu/isrs.c create mode 100644 Kernel/hal/cpu/isrs.h rename {SysCore/drivers/cpu/irq => Kernel/hal/cpu}/pic.c (86%) create mode 100644 Kernel/hal/cpu/pic.h create mode 100644 Kernel/hal/crash.c create mode 100644 Kernel/hal/crash.c~ create mode 100644 Kernel/hal/hal.c create mode 100644 Kernel/hal/hal.h create mode 100644 Kernel/hal/keyboard/keyboard.c create mode 100644 Kernel/hal/keyboard/keyboard.h create mode 100644 Kernel/hal/mouse/mouse.c create mode 100644 Kernel/hal/mouse/mouse.h create mode 100644 Kernel/hal/sysinfo.c create mode 100644 Kernel/hal/vfs.c rename {SysCore => Kernel}/include/ctype.h (98%) create mode 100644 Kernel/include/debugio.h create mode 100644 Kernel/include/fileio.h create mode 100644 Kernel/include/memory-add.h create mode 100644 Kernel/include/memory-add.h~ create mode 100644 Kernel/include/memory.h create mode 100644 Kernel/include/memory.h~ create mode 100644 Kernel/include/multiboot.h create mode 100644 Kernel/include/settings.h create mode 100644 Kernel/include/settings.h~ rename {SysCore => Kernel}/include/stdarg.h (72%) create mode 100644 Kernel/include/stdio.h create mode 100644 Kernel/include/stdlib.h create mode 100644 Kernel/include/stdlib.h~ create mode 100644 Kernel/include/storage.h create mode 100644 Kernel/include/time.h create mode 100644 Kernel/include/types.h create mode 100644 Kernel/include/va_list.h create mode 100644 Kernel/include/version.h create mode 100644 Kernel/include/version.h~ rename {SysCore/lib => Kernel/library}/ctype.c (100%) create mode 100644 Kernel/library/memory/memory_alloc.c create mode 100644 Kernel/library/memory/memory_alloc.c~ create mode 100644 Kernel/library/memory/memory_free.c create mode 100644 Kernel/library/memory/memory_info.c create mode 100644 Kernel/library/memory/memory_info.c~ create mode 100644 Kernel/library/memory/memory_init.c create mode 100644 Kernel/library/memory/memory_init.c~ create mode 100644 Kernel/library/stdio.c create mode 100644 Kernel/library/stdlib/convert_ops.c create mode 100644 Kernel/library/stdlib/mem_ops.c create mode 100644 Kernel/library/stdlib/num_ops.c create mode 100644 Kernel/library/stdlib/ord_arr.c create mode 100644 Kernel/library/stdlib/str_ops.c create mode 100644 Kernel/library/storage.c create mode 100644 Kernel/library/time.c create mode 100644 Kernel/loader.asm create mode 100644 Kernel/loader.asm~ create mode 100644 Kernel/main.c create mode 100644 Kernel/main.c~ create mode 100644 Kernel/memory/mem-heap.c create mode 100644 Kernel/memory/mem-paging.c create mode 100644 Kernel/memory/mem-paging.c~ create mode 100644 Kernel/memory/mem-phys.c create mode 100644 Kernel/memory/mem-phys.c~ delete mode 100644 Makefile delete mode 100644 SysBoot/makeall.bat delete mode 100644 SysBoot/stage1/BOOTLOAD.BIN delete mode 100644 SysBoot/stage1/bootload.asm delete mode 100644 SysBoot/stage1/make.bat delete mode 100644 SysBoot/stage2/MAKE.BAT delete mode 100644 SysBoot/stage2/STAGE2.CTA delete mode 100644 SysBoot/stage2/a20.inc delete mode 100644 SysBoot/stage2/bootinfo.inc delete mode 100644 SysBoot/stage2/common.inc delete mode 100644 SysBoot/stage2/fat12.inc delete mode 100644 SysBoot/stage2/floppy16.inc delete mode 100644 SysBoot/stage2/gdt.inc delete mode 100644 SysBoot/stage2/getdata.inc delete mode 100644 SysBoot/stage2/memory.inc delete mode 100644 SysBoot/stage2/paging.inc delete mode 100644 SysBoot/stage2/stage2.asm delete mode 100644 SysBoot/stage2/stdio.inc delete mode 100644 SysCore/compile.bat delete mode 100644 SysCore/debug/BIOS-bochs-latest delete mode 100644 SysCore/debug/OSDev.log delete mode 100644 SysCore/debug/VGABIOS-lgpl-latest delete mode 100644 SysCore/debug/bochs_config.bxrc delete mode 100644 SysCore/debug/ctaos.img delete mode 100644 SysCore/drivers/BSOD.c delete mode 100644 SysCore/drivers/clock/clock.h delete mode 100644 SysCore/drivers/clock/pit.c delete mode 100644 SysCore/drivers/compile.bat delete mode 100644 SysCore/drivers/cpu/compile.bat delete mode 100644 SysCore/drivers/cpu/cpu.c delete mode 100644 SysCore/drivers/cpu/cpu.h delete mode 100644 SysCore/drivers/cpu/irq/irq.c delete mode 100644 SysCore/drivers/cpu/irq/irq.h delete mode 100644 SysCore/drivers/cpu/irq/pic.h delete mode 100644 SysCore/drivers/cpu/isrs/isrs.c delete mode 100644 SysCore/drivers/cpu/isrs/isrs.h delete mode 100644 SysCore/drivers/drivers.c delete mode 100644 SysCore/drivers/drivers.h delete mode 100644 SysCore/drivers/filesys/fat.c delete mode 100644 SysCore/drivers/filesys/fat.h delete mode 100644 SysCore/drivers/filesys/vfs.c delete mode 100644 SysCore/drivers/filesys/vfs.h delete mode 100644 SysCore/drivers/floppy/dma.c delete mode 100644 SysCore/drivers/floppy/dma.h delete mode 100644 SysCore/drivers/floppy/floppy.c delete mode 100644 SysCore/drivers/floppy/floppy.h delete mode 100644 SysCore/drivers/floppy/storage.h delete mode 100644 SysCore/drivers/keyboard/compile.bat delete mode 100644 SysCore/drivers/keyboard/key_list.txt delete mode 100644 SysCore/drivers/keyboard/keyboard.c delete mode 100644 SysCore/drivers/keyboard/keyboard.deprecated.h delete mode 100644 SysCore/drivers/keyboard/keyboard.h.deprecated delete mode 100644 SysCore/drivers/makeall.bat delete mode 100644 SysCore/filelist.txt delete mode 100644 SysCore/include/_null.h delete mode 100644 SysCore/include/bootinfo.h delete mode 100644 SysCore/include/cctype delete mode 100644 SysCore/include/conio.h delete mode 100644 SysCore/include/crtdefs.h delete mode 100644 SysCore/include/cstdarg delete mode 100644 SysCore/include/cstdint delete mode 100644 SysCore/include/cstring delete mode 100644 SysCore/include/drivers/floppy.h delete mode 100644 SysCore/include/drivers/keyboard.h delete mode 100644 SysCore/include/hal.h delete mode 100644 SysCore/include/regs.h delete mode 100644 SysCore/include/size_t.h delete mode 100644 SysCore/include/stdint.h delete mode 100644 SysCore/include/stdlib.h delete mode 100644 SysCore/include/string.h delete mode 100644 SysCore/include/sys/declarat.h delete mode 100644 SysCore/include/system.h delete mode 100644 SysCore/include/time.h delete mode 100644 SysCore/include/va_list.h delete mode 100644 SysCore/lib/compile.bat delete mode 100644 SysCore/lib/conio.c delete mode 100644 SysCore/lib/stdlib.c delete mode 100644 SysCore/lib/string.c delete mode 100644 SysCore/lib/system.c delete mode 100644 SysCore/lib/time.c delete mode 100644 SysCore/link.ld delete mode 100644 SysCore/loader.asm delete mode 100644 SysCore/main.c delete mode 100644 SysCore/makeall.bat delete mode 100644 SysCore/makeallh.bat delete mode 100644 SysCore/memory/compile.bat delete mode 100644 SysCore/memory/lib/pde.c delete mode 100644 SysCore/memory/lib/pde.h delete mode 100644 SysCore/memory/lib/pte.c delete mode 100644 SysCore/memory/lib/pte.h delete mode 100644 SysCore/memory/mmngr.asm delete mode 100644 SysCore/memory/mmngr_ph.c delete mode 100644 SysCore/memory/mmngr_ph.h delete mode 100644 SysCore/memory/mmngr_vi.c delete mode 100644 SysCore/memory/mmngr_vi.h delete mode 100644 SysCore/objects/CONIO.O delete mode 100644 SysCore/objects/CTYPE.O delete mode 100644 SysCore/objects/LOADER.O delete mode 100644 SysCore/objects/MAIN.O delete mode 100644 SysCore/objects/MMNGR.O delete mode 100644 SysCore/objects/MMNGR_PH.O delete mode 100644 SysCore/objects/SHELL.O delete mode 100644 SysCore/objects/STDLIB.O delete mode 100644 SysCore/objects/STRING.O delete mode 100644 SysCore/objects/SYSTEM.O delete mode 100644 SysCore/objects/TIME.O delete mode 100644 SysCore/objects/compile.bat delete mode 100644 SysCore/objects/drivers/BSOD.o delete mode 100644 SysCore/objects/drivers/cpu.o delete mode 100644 SysCore/objects/drivers/dma.o delete mode 100644 SysCore/objects/drivers/drivers.o delete mode 100644 SysCore/objects/drivers/fat.o delete mode 100644 SysCore/objects/drivers/fat12.o delete mode 100644 SysCore/objects/drivers/floppy.o delete mode 100644 SysCore/objects/drivers/gdt.o delete mode 100644 SysCore/objects/drivers/gdt_asm.o delete mode 100644 SysCore/objects/drivers/idt.o delete mode 100644 SysCore/objects/drivers/idt_asm.o delete mode 100644 SysCore/objects/drivers/irq.o delete mode 100644 SysCore/objects/drivers/irq_asm.o delete mode 100644 SysCore/objects/drivers/isrs.o delete mode 100644 SysCore/objects/drivers/isrs_asm.o delete mode 100644 SysCore/objects/drivers/keyboard.o delete mode 100644 SysCore/objects/drivers/pic.o delete mode 100644 SysCore/objects/drivers/pit.o delete mode 100644 SysCore/objects/mmngr_de.o delete mode 100644 SysCore/objects/mmngr_te.o delete mode 100644 SysCore/objects/mmngr_vi.o delete mode 100644 SysCore/objects/video/VGA03H.O delete mode 100644 SysCore/shell/apps.h delete mode 100644 SysCore/shell/compile.bat delete mode 100644 SysCore/shell/shell.c delete mode 100644 SysCore/video/color/color.c delete mode 100644 SysCore/video/color/color.h delete mode 100644 SysCore/video/compile.bat delete mode 100644 SysCore/video/vga.h delete mode 100644 SysCore/video/vga03h.c delete mode 100644 SysCore/video/vga03h.h delete mode 100644 VIDEO.CPP delete mode 100644 Video.exe delete mode 100644 WPROOT~1.SF delete mode 100644 _play/fat16.img.gz delete mode 100644 _play/stage1.asm delete mode 100644 _play/stage2/MAKE.BAT delete mode 100644 _play/stage2/STAGE2.CTA delete mode 100644 _play/stage2/stage2.asm delete mode 100644 _play/stage2/stdio.inc create mode 100644 bochs/.bochsrc create mode 100644 bochs/.bochsrc~ create mode 100644 bochs/bochs_run.log create mode 100644 bochs/bochsrc.bxrc create mode 100644 build.sh create mode 100644 build.sh~ create mode 100644 build/clock.o create mode 100644 build/cmos.o create mode 100644 build/console-base.o create mode 100644 build/console-in.o create mode 100644 build/console-out.o create mode 100644 build/console.o create mode 100644 build/convert_ops.o create mode 100644 build/crash.o create mode 100644 build/ctype.o create mode 100644 build/dma.o create mode 100644 build/drivers.o create mode 100644 build/floppy.o create mode 100644 build/gdt-asm.o create mode 100644 build/gdt.o create mode 100644 build/hal.o create mode 100644 build/idt-asm.o create mode 100644 build/idt.o create mode 100644 build/irq-asm.o create mode 100644 build/irq.o create mode 100644 build/isrs-asm.o create mode 100644 build/isrs.o create mode 100644 build/keyboard.o create mode 100644 build/mem-heap.o create mode 100644 build/mem-paging.o create mode 100644 build/mem-phys.o create mode 100644 build/mem_ops.o create mode 100644 build/memory_alloc.o create mode 100644 build/memory_free.o create mode 100644 build/memory_info.o create mode 100644 build/memory_init.o create mode 100644 build/mouse.o create mode 100644 build/num_ops.o create mode 100644 build/ord_arr.o create mode 100644 build/pic.o create mode 100644 build/pit.o create mode 100644 build/stdio.o create mode 100644 build/storage.o create mode 100644 build/str_ops.o create mode 100644 build/sysinfo.o create mode 100644 build/time.o delete mode 100644 buildOS.bat create mode 100644 change.log create mode 100644 change.log~ create mode 100644 filelistAsm.txt create mode 100644 filelistC.txt create mode 100644 floppy/floppy_mount.sh rename _play/fat16.img/fat16.img => floppy/grub_aux.img (93%) create mode 100644 floppy/original.img create mode 100644 kernel.bin create mode 100644 link.ld create mode 100644 luxos.img delete mode 100644 preview/booting.png delete mode 100644 preview/floppy.png delete mode 100644 preview/help&input.png delete mode 100644 preview/help.png delete mode 100644 preview/memory.png delete mode 100644 preview/pageFault.png create mode 100644 scripts/build.bat delete mode 100644 scripts/format create mode 100644 scripts/pack.bat create mode 100644 scripts/pack.sh create mode 100644 scripts/run.bat delete mode 100644 scripts/stage1d create mode 100644 scripts/version.txt delete mode 100644 vidbackup.zip diff --git a/#RESOURCES/Text Mode Color Table.png b/#RESOURCES/Text Mode Color Table.png deleted file mode 100644 index 9d9f3bcbe7aeaad73001c725acca9d0a0690a3ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17969 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 diff --git a/#RESOURCES/kb.txt b/#RESOURCES/kb.txt deleted file mode 100644 index 3ed4e31..0000000 --- a/#RESOURCES/kb.txt +++ /dev/null @@ -1,635 +0,0 @@ -================================================================ -IBM PC KEYBOARD INFORMATION FOR SOFTWARE DEVELOPERS -================================================================ -Your host: Chris Giese -http://www.execpc.com/~geezer/os - -Distribute freely. Last revised on Jan 3, 2002 -Sources: - PORTS.A of Ralf Brown's interrupt list collection - repairfaq.org keyboard FAQ(doesn't appear to exsist) - Linux source code -Test hardware: - New Samsung KB3T001SAXAA 104-key keyboard - Old Maxi 2186035-00-21 101-key keyboard - -NO WARRANTY. NO GUARANTEE. I have tried to make this information -accurate. I don't know if I succeeded. Corrections or additional -information would be welcome. - -This is a plain-text document. If you use a word-processor to view -it, use a fixed-pitch font (like Courier) so columnar data and -ASCII art lines up properly. - -Lessons learned: -- Both the 8048 MCU in the keyboard and the 8042 controller - on the motherboard accept command bytes. -- There is a bit (KCC) in the poorly-named "Command Byte" which - seems to enable AT-to-XT scancode conversion (scancode set 2 - to scancode set 1). After booting DOS, my keyboard uses - scancode set 2 with this conversion bit turned on. If I turn - the bit off and switch to scancode set 1, operation remains - the same. -- Scancode set 3 is probably the most elegant, in that it returns - a one-byte make code for _every_ key. Unfortunately, not all - keyboards support it. -- The scancodes of some keys depend on the internal num lock state - of the keyboard. - -================================================================ -KEYBOARD I/O REGISTERS ON THE PC -================================================================ -60h data -64h command (write) -64h Status (read) - -Bits in Status register (names from Linux source) - b7 PERR parity error in data received from keyboard - b6 GTO receive timeout - b5 transmit timeout (or PS/2 mouse?) - b4 keyboard is locked - b3 0=60h was the port last accessed, 1=61h was last (?) - b2 System Flag status: 0=power-up/reset, 1=selftest OK (?) - b1 IBF input buffer full (data from host to keyboard) - b0 OBF output buffer full (data from keyboard to host) - -Bits in Output Port of 8042 chip (Table P0383 in PORTS.A) -The Output Port is written by controller command D1h, -and read by controller command D0h - b7 keyboard data output - b6 keyboard clock output - b5 input buffer NOT full - b4 output buffer NOT empty - b3 (varies) - b2 (varies) - b1 A20 gate - b0 system reset (THIS BIT SHOULD ALWAYS BE SET TO 1) - -Bits in Input Port of 8042 chip -The Input Port is read by controller command C0h - b7 keyboard NOT locked - b6-b0 (varies) - -Bits in "Command Byte" (confusing name; from Table P0404 in PORTS.A) -The "Command Byte" is written by controller command 60h -and read by controller command 20h -(names from Linux source) - b7 (reserved) - b6 KCC convert set 2 scancodes to set 1 ("IBM PC compatibility mode") - b5 DMS disables PS/2 mouse when set - b4 disables keyboard when set - b3 ignore keyboard lock switch when set - b2 SYS System Flag (same as b2 in Status register, it seems) - b1 enables IRQ12 from PS/2 mouse when set - b0 EKI enables IRQ1 on keyboard output buffer full - -Result Byte for interface self-tests (Table P0406 in PORTS.A) -Returned by controller commands A9h or ABh - 0 no error - 1 clock line stuck low - 2 clock line stuck high - 3 data line stuck low - 4 data line stuck high - -================================================================ -CONTROLLER COMMANDS (from Table P0401 of PORTS.A) -================================================================ -Before writing each byte of these commands to port 64h, -poll the status register (port 60h) until bit b1=0. - -20h-2Fh reads byte with address=lower 5 bits of command - The byte at address 0 is the "Command Byte". -60h-7Fh nn writes byte nn to address=lower 5 bits of command - The byte at address 0 is the "Command Byte". -A7h disables PS/2 mouse port (MCA only?) -A8h enables PS/2 mouse port (MCA only?) -A9h self-test mouse interface, returns Result Byte (see above) -AAh self-test controller; returns 55h if success, FCh if failure -ABh self-test keyboard interface, returns Result Byte (see above) -ADh disables keyboard (sets b4 of "Command Byte") -AEh enables keyboard (clears b4 of "Command Byte") -C0h reads Input Port -D0h reads Output Port -D1h nn writes Output Port - Important: bit 0 (system reset) should always be set here, - as the system may hang constantly. To reset the PC, pulse - b0 of the Output Port with command FEh instead. -DDh disable A20 (Not all systems support this byte) -DFh enable A20 (Not all systems support this byte) -E0h read test inputs. return value= - b1 kbd data - b0 kbd clock -EDh nn write LEDs. nn= - b2 Caps Lock - b1 Num Lock - b0 Scroll Lock -F0h-FFh pulse bit(s) of Output Port low for 6 microseconds. - If b0-b3 of the command is low, the corresponding bit - in the Output Port will be pulsed low. b0=system reset, - and should ALWAYS be PULSED low, never set low constantly. - -================================================================ -KEYBOARD COMMANDS (from Table P0386 of PORTS.A) -================================================================ -Before writing each byte of these commands to port 60h, -poll the status register (port 60h) until bit b1=0. -Unless otherwise noted: each command responds with FAh (ACKnowledge) -or FEh (Resend) after receiving each byte of the command. - -EDh nn write LEDs, as above -EEh echo, keyboard responds with EEh -EFh no-operation (reserved) -F0h nn selects scancode set nn=1-3 or 0 to return current set -F2h read ID. Keyboard responds with ACK (FAh) and two optional - ID bytes: - (none) AT keyboard - 83h ABh (?) - ABh 41h MF2, translation mode - ABh 83h MF2, pass-through mode -F3h nn set typematic (auto-repeat) rate/delay. nn= - b7 unused - b6..5 Repeat delay (00=250 msec ... 11=1000msec) - b4..0 Repeat rate (00000=30 Hz ... 11111=2 Hz). -F4h clears output buffer, enables keyboard -F5h disables keyboard, resets to defaults -F6h sets keyboard defaults - -F7h make all keys typematic (auto-repeat) [*] -F8h make all keys make-break [*] -F9h make all keys make-only [*] -FAh make all keys typematic and make-break [*] -FBh nn make one key typematic [*] -FCh nn make one key make-break [*] -FDh nn make one key make-only [*] - [*] these commands may work only for - scancode set 3; I'm not sure. -FEh resend previous scan code -FFh reset keyboard CPU, do power-on self-test, return - self-test result byte - -non-key status bytes --------------------- -00h Key detection error or buffer full. -AAh Power-on/reset diagnostics successful. -E0h (scancode sets 1 and 2) Prefix byte for "gray" keys - (keys not on original 83-/84-key keyboard) -EEh Sent in response to ECHO command. -F0h (scancode sets 2 and 3) Prefix byte for break codes. -FAh ACKknowledge; response to most commands. -FCh Diagnostics failed (MF keyboard). -FDh Diagnostics failed (AT keyboard). - The keyboard stops scanning and waits for next command - after returning code FCh or FDh -FEh Last command was invalid or had parity error; resend it. -FFh Key detection error or buffer full. - -==================================================================== -SCANCODES FOR SCANCODE SET 1 (XT) -==================================================================== -US 104-key keyboard, set 1 scancodes - - -"Make" code is generated when key is pressed. -"Break" code is generated when key is released. -Hex value of make code for each key is shown. - -Most keys: - one-byte make code = nn - one-byte repeat code = nn - one-byte break code = 80h + nn - -"Gray" keys (not on original 84-key keyboard): - two-byte make code = E0nn - two-byte repeat code = E0nn - two-byte break code = E0 followed by 80h + nn - -"Gray" keys noted by [1] are NumLock-sensitive. -When the keyboard's internal NumLock is active: - four-byte make code = E02AE0nn - two-byte repeat code = E0nn - four-byte break code = E0 followed by 80h + nn followed by E0AA - - ____ ___________________ ___________________ ___________________ -| | | | | | | | | | | | | | | | | -|Esc | |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10 |F11 |F12 | -| | | | | | | | | | | | | | | | | -| 01| | 3B| 3C| 3D| 3E| | 3F| 40| 41| 42| | 43| 44| 57| 58| -|____| |____|____|____|____| |____|____|____|____| |____|____|____|____| - - __________________________________________________________________________ -| | | | | | | | | | | | | | | | -|~ |! |@ |# |$ |% |^ |& |* |( |) |_ |+ || |bksp| -|` |1 |2 |3 |4 |5 |6 |7 |8 |9 |0 |- |= |\ | | -| 29| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 2B| 0E| -|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____| -| | | | | | | | | | | | | | | -|Tab |Q |W |E |R |T |Y |U |I |O |P |{ |} | | -| | | | | | | | | | | |[ |] | | -| 0F| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| | -|____|____|____|____|____|____|____|____|____|____|____|____|____| | -| | | | | | | | | | | | | | -|Caps|A |S |D |F |G |H |J |K |L |: |" | Enter | -| | | | | | | | | | |; |' | | -| 3A| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| 28| 1C| -|____|____|____|____|____|____|____|____|____|____|____|____|______________| -| | | | | | | | | | | | | -| L Shift |Z |X |C |V |B |N |M |< |> |? | R Shift | -| | | | | | | | |, |. |/ | | -| 2A| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 35| 36| -|_________|____|____|____|____|____|____|____|____|____|____|______________| -| | | | | | | | | -|L Ctrl | L win | L Alt | space | R Alt | R win | menu |R Ctrl | -| |[1] | | | |[1] |[1] | | -| 1D| E05B| 38| 39| E038| E05C| E05D| E01D| -|_______|_______|_______|__________________|_______|_______|_______|_______| - - -[2] For PrintScreen/SysRq key: make code = E02AE037, -repeat code = E037, break code = E0B7E0AA - -[3] The Pause/Break key does not repeat, and it does not -generate a break code. Its make code is E11D45E19DC5 - - ____ ____ ____ -| | | | -|Prt |Scrl|Paus| -|Scrn|Lock|Brk | -| [2]| 46| [3]| -|____|____|____| - - ____ ____ ____ ____ ____ ____ ____ -| | | | | | | | | -|Ins |Home|PgUp| |Num |/ |* |- | -|[1] |[1] |[1] | |Lock| | | | -|E052|E047|E049| | 45|E035| 37| 4A| -|____|____|____| |____|____|____|____| -| | | | | | | | | -|Del |End |PgDn| |7 |8 |9 | | -|[1] |[1] |[1] | |Home|(U) |PgUp| | -|E053|E04F|E051| | 47| 48| 49| | -|____|____|____| |____|____|____| | - | | | |+ | - |4 |5 |6 | | - |(L) | |(R) | | - | 4B| 4C| 4D| 4E| - ____ |____|____|____|____| - | | | | | | | - |(U) | |1 |2 |3 | | - |[1] | |End |(D) |PgDn| | - |E048| | 4F| 50| 51|Ent | - ____|____|____ |____|____|____| | -| | | | | | | | -|(L) |(D) |(R) | |0 |. | | -|[1] |[1] |[1] | |Ins |Del | | -|E04B|E050|E04D| | 52| 53|E01C| -|____|____|____| |_________|____|____| - - -code key code key code key code key ----- --- ---- --- ---- --- ---- --- -01 Esc 0F Tab 1D L Ctrl 2B \| -02 1! 10 Q 1E A 2C Z -03 2" 11 W 1F S 2D X -04 3# 12 E 20 D 2E C -05 4$ 13 R 21 F 2F V -06 5% 14 T 22 G 30 B -07 6^ 15 Y 23 H 31 N -08 7& 16 U 24 J 32 M -09 8* 17 I 25 K 33 ,< -0A 9( 18 O 26 L 34 .> -0B 0) 19 P 27 ;: 35 /? -0C -_ 1A [{ 28 '" 36 R Shift -0D =+ 1B ]} 29 `~ 37 * -0E BackSpace 1C Enter 2A L Shift 38 L Alt - -code key code key code key code key ----- --- ---- --- ---- --- ---- --- -39 Space 41 F7 49 PageUp 9 51 PageDown 3 -3A CapsLock 42 F8 4A - 52 Insert 0 -3B F1 43 F9 4B (left) 4 53 Del . -3C F2 44 F10 4C 5 -3D F3 45 NumLock 4D (right) 6 57 F11 -3E F4 46 ScrollLock 4E + 58 F12 -3F F5 47 Home 7 4F End 1 -40 F6 48 (up) 8 50 (down) 2 - - - -code key ----- --- -E01C Enter (on numeric keypad) -E01D R Ctrl -E02A make code prefix for keyboard internal numlock -E02AE037 PrintScreen make code -E035 / -E037 PrintScreen repeat code -E038 R Alt -E047 Home -E048 (up) -E049 PageUp -E04B (left) -E04D (right) -E04F End -E050 (down) -E051 PageDown -E052 Insert -E053 Del -E05B L Win -E05C R Win -E05D Menu -E0AA break code suffix for keyboard internal numlock -E0B7E0AA PrintScreen break code -E11D45E19DC5 Pause - -==================================================================== -SCANCODES FOR SCANCODE SET 2 (AT) -==================================================================== -US 104-key keyboard, set 2 scancodes, -8042 AT-to-XT scancode translation OFF - -"Make" code is generated when key is pressed. -"Break" code is generated when key is released. -Hex value of make code for each key is shown. - -Most keys: - one-byte make code = nn - one-byte repeat code = nn - two-byte break code = F0nn - -"Gray" keys (not on original 84-key keyboard): - two-byte make code = E0nn - two-byte repeat code = E0nn - three-byte break code = E0F0nn - -"Gray" keys noted by [1] are NumLock-sensitive. -When the keyboard's internal NumLock is active: - four-byte make code = E012E0nn - two-byte repeat code = E0nn - six-byte break code = E0F0nnE0F012 - - ____ ___________________ ___________________ ___________________ -| | | | | | | | | | | | | | | | | -|Esc | |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10 |F11 |F12 | -| | | | | | | | | | | | | | | | | -| 76| | 05| 06| 04| 0C| | 03| 0B| 83| 0A| | 01| 09| 78| 07| -|____| |____|____|____|____| |____|____|____|____| |____|____|____|____| - - __________________________________________________________________________ -| | | | | | | | | | | | | | | | -|~ |! |@ |# |$ |% |^ |& |* |( |) |_ |+ || |bksp| -|` |1 |2 |3 |4 |5 |6 |7 |8 |9 |0 |- |= |\ | | -| 0E| 16| 1E| 26| 25| 2E| 36| 3D| 3E| 46| 45| 4E| 55| 5D| 66| -|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____| -| | | | | | | | | | | | | | | -|Tab |Q |W |E |R |T |Y |U |I |O |P |{ |} | | -| | | | | | | | | | | |[ |] | | -| 0D| 15| 1D| 24| 2D| 2C| 35| 3C| 43| 44| 4D| 54| 5B| | -|____|____|____|____|____|____|____|____|____|____|____|____|____| | -| | | | | | | | | | | | | | -|Caps|A |S |D |F |G |H |J |K |L |: |" | Enter | -| | | | | | | | | | |; |' | | -| 58| 1C| 1B| 23| 2B| 34| 33| 3B| 42| 4B| 4C| 52| 5A| -|____|____|____|____|____|____|____|____|____|____|____|____|______________| -| | | | | | | | | | | | | -| L Shift |Z |X |C |V |B |N |M |< |> |? | R Shift | -| | | | | | | | |, |. |/ | | -| 12| 1A| 22| 21| 2A| 32| 31| 3A| 41| 49| 4A| 59| -|_________|____|____|____|____|____|____|____|____|____|____|______________| -| | | | | | | | | -|L Ctrl | L win | L Alt | space | R Alt | R win | menu |R Ctrl | -| |[1] | | | |[1] |[1] | | -| 14| E01F| 11| 29| E011| E027| E02F| E014| -|_______|_______|_______|__________________|_______|_______|_______|_______| - - -[2] For PrintScreen/SysRq key: make code = E012E07C, -repeat code = E07C, break code = E0F07CE0F012 - -[3] The Pause/Break key does not repeat, and it does not -generate a break code. Its make code is E11477E1F014F077 - - ____ ____ ____ -| | | | -|Prt |Scrl|Paus| -|Scrn|Lock|Brk | -| [2]| 7E| [3]| -|____|____|____| - - ____ ____ ____ ____ ____ ____ ____ -| | | | | | | | | -|Ins |Home|PgUp| |Num |/ |* |- | -|[1] |[1] |[1] | |Lock| | | | -|E070|E06C|E07D| | 77|E04A| 7C| 7B| -|____|____|____| |____|____|____|____| -| | | | | | | | | -|Del |End |PgDn| |7 |8 |9 | | -|[1] |[1] |[1] | |Home|(U) |PgUp| | -|E071|E069|E07A| | 6C| 75| 7D| | -|____|____|____| |____|____|____| | - | | | |+ | - |4 |5 |6 | | - |(L) | |(R) | | - | 6B| 73| 74| 79| - ____ |____|____|____|____| - | | | | | | | - |(U) | |1 |2 |3 | | - |[1] | |End |(D) |PgDn| | - |E075| | 69| 72| 7A|Ent | - ____|____|____ |____|____|____| | -| | | | | | | | -|(L) |(D) |(R) | |0 |. | | -|[1] |[1] |[1] | |Ins |Del | | -|E06B|E072|E074| | 70| 71|E05A| -|____|____|____| |_________|____|____| - - -code key code key code key code key ----- --- ---- --- ---- --- ---- --- -01 F9 66 BackSpace - 21 C 41 ,< -03 F5 22 X 42 K 69 End 1 -04 F3 23 D 43 I -05 F1 24 E 44 O 6B (left) 4 -06 F2 25 4$ 45 0) 6C Home 7 -07 F12 26 3# 46 9( - 70 Ins 0 -09 F10 29 Space 49 .> 71 Del . -0A F8 2A V 4A /? 72 (down) 2 -0B F6 2B F 4B L 73 5 -0C F4 2C T 4C ;: 74 (right) 6 -0D Tab 2D R 4D P 75 (up) 8 -0E `~ 2E 5% 4E -_ 76 Esc - 77 NumLock -11 L Alt 31 N 52 '" 78 F11 -12 L Shift 32 B 79 + - 33 H 54 [{ 7A PageDown 3 -14 L Ctrl 34 G 55 =+ 7B - -15 Q 35 Y 7C * -16 1! 36 6^ 58 CapsLock 7D PageUp 9 - 59 R Shift 7E ScrollLock -1A Z 3A M 5A Enter -1B S 3B J 5B ]} 83 F7 -1C A 3C U -1D W 3D 7& 5D \| -1E 2@ 3E 8* - -code key ----- --- -E011 R Alt -E012E07C PrintScreen make code -E014 R Ctrl -E01F L Win -E027 R Win -E02F Menu -E04A / -E05A Enter (on numeric keypad) -E069 End -E06B Left -E06C Home -E070 Ins -E071 Del -E072 (down) -E074 (right) -E075 (up) -E07A PageDown -E07C PrintScreen repeat code -E07D PageUp -E0F07CE0F012 PrintScreen break code -E11477E1F014F077 Pause - -==================================================================== -SCANCODES FOR SCANCODE SET 3 -==================================================================== -US 104-key keyboard, set 3 scancodes - - -"Make" code is generated when key is pressed. -"Break" code is generated when key is released. -Hex value of make code for each key is shown. - -All keys: - one-byte make code = nn - one-byte repeat code = nn - two-byte break code = F0nn - -When operating in scancode set 3, the keyboard -does not maintain an internal NumLock state. - - - - - - - - - - ____ ___________________ ___________________ ___________________ -| | | | | | | | | | | | | | | | | -|Esc | |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10 |F11 |F12 | -| | | | | | | | | | | | | | | | | -| 08| | 07| 0F| 17| 1F| | 27| 2F| 37| 3F| | 47| 4F| 56| 5E| -|____| |____|____|____|____| |____|____|____|____| |____|____|____|____| - - __________________________________________________________________________ -| | | | | | | | | | | | | | | | -|~ |! |@ |# |$ |% |^ |& |* |( |) |_ |+ || |bksp| -|` |1 |2 |3 |4 |5 |6 |7 |8 |9 |0 |- |= |\ | | -| 0E| 16| 1E| 26| 25| 2E| 36| 3D| 3E| 46| 45| 4E| 55| 5C| 66| -|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____| -| | | | | | | | | | | | | | | -|Tab |Q |W |E |R |T |Y |U |I |O |P |{ |} | | -| | | | | | | | | | | |[ |] | | -| 0D| 15| 1D| 24| 2D| 2C| 35| 3C| 43| 44| 4D| 54| 5B| | -|____|____|____|____|____|____|____|____|____|____|____|____|____| | -| | | | | | | | | | | | | | -|Caps|A |S |D |F |G |H |J |K |L |: |" | Enter | -| | | | | | | | | | |; |' | | -| 14| 1C| 1B| 23| 2B| 34| 33| 3B| 42| 4B| 4C| 52| 5A| -|____|____|____|____|____|____|____|____|____|____|____|____|______________| -| | | | | | | | | | | | | -| L Shift |Z |X |C |V |B |N |M |< |> |? | R Shift | -| | | | | | | | |, |. |/ | | -| 12| 1A| 22| 21| 2A| 32| 31| 3A| 41| 49| 4A| 59| -|_________|____|____|____|____|____|____|____|____|____|____|______________| -| | | | | | | | | -|L Ctrl | L win | L Alt | space | R Alt | R win | menu |R Ctrl | -| | | | | | | | | -| 11| 8B| 19| 29| 39| 8C| 8D| 58| -|_______|_______|_______|__________________|_______|_______|_______|_______| - - - - - - - - - ____ ____ ____ -| | | | -|Prt |Scrl|Paus| -|Scrn|Lock|Brk | -| 57| 5F| 62| -|____|____|____| - - ____ ____ ____ ____ ____ ____ ____ -| | | | | | | | | -|Ins |Home|PgUp| |Num |/ |* |- | -| | | | |Lock| | | | -| 67| 6E| 6F| | 76| 77| 7E| 84| -|____|____|____| |____|____|____|____| -| | | | | | | | | -|Del |End |PgDn| |7 |8 |9 | | -| | | | |Home|(U) |PgUp| | -| 64| 65| 6D| | 6C| 75| 7D| | -|____|____|____| |____|____|____| | - | | | |+ | - |4 |5 |6 | | - |(L) | |(R) | | - | 6B| 73| 74| 7C| - ____ |____|____|____|____| - | | | | | | | - |(U) | |1 |2 |3 | | - | | |End |(D) |PgDn| | - | 63| | 69| 72| 7A|Ent | - ____|____|____ |____|____|____| | -| | | | | | | | -|(L) |(D) |(R) | |0 |. | | -| | | | |Ins |Del | | -| 61| 60| 6A| | 70| 71| 79| -|____|____|____| |_________|____|____| - - -code key code key code key code key ----- --- ---- --- ---- --- ---- --- -07 F1 2A V 4A /? 6B (left) 4 -08 Esc 2B F 4B L 6C Home 7 - 2C T 4C ;: 6D PageDown -0D Tab 2D R 4D P 6E Home -0E `~ 2E 5% 4E -_ 6F PageUp -0F F2 2F F6 4F F10 70 Ins 0 - 71 Del . -11 L Ctrl 31 N 52 '" 72 (down) 2 -12 L Shift 32 B 73 5 - 33 H 54 [{ 74 (right) 6 -14 CapsLock 34 G 55 =+ 75 (up) 8 -15 Q 35 Y 56 F11 76 NumLock -16 1! 36 6^ 57 PrintScr 77 / -17 F3 37 F7 58 R Ctrl - 59 R Shift 79 Enter (on numeric keypad) -19 L Alt 39 R Alt 5A Enter 7A PageDown 3 -1A Z 3A M 5B ]} -1B S 3B J 5C \| 7C + -1C A 3C U 7D PageUp 9 -1D W 3D 7& 5E F12 7E * -1E 2@ 3E 8* 5F ScrollLock -1F F4 3F F8 60 (down) 84 - - 61 (left) -21 C 41 ,< 62 Pause 8B L Win -22 X 42 K 63 (up) 8C R Win -23 D 43 I 64 Del 8D Menu -24 E 44 O 65 End -25 4$ 45 0) 66 BackSpace -26 3# 46 9( 67 Ins -27 F5 47 F9 - 69 End 1 -29 Space 49 .> 6A (right) diff --git a/#RESOURCES/kbgiud11.zip b/#RESOURCES/kbgiud11.zip deleted file mode 100644 index 92e9ddbe16ffe0f776c9aeb33fbeeae341d302f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21464 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 diff --git a/#RESOURCES/vfd21-080206.zip b/#RESOURCES/vfd21-080206.zip deleted file mode 100644 index 263adf837addd8354737475d5d458c34c457faa9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143704 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 z z_A*Vob5Z2h$}Lo`{fO`Oo7o+5XuEqB^cMRl-^M=ET$lw^Q%e--vpmR!m#YfAyD5ci)1x| ztY@m?0y1~DLe`5E8}p{090_6hevb7_^GSC%7&&gzQ}`Q^4hxg7;m_%$nL{)TR2 zH>)Et+_8R)_&Xq;iK#6B9l(YIn{*U}Ws(A+|IVAr3zjDpH%GKWMi_{d4MO}FEE+dV zm>Eu5(BV2EX&4}vETzfVIpW7~0qs_RD`FlW#`S>6L=EondB@|Cj>ktjQiloodST|U zh-RVE~OV&0mTxDNofEXM{lPd0{1|bj2z7nyAGy%G1!i ze>BAf3W+p)mpp*qra;cON`u>55KFMYWMstzs}N}u*3&|KG?Z+Z5Xj#MLu-?YB`E_j z)0G!K!E=oW;$A{yW-=u;T%epweOwR7^|n6u9-J7w1RuKX zJ%t|+pP$43z#w$Z?gR){Oo4^woNS6`)a;ar0|biVOi`C%mMo6G2kId{)UL+ysuJ7) z_!%w;Gea%OqCpNslaW;#VwB~F`X6DC72?sPPdriaV*RROBT=IWfU9)H?Z%%e1L_Egs9Cg)%}_TY?5(HP;JPLcBK|2Iq=@v%q>!~a0=A)WJf z2g^nAtBNBny-MTLj*HUJXT}1jhWQ_GF7iayKw5XIvE&e&D5U614nfzBW+#G=@R&i! zjTKTtBifu}VoZOmr6Z0Dd!d~~%2K#n4%~cDx~V0D%ETsvUCV_WK9+~3?_Xj z4Dcmuo~f}BH#FBG4ict<%q2AzutU~Vpaaz7W91U~dP=~^`{GE+3>}_Y)NMD6#&aHF zGSxuBU`GkbVG90(AOlmfF}Dxo87;_+3r!}CETy|i@v&$K2@O7D3rDO>KjnN(vQe`= z$r>Kit<@s#8AJ%I+?5iB7|W?VSnEn^K}hlzdwmD?Zv_7}_TindANGF{ zd*A<#efQ4Ths$U)9<I5arQvcRA$LMkZ?~8UN};(#=9YaqY!*-e}RwD3m@PfMdv6$$aP+? z*&B7Jj1BMZItM&0RI^v(>d2#`_Xd!nlOgjXZ97JJeF=vqv8Q-p1oD){M_0UGi-}-d zWkZD@`E!1U#fbVUO{lEip|78*MYJ`!gAwh`+PkBzAt?WXVu$LW=$J_p0VIjPp;?y; zW9gbrl-?z(t299hRQ|HM{tv(bJ>zE$gQ<5_{9J$1_$&yHWyWH3MSe-@}gZ{6z;#Vu2;) zg&QNTp>?|zeX3DW)p?q1m7j*1&lnUTs*}k(){J%q8t73{- zx~D`^h1qgP)DvoCn`SP|U5G8n8y{Q1e{M*r*}5Huv~8ovnZjz9sNpYbNR^)R%W}+0 zT?26A90Ya_NV(ZNd*BjWb?$(u8bR_(EXPgFo&xe{YIe@QojguPoHJKCRF3#r&gUEO zxQH`;t|hsOLUw2G;f!Bnfj%=2WxYM2kmZK05z0BgzlP%13Caxx%0}K5=o0-RZsJLNtX|Dk;qj%= zqBM^$)*Lh)mwNzO!z26?SCAy(airwqYv4I;y5sR|?h27CQWpy|mumLL%*@t3aRspC zO?`F6mw`pxwNXNJrClOhOd-uuCA!G1TcKpjX$%|fC7+jKGkn#zy;-irZ-=iu7GeGn zhxl>mm%0+OOSQE3fO(c=XtGrlkyzrFTAa`lQtWEc(kVlOBErwTR}tZd`N{|3WJb+P zzBvyU0Y_4!QI-shOw3rJy?TqDTvw5(CARk*k&gAW#W6G5v0{Qaiy=Vf%F{R@Ql7xU zYz}ADn6}Fdt{&|m-qD{7&@T>{e#A>u16RR{m2v19dMs9}AGz5$A z0_{cL#5-BbDe!HlcP!wq*$XIurz~I?2*i2qF)Vkj#QVH6nb)NfEq`5!r1C!hKdwB> zf2_Pr=RZ8-*UOs!OZ8{@-|7#l1Z%Ec>M&xpe4!?t8d1jDnK_kIP)K_PP4`sLb@l&2 z1x-~dXsS{{#9lmh-kBpK_5#%+V`ffW>uDYo;xQ5zzcoFTb7v^eJfSA+Co%#`I2A;l z2@!jR)JPMNch>6hV~i$s7=A?@bZg-&;-Drql28a4C(IhKj-uE07WTSvHGUWZip4NU z6Md%)6@jvl5vO$UmKy8!mFov9u&f($ol>%mMY> zS#`zV%9h)Pm8Hg(b|YyeD4!B(A_mSRhVu?lUh@1?s{bxb0udu-5qxK7;;Zsh3SXa5N;_N`|Ed34UQ>J+ zYg6*59pw?t$(o$*$(Lo*nPlnBv+g#F3>U*3$!Oo$=-5Cna*TE)>oZ}DaKuMv>{QE} z_0dEL6*282TOS-FuY}{B3IIRp-HW?t6rIP7T$uXJoKSMvF?%FOqs|LX;%Kg~Km=7?$ym2c*IQmV zLr}-+rZ>f5Eb8+(rO(Tw^u6;b{d3^-1(g0ZaG4t^eOMu-KMZa~5v4x>t_7Ut2}*ws z+-#oG9|5QjT#sic{deH1z=b_a>9ZjH zQ+aUUw_ZZlA+Sz4sEVPy0QAG@-p89VINP6_J+hTPk!5YQr zJmf$42O>8y0{uk&*Gl+#^&R0_4DU_mWXR5%PeR7gh$rrjYW4yXjHI~m2$zQ3_F;0Z zT^!*8>;QSU6~0p1zY+=4uU|yHF(EI^C)t1h;Ngc(`ukuewz$!)e{d-*s1OgoWXZTeV4d*ad^*y6(DFf9h6E z;wx$0^)~(oqt0EWJ5{GEsMBpcEzrDf`+nW3nuz+&ttd>bw4$%;yQ!5{gf(1;Lvo#t zH2`qks%l+#jYr6~F zlU~iFLiYq&mfs8Xxc*-n36i0H6jUJaW&W0m+ezBWXLE$TcWEgkGO{;;w1+b?K8Q_$ z%Y(>Xffnlbw|U}xbeA}|kF41z(4}(A>D+bz`F|mQ-Y2&mBeosW!L{=u4wCx4?w$=_ zGuppmm3A|%quoIG2ommTGY8l9X^*eRIN-y0e1yGTga`+`zX}5szeW+pJ#w3o)#8+s z`Z|zUIrxfd55uGXBflEc{*A-=JhI=E7%IeuIrMHy;fS1C_yq%neS#&-Rj-M-<~pZ| zIO$lgb~k&*4~tnCZr}`n3?79yXs!$MXx<&Df_F#cH>Ah?I@1GNWYd|o0TE~Tia^Ia+8q#az4;7Z8R%F;qyCxc?AoA+vqcp+emLgo-9Ztzn$H$h zkF4jOYE8^~NkdZ($p?B+ZX*3B!=3~NcDB{#a&7p{c>xY8)r(1iqAl32J z5<#Zp4Nc#y0tSkMm`txMVJ^KgOEZ_Al_kugXJ={lW;y24tFj!k=rw#f&A0T=IW4?K zr~nmmYHcJSY=+@?ux`g(Gg5o*N~kZq*EY*R&mf*a{kbchbLXy%HC5!)3RS#FeT^aq zYf5C%TF02!NMgw#vJjp)>2k;HEWb~sAB7jTqI9s6id4SH!Wtg*?*TROrd)et(6fj9 z9tqy0Zc+Xq227N(0fmdG%TcFzN#(RiWa=+BC0sCy`N3N^9vpg;}>{!=!K z82b*-5`1xbIAUMvtnhBS9o442`C4+;4^RDccaJIp!4CQG38c$`I! zKq4;?#bHhH4^qM;w6ZK@5lbv7ycx zl2WLWA6VamV#yEOO;m7mCQ5^U)Km-gZgtdUL>XF5mNaYbEU2Nmvv9}`=lYxG;$8y| z2ExJM=Huz6d1EfsU6<^0=9H%&%+{h5Gab)0I@!6ibUP+RRF#w$=rC^F6u{{qgyrC^cZoRhQi=j% z3($j?TdfK&0_TE+-Ab(-C3v=X+fwZ&A-HU6xS@3Fb1H$@r;4a{-B4p4Lp$B1uAhdi z{#z2gZ1;$YlFLZ^*wU%t-INMoGf?B0tQVgmi}iA0e>7DSg$IN1K-4MJufilkE!55r zheceAbZDRKM1H?bccDM`J{C;SIcZXjsMD;ecIbfMo8?KOqnpAN+7);3L(y-U6;8`a zy21_DRlU5Ogo7Z?K=r!qFqjqHxCVYXzD4!;)Z8eNl<%wf6slZx`bB{*w2ezn?xSU& zOxc1u`ti5)xh5!eH-$fL_tjJ7zV- zm8YNbWR$1B@(fU(fyz^>JcE>Hu=3R5Q*(o_)FB}XjT7^GKnwo3bp`?DATpBhk>QGs?C`Bnm2z#*{*e%R>qAKEMb7%QBW13C( zL|^2LZLX_6Q7R%+>b9R2M*g!rS_N;11jCEvV^sR6qrwRsPF?O$3dI34{tr@_!8l1kf3a4ito+ zqkgyp1qFd0gpmXVNFVh>RE1CrF9Z)y?qq{!`{^hH0g8fhJCNT0g$|vG(1ieq(A|j8 zL4i(a2q&VB-a!O8_oKqd5>FA1{s$zG3?0ck^2gSJ`Tu|bD)=kLIl7YHaeu0f&Pf!G zxqeqisXDNd>5&)SU6}Blg4pd2s4_;kqb7JT;;+y%geva4lBPu&>>!z+{D-D_A+x!5 zL3%|OeNdQUm(*}RQRTATa6HpTi@ty&_5^9jYlBpJX~<^s`{p1#m2}A_rQy7@+pVk zf^RTj54`RA8sDnnEeoUUhnEVhLw--=KThVi{Ub{-w-xT!W;x8QCm(4&o8Nfykv75H zD5SO2R7fneoQB?jM}=JlAB=dW4f6dbopf`s4Da6n~qy8Q+72~TzIM=~SUNMWqqSemcPBKH2b zv6Rdr<}tz=Egr(X*8~$3c9?U_T0#3cT7PvUYWcj+X^QKfts(}bK4(N!Hk9Um&bTX< zqOBlvOwhp8~jYh5l=f- zXww(8A1qM#dy+n|Mps;qSaOVzuk~W}vvH5?{{%VDly1J>68n`A_GLM%Cb5pd{BE zb@RzigF!HX|1TeTIM^q+JOe^9v>9ijs^|tzwV}xoQzp6{beuaysJ04Y@zZsK(QQB2 zG}Wpq%w&TLm$gx)Nv);k+jh0vzi`=Ys?^*HZP=Lre7W2?9@ZPP;p6KI^Xix#<{#`Tu@=%h4|w6@bv>#`j~!5DPdx% zQKe^t@nV@CVjc~Q*{)guTv{*oCnmL)v!Tw1PHxvCU+f)1}&qancUgJcE_Z;;xcT( z#D}{gCtV2vGr5}!GO-31RXBR_RrGZB23I+~@YPj5b`G<&((sdOc!#3TkD!L+Nk z>bF5XL`2}Bs&sb37W|B=DGTbhO_5$*qtHvgH57gwL1FL<)uM52HDJ1lVdQw1zc?)d z7t7o^Qpi+1{h0^NSG;c+h%-yEnsvZ-#lyf6#Sr{CKM=1yUJN1bNzi*;+{l<9{3`fP zBF~thL;wzKzZoKm&xFIzurN$F0x$9ATQrham)S^Y`Z` zA|T2=ly6h9FiNPoL0bxUk<(@VcviX=ZDGKR_?v9H1Lfe^_&wkUl=M{&vz9~KY7f|e z^;BS-CIqA5hGL}8|FRBRBMwBjeOfln2b z?K>z85x*|OOE%g645@?82f`QdpD}1=aO|)Rc)6uCHdJ{s%2QmA&&&!KdL~9f%v~42 zL+}LzB8u8D5#9odiP*kHZJ3DdQPhTs*g%VPTpB0d)&cRLnHIIZ388s=6wt?&td1*L zA6K$Ez9|7Ns%By8cy}Z+?$#)2=d|&CDO7m>UX&_VJG!gmVUX zIOpI>g>f#s8{^a= zQ@`yAT`^h=z`da>_*Ahy`7D~k{Vm*25@s{uZH{0^0>;MxewmgEzp7Pdy{lE>J>7$f z+R7gXx-vy=b@1c@Q$;*|3QU9Zvx>{%H9f02LCdIY?88C=BTR~Df$`N5EX)p_ULrYW z(*=6$N)~c69LQ=~_c;ER#P)_kxx#hBhp!tTXq}6{Q|X;_xsxt(`|K29BGVL08`&Vd zCL>jxc%N+II)N!mVoDh|UdeA}79rG|_j#bkWXLkQPlSoLs4JjSmh29lJ<}{;>YJ- zqI6G3K$OB;#=IVdx7KeA*6pe&E8J{>j$Wt3%h7eaie2UK>1v_*7C(o1kM5~@Uvk^! z!mlVj%*2z>9!9ytTn&=F!+aWLSM!njA0Q5Zf`OSe@uG$u#fuC(ATg2c4qv*Gw^8s( zYGvyGDZkM5FUT*ddI4SvlUfVwpOAgj^&8OV)(CDe%uX%h6k^sh9dgq-7b&TmA?FkI z$tYKW_pW_Ty3jc_uGU?T6OsBDC4GOAUhPTWqH_))>06}wo+N2YM^Xr`SCMqn*-?eJ zve^NJw^p*<3U95`mDGa}=AYkMf6j;GuCG5KzZmO(f|tTc<2XZMfocpFoRCnMbh{Ah zp?*8YShk0fr89on5lXkcqG@Uz^qJmH^Cg%8GC(bhSOxLQ`a=UqfK=WA9}&S%TmOiU zOxKo&bQB@eAlL#_Ni)iv!8mfLqCnT3tzh5U#SC&8?9P zr-2gi`7P2eoZhn}p`71+0dpotexuI$BboKJ;5?)rx81z( zkuyd-Sd+NU2NxkqFr7u*?CER`CFS||SDCAcV%TtAoX_6Ri~j5niMnFka;l#ILXJ29 zlBSoEq%Z>|yBy>L=FIhd(XJbo^d>C}3ip$fr))$?ekQBJumQRop=0;0Ba#Jq2@YciJBq$R>YHUneOM%9b)>4$;f>Y9haA;UQ8N_N^ zOn}n%YFR&_1<2v{gJfIDycH&F<$O6z72%~tNNjN=eIdj`U)qWF?=*j5!#nmNUx91o z_ZW&UqRJQ>jKt;eqFP)(Nk>Gq?i z(b-2=jJKaB%H{$R*<|dY#dSchMDY8B#DOl02j^k7eh-#$LWJvJOZ|^3Ps{j3ZW&6G zU>UqFNfYb77U8PjMv}EK@?0Mkrkc#Hg-|VchJ;;MX5L?E{ymaTt}>s-ea%v{+dWN* zfoa(B{%Ni5v82WlH6*byo%PQWk}hRA7`G2R9gNZ*>L;p6Ka7R60VJc_g{+n&?W4h2 zMI5GP2f}YGX=GaQPe_rj`@Z~D_Ykq3yzeM?|Ir?S5s#p!yH4DX&!|Hf!uBgUw6S*{ zT~eOgqxl4Xh;o?gntw(jJJK$=ec=n9m^VlB%Pvq@L;3!m*3pe$*4n%iIdF^_n~Awa zFxLf|FJRo$&@ewI>pCq`QcFqsMn(=}Cky6=SB0BG1IP#51&ON@EAFKz@&WV6ib(W{ zyBGIDV&vQlG@6Y4g1J#jYAg+Pe+*zF;KSSqSgE0D!&sHnSQrz@(RljwBT z@%h!1uB4I31g%XKvFy;MDi!Msbu`LtKzo7s8sYYDs!+3m@M?s5Biw*H5y72~;2N4L zv|M+Eb6M?1aRj-TRF6JR^Y3H<<+MdK%f3w&4BM-zg7!)gDYlT60zIF9gkt0P{06GP z1mzbp8lCHVPQf!dK)rxNuhFwdg!^kR+sW6(B>}ruD!F-8GCC`0M>6d&)=?lQ^ z1*d}V0B}>l9Rr6#V3JmvPOlFZx|M-Mq?S~=?d9%3#8n*DjB*v<0^neJz%x=tg+ygk z5c50ye({MVFAcw#8%}dAr;}PvKhp3^hWLwFJl!uEg3i{xzSajOI5ibf zP``wQi}YyhZ+haJrgbK$EFgyEH;mG~P>yD~bZ@vcwVJ)j z;<88_>Kbr)mor##;nJUsG+KU7q`dYIbCT$cP>>!CxM0cljVh1H(CXeOM}U(Mo~Fto zu0__D4&Oo*=UeGF$~jF1u?o7ESyUhwm+A$VOz2W3ss^BC7Xle{FSs<-nj~$qSTg`v zT?Whrg=$t)sWO959*0z%AY{@rH~2K4s#J}N<8Lj^>n2p#m%f_W+(xN{idUQ4grC7X zfOrRV@}|;NXvA?r#(yBux%)auWNy?{c2G!T)>_1w_jxGOnJgnS+h-ekm=oEA1Uj)W z-$1c_OfZWMiK-z~!J_RGT$NO0;bIkqgt-NT(Ts9Fu7U*6!}NI50p44dUg;N^KFzJx zwBY2rU@H3G1OA(lUg@QN!diM-dP!4$1j&SMKI8UlJ`=-f^E3|J3DDZa8)TJ5Ymc;v z9}gl{mlok|cb>ARTA}o|uBHF=UMx?ekfC?3k-SSTv|!9sn>a&`!S4x6G&Sg6bMY;$ zc|%PV`GcU*2bAGz5_iKmtqp0UvZNx7{@sRrM2`#={h&n=?;W_ExX0j`r}6pvWgwB| z>&@&)_|4*akc|zpm_D08&;q05LOXoNKu33X>*S>-Fk#9}?3k8FY#(A2#wvaX^Tk+; zRnu%0yOVj6K64S~YL~K0q0wc3AW?dGm%*Z}S_7NHRc($zL$Ij*xFzvBT*J_CCcD3Q z{VMPd+^4XLi8$?Zm@nX}iq#@6y`QxCq*h5pL6y(HK)I74#h?aAQGvJmroz|fn7+!~ zN+e8k9aO^!i&cDZf+DM)#!UyHRGq|~5Vy*{1SC14oqw9*`ayBs0RU+)LaKmSvNU$; zcgP)|M(amO4NDzCo}Hr#X>9eo5QJM>xRM8an9mER>(&h-YcFAxJcaEUGc}xH^~A3z zR`xq1Gb13==D#A77Rc02n|L6YX{_->=*LezkJ}~wV)d1FQaw6GCKV|PG15ZF_DKDc za@4jf9vaPuHi=6~&NVvzVuM>_*JnBqGW)tpzwTa$nscRtfI_891b$v_@`4`ZfzFMx zy2Ah~Nb?2(Paty|;Iw?XF1*3gLAl~PDF^Z@tJc}K` z7tj>Dn$HiTxaD|}BWZ|Yn1-}4x0Nr@QmmyY`k~xM>bQ|H>kVt~5fa0M=?u&o`suc( zg{MfIQR2d^?R$9SP=nDuK=zloaIYXSfQTAKvS*}p<4|Beg}AL3%Mk054S6s$gqq^$ zJRk9I{_^~u`3Cb>iqKzIG7}}J0=q+)%OU0$~Zl3BlZIGK)H1zyzj^d8Wtdjq8MXm^m>*ytbqqMBRd= zLPD4jt97miX#;&)3I<4P!=wk04@^{f?uF@nC&6#SZi&3+=RvTX7!gfSV_|LVg$y|K3!p{Z*z?1EEq& z?i|ykym(Uqy>SvQbIsPf>S&EiNNj{g=3BUdp}3)T6<^*UXJsX0dgttngjyr9pp^#q zyNh5bBhsW+n1-jGW)!YxD5r&C<4`~pX47a3gLg5>DdI~#m9{Xb$yd$#H2E%mem0Ns~3Gp)$#d8Dpj`Fm9GUp2@S`Fi#ELmqsw3 za3r*f&)}^FNf#W6D@C5X)&UMhlL@07&Tj-(GPr1?0XY`ehm3ayGN}s|Zvs4vO}wTe z!-L-Wtj?sdg0a8o*tLC?kb z3UYIvUW?>tQZejQ99mS;+EDSw7(@x9MUwS!n|Qq42TfxL384-@A<2L}$0EK=3gGao z$NQu~if-~%u_*#>6-v3GVo`g_3zQ5?X!pS*rqWsiM6-zrLuJvRz(B(k6D!6Kqo9R6 zzLK%JU*-!!DGyX`yg0la%F_zmD8+{@0GOBtv%g7%1R(RpAq2iVOS~Gb#Is_m+n%pP zEO}rI;R39w$(Lrs>?&shV?i*V%U~diO?00IVQqjXL;v}~#2SL7Rr~v{k=#f@&E%Y0!O{!g# zDg2TFerbYR-e%`~zQV<-WN|LU$VgvMgX+7Y?%%*0LiDnY=&f~+sr2l4J8M^o)eqq9 z7$E4Uv%{^@SPYRu4Dx(8)GDH}x^yWd6cf&-CA-SuJ1-MTlvyGE8^+Qt7$2|m3x-*; z79#}_2&CUs#ah;bG*uOAAbJykEiv~fXM)%KF&^8qlL;ylJ5U+g6_pUH_%7}vb)e$# zbu)Ior~xd}Z5?+qR(Md7&5bIjJh>oCM|SK=At9XHZ6+>&$$PqxFiieRlD{J5ugUUP zwEQ(%{)&~q2FqVl<*yL=%Q6v*iykz3SjF4daa)Y?E{bPtqEh~28;fdkaINBAn3cq= zS&wqSnR4yYxWpOW0gW$TE~>@BEtC3yZICL@$%wluthtKXrisd8k& zY?SZZXJUy^5<=q!skzQn!9L{3Xmw7YgetyV6W%KJ8%I&txf>naXD|gK%-%2g8va#N-~G@p!zc&5+5c&jO`>g+H7)k!5r>IVxvq9;e;dOg6XWT7*9?(@>`vB zUzyC?$H-*f15;2UMD_5{S90VNA0gvHO#W#$3u^GRoC6YBfeVFBg2Iv@8OuguvfaU* zFg3IHH<^QIHZ~?dOg@Ne;=(remy6al37%SiRyNhUth!4Ld1lS@I2mWPg7axdMjgSq zdppiirwGcB`&sr2Xv??)-X$OQHNeMa<7k`B?JFZ=P0co{Wig0c%!2p$>WUvl>8-MU zB|h+MDsa$}LssVui4DR%3no^$HXS(Gb@<5Sd?FyYLfBog<(0K07qwKI9l8b@6$3va zUXzzi<0plmr{pE%3UU_=8?IFZL2ZSsQzg>Mr%il=jM|H0CeFgf*9~X%9uwdp4f3V+ zS_&6-4UUPZK2q9mDn^{JWsR(wF-Qnn32#>CqphZfoE}750#M_x(5A5%CHHb>b~xe{ zhIqx3Q93&kJ%*vj{luf>)B@H|MD@uR-{lu=B(3be%$21Kg9V)ZYO*fAEj!>fE219C>J^(Qf= zsUf$2A@0uyOMDhXRVMfZY{7VZWw;N9yU#eyJAov1K$0vz|96n$4ic&L5_Ubj0!4^+ z&ZC{Q2?p++xSwrm$x{n0F%vPLeCw{I08GZobp^Ft(%A{TjDy41SxQiF<%Sh51{4^H zUkoV3`UD8Ue0g}0iy%;k2lxoIyd7>|fxJaEl}H7%P%D$+Z%Ax(nFc0F_itmkz+@@p zg4`Mh3kQVCyQl&PNv(pvgDDFvO{95qE1eK;YR>y2>XZ;9$2rAMD3Y9GinyebQDiTTWFaHy$A(BgAcu8V=+1fMI672xTB;+%`g|q2cw+`2F0^pT#)9_mu z&)?GIy)2EzB1j>ZjCdylbVI1MU6?ni(g%bVLU>b4?m*`vE&q5c#rnb6fqFTDFJC2B z3ttg#YRNe-jT4`^1ftkbMf-+OX(w(i5Ji`4Y@jw=U4V`)j78n4D5=bMdU@Rk=kc{T=oWi`e@zX*;ItjVy@lc#XtpNJ5m2e2_|HgP*zl@im< zg_9?;gVMwcfQG3e-Qi23+fET#Wt?d7mlcE3HMgS&a5WhcK|=h|jSaFNzB~Fa%B=EP z3Yg0Fm}NchPT1!}QPeIAphB(z!-13qVr)UBFvr*l;4idAhq7v1SCyytsi`(GiL}xd zsBI@*Y7wVi!b0(TLQU5JLq`1aXTZP{9~zRAe$ryKiM>cF+}llbj1Aw06|~g|4|zBf zl0pTuA=Szc#C2_)yH-((;&h1wgVY0j7468^7Df-^rj}V$v4uAWvBQfGu|ss*4>diZ z`aq?pS*@f3!OXWzU)nPvmb@P&@9qQSgDxCOB_M!=Sa&?}@gc!w`dHoepPP7ZAUs8jE5V;#J`$YTa3c3ZLG8s@|$K&n{doM)n z?NvlynLaXYbY2A1fUl&At)C|mEjmIlNmbtqKP6Vf-viZwOX0Yamz=z1?z<{|YML;r z)`+bMg_|g7s9Y4@4h15Pw#o-%kZs{%Qpgd~vGHDV99ZNqlq%|<^@s;WINV-`fsdru z6{7}bR!o1Pk`0cH&58--Zpe>6A}WQ6IOZK}NllGSO|@84@!0hkyqC=6X75iEKdqO$ z462U}PEAd-zz7fyv83bVvP#r2drQQAvM^ka#~VSkJb~y{xKokE%rf1=%fmbvvlF5R z2vuxAY;-7h3xAp-s$vB(O`K7$bZ3r^YH|mr*{tGwMB^E6>_1Izyhr(sTydN3xr_oh zio7|PRTP~xpEC%F6JP=uq;Zuc_9+c6i|t#Qpdy3L&XL`Lwbw+Tc1Jc;L8_&SJYOIR zh}AM@?8ASz9{ki?H~u>u^?hr`;(kT0t0gVa>BI=p z|HNOmN11BEl00U@V;kv_#!^*WbZ_pm48h*hlD!y`i}xNS8yt8!n;hbv?krgf(+T+& zNQHSs{}a8OPW=4~s2F6CL0H6=(KuX#q{@LoAj>CzD%$x0aqdAjJp&95G%3*{l zCq&qatLf}G@p;^}Y0+%Oy#X#Ly9M=Y4u_&rL;yC0P_frQ`F2Rp`uiRuURzA2{A5GH z3aM>e7U8R*AL1FVQMkEL5W6MpL)3Bn7Vl+Vqs^vbDcoh&Q_?u;cs5=sU?;EATDpC4 z|0rK+h&K^1c?YDi2%sY@V}bh~L}}3XmI46WEF@q92v$Hr!7wLboT-`nw>Pdho%L31 z9pO=I9hlupjxyn{(LCsk>52r1L#?PLt7Jq2?@h9v#6;EX)ISbW6g?Zrmosq_H^WEH zHLGyVbx~t_34?Scc%PCdGhMMrwrsc{B}4i4siK>$M2YJf(OO#A-g@km+{WWUW> zvKTr@b|Qg_hD~J;8_d1iKeDHiP#Puc?FJ~5>}?V8qP1+jQRRsjM&f--cIiegau0Qy z87E1AH8D;^!?Nk{VsDfs8jF18Q)U+pdBqM6)4ZGLu1^ru<5k?f0p;w_@k?Ml2)MxZ zbBX%#acZtNcy=4VM8lDziM#253)~?=f_Av6Z~4Kx*a|^v-c3%u7|PUB07!itB&ciN zjrGWG%M#T5ZiIaZeD@;k8i4KMU26B!-uU1~5;?I&{^26xbgE1ZY5b<>-lxOe*9DH@ zYotwaWxnW{pxa7^=l&tM_&r8aG;#*VrIGPa#TA#cvGON(jU12>R73$^QNM?h$jbMk z5Z4NE?=QZS{m`4>trg*#t?;7#xh!{;a9cN!c8AA=7n zmUc>~smc=60Jd}*n%v>52=M*wz@gsSOwq190W&V`lIe$0o$i`&}-%;)89|n;Jk0Ph2NEy49H%)2h%v zyo3Hhx39m|3i%rAFyH2rK;_!Aq`aQ`xFOd^1lGr}v!p&S@}_8bp9iiGTv>u<@WIk) zn%Mw&4uak81s3sA!aM5dikiPlsQ;A-Go^sh2RIa~M2B;TZ}~13V4z)WZ|QweZx!lYu7#Pa2+d=X#Op6A8c3 z;1a?h+kzy|0f_XqvYebUPl%&rc4zH5AwamZpMgZq0nHwsppx9Cdyg-;gN0_xHvp%ORN)pgdSF(vL zsxs_@cAv}`j^SpBgNC)!#R#vCNOzoEX$~{vu5u6wb{~o`H^}>~KIQM?`XR{P zV!zY4&Vik!+!4pHLHu+rQxzAAVeW45K|A9N5CC2%vj}kvzl5e7D$*fLWLYZ*_ql~? zs4r+X&{&jaQwD8@2N7sXEK1{cLrHli=SNhK-M*&Ed_SRbD~6yl<$!)rl&#?(Vv*Ci zfp*&J7>i+|Z>Ipp-bcJz1L%Uxi(;-2f*}sN8((gO!FQq&U-qN?&z;DE0Zgy z*F*~7uhU1kpqcXJVHPoBFVQ$EH(KN)Sh50Ziy=Rd1Zzn!Ids)I%3nhq?*(z#oe=wW zfk>hd#lcR;xa0#|IPt;bT%Lnm`8CQxE?I8_k8-6u%-WJu>EtNa_ciTDx#W{~%5gG0 zgqu;J9O>e^X9-E#tfCtdwJyf4DrM$nR5+6uei?%|u}b9pmc?n-+Eo^L8GLL5xzJL+ zqMY?5>mI>k=n!n0BXC%(mNF{#r&`e%VqiIk){4<^ls@WE^EKfF+S`NYVRxKRO-xG3 zx8G?G)*n1|@b`l!0&BR&=IcU3^V0B8VvEnvd{J{SC)fn>)-gGLCWyOMH9P8%P?@MV)p`6ui{%Aou>OwZ`TOLPjKTu|YDt(z&_&mb1Gu&?MGs)Vyzhz9XE-@r<@I&gO; z!lS7LEJPw51~uznO>e$oA0VLdPW`LRH`38NVlTf}I()wQP>JCaE-Zm>)8uz^(x2cp zaKQ;^wysT+_XprE?}1|q7^&<=Y9Y65U4UA{As)k@+gYxmwmY2BF5T zawN4l=~8GA5r51V4jevTqGt!jr(*XtU`s%z7)-{*+4u>gUplH3?3FOCU6Vc##?h8o zlMB~4nTTrVgeRiPufGqYl}A?zuS=q>c92Tv3z3d7Dxks)?$1o30Sndn{`>FCl223( zQYk17sdPi8lA;&GU((9OffD313-|-ltHQo2b1TZc%{R!Y5-pSq4?_xj4_}PIFixok@rB-*h%l2PF_(5tRas z4Bw67J0Gs1X2LvYLtVQXFsd|St?70o1_&piz2FUzNsN%_i^qf#)w&&&kgqTL6%8U6 zxzRK-paHU9(JfUup3`dOhQg2^)npNUC9-uRs~v)$MMPt>>2~$JdY9sZ3W(wk+_qoG zkQf7GU1ewhs(4`e$KwFs9Tu8njL5p_l4AA5>57<@pDG~_=pTcF$ z8!?9Fx;VW}R;hvp95F{LY}6mVC?qjx860~TRTy|JkZa_nSS|<{y^z-8c$9W@a|iH} zk@Gs@cPCir}DZN#*EDiN-T_y;e0BoNcW#@RNzqK!A{Ma3nCg zUFM%1zPj&Gi;Z@gPg`u_psS>29R*rca8V3vq+x%`5~lcmkA}R3>LJ*SUG?`URQmHt1d9G8X^QHwYts+;;pOtk^@{nL9eMnBVz*sPdc^T9hknT z3Jop@``l-tDFptM1M#2KUL8|8czn zf&cgQ3XFC4^$I2ZeeehaX8@-KM}unx92&u0y7GV5dIh0`gax*MTL^B=)&F;_SJXDN zuU8Z{{N;MZiL0bOF!Cl5-Whm_Z1@lB6}1ij>v{!&`G2%tp};PN$J5|m0QVZWH^F@X z?h9~L4gYtoSIG3KgI^I`3pnky|C`n;>}qk)cPP(i$EwJtgV#ZVlJc#%$-t?I`6Pab z0X`^x2yQ@7XmJFmJwbR-qRNMXUp&(~uVM=ZJGF&mgTtvUHMw$8Vx}W3S`h4DLYL#m zmmA!oXW&NbMzVo}IK541<11SuHfUW}b;3`}YjCCA`Lt>(T3b$P5Q3*Sxj-0c)sPTx5(i)p~s~j0xuE2GZp26RoyjEkMJYSeen`Xkim%nMu?f(sO zD;V$H&RJ@@`S8GnJEyk!bHf0GfxX=Woipl4g!bUqcJ6_1h~bMd(rMIS$k4hq_)KMl z1+*rq(J`L}P6+Z(+!%k}_7$zgdcz$#CJjEiqnxP1F}|h^IJz zelgufeE9W@#4S&SzOhCt9V1@S8hz)}N~F~bA*9XIg|0faP)#C&xI3%crDSKKA=x4> zxPb>~88jpqgz-&27-cQZKf)MDcOhL02g!+uyr5GoB`d8Aq)7aK^@7&*Vynb?az z*8p9_b%UPH-!SF}g9Lo|3b9VXHM;e@s}82PQB8+M_;i?Cwvc>In9hQ9lG__^Wibs- zY8l)X_!Ae%R~Sqgtq_p&8$7uU!q27?7%ikzG#`lOzGynZr9-6LZv5j6v>)(;nC{D% zZm1_+5D6pkuR#1@5e+xs)%Fm`8dAldaR*PBsVA2i^U)GniPNDu?S2Hyc)g(KZ%U4| zR@NXqy=f1z5VdKl2ayK^*=xVh7JQ@G_Vv$#-+gvOQ$-(wduHMJj#)D zX<(pxv~x~Jryy~iPm|^eT&Q=O4w7+!O5~X|>9N8LMtF?I({u`J-yvpeA*`o7Xf-QI}T*&_cA*rRLh7EKCIA(QgMV{Fra1EM+ z&e9Tw4 z5q3J8GAdj0HYwx_B}B^^q_rKHJWY1{-M#qPjO3W)D4-=Dl0|}^XC$I4P9$j@;B3O9 zdLa(x0wv|pp6cSEJyqBzFE7UyINwSr`ez-Youf= zU%>^nETBi%m@=_R~%$64BncQ(hiHoyZ&SlS9wKFHNo zg(7&Mrw@X4CN`M%uB}2uu%6P{@tnqgJ^i&ZGX36sXrP4=Do9=N6Bpw|EH%w)UR1YTyY`9NVQ2vaWFtbcsmicse$XyPsBH1He2z@ zPn=7>!nWem9pdoaf-f-Xag4ChGE6*N9bL z{?)@ z-GF)xRb(amv{323M^VYJ$toE|ZHOzY>vH;4)(euiL_F#sYxQ!Hn6YbKNA*A`z*c-y zKp5d$2nIL~M)1Y)I+6BS4WSYq=yS#y=Oe?{PC<&2#lO6(@)Hfi;YBIwCW0gzfJ?TzXDt#rPbMF5 z`x;Aa7519q^lN=gafTd5@Hg#cA8=pUrsGBn4PWCbUeQIofy(qpju8)0JA%pazv`@_ zb5uiw%Ml#0JJZ!dJEt;?XSI!JTtp=5T{pDOsnxhNtJQ7qrqUM7@EAXTw6HVdwo z!;>O!;;M$CND1V{y0HmX9KCeKsP-%rFwSQ}jcBkwqLLRwT`d|{omR8k zbOU;R?s!25eBHD!uTRV(dTmH52n=7fp8@4iBw9rCRSE>sbxFFMYI!_J0O?HcEC_|+ z-P8iIWNwt;XR65Sjlc}4Xk}Nlw}TrBu!_vBq<*RxQ+`X%AsNaz6G58|sgDO*JIKfI z0geKuewa$>X+jIXQ7^H+{6;MWQu}0>UK8CNw5q*m^jV&LYrD+t^+A;$SCG6vHhAh8KmC}9nB z(!EN1nJRMqRNaOr({6v<)pEu$4izwudOWS7X)c^Zv1*~xIYw`~o*Q2lT6~I&guXLR zm04(_I66MT-E8_Jcecsg%K3nx?$!?Hv@vN~-4n#L9pqHu_R(#>t|1UOCg(fnql~FJ zx4=pFG?|&)wPn7=vy%DI4*rSYNbg3R{&^^wy zJGaMhGiH=CM!4?&NVmOQ)8Kx`8P-!yw;R&Mc^9a(r!#?BQKNI!(Gjk88tu2n-ybxHwFv;S>w%qdArs>(!M!AzPg$){$GC<`zeMtB|V|9%s-J?-HkWEuZ%+O|fQc znsbF-n)@uBkqHn2%h{;)6ChTqcaS=O3D-NG0tWOFBf z`DjsL+J81Tq5GKAI`IDmzO8PZA?lRrIvOj;)=$DsH^#bng6nG$!wofvfrX0Z^t_(PB7g*e5? zLJar@eRzkFg#|agV9iosb;q+cbz;NlSX~&bO zC6UC8hX;{cAILTu>bjl-4G?RNp~kHEULa~M+BM>j`z5L4zKe-O9)q@&V<@V}_fhy$ zq9Xpemm;c#JtZpPoPbunEy_*<10INiU@Sj`Mj1Rks{DKE z14zY**WZ87L7?lNL}OEh`Bx}i@wX_3CSAp4ZdoMLZI6?5+Ygy`>z+c%qOg>xkjJ{O z;P_yV^}utENxA;M>mvQ0^Yu``1K5wSj~!W-tde#2Rl4mrO;zg*!2QeqMnME-6T*oF zIpfc`xWX8UJ3=fQFfg>xIWFKDRX&&AlaCqGSx2*omm$nsY5x#QSjMxQ?+1(+%?xd{TfqLVExG_uaw##3S$GKD~~d z1{S|Vh4rU#!{LAgm2&+()M=<}7g+cqBsSmD#_6kkjwssi(vVm1)Kkmt&YrIk&sI)H zPQ!JC5J;om)KC;Vh!<(L7cT~}+C*~7ezOau!r@8*#lqqFXBp7~b7cH=(rVMmU zX)IzRXN@W^kkX3AxX=6mJqP39Rk$S7+8%6`6N#ECB~I&|aTIISB;Kh??Bolh%AHQk zGE3;zv|GjYl-q#5>;)gpq;wPYK2&>H({44ZmxGKL1hCz|7H-BsDmE?-2=KjoxpZ{!)UHgNH{k&sitBE_ zErzxt_wvbBPU%z-l`Fl+DW~f6%6?TU+WSPy4oukq=Q@>xYwa)>w!Om6Sj2t*lFfxF zX41D;5OZO8*xaYAe}cQV@YX0u#rg6{2DRI#@Kyxp3;y5*qc8BeryVN!Fh+49c?s7& zyAIg|QHu#LycNm%SDE!_FT{O+neT-4Y|w;x#0za1x(7It^f5_#t`|h)x|48v!aR;C z%Ty&`9=JkvsF~A$uOU<6Mg@70T?({z+A0SBtCJb?HN?&t%jkCPqJrE^hD!0S3l0z2=&O z0|A8SZH3k^MTTKENMtd18^h^KPO-k^3Wrv#0QbyoG%+j6_1&i8Ch>J@*1sqp1;4^| z{vdjfjNw|=-Xs1)jV2lmsw!#_>i7EMTAf=DaKqJ2C;FB*pU_l-)B~V>Q1aJ6R5i;8 z<`y*e3b?em0|hfqy3~$nk1XY!A}y#;w3G3^Fj?m?RXE|Q!e$`t8PY40u6OCe*&>Xc-)1bM*Uz1R^_@}5!em4yhCzYy*3mZaI zj1S{O#W6(}v3T5`%tZ@O32RDg^a*wxFoUbnr`daoFR;J4L_K(gfY)j8@&&IW?w2wb z$rw**gLLq?Ek9cE;kh5jmTE2QhE@S#L|9(-sH(V$og*}(eomQRLUb(w8Cd3vuK~bF z{>)sk2rxj82F~p)kjj>*A+up+zI>%Rx{ljZ7N>y}p=DVT?*b3@tou`tqZTYG+g*Pc zx4@@K@KGUD;V(I~apGNa7;Z{-bsF-*?19RupNEC9XtOW-TRcP{9V;o{iZNMB_6M>@ z_AB_@dKzW1V_WOsvE{TZ%=MINaru)C-cl!f_@ttbN1YKJ48;gdzAnNIbD*{IwY5xC zlY`mWvKi(`46y%lCSl^@f8qGe-{_Guh`$lOuAhk4*Hlp`b!1kEc!!0c{j(KPWIC9N zq8m6;=Y$m9*bC2fL1GAr%*c_6l~Ssw{P792VaT9De22Vf$rg~+6ojgFw%mCFDvLQM z$Xb#vMM=`nbx}>UAyw=HIK#W&bC_g6RCz=-tDnv?)43iNd!w7N*#C5EEcPZTex&o^zSJ}mft~kOrd=(rBn+=& zk+Pa(6$dL*2_K>m+msL#3)7RedeI5lHJ?b&>|0J2LsE&|xu{b%G|5yA<8|Q;HTOW) zyNrq*tyl&xkqU;|ESNU-2$7pjRa`Jc-&V*5hu?N2XhCY4tu^xdBuIeP$Q{1KfL{d+ z=<*pN6kmZTQIfb6cy?4%dJIvyEMS$geggDZMCg%jv5JF^drFxOK|-Ro$;GpgJg^59 zr?ZG*SlLLge(~-;=u2@unp|o&*dnTwAWj|Fq7dy9s~CP9$B6_J$usY1Al78S0#X`O zKrxthS1H<3M8AkZ;WaVUnrLGmPE2GIQ2dHR^WGEiZ3Hj+vZ0AAS(i;fIlNyh^x^OE z$2~>p*McAT;~p#Yqd+$K9)H}!#Ds6~oS?K8t+9&T$vLHTzKTf~2DtkP{TeYD{@7I> z8y({}qg5s*9j{vKiR)^*;v?XnDn0=L>GgQ9G^)mQk~734wXzJ5+P;~zIB`+Ay#Lg~ zumOBaAT)p$ykg%v7knIPEsoi9x#@y+URA<8azAZaBlvR<2tf@nncC6_KN^>*I)9jx zo{k$_RtvBNeyO^Z5<)PBFcG7~X>OW+$~*5?J9OmEBFz8yH_&`uKErT<(%N}2t2zvW zb9dAhKMcNs=|m%w=DNeMhOrz8b2(qsI8Kk+B>}I<=Cro!v z_!_VY&{ieM+wCO-DY6qeoXQm@SQFX^b z#wtA^jT84t%1K7HmotF|;ZuqfceMLyfC-?tw2lV;h9 zas3AG2Y(OzX_3RiIG9Y&{<&G3DrD%RV76t2CNet~s;-A4m3E{uYm;pbvtGFF%x`$> zt<<-~HF!`|wBvQvXbDqPlkfSG+$@x@~1c^rGtFE)BL7g1;Src`FymfpC%HE`VGXiex1X7#9^*=m@j|`$ z*8!X(tsxHt<(PtxWKi;47$j$QGzin|NEC`w3U9^hp22JV3vZbVx)Y9sdNdu6So#A@-7{9G84uiaG~RbBQdjaNvWVUF{cwFYtsy3a+*Z*I zgn6q){QV_lXm-_ncd)mNkM~xv{h>eh&efw~Y;$X&J5n;Ed2EejZUIWUcPONISg5Su zjkOM)7r;BxPIEyhutNhN@ve8yaKnGdFpOl_%{xN?QW}b2z5){IiUUZQM(K)?J=fzs zMKW~A)ssQ!UuU2zevd5bxNXikZCDpcdbuv9D)q=hJuW5nsKaRr<6h=StHZ+hAPP;8 zMECR`q`G2s&*BAI?f|5HFt!kXyZ^j7^*e79qH|N-E;OCTjsVEcIT8Se%veKWqOOD( zDoYY2yWhNe2Smqb5k3Rv%;Q@Ebj7%mP`?^ADf9L9rNk0^9XaIR)Macj_AE{-%$zJ*ru3!^D)5Um*Whtphcfo>~t ztrpRaXI;z}qH1srElJE*!#u{^5|dQNX*A~0n55I3Cc+#x5lc`I>A6ZFLyx+Nz^Bq= zv*(MWPVGd^L9&$`b*RdG31tO$=EP6jl7zfT+YUjl9?xbxs9_E71+0QWn%F$R^s2e?hUrFaBgsyz+DD+SWLQWi9Jl8LuAYrs3Bp z=u545u!eHdAUA`qFh&)EW9Vtu5xN;XF1YtuBb_JPh=fD7QAwdp!lpOtTGKZ?N98qjH zA>RP0G$501Wa_V>4syPMmqH3O_K-!o9o)^LD{YhUs*Ythp#z37M0*;bWV8V5NeWBn zu9Y<9_i8>=vF+qk$8KNlAuM6}Me5hm|EtiHU_b#yV%xd66bp zjt%=j<)Pu#7Q*TeAJ6pjj{=u z?*p;i-GziOJYi-LN52J7vcjlz%!I%q$2m;>7883kxjA^-Qu~~RA$1iQ2~3ip-3<9J?AYje;Rf=HCjrP}DOQuQj3w$Pf{b zgl;@9KVlSL@|7Q<``*knpHP_@;Y5@9vv!&i#&8H?eeK(rFd2h0|2w zI-OuXJw%dJ)I_RKMR8;K{4)|al3#X);`7f-Tt9xm?SOxP(BLj--vIj^tgPdCEj|R<1kqc24lp@ zSM*lQb>(X{e4U@k#optDo?kS9rwW~8_#CY>zwxcN-jb4lOq&0kerhh zZoJRWM*sEs*?u;w*l-2=ujkxs+|`c$E2^)wFP>0WJc}nC=YiQP${c$_`;B}(Vcwhp z-gXthnu`X?O;zb^m{m-?B6q*Uft|Wv3v@ro{e3idRf&g!TYO+TPr9{J+f=x;lt#ly zTAN5;#(874BySfh8>R``Z9Lm=8^iXN)-qx%Ol`A@vb4>&qRP`9zH-~otk^FNF+x^d z?wiDmCJsG`n{zwY!$?-Y<|%A+|NnpgKl*RPLKWo;E)-nD0u{9uTp766z`Y0VTW|-! zodNfEh_fEt6mTiv9t2mqP(|SU49{K4dvS(}dI8*caO=T62reZ<4%@UuMX?X6s622B z!L??osLe}NRNX_62A<{cyaaxA;EsW-1h*aBE8t4OJqFGWE)$#u+!SzQz=eYg0N1cg zMV$b*3*4LF{syiX91HG2aI?Wp0(URCFmM6j8X@0{;7)_91-BdA2j~EoBjBEd_f_Dm z;3k0^1TGWGu?k!;5Ndu4BX$r zZ3DLx+#Ybpz?}z|2yxWljNrzAn-6XcxI%E79+K&K2I$%Z&NovGcm#dLy_i#OX)v>coujr1{aI*Vjvy3l8}|dpMAL4 z{H$6Z<2v}{ta^i5roEhDg4pHzLYHs+Nqk$SrwY~7Tn?VKYAO+*ln*rlpPPNCNb(&( zg)7fce8vV+TIETRbXuyBg=cwpN>rYw@mbiD+Kbs`c>~lkN*A&^l5D?HQ zKm`GH)MEb|ew6Mm0kMG%{#5t71Q>%F0;rI?1h97oVCD@#IRF*z9RU9p&gRbU(3DSeK#$0k}!!cdJtW$>6#{`FW-O9|boW!gnk6zXaSs`2H6>q319~;Nsx>yi)(^ z;CjRN-<0~_04@f;4=MG(9NcjD{tTXouLIn4`2Itw|1@wRl%7$mNO8qYb zHw3=lgD29f1e_VZe^=^116)7&{<~8D`QRqP_s>fGKLTzPe18p3gy#g81m8E6`o}aq zp!^j|{pW&%dhoAQ>K|ze{{C;n6XWyXpq~9ND)qkr9MIYSC8ho!2M2WUKc>|G3UE*^ z|LyQZcmlYY@ZF@;zYSb3ulipH?g0otpw$1v;O>F%kKl>m|KE4%{}QG5QBl2oRH`06 z-Kf4kDt$K}AF8*HiVpFKqx$)%V)Z^6D%3}%Huwyr!hBT5?mqrhA0HLd)2E1v1=RIE zYDixM>3d`P&~83{nBF(UX9=cXtoNZYy~f}(8q-I1_X)!E+MYfxIX%@4#2aKQejqXV zf^g(R1yVGnr8HC!$ST1gsiDg6@>LJ5&dFK!5NlkyY}LbTw(+6tWe=_J_FuY$UE=XY z|Fuh2E?;U~x;&R%vg)B_Mt1dTW7d)!7ly}d)@L?OINQm<}QD1Sv#DERzI>PXIXCU^3|)1k1S)eR|ESt zE?)(3*=5Gj_uhYRlretwnhiP2AI@ftqhn&mj=DcGa;!0FNzMvm+|reh2^!gOu9Q`cea^!BhklMVY90DwTSO%B6T}D^)@LN~smWUf<=foATFP z`Rk$l8I->ef>HE+_6LmNL3}T$s##N?F{qk8C;uasxdGz6b9lW5KFzpCE^L9zl zp%q^SymfQimt$AH^4XMQHQ$_yz47e_zpgxSKezC#`KO>`r_(1MeE);UlS9W-XOat( zk5~6xQv3avjb98LyytW4t1o{2lkTnWcD}w-J&Y;!S@hXSZDn|U;HOXJt-i0@tn7L3 z_gmtcI4W!Vrnu8x-jdIf4kUj$ zo~6FsdOq@-BXMt?opJod6B8fVbMVbujmHk#>zBv3o?JC1q4ePoYj-aGId>F2_22z8 zQHy2;yjPPK^vi@teJtuhg6z zKIoO&Prlf8ysFp4&(n*7zPQ)4@Vgx!uKc>($nU(o{qyhtu06k9^Y=ravN6++{{Hd0 zL;nmJdWzZT=S#wEgpi??}gYkN&ClOX2mCBl~@HX2B=B zm;Phu9}iu6ZL6INc>WRfyT1OfO&%BQE_v85r-zO5d1A)*FB%@(dH$n_Palu&yIuQ_ zXAb=>XxGty@3?w8Z{XQefkzG8l$ z(2Mh#(lvISwAbXDwJ=cCO?rLVv&%nvu;s9{Vu|^ul|9#=57>O=P|)$YJUx5&=bD%$ zLmz&px#!~Aq-o2ipIWzS(hU2-k511&b}}pQY;1$+!~>}xef#bYuYYr9<4>PWtCzlv z4Ey7|@5*+6y*Kjt&r{#t`bD_UxZ1Cu_dWjOaNC)=-#>hE@V$>^eZF(Xl0E9a*%>cH ztRC^euD~z0Jfp4Xd)8;Z^Qw9j_W!uieS1Ig;JEuMQb$G5KdfA8Zd{lDzIV z=l}Sx@ZuML4SC~fW5Q?eELr#NuD8#L*M6(LE{5}GDwcir!_V)1l#$_nBVp>W{VP^4 zzrAMdM=M6hT%A9{IMUxQ@R8`S?$^g9oc+u%qw>+YYc5AFThZ8jeZ)80caQ!T_gt7` z%x1q$x4wO&*VoSC;0$$rUMSFhVAL1sAI5W>@&W47m1rOFgHEPc8 z%CNboRAnJA#C{X(-s*eb5h^qh~dKGw|7WUJ5wylCy_DwSQsa=;LPL!JDi0 zrk-0jH{+YHLso9ydTg?@^yT1}p0m7i{7koZ_g5XddG6Bl`)>ZZ@c4r{{Vr};apudp zv2PU5NuSp}xM%OdA-bQ}M2G()Zt%o+R@`28asI`;A^!VpOQUONZ~f>w)%iEdLI>`D zCu;HSZ%2H5F8sqQwUfUX#dm*WA;p5o8 z{{6;|=uZFfZR*U=orx)H&Mez7`f9=Aw(A#v`+oQBw!G(Rk51gYZ~x74W&AgO&;5P< z+;2aPS@zDhnXmAsfOlURRCDu7|I&RQ>E~ozT@<{sG2zF_Cm(q_csCp0eg1Xz;JDvi zYgW1n2g=5eetcjXRUI+3$yq56uEG8sQ@^?U z-M$Y$R~$KX^Bco=e)PkI8*iMsJ%0c7V~^h!fBJUCyM?#sfA;Dm|2IC{7+w7SC*ffu zuZ8%Hy+2_@|J-$>{k}N2Ch^bO70KiHgvZu>mhsT+<2U!|E}lEI|I7V1oW;lMW^{k) zsiTV2$6(=stTUhm0->4jwk;l{pV<-kn=eese=w(Y^;~4fr9t zD6?_!EB|~a`18{*g}m37n)~nhqvy1~`rw1dPo!=*&}+`Q>DGdqmKR4IfBZ<;{s()M zIY*^@^U|2-#BT=Fp4{wv>3Tuthr5?eTlHMx%KJ8_a^kq|qvMeQRi~eJ5x#UpBPhv*#v% z6<)ihC1l@nQ^Lh5kFC4C;L8=uPB+dk_~8Nn)GKSF6PrK%$bVHEP=I`g;z0dcvJSSb!bB@o>5V@A zsn4Ha0!F^}Q`=$~IM?_K@J z*zVFR%{|^8`f0c4X65P)^CyH1j%+hL_RP+nNf#dLRhN(yeSGAzG0*(1#`IN7;P?qw zrcMqlesWUE`0@$MEb58#dS#AVo&VYc<0^h0t9mzdO!4=&(VriEG4l5nhwuMI)h%k% zzgL96^X$7r+D2c!r)I&Zp|g@69Q^n_n+FYg^`bH4dicO$U#uT7;LO(%35#2YKN>J; zSYz0uqbk;ZKJxF?f8P7yzaF@+-1+x4&A-ii^rQ6txvxf@&Iudx{JMxa$!l}2^jMj(F%-QE3Hv4Zo=FfWTmsgTr`TL%Pj~jfaHO-DS zyTYHCI`#e^<8tTeVn^2U}lX`EuL4zG>1(eV?0sA3Jet%AVJ6a33vfNvx-?Z{&CXF?3>a zLpNK(wHM<28@ER6`}5|D&gLJbIZcZ*)}ORJ@b!scN9)fqzfL;!?VpdH5#IRx?4f~w z{_^jc51c-sU2*(s*1N~HpSXIY=(ABr={Fy&jXJRTpnc87!x??T59!-7f4Jv`*Y*^Q z__=a=Y-rVft8MqK2`^Us>xsjz7sYPn+dfX(_r?#;LQU0FU+WfF!}?9#AOFacKlV9X z{?n+h)CXc;`uMqZt&eQFcS^+HdJn6A{S`=A$pD6D&-rRv)^e)_QB z^_O}?zqVz=&3}fk{_>R`KI>kc@y+Oe@A6UQY$(9DQJNuhe)vIX(Y1H(b4R_sHjR5TZt{+|_6%>? zd_8{rmiKPwZT;uVyZ%+1yXVW_di#E{>z&x`jvt@cp*{8EXQoeepFgOZ{%P7W;gjq^ z$G=&W81l7mQ|ivquRZtG7iDL@(TX8oMIZm?)nQ-!P&S9jUt0IwYSmM!<2%1UHshBQ_CKQ5ovpL#ADZ`u zt+(Z7vxTUsI-_Pp_O;)uvW^XJ%J zKi{-^`o`y(KdbWJi9H%x-ulSw+Be2V>=^9)A@rp;Hg6npPw#2Bzs@tpssHwDqrO>8 z+%|EZ;UDuRZyUUQQ@_!No3}XZKdm+Bw(b4koZrS>#fvL^53SjpxuaLu#q^!;HcmJj zGOOgb-3RLm3zi4px9{;4iR&u0umHlb%@G5%Atj#-5{`t!4shgz3tp%2>D}5jM z*_w3ESHZ(#eYRI#{p8K9rP{DQpPVY%c>Lj*=hh#JXdJNWc}??BQ`V-x^QDvTd+zeQ z=ZDW-JoSswel6Ow+miZ!{nNF#FP;5cn`7s_2@m)B$6WQAdoF#G*zo9?`)1Wd7T!3O z_M7>k*EUaHaifYq+$(#WD@RwhVc!E87e2C_TNo?Nojv3gu_?Dy_^9XA2YR-|K0*KU zo=M+^52zm)w?6IFkB`?0dp}tiW!j#8IrHGZ(>^J%Ogq~9lC*N5=|TU5r+)se{{HGG zo_S`?k=HK|`}9WgrbX5ZPmCWuZ#?h+>^m1%MGatFPX;~m_V_Q~JQw?&>&aH1`-V^N zHDmUlA75WP=>C_wy1zy_FSb56gV1c|**IIWNET zM#dl42LIcq_ll&&1;_t<=HP?BxwoHLl=6)K?g#3>eC%WbmHq9&Z)<-aeYW&j>qC)C zZX6p#zi$8gcW-~^cfzIme%z`rK1}szLjFEGr=K+Zz+2s(e0&Fcu1fdgN&Vlp?fPIu zLbu-0gV(-Q$YoWY(5oI>-1gB=Isd51-8<;oo3?2$g~*zq{)zZ+!mr7IWZ(!419rme1O# zc+dOVna@aHP^vrs4 z_oF{g8hK{*$mw4lexad=_J8r>&QBko9<;Upy`T0?oOCFDRQjr06-}q=-+u1lnHHTB1cKpj5%w3zn#eih_U&hy_AN>7gis6377pAqgooy@-Nc zR4j<)B38tL6-7l^!~@0yvT#B4~-{coKuU~HGS_@{t^AK?p0G| zzE{ev1(&-CGW~c_yU+dzX--^9l)UcF2=oY56I6fgJSj9yL+9fJA?u1OpE>h(FuQJB zc#LGCYTb>g9V(q}>MZ!NQ!77eT>kE_wudtX_fM7F*;m+XV|G{Y)S)&|{@{*I`Q96o zrW;h7?DMKYR#&RLlFw9ddk#9oyde-r0G$NjSy91X-%l)_6Y{WsZI63KF3WGtY5Z2{O1K^7PP5AQ zy1u;-$tq8oJeg9vlRfF~x~d&FE=1qD)AY@b|1xr{u=@M{@Wqbzf(t6_I~YmFsP=!h zN6U5AL!CJ#o*iQ*4pU+8Dbi*#OFFR@`bXpsWr-FXIT2Q=d7WFgWoAvY?uhD=%!3t~ zgD+R@K05u#q+Z5Hb>WsX1KugcnTy@GPc8A2^ z+Te!syTfaJO@%8O9Qj2FrQ9RS3&T?S4i(+Z_KtXBUe+mY-6?G+)xjz~Pxy8;7=7{N zgrdWzwTF*98n8O>NMwiNs+OGmigMFY)mh7C)a3Qw#4A4dI`o5qJaYSHmFP8En>E#P zU+J1#OVq;`bVUB$)}5I$|4Bh&_t}R==5;!zXSw?3icQaM7wOD-&~RM)e(j)zw{BLx zuY6(~@$kr(f%j5`^NM<2`*gx!hUj429(h@4V=C*Xli zt#+8j-3jk<3-dTNr?M_O9WI}1lHc<3^yv@%uAVGj$~m&eME~gaT_-EdJ6@|&TjNvX zKVnFA_?aVNiN+VWQwoA2^i&K*BiA0)F0we^X~ounjO&Kvdzpx=8rVu zoaYHHcK9Q%$-yrmXQ2l>V-1jdY?|RW#@%(&EivGQehl!w|ygl}g zTV9Ex%7({^fAGhfM&+>#0~)l|HAi*rXBl1VXx?}!Nd52|u}@4>6k&48u<`RY)8b=G z`lZWPsb`PvwWaWzZfe@ep}92)6Aw37N*fbeB40Qcu`lZVF|EdM;=2TojxR%!?2A2& z7Tx#hcWG^prHnM)Q#QMXyhu4?SzT52*Jq)g0EsylJh$lo`#Axe;Pv-j0$NOvQ$vSj395P=#%qv|yt0Bn4u}PpCU2T0$R;;_cF`%p6U+f_&=LF(&cjMT}>&>g2Rv6W* z0Czx$zwJc%7Yp@LQ)Adm`$hzunqe3BA~QfxUERaTV?ZbKq*=rCj5be3{T`mkL|wB} zOgYQ)LRPKL=iGSMbg}1!h9>`p;+(agsxxlqsTaOH-Y;$UX49Ie1%?fVSECZ%+!8zQ z`x2xldhBRu99CogcMfFFmqXinanYB_gQKmCK_)O)-iVCZP3ZWDMavn~&=|H<#s?J*rAgJCMAcN^UfXVdSR!R8V>tVTKMQyMcUT0KWaj%>l=o2FMNDj zC#T}O!O|3K>-57(;tKr}{L&s@Z0j8-%=i(P_<)GYznB!z^p>M(@!8ojwm>uQ(AKV7 z-YvB*8?#3LhXl`mMscKtYHFoW#j$9*y5{Z&YNf@mI;71x+|i@w0^M$21)Xn9SgEsq z!JSUN4UaYZHuE&@uHk598EI(;I!)?luwC50uEc5JwzvTUg8Prq8?C*s?;Gx>-g|3{ z`|$HWb{+TOO1ICMEnN;7>|#n?(|b$|=-&OO$&j7}D-wGp*11`_IX)V{a#YoXlGQ7$ zw7;CNwtqWu^1@W@iD#|6C#iT6<}-Uuv)KHHXxzQ?=3{&3GEDu?q?)X|eZ=fm)L&z| zFdphhJzF(2cV*772GgGgMl(u=gt)m5&K@?KRli~IApOQ3hVe&-k33m3aK!gu$KjK; zVvJ(?HH|tFd*1ltm5rkhOgkGh?fGZvfa!UX2V*wGtr^-c*2`n0tk-*q{Pre? zq$LmH=T1H5@rRB^&pG8GgA$TuJK}8ztV!&UeRcMwt3L#V#s{O5>=%hFzt#x9u6h}j zzfcev_j*QzskaKh(Q;hKfw>x?(LJoWBlm^{zdYwf?5e8d@lHPt8?1UV{1HFRxvG@q z(qn6{sholCQ_|%L9yOug-TP^lx&|Cy?Uwm)r{jf~#7f$v&en*q@0xgcPTR5QP|&ONv4JDLsm>HR1kBn$I{NWAz2rxqV~#&LRQ~pup(nZ-Se+FGfG9d--PZtyg=^m;S{MJpH3v!MpD_ZeISm zUXaz|tCst&rA{(<@95v9Nt3c45qB`BZlN;7h*>LyR zZKK2UDnfR2xRHH*%&mHHsoR0wS65!#a;0SUr4sEf@5}7fW!Dx)+m)Za)%Uu}38VA_88)k;zsIc}X=}XZ zzUxTWy&m#n1y<(nCF4w%Po1T{Lg(?!mF3I$OOyY6z0CIW{Use-<}bc9BtK;%Z}I$Tx@VFH9IT)B z;NFeYHDx{vymo~y>ebt7;cbad?vsk_-K>-A_k?x0zITVPIqy~coC71ePTeos*LC0i zOG9(s&+ENw%&XBmxk6W{|zl^xB)yl4M`Q`7B%n8hDObL@Mo3fiHk>vH~gXDu~c;W5wD7|h%x2P znSu|IcOO2gjTrxI3E}yN7om#Lo|gRe zuV-~yF#X+=Nzc|VA{H*X@zCng(ejlZ0dZr7TmMzZTmvGe`J={~+cr6WM1Mcqd)$@^_p~9$M{ddJeQ}uK-0YJ-ocgG+ zS#y|8D_8G!e(`xz_i2-c?6#g}+JDutC0jq=>KBIR>1f^aan4btI-R#k4@F$&cDOvEx**%tUX=Oq`>mE$ zZ^Jy3{O(!k>7E$ocC4e#@Er#mF7@lQc>BEj2m6i>ubMmZW_2pr?XLIbCx5Q4eeGymu*7FmukhEy#40iGoKKawj;^`i zoNN;6@Z2}bI(zf2l*`TM%p-awEbT0*3$iE;eC(O$?$cuP=|$$yyk(1}JuMn~c9?JT zrEv1FKL@=WsK3ECp1tf*)qydA2d}=Fer$s8vl}y=Jd+N#yzX;5WWpf9y+w|iSIk~M z7q3_`fB2iM%2i&?hvwJ$&9a(iYL&B6GiBfyVZF}6a~kvW+2Gj5rCD7vGDjB0v({Jlk8diOde%A5_~sAB*+_QS&d(V$`*|3SPYBwQvHsbR z_aEG%`gHtQl@$Cuf(vnU7JKhg&=$+y8WB>SEhb}YAV%^@VU4OqM^ntxW8t)7HMf2zc zFZP-NV>t$g?!DT0=gg7jOE0w@wl44UPB&z$D_?!$Ca%@Anaj2mo;L`Z6T9Tdg{yDxOz(e3^mywbt;X&H>Za~anAfe8U$r+* z_wb40t$~cBOXD}^{!G^IvEdnP|Fu{2^Aau$>zOn8UQF>QQO&5ew@$cdc9{3>P(l5= z?K&>A^$r;iu)8_g`I~UM(aZav&U=NY?REIDN-^@cA!4bjW5E6^y!D-;@QR+y8 zymf~!*Sov0bE|5>Y52m5L;e z1Xm`P5S|i3N(k{Kk*N;e?hdYF%#>3gMw*zI;Fp=TP>AsMFKx?f4^7Vie~!gRv6?h5XJG81i3Q4 zNZ2N4{;zUU8Sg)k8;9k@Ff3THe2GlX6|lnO!cfe^3grp}BqQb<`>*NG5($ZTzHBsC zhCP-HSFtsH)A7I7TO=m%JtLu11YsT#%MVrJrQ3*z7Zaf}f=9NDa=T(4i{E&nNoy>Zx>n!Uq1tO9W8E%P$Y?l1`ta`;Sz2%OGZed`NCh@%Vhk&rbh^& z1x3PWm|MV(c`g5ymn#XEV@9c>eND_TZ0qV*Rk#Hpmm`@9jIhyQ%n`4lcmM2vyD;UDa*w`3NRMb+)1upsq z*yOhP_ng6KopWLp2GfarNh*Ov6#aCo!K0xkO6S{0W|rpaVW~3Ud<)NdiYs z`&=28#d4S*^I;wwk4%SnxwG97_%81FVI1t+lRk%}0}rr*1PFpWB*P)^DMHzxh)_}} zFq9jL54C{GK%Jm!P(xf%@?ISJ+w(rkVf+GH%#-QQVE)r{d3Y=^2QZi&X0$zl6N#V8 z8_Ylv)7oeU@iTWU20Exj`vf#+pmkT09Tmht`#`o(iEjtce1MOo#8(Wo0^l1S&_?Tx zpVu11KogZ{-dqN%1lnDt^qAocBxW(%pEGQK&hUTSbB0>TkC1rD2}yz_y@&O& zBVRy31ir%SA`BC;Vc!3p$^o;3jr<(EIW8XVq>6sc@Fv3BQgZ+Wj+!xzL&(}FC75C- z5J`!tL;|`-hF}eq;UH$Xi7EDkfRGV%p(@%az{5tbe$5BcoQ%i>IfMk;0?u3^PXIcc zhp2>UGVtwXc!24^v2)`JVTq9d#T?m1aE0Lt9y^gRj2{m4{S;@bkD~FK`H^3TQMP#C2%4L zLgoo2#=kR4)#-0hP)0isH#;9!MJk%O&u}Ghzq!Nu3>?~+#^J^iO0-Z>G*1w&kUGi$ z4j&?3<`6Ff)4~&*5M#{PNLPge^$(SKghaxBgskXtI70ngggidJB+f=XflFo^<%aLe zPsBJ*$xb8?!9u%|Zb3x~PWFllcZ2>E5M1a#S-2a)|Oa_Q@~D#0j(hrIK&g7av3lt0Uy=7?jjjK46mKe4z7v@%0l*F z%8J6l(D3Af4Z}v4kb{s%5m6W14)%g@7qAl$8V7ZOC@M%BC~SQH9AAg`=7MQ#E0@V& z5k_-yttm^!RV2hC=>nvR4OiN{L2)=`Du7!DIJ~h8oj67E#S}+TC>~SYluAOyT9Kt` zEd~;{rAX&l!%()OwliF$kN{OgvdCaIpkTTODM38*f^a&V1SwfZnS>t-xocyZ9atzL ziKhs{BUI?VvbTeNfS#c%(TOaj9m-Up5+IutdRro;G)NDS3x{qZBz6L>R0?H0!Egnu zluDY78u7@qs$e2DU2#O-k3saS8(5Xa`|{m z8bH^B8hAR$7IGHSaT^qKi|!6rGAFVSXhB=w(LJ+X!Ri`w3lQ>S(5nMm2BRhf=AM)s)vhAg{5e8BU_1f`y>`IP zfzsBrn&y(ya)AKPXIdvsCEHB`n*yH%F%V9x3ZNT8#R)=xRM?8cN`M^kZc9;fe}w+} zl>%vHl5K%U36F=LOM#t)3Lbg%RtGqaQz=G^`TpowD-OF4ED5?yE>PB&FWdT1YESAt z5t)jMDn~%T9>ATdH(LN3Nrd{Va(-zmH-+9LRhbr!C1XgHiPo$7OZZeIN`bM5*9aF8 zy@sH@&^ufn8Ht!!5~JjZ!5f(wieA7AGc^Zr2v0xUAkgx*35u0bO!lBCoDT&hn;BXq z7SAcZkgyj?sf?jc>r_a+t3+C&>d)s9pj9P4A~(EiwoQ-`s3TbqAD&1{z72$_Q z*@@(M^rnKYm0~66LvEMprnln?1X5&0YZyFO=~E_3M^Y_M6&cD>rs6FV_zLkOM`(bG z3$8TYsuMien@EUga+VBMrn?AR=^A7nqUdNy%oXa$Mty)&ad=_}ZH`-lLy$)nD3M;N zey6Vl9fK9vZ)D`8;!41p`ZxLkpu1 zqzbzU`QZ>fqWm#VCNm9VP70nVmDc|75h*$e9VT@lOiN)nHI-2QuN0UwRw}Mw5s4`p za7<7RL%f%&4}FM1C@O>c;2x*?hVJ7-RJuIH7@MgWfjAd*fQkj92@keermA^+IkAJ2^**$-Y@#9MPcp$P-t&&c{tDhFxC$zpt8f1u?s|dxb z`cdavWV?SS*D6n34J22@(7nSX<-7?hI7-DuYRl!3liE`zL6dN+`3fV*CgM57hZ15u zRG^jc6dplw<4KO0K^v1{J5UW|_#=5%V&{p_GF)~K2RDq5!f7hC`!nPykV_+Q%iGGs z!k~g}XS9_5rd)+nt`mvy8RWix6b;U>-~9rxI|BBWu){Y2cn4A@u24G>FvLJO2yhSB zqKg5dz?O(a=urghPw}tj`Qn2NgtGa-2Q5-D3&P>R19CQ82t#>nMgWW?ACyCndIRq; zK;3``;!J>#X@pQR_-7%VifITPgfbk2{8m9;$&iK(%n(ng`#W!-4+gm@faAxEp)S1v z3;`wqxB~FdD!PfCCT=5Cbp|U==_XKrX-;{E{}MCk>UKcI*UJi!SO+ zKOftTd~&cS`OIJ+@@YZ*q~HKF5V62I9*l+{eKZsqpkZh@8i5SaNE92!BfHvOAh6>K zeTDe^&mF8C2;-rPEil>)_Y31u<^f&>B&7CMkf;F#!$(1IiG~%mjYR}&xGN#UBNvD9 zl1_4vA#!6wB}#_LiS$bXup&fb&EY2!$fHS$V&&%Xxj2YT0CLsA3-7N4IeB(RlgLb{ z41XcvO&ReEMPY$ZG$(;5ge!pMAc`iC#Up1m6(-klrFgPrtkCJx=8)-Gq;`st_-i}nB*!FMPW;mZZJ1) z6xq6mf5@9snG%tV+$*-bcGvFO-T#TxsYA@;Y7FKx)b^c3eqGylzMs(F zzpLulc1VdwBfd9aP{|m(MAK1wM;qV_=Q2<}u`U(YtM`tmdADuWVkuSyx z0Sc@TKwx7kGB-3f#BqlBwVuBgnbf(sP7|S0lkt}{F0KybcNf4-N#O64VhKg%B!rCo zl8an}!bDh0BVG)H84M5zz;d!hEH{9uwnz$c__6@Cuvw#_QkK#m*pov|#t7sH4TXP0 z#~7Q00TFyt+BYM8h&S+$;L3(cSw0bbsp5Mk{HC&l5(YCH0KdN$|0ZN6;EMt9PZ!}A zdd~qo0)Tvt4St^);GO{5fOo>SEZ~*^n&eqG*p`5^0Af)X;vq4TAQAorWo$2rB_c7R z=saaQ57Q}586r?9!po7EUYIEUP$Ym@DI%L0%Y>3^KE}y-DdGY~P;t1)Xgbb=KthTx zBFzEhi17DyQhbg%#td+KFj*W|LIk#c zfgDIn1=71$+Pn%RPhnZ)0WuCt1KDC|uvmhJ$P5F?+7a=Aznoz!7XLt8mtXnt`L8|j z{=)Jb4?ZIy;>qK%U)d0~r-tnyK4KBz?{&d0p^gQRoh!%1K5(cs&_#%Mw)j*Yf8mVV zlSQV?A{4b~<;Cqdd#H(JywOmTv915i;xV)$zr!C0jWHfKm<0`NY3YW4sEH1n8e5pT z*|O~29F=M2mVc*>9ZSiLGd2SPbQ1(|oF;|Re3oV=FfS<{3lgX37D{yUv2An;r|4tM zm2f3~Q%fbB+5a@G#KAN52QBmiu0>Lld&e_O~%@q1bV;-=L;bv`aBNHV*SJRF*Rf1Ul>Qo-Gk-M zc5}c#If(laMl_4WUrk(vb=t2sI=Co8A|wQDdt(==zbMXpZ0kvfFa2H{DS1>%U*Q3T z#u{!CkB7ksP%PwYZIsrJ-@h%EXTqGuumdrd(ty7!|F<>kYAl0^0nhf|Kf_x;tpCEt z`ET#S`Sp|f51(H-<|%y`|HY58{CuU4%75{rkY%--FXUJ<{%uUj$|?ILKIfnBSt#7@ z-{Q~y7GCwA$p7DTb~OCIcK<(=VU!nx*$-god-RX6Y_%4vHf@y{6u^o2mJ5gXM>L~f~^AIW@yg@74|o$@(=p-_jr|d zHPP<=cN}aU7~fl3@Q-BTy#jvYS_^C{lEKHnJ=vSyPvG@uE`HN?66`AgB4}u#-8+bT z-`<+-uHCh}cGvFOUAt>{?XKOmyLQ*^+FiSAckQm-wYzrL?%G|uYj^Fg-L<=R*Y4Wg z{|JZg20UWmU%5tSwP{*^z&p@*h7z6zxCV`{P{LO#;j5JJbR~SX623+W$M>P}9cX<2 z2H)vnsB|Esc0fe%{Dk>~Xue&wl)rT+<|^ZNImj^)L0D_mlE% zXg~kI$j_$zW58d&t!`Ui^laOUZ8QEo{iLlV<^>Jvb#LZ97MgW0@}Ak>`ET8=dDM)M zX_7*cavIsx{h}s62J;=jYk(I3bpVe59spDVlmT1-C;-?8umd0yU@gEZfaL&-0a5{y z0pH6Y(Qaw@IohVh>$72uQX~FmCbr5xzUXva(_@2B5?Q7D$79FRp z6xWlM#eQcxT_#P#_r|)?fa!y1`Zzkwro(o0*prs=rs*8o_ovgJPUkJ4>CuR~i-Ygv zd9**Dj!&WEQ|WYIE|G6N%%a0v>GJHL^UI;>$LaE2r{k;W_}=PN zTO^CAwtn}%rNxuu^WW1Q_WwP3!8RDX+ZeyR_fX+}4=d9LfIk5sfYux9@q7lT1Zc$d zhYFeixC2Bp+GMQg{)waX8afJa3*ZAD55PAXzzsm4d}%LR#ikX%(y~uS(jX02H(|jh|{>{9uE9cEWVRL5U?Oo+9E(7C>Z`p`0 zJzD-Uxy0$@n%(Te1yR1k#;1K2Kbm7(_;5u{^Pk^dCGGLD+gcy{wCux((W&zc?1wXZ z?fH_&e0uT1SNm5vm5rZYJ)V-duH1nryPU4OD=)jx)9sErM6XWrc?;#SCC+ZsZ0mB? zjGr*B;P4xcTh6nfNf(1AEX!IQ&=R!k-B#9FpPkDsxHo<*3s`n{XwZ`8`{8@meQ6wa zX4{pZhsi?Ml1=MbOI5ssFW{$U5V}@&t&DQttYao=Rc#mJe_yNvcoS+p($)*RrhK$M ze`^%c=gG8Q$8Ws1uIM}@)k)83-^HA_);7D2@dXDup0-%{%6iPCLfgb=x7VJz^W3`l z$B*mW)Gl#ld+V%6yUuv*cA;qPy8069)fYGuF1ITaprVAHOso{?dUYMqSXs}e6zRKx8C`3{QqL_Nx-8h(yd7X z33vtdDG2Hq0iy;|-92Yd&rE<20t6CCgdiv+kV`@mlfVQ786d&{vP8ti>n(zau)8iO z`oskv!2?*I0^*H|tjDJ!U^d{wDlq$3RrmBUJ%lLk`u3wkPfu0-|6hOoSDn*5dBee3 zYj5(;{Nu_mwoIInwda#teG~5P_{Q}Gfw|%PXM6AeLF_htLazZ_^B<+_7QE$}GidoH zbn1Q2$DzWc?$3Pv`Mfppp6!hT`zQX-!&96e^%aG?dhEUaBmT(XrrX?W=KpW=sC`e) zS+nYS{5ZfBbs;HNX2Rbla%= zrLB2$Q@RcxT2g#!?vnK#m(A?*MW6jEcJ1An@X4AFI-eiaoWIUr=dbhE`Rn|3{yKmC zf4w@;d9VxS4;|QCCrIXUkHhm~GS`MDnLHg}(@4!lU%`(~Kz=sk-sM@KMr*Q1ss663;J49kM%tZv4hA}^S-{kaG$<>?MM3Zrv3WzrvI~`W19LKc3MzZO**vO zf;MQ9?NT*;;8P2_@FF#x4g92NS`z$7pWgJTKArK31=%{NX6jd`@1{jQNaJ%WVKO+C11dlpF{s4fPjA~F3z)u5iiXg?_y)cx%Pr(Y$ zBA`!Sd4P)1)qtbakqLJlnn3HW0hkJas-kcs;d?FQOaa_Vppix2>OkK8Fbz_f6ob6Q z!HRO=TQQ`I;HIx_N2$cNj$Fk>7|wP#^i5i^?WiMlQ-%u1ups z=1XZ$RZRYhDSvtN?HCh5a^&q8T78_oOo`rW;W>)dPTq|XK=joBD2>WiUx!h`ihOMm zyW!yP=h@92sQWp#n{V)H{2u-WAH?Tv=GS90*)-CRq~07IiHM%a3U~qa_bR}zq%u(T z)G1*@LKnDMk0GzOCXoLVVJ975AoK%WCq*Eu8d;8KZsTB(MG?rfL|(;4mSGStt#Fq^ zUM0oIgwHZVw-}d~h!Vl(FGSzQll9s;sJDieHPSj!hZaP$^CZBV19*oh-fUw(n70ke zd2})QftCk>ZhtD<0DbFCU;1ZY26*WXydB5S&&kHZseUqMjg+RVdG@j0o2|nP>a*oYk_*l!MM3I`bVT)qo`i% zsh#B+-j<~Iiwuy}jVGd6)W&~|Z`&WdGVI9+ zY<}cDUPjnD8TM2Jc7X1kU|QI9GVEzh{7~Z*GO@K~XRtL(-XiE}@_=4ALXW*g%u0Lt zDmu=trdFRvJ=*Bc%wI02{&G;()wviSnDvLry8cj+=P%SBqUiqcZ2ge*hcCqN!yu*G zjrMKr@fQhj#2EfUXg0_++v_h+1721Pe_?&g%~S?0GTj0?(jhV+TJ0TM4s={_Gnxyy ze~URTxVc^90w%kRpExeah&e7GaY2GU=>@X;pP>5oR66DhXyQW=wbK&RKs8n`&p=7s zXHq~WbgL;{ON1^N3r?YZW6@8b3bWNMfAlQiNlX z?A+FHdN@UsPESt{r}xyRQ_}V6=yEN-fqo{tVy3eRSB+{flRYRyKEOyrG)=5%d5GE@Q5>C5g56{!w6?;tl|EDCr<#Ux1zxZ3j07t5K^X~+ zAnFG41QkTmne-WG$UJwFii#WYy10?>Z;l)PA>$4C3M%6bwE@aC{8eQ6FgbR5&>>_w z-lPqv2zAlEgb{``^HKZKnn4f>H3ZdN$)rGth@~ZxJ{~4=O^l?&A@WYWKm;K~6%){J zYbF`f#|`OF@LY{I;$gf2)%)`uy8Gm|9pMuIqu%l1lg;r^-CWK6>l|+&Hr}W~ zbi9FDFp+IQKpW#X0OAGssE2NUZr!?p>{obN(2ww(dr49Yb@2F2EwtPtr-h_o8{-X& zJl?R-J$2L~-zP2dy}~SRbkN0(j+!t-Zoe#7Ojq#9s>f>lS9}t0!b|a@2Xk>Modw<~ z&qR9x+(qm?@Bn{g_|ft2;=}kA{0`P)4a4`~(KrsP&}2U$n*M?Z3-Kaa!vLs3g|-3g z>AKWWRoJ`+f@iG3jQ>w^3&*6=nPD{lY8@*4yLcs}zQvO$=BTJTdIHXg(qVYZl34%| zSd>av&a|8}x_`wx@Dq3yuEJXAr8sfKLL4s5j-s0y;r)GR>sxp`U=!MTCbW%k`()nB zL*leiCUWl?!70<})2JJz?Mtx=ZKlW6Gw40n&?a*@B3l)%E5IpbqJ}H0CO?(#!rX|o z<(ETw-9kK5o7V&Kh~!_y>v7-dy+#F$BPKEfyAJo^?=Cp$tnmRw2M z*xcmeXbWd$TKhDX#qy1wR9EXjF8e{QJ1In#0blinjrb_Q90urb!Cu~k&s4g)sfQ=B zemTGFu2j1E6zwad?N8&+f!1cApx5zdC52;D+vz-=qDx8HhLR-4i9S9jb%diuM4+PE6Khdm&!Vz0qJV zPcNK>-^*W!h(yT7Qi@L;TSCrxq^5B#x7n>3*nyLX=^xw?s!sSHxGWCf>3X2Nu6O!Yr;9oOPTh z7@bBRE3L+L`A^+330E|wPPrA|XF@YWBjcqynp&-vLn}&6qjQEF8@|QOfKNP{KpvUe zIJJs$q55f$ijlF=>OIW;sT~kIfz>QyGIF z(9zNMt>76^jc%kVH0SSb?QtTeu;cuWsOYSl4tt>h)}!_($8PQ5cqE+ono(>3cf zG?A`Xr^)|I4|!HXyh(#nvXaf7W$*BtN;i}c zu2kzKIBeW7Y{Vqf(d`J8#7Lh>FPmr*V|TVup%Ab{(f0c4bR-yRuqZ#yF?l|2C`LXd_zadb+D? zMH8UjTKFrWd)PmX8zu+sK6Bf0D4?fP6^vNiRA_dRD`;M|EH!1%PfIn8@)7%-g0}vN z06UQG)fH1Z>2wFLE|OMxnylF&*6wlY|F<%>yQgnss%G5KTjr&P?v>VqG*!qPfMa{x zHT2xuG)?UaevJX!N>5lu+eMneCIgh;@(3j@tfaF=rA9@v(YV^0GIY3Sd$K@}-~N*c z`thUrIRpLpuy>nK3@+CGxN!_@b_T%+V}7Q<$X8oX3Y`8VfmsW>>U6H3TaXw*{E6+M z8*vm3MB^xt!Z;t%pQACxfVR)X7-eO4mcdx3b}wFAmPu`}{ihGKH4qx@KWWf6YHm#W z-%&B5uT?WLL!4y>e2!meQ)D z_GoO^Kq{A7YM=E62;4@zHPR#YtcC7JPZbf}>mlpgnA@t}qMzSRlzo%HsNQvUGhA$l zCu$T_&RFYpo+qCck3QjHrF}>>SX8|xs#ciL)>4!V{h`+9+v0_-`ROC*#7LZ~m!;J= z%6CSdv9H(md*(FC{B%-vRV4SIMS9=;ZD~}#C<;yauH|ZN=M;kqz z4Zl#I&umf|!Iab5%OZN5BztNJNTyWAWUW_gsi)jdGw?gnw13vht%y=Cq8PFHB(-SU zq^*VMP#b~Ov$>^IniJ*o{7kz9r&K<(t8!#+t@^gih!Lw58nI(7p};Jwt{vk=ZS6tR z7=LE&iBwDF-+~Y-tZs$3_SJ8reiGaI%_LS&c{Yy7Dk7R-@|a9Lw^E}ug|j+pQRe!O z<Gfia4J=9@Ia!YEW?Eyt@UL<0#A@2ZTXp?hdsbBXMQlym@-wfgd`$cN zBKnIe<~<^f@@gNUdVGM=t)$VQmc}-wyGpr7E26$?m32X^g875e*Re>f?UBYHvdVJ% z8T%#`KaFB&N1H0GAyCL*dnyFJ-=~= zOU8R8GUqJju(7!!HNQ^Yhv=`}ie%i05sCyy>7^NmQ)zskB9AB7n2GgP#7n2hwbj%9 ztX>`yPcvx0NQP2;uY$^8iaeHQ+F*S%DVd^)?W8pmB2=R7ig8`6YcZ3Ter?LEtt8G* zrX#Q_ot}UB7VFoG{^PG?cD|xBPR3W^-gqRw9Y2G2;4NG;_bRuOdxQILo)=ugJYk)% zTX=lhTO*+G#W7U+NQEW8Lm zLf742#&6<-IF7rN>&Erw`fww-dE7cKk-wO~g1??G;ivL@_)qz7_&6a+=qB`p*7X-k zgr&kG!a*U~*2C6dyVuraJ7J5rUu*Ae&#_n9@3zmiFS0*if6V^0eZT#ny|*L7G0Cym zvCOf`vBj~=alp~yIOaIvIO%A1CcE-n<6UL0Wv-R3-L8GEFI{o&iSD=E``n+oJBpWz zoahwCi?hUe;%~%9#b?DA#ckp)vA5?|&p1!1C*Yau+3eZvdDml+E|e~pu9F0*M4BYc zmcEjXNnz=T_qaE~cbV@RALsM=Hu=8w-R!@`KgM6~ulLXMKkVP=-{ybEf5d;%PbWmE zC&=a!?8d9`M!X%j;3V!M?kbMshH!UtN4X!kbY9{!_)I>V&*Ag<0=|$R%a7+L^5uLb zU&Gh)4g3r~$T#vK{yx5mU&gQIpW$ETck;XWzws9c3xq7&Fk6AG#x}>c0A%)r?Pc43 zTZ=8pzRUiheW0V#@wlVGxxo3B^RV-z)9Mmk1+Jj$Ue_O7KY~;^_dxeh_ZWA*dzyQJ z`!V-g_h$DF_a65b3AH^4X4m+u?no9qkuPWZyUF8==h zYX5IQPSk!f*t`2?<0kwZ-h{W{X8bA+arbde+%oPV?lJChZZ)@wdx?9Us|6W6$A7>l z3%!IiK@x@uGljXrqrzU{6XAQIt1Zhm()Oh7Ion&duWVO>UyK8bdDyD=i&;QY~<<|=m8fsefC`pzY~ZwGl?DfSV| z#ele2Tq-^+t`pabFNuE<4~Q3ddU!HDd7der<({>k7d$&W2R+|=I!RYZE-6d8O)8Sg zr8=;h`O-tudTAe6&kf%3-b(Kr?{e=7?^^Fx?_azJy{EmkzI%L6_}2Q?`=0l01@HRY z*UjI{FZe}&hCjz&TMNzNB_!k6P~FpvA;T093ogje7- z5I0`JyYYwkYkUe{&t-5~+-+PCd~Yqcg9~$=`TycMu&|H$&canfy5JDJLbgyK6bp^Q z8sU)ecksO{Y(9`-gY7}vQ(#GZZJ*c<*^b+?>?7@^_R02{_IdW@_TSt0+OGir8{-H% ze(Tun*ylLt=2mrZ>fGZDIafG;@7(4*F~72J7l9T`dj#XFFFKomF*3!(ApMALKqejreG5ckx7O!g-U=$0|tT0)Dnh53n>E9mNLsAL;?k6 zDr7-Q!GxheF-TBAKwO{@>HfaBT+846(;wgY^Zk48o^$rud!MYAt9q&&wOJigXMwB+ zI#G84vR3Hzx`uhy{M4kGA?7!zUAd`md)SF~v)ya2+B-J#;cW%rl}soZO;(ZiG?NaY z)9Ds^jy|NVF>h1YcD9$@WRF-oAZa?E$BXz;{;WtAT}7H0gn8N}$}vf8oc_+c&K~ES zbKOaFH707k`wuW}U9X`x#+%?3ddIv>zsrIm_fec}9LF zpAHESQxu*EuY^^htGcLcHB}X=wd#N>QRS+IZmnO@!}T1!NN)n$p3tq0Yph8(JIoPt z&GfR_c9flq4F7FEw~uZ0CybFVA}5iVWCGoY z-5Kr!FYwp+#r`4xD?dHxAB=$Vei_u3ugHmVnw%-;%Hy(1HU|2Kh1b+ARi*0aM!Fdg z-&z~pQTG5ga`jX_Lm$@VT0o1l%@i}!%r%S5a* zcH=#bNi*^y(PSB_e2)wk!^J{psq>M0-d*m$?N12u;6w_8O{mE!sLxeY=3!6^Gn5R5 z=qWShujFZYL*A9&$Xd|pp-}0a;rro7;q~x#SX0$g%~e}v)XQojX6d5(M%B_k(JyMH zJL_ILLl4t4^=e(D&uVJAplVml4{TT4*JjwkcDQ}pZm`?z2lgn=d)D5yUq_~^G%hY4 zczFt_e1UK>hb#cU9wPV2H>4>|r9ClWv*2p}MgK#aumtuT>&!-hQ|7Qe>^M--JnCyY z^S(TTX9FGkd0i+qfnS>j7G33Rbc&saPIoukEp&_Ahi)5>cq6?6&jDL@_s9AZpwk8Z zGJmDN7IRkSU-GZ{_x*-J^B^fm3A~_NFb*}F8~h%seG+_=B!%oFv!T)pqCJ_c3!+N1 z7Fx4WpV1HXGbYg_nN}vnv@^sA6e+?LokUMDM2r-Z zM7~%kHi=?!0-W%LXyzn2&pWBk2e8@>bmx+&^7-EiLCZa+5@ryk_K=8km7 zxZ~YiH`)7{*T);@9R=^ylkqZ76{!2F9&~uI-U5e~XyTG;MDGEwWH;Dtb`J{r2ydv3 z?WI0%#N&AaPvl9M_Y}BN0$t66qngi`@It;5M~?{@WJ2=Hi#g+kr`niGj9+g zAnwS9=W}**dXjB+kImZFp4z3`*fou8nkvQ~@mJEQ>6)$SS)0vv!EqZKEsIKh`?>GE z5ka%t-E;PjJ^MI!?z`Xnz2E!&e((4Dz2AEuIGetoxrYy}B%VaH{M+_zvnbDX$;=3)II7#DlM({?4424*oUjDqmwW#hb|sYbT^k zV<5%**_CnFB{Ex+tVv+{9wwyEpuqOv{gM_hCfd@F4E)lPa95GXKB3@kSwyjjq9F^d zEoyzIlAkvpAtZ~^nomf(?p|H(eVmX{)CVwcHTiEmz~BF$bT8t$P98O5Q25PI>$@Mw z*Ssj$)WA0oGN8)7_l^#x9;~@@k%C4T$}^+rhSoFiPOwF*?DYL7=o`MP%$T>nw4ziN zcMlXx*I}<(&%pa+Q7{y2B#Q2+4*S%4#=I*R1-X_sAQoyAoyO~#c=30!BvbEN=k|!5 zS$@mtZxdlDQfj72L&Sv{__bbixm?jznJz%n(aznN%Ntx$Y8u|7o{Z?)H0c-l$M|1H z+xLrwMxid<{FX5?rsEfu@{dHuOnlOa0C_-$zauT8A;Yn!rFO>c8T}U6j(sWWWGbb0 zJ=*6XZfy2c`yXLNwz@R&ee*Zpl~PkMOYF5X>%=Rf-RKfGFmACu%Oe)oM;g;f)RlfD zZP-9WCzJnk^Go|6sCnl~EZY&I(?BTb?+FF{DL^~M2r=OO&j5*xW%8SMjD4I;JGx7NIKAKHH7dYe;k{*&35N_13sEOR~I@yreW(PwU$`(Fn>m@bQ)BO}_QW7=!q6;FtECh}|DwSDG8q_9xXj{Uhh(_G9Xb}(bx(DrLK+B)?i(-B02 z;jxL^pi|83s;~?gg}kvkAXH&lr4ZvDJ#2{jyuKC8uWrKO=Nh-u+t)caOd^hqlLlO#^znQD&|nIgWA~&{$(-yyG%(WB+pZlzV{C=PkND zmW(NOjLnBI{PrDVzkX@~;p<>#uwVXZ)XPy4=4L^zk3SA+?4?y3Tyf5gmAs zZNWOFg-k=T`c42v>|p(g{p0Jy35T;77}7T8+IL5^X_Tu6{CaABL6fZi0R@+T*dftr%>8wgba8#uRTHg9>vQTfQAY+mx*4|WCz0cse&Uu= zbI}?r0;cS57WYExN4$Tbr4zESk%|dx;(jubT8p$xq`*JN1PyBXuyI(eERe3Jy3(3xFGAk1KE~Y#e=Jj@%P7(?&Jck6K=R8mZgx zEVSU&_)fhG%mc<>Qi;}Ak&l-0WX?Vk7>Rho7(Ww_%i%YCw ztdj2Z+?%4iTG%jQy?FGKr2JdYcPDONn}2HS8nILVwge^h-wYRsQ~!vNiY9+K{}M4f`{;@C(l7B^6t`XN6#nmp=*vlu~ztRQ@r+(7gnU zBRJAyPm8N-ftoI^OA&i49-XNYDjxt=6u@_dA5X_`u zf4nd;flm+%nOK>`XBzzw%CC{v?G+k#m$^kiJwtT+K@>?8ZzP|1V!|s_B#s}Y;~Y#Z zN!Gy2!1hvo^?42dw6X3!lJ+COST728=5Ap-Wn-zq?(yW5uoA{VT=1|bE-tHz>l9bj z0y$6IU=hnxT)@<6fcKh=$Lssn7HI(o(w#0<7ZGn7!Ok>O8PWm<{nCOg`M1`jxo`eZ zHxK#6qlCPR@=KJQpP_t;GLFK0iI68z3Q=lMno$N&zK*gNT_6_r-|lWP8`wzX<`Ky74ArD1X&Xq*90QsGH6;0Be>O#DO@ z9>zD|W_ z#)cnLIk~k9nUH>>gS9Ivb6&APy z`gN>y!7W{YQ|pOXmT9DsEscy6rBm^h=w=;;!^^XX?Rt!VP;_MNa$0ttJZCaVr{08Miq<4IxOC5?sPj!1_!;OL+ee@60cCKH6I#g{TeCNNW&&JWMP}0 zx0w&E(R#&1@vK+SS%+zMGAN#+smb2}>IIh%i5+@zo8Elrgm_di&;s#cb z@PIX-$AOV?3`D%hm3o)kgUz^y5qc(to{6w&i0+GHM`*q{ubxgi?r#2M7E)*XUjJHl zwEq^8f}dH?Vx#t}taLtVpJYAF3BX6&Z(#jR*b}AH8Vp@Q6L;RQ;;V>Y;Y3H|c2n?R z{)l<^CJkK)LPOoK-v97=3ESsn#F=hEg)I|`z72iZC!@$x6S0fYG~L0_={%!bki+y3 zhnXWZAX_hv(c}i3GWZ#Bu*PH!X--70OF6xG^BzvGdZ0;GUMTEhx4Jh)9chTu0#R~{ zGW58jj!Zv|#7;Ca>T;#d0}iE?2Xpn@^$54Q^$%F|(BV zEPaWqN-~Ngu`IENfmvYxFd$R37-;TclvWvSH95QiO6#jn-!AmlTj`!bx9~sG4r=Ie z#cjPPpH>|8Ag`00#+i&$6-XU9%E1a!h%2ZB(go3xf)P*Qz$B$MQD!GJ0O6R!>mjIC zx*&C=C>|n?W0ex07ZN9+?cln!i|9N6%O zQO$%TL0n!A1{-4uLx}Z#be$PRnogQ-auWz!8;oAjX>@!0PkNM7nE8-vHO^B-`KNlH z7uS>_sLrX3hn46y=O7%8F&`>47Rs!#esXt6D>Lt$tCh1{FPza^NaGe_Tk-1Y!HxRr zwz7VS&oCcy8pX5Gc9Rm^PN~N-09|E$nR5tb&MT~On%{D2qD-ln^IjT!H@f^i>cYr^ zg`TVCH?}e_o8MRlPUnjMKr`S|ICjWqrHk|sm5W2dMjCdCop9Kw{Sp+jlZtaP|EPKQ z5PB*r0c~zJ(nFtM|DdwDkI*PJS_$kED3i@-4@1)@=xIeLKQm(guuy*cNGShUO6{Xd zW1mn+cT;89C;ErYyKCt&G9hX|;7zQx_S2jx{0lOM?7vliPLueS+RU* z`vcwj{1YJt%PC6`rPHh_f$Gbz_i@RDtz=osO`lAwP^Q(LDVATS>m(M@UBDFSd^RPl zKW&)#bdPJRE$u#TS8 zd#+*;)|9N5ikI(VH3P1~U95J%RkW*6H&DD%)Ct>IAyh3mYoTK`a=GZf%OE5=5c|l<;9vH%g(d7MrNz;qYR&Cw^Xijjl|&MO?>- zzr!|jQ(^agm0ja5XW_tVO377eV{?sBdiSgjMCCBkYw z4A|)vR>RBMo#sRDN4re69!tnFL~kdM(~oFqRu+54i}WH*Y%fDKC;FmEJUiVV3Z1}> z44VWEjo0#dCmydCkgeF=^W=;u4qGMf^PA)demBOwW8`R%<=VA@u@3j$YUnoh-Fk7m zuJ72Tofr9(zFS4z34OP|)~mYH_vj@9qM%1yK||`U3YrS7Mv!xu4oCBjnA5HvQ5( zgcsdI*r8XWJgX4b4b)jw!#Godoy>>)ha+VuJpMR9rtN1z-?a z&7V9-h569`6g&F%=aPh1Oe@&;MeRnvUa;@4iIz_a_8$oLH~qldL(i6BcXp&Oa9TV#{9Fg&m_nurP{JAcZ!@@c*GjE|6)A7e2@BJ zC`FDe<~KqXH(~=#pziEAJ(EDCp=Ipb6!ra~aXgCm+zBt`3<9J1jbcVugiY@%F~4zK ze8DK#uYe+>d%+@Zm@vO_%_`p$R@UTS;4`B3D<0M*r*zj@kH=G`p4mrm&hO5SJt&sa zllY|WMCH`21hOsr72UBpJy)$KZ3v6@E8RcbuFpT-v0o0EawcPERLhi~3aoi6yp&qN zTH-~f+t$$&;Dyj9wwW`2<^dvO@=UV6n)k&SMg~D&5Iqu`%C18Pd68W07q} z5;nO;t7+#*EN93xi{3E_j$FY}IMinV?I!_o3yu=O;T&6?h$Cm1p}APKlEJ9{ zeCEu@k4&BaX3xL(JI4RDyNyOoX0U%=ip!q*Hp!|wsmk$3@P(binlduI2XsWL0?~O>Hf{#xh@E3n6c7*KYEba6!(C z5@?JwLvARu**id$kTm_*widUvg*ftK;8#sYUfJbr2sE{DBQL1Aq!t_5^I)490P)^?ai8(rz*79W*v6i|g51>oWu!*tOIaYB=_@!iF|!w2ON zmU2kVY6ge%sP1K23f@gE@QMNQPz<>_&6`MoZwqY+ z23i(zo!tE*iblR)!vUagCY)XvW#0!*A195Qh*OsPd>6Lpa%e(DTx27D?W78CrPv87 z&@RQV1Ml?tss6Lu$~;=~isl!FcwL~<(c@32-aE#hb}b#@LViK>jR4sUYCdEc94H5{ z*U$_4G8reE_|HK+q519b!Fx5=9-3R({7|P$W(TeA%?(IqA9i1-1f5L3P2#f)@+=3tlf6 zEckK3v4S%N=L)D}Q|I+$H)XeGZ_obA?C)g%DEou#vFvNv4=hew{LrB=7K!}_lEQ>$csIwvouKIh+ZZs#mt$}SBq{l?O7F5S2E=S$};Yh3oD zWxrhZliYUeDW?NB-9yP5c{4k}0`uliwTU zYJJw+rL`U2rbVHy5c&W1(EpA3&XjIacIuS>IZ?iMn9pBNL@uc6O-Bsp=>H9!zVp4p zbiNFE`wq2VPm<2RkM`!NZzI~JNrddXtDpW)%<8H6v?iQ*((n3~@+8_%PJI*6l%d@< z)vr5__M=ndHCeNfm*VANxj*TAHtco+?+?lSbIxbYLH??K8`BZv`Ej(*fzW&z|B>@2 zQl|bnM&>7#kb_hFp3^@_$gl2vw=tZjgsGK0BDa&zeI4!fYQF~UD`K}`oAp1kw;Cj7N%G`(>&XoHj)1TP)h>@6aWGM z2mtOWa58(^Q{odF005jv000XB003ieaCvENXD)Pjbe&vVbKA(3eje8HKXmEEQWeb^ zdp4IDrKXCKD2s_qDI{e_Zwr!55itmG(SS7k_xqhoHyXS+*|;*XMFOW!pFWrGTv|W; zVDRVD_{n@4j)#-My?K1Px*uH|{5Kp=huzK(`~?1dv879k+G7B5wzSqvi&gcOl-Ar9b-qk0km#9FzUbpk`tyfh%*<}K znKh4Dvamfft<%bypMU&41cYrLAJ3!6J@mc^pp*u3f) zykHjVB!5Zs7n4>*KQAhiWLfcMmwnpw4IuiTnnz!sPfY_aMabF~Bac~vG3OjcNo&&}qx zOfvIW&#`v5bFbS0(`jDWd?|~))Jd7(XUmJ3@2y4ObvvHz_wVt{hFEnqo}*>Mj<5zj z%zK4&z@;;_gP!zB7%8OO=FWKLlI=FbDbVsPBR&h;R+w(5(U^BG5@XIAO7fj4@KR~E zW${ub8}qg~?A=2MMmur^UwVd#BX1wZBCH&4CE#yKcve{63wR zNx3s8HkanEvdOZ4Va#(;n?;iIes@OM;R8^n9S*W6`l3Hy*ETnAknh$e-$*7bT+dC9 zz9OzlyRv0TTY?z$AbX^t-OjcI57_1dRyfX`J5a;;Y?F%AquW_0uX5Cpo~^5JgT@#TOv35I0Pd1ikk9g8U*c8ij zMY^o=xW!lY_k=un&p&gNpsN>alX%HPU~5Ze*zMrQD&=jnA2BNnO1xAJ*YJ|6Dnd_E z(8?hp@->YpSh{RhhV-^CX2&n@={DZkvBC9%)fTlcFu|8T*9OCo7o`q0sC=ltUZ#0b+@ zjfq0n+d748Nm7o#%D; z9U@HDgH4J4vweE~SM4Jo0Lfb)t83C@SK&Pu&O|(IUVuPJL2Acq@($av2q!XH9fTm> zK*~NEpKmNJV>2g_Vw*UJuLwoFfs(oq7i$wZ*24okZ(dJWmwf1_B@3KPnkQKgi|DQ> z20<7A02_|BWwERm!U%^LI%TLTQGnCVNCoIHB4Y3c60hFjiEUkR0P>o1OHX9G9y5Vl4ykx!y@qUb4%Y>6pW#RP?{>q&PTl zRwEYtCRq~dF^kM5$|I!U_ap{64{&QKTB=I+PGJd!0DMg156>lx(Yvuq} zV3*=gi7FWmcF}9Rnks&`Bbv7m)UYZDAA<6KdC>elSdFh|!^!8V8H{ht^~3mPG#fpP zr{?xyf*&8BN8?XDb2FOGCZnq-`idX?{BSe69bFIT1KGk)eMVZxkdGa?8g&R!B1;djj{}ju zi2v+SI6MRFwvZoO6yuw)0}dO}HfRIv5uu@HyqkF<7S2n1ayT4|SZHj@+m5~>B19O> zrmr|UC>xUz_M1It$=k1L=P7f8-D6>SSY@Z$-6CzaMac@mumk&17D5I>n;_>OYmf8Z zI7ILzITR8>AyG1ewbscC$?g0OE)%|C1v&S^8?+>Y{zX<3=%+P`np7V+SijB%#M1eg zvv~b8LaRga@@gsU`jX`m;DOD?nKML|Gd7$7eE+LJi9)4IIP8?2v^L7{ld)=ptVK;! zFD}LVGK#A!m$Dl`m<4&SGYR?86%?h;4^BWGwns&F*;9nak)^NXBt z`ihsNGv)xn{xz*QW|{+)>vsIw=Wvg9OGqu}lm?EB*qd9xdiH17>JgqVAk?n{hD=bm zvL=*H#2l^T!&2Divami(eCP|{Np}BE=IgPY5_;!an1>EJ2IYjd)12*PgAh>zx4{+> z0_-wM7f3+cbWs}+3U9*r22kyB+N{8gC8LFIV|~zl0r*>)Hl|OzQ{(Lje`BJA_!xWizb0sB(;G8izgBi-Y+dFUsElVr~00i`2j1esw9R$ zIFcGfq^71hGC6#r^M(MegU2Xg2bLs3BCrIdU)v7o|NnNXC1_wf>d z6NdARGD{ICDJ*}96Duj~dJjz<V`QMY)fHczDEb{@5=o!wM3-g-Vw>@VmWEwnpKKy-Q*@^v1F}M}hD`&Hn zFKYUO0Cz%zq9Moqpb>HeQgg^#a_@;}Yk8%xp+g+;zjazlSw~3jQR`nY;Pr&cnkEMEy#MTt#LP+oYT@VIwx#9+k+rGTv;ppx767z=pNw zq_~2TxV^=xyj@q}g;p@&gg@CtlELfjjW|yguOm54>RJH@A!#q-u)~c3s)jTn;?qif z%R445WCkfnrMaoENTMi6!Q*G79=}uhT{Qq{08Y5ng*+&&Igm(o1s`w%D?2OgOHwWo zCRh#dl6j**?(1$dyxNO;6T~f-`>WtbRahLU2tq~WMMk!+(o(dqq7|APmefcARA7Fk zrhw-z4GwF~2}iRQCq~%X@3xdA+85=d;zSjZ?5N12%CB zskD(cp?) z>WY03p|>Luy4#t06a2tjd^8NWPT?*12dc)YjY)+BVu+#EV1cl`C0GM(4yQt&WtL-M zDfMd(lp9zIz}9<;_X+pi7;828OHciPH{_^5@g3l(k*K{TK59M11;`bfq)cHBwJ$d{ zHAo6cg4`}4$6kcq4tJLX17o1xGp|XO3PDINgWs;Wwx@gB*`(wqQInA{mSQil>nV;` zu$5CgO^V&QHWe8`X^YLL78D+B=>fV*FIL_j2WmM1A+ay`D30%+QR_4qC2EZR_m1N9 zDd=YYqoY`yQnWNDIf(a&5?=I7sNxC=~g=2OAdQJz!86` zR^S*QQ8_-#k{Dk!o5Du#pa8EVdIExgOIyoFZ$13&9c(E!9&R&INYPRscNDot8Olci z2FLH6Q~octNF@z9%{g=FcIdb+8nf6W|74u7fp#;RJ(o=q)8C-dHWLWr$iZLeCV{r# zS0wLsJ68ecap{U2a$5$JWI?ob&H#tG4r>7o3)oN8V7Z*#79k^n)d8xA79czp*#otS zv;xOk4;CS|#e$dDi4jKBiT1`>Ew(a|!Z_H!W(ecMXEUdJ6b=;8V{}HZObuVuoE^9b z;zoMX@}ATfAxvGrtRt_VY7<|psGBV^u4wQjqOwcyOXDIV~iKEgEAR;8*H^ka)1FdTYg^jMr^;Pm?JSE;8Z z3dwD%q^1y2X{@6VlhT2<`maYA>vn=+dN~vD=6+Ogx>5;af%w)xA2S7y0Oz8LW9R_- znToV*hJ*rZY)O1tlo_#;_ADTuq&6G=x2iL7Hd&e={Zw%H2RTBYAI2Fgspq!ZOW|Bf zRZrh77cJ6h5ca}B1_Y#8;i;GULbU>^4Y&KsS}i2!e&T?r#8kQcev8ZqQP!OJq^^`U z;X0kCl{5yjZ%Q=m-STc>w)ux4#+>sK<%B39ilR7PV5o->#`JE)5L>-I!b*3WmS%SsV8v@W`; zOX-!hW@0pjYbyBfOvqQ&>8eX$9fvs9++OQTp}w&zouUyuh4dKzzo7GKEK++}k)M{W z93*sq>YLF@!avt%V6&kYK@p;?%s=bp3zrE6%tRTkw7_YeX+;6a`lnWUu)bqK6(Dmi z-S17Rvys|AhyB*pUGx~lc$H)T&EjO0AT2uADIMCG@CBU6$OTEaUpeyO7e1KNm?EsE z(gY!_v1c+p>Gp|nb10$WDy{Dh&7h&hp>nA|dQaiO!BH|?_ey%g6m=NkaEK}iha5(HiaHb2C!?;W zEOy8)cJF!8Au{#|OZa8TB??Y1cvz?i?LBSlEDq0eZXBx*V4R{fwd30i^_y zRy*xN0S{2!Tpqn_FTYMS8KNylJo+}HANQfHzm!VTPm(rydh4(ySLlTjF5V_fAnzhD zU@Ma&-WIl8|0l5-^O?`n7BoN}28X(x7n(VNp^GQdg+fOEMpFeP_d#he@qj5R9DC(w zf2P?C4^yhEFLJ4@JNBnMcC&~wKAK3Bw=T6zTW>?>nMb~UTo$<;!xEus$@8&18D`v? zwTFgki$Dijg;b`*F~xba<*qhvC{G+A2CY{Q7?g~vEDSx zoI@7&RqbJJ4`Z3cT~{3`YjXDS=e}?4?N>d1)Ct}_PnNo9vV;2-e#n*6s*;?Urnsaw zjV;V~O;;_>_r-lju;pOpiQFY;Zmz}2VfrB6K3OiMhC%v(gMYE~{C3SP{njp{xg3N& z=>(G670x!h>B)R)QnlZ0-FT1!QO-bNQxK6x7~)N8r%Tu+#mrp#Vv9uLZ{((t8Wb>T zYRfor_7Rt`e5k0eUTOn$UMzPfs@A{sd0OY>m_3QhPllBCHRU$496ilxzsh|R$72ON zdVhS}UVs9@UNSHIjV(@Te=!j@CRS3wfRr3R_;=g1&5wf`|`|rT{e>pRr%3!LrhmIO{c8Ajfq-KhhNHqY`Z!gomj%-=p+w6{R0# zXszWBx*0CKb<*nVfA04-N`+MSwtmlaMQv3?U*kMPujp zuMS{u!Bh5o$yZg1jU}6NT-vow3DbocZoQ5|L5{`G1rZn`)PLDHGx0!cbZz)gp^dVDMIc~mz`wdVhNw45hlFzA|58&#do~M59aG& zG8v3#&#DO@`sQkQJ$RZ9&FpSy9w!fZ!Xxyg{8 zXi=kK--rSpd*Gjk|CkNOGxIo{d>+kaAb0g_29J-RKDfFcn)|_52zB_6>*3?fe7zfv zyPXGG;Oht+O=kmoV>C8jC!^VD{D~>jNbzL!>27B39`0|36P`Q%5zF(7=5a8YjfT^1 z2b_Ev-L&_0Hkg9*GxK#cyL)(=1^#J&gYmQZ+h}~#Gs6*68vf&PGMqvL;Avt;pTYDH z-;T!D_fI!G)O-aJ&39#PMu!HM$>RQ5u839nHpA zgomXE!u<8q{Q&!Tnmj&Chg1^y!R+bboKg!)tInm^_>5 zaPnnzO`_;_Cd0?U2!}v3-;)WEc^G?t^RZ8d2z?oTA!T?P-_w>S!@oaaQ%6*Ss0=8tW;(MCN3UdE2CB4Hkvw>lz@%Pn`9-j=ykQv+7;QIP$ z0z0E8=ne2QeS+nU#(Xl}4(*wZdo;Q6*2Tg$w}a9B)8s(gu=E4ONHkgN!l?vxn_l!- z70l=si(TL88Jd<6Kbt$8$JG#z4Q{@S$Q8*#AOk)}DwhW(p~6&m$MzP{SGWfLzOAW?OLj!~;V- zfyjHUrOm+?Jt_D@QelMiFC7xqtu z{8-PMDUa45%W2YnbR+7gHWIz0ycoLwJ>V<^_J0RL??3jC-d4dxU zve$BQd89S83!AcG0PIr^bp9%df!Fvy{?gksaucOTA9WLn&uv4HRuuTD??-$_V8<$EpHm@NzyK(Q|lcVRn+|{YHnZvJ0 z2v=rw$2?d__qF*UvYldw7tj4K2?zt$`u@h27e;QpLunip1Ttx|^1ePLp5o2VyZX!TOJG2MXXwZ;3jq#4`rAT|)KLEqP)h>@ z6aWGM2mo_;MmR8fO~b_q008C{000UA0044jVPtJ(E_8Twl~`R<+ej9DUaI&HH}evx zv1J=3nN3o)wGJ5K9Rid;$WW;~w568aK~ig562^I$|2zL;&+V3E*%-naN@Yvk_p8r6 z_g?Mq5k8ZJ$_W30Zj{Lj5z$$s({x3rM%_y~xH&sLq);3BqLM%_GrF8m8i^dYVsGDy zIMM0KsQDtNgOfu#>UNLYxcrm;kO}=Ea!m*RLgoHKS>T#-$x}rXgD7N+%ykDm*uIFHMHubW~|6MYc#AC+0xp zY`-C$^3FpTy&^G z)W5u?Fa6P|e>u7RfaUo@fzqCQ>sN0Z^n^rAna>*?tFYCQ0W#*$5wPQ){@4()*g{%0K2#b8{i<}Axr z+5X-?kot5dO(LTNNQ`Yu{ zDv}wz$~afWOv4710Am743?S#)tXPepNc(_*jlS0aNJ7)hn&%Dv9B{tj>zCoB{RJ_l ztq4n;>O>}a=ESp4&fxczur@&J7V|@Q%-f6C$8}JuJgg4SYOEvMTvnQcm0xW+G2f{D zFZx<)`_|C!4q^#PY1#k_u+o6Di(JP@Fa#o6F&iN^xr*fu1MP5?#Att^ zGlctVAC`P8t;$zm)+Zcl1auq7Tajg!sht0r+2cF$6n_kZxuC!Uq0QT3ClBleU$C z>9I(-V=d#H0P-T4OPUD)ACKL3CvvAvJIV8z&{aVhJfso25%eTt#T^39h_U8yaf%F8 zag44L$O2o5klQwP7tNVqc#dQ7k1o$=7 zFHPIhY@3b1Dd%>`v5$?G9a0v;1RJ#ZX*ix-jc%*`-M8)Tk(&wWrY4b|$9KH$QTHv4 zT>h->tv>BG{XpYaCvA};|6>a|o9mgyVdnZ3X+mU3sq?os{-NQ`hR#h*N57Ygj+^}? z^}KG6HJ_;mJ4=Lei5Y3m4b)Cuy|-&I!$jo@oK)-Kzmu!$+tKj+(`3ARc1`@K2;fVS zt1$Bx+zq2|Ozm8Wae+Sato65}hkE98g4T2EGxNehVIi-5YC-Tr1M{v$=w zj&zZh10$v%CRjw}vp_r04aGM;!#5Yw1a-oW=jCkA zNI=c@mB(dN?!~&U9AGuMs0@v&Zh`WN_Ft-u8YiVMYRZYvBErAO> zxFjpofHEOBx7WJMIJYWc4gjnkk&mVEId@RTfL=#oEmz$kJ>oLz-rsD$)2XB}cB2&- zqL?vktBF0-5vDL!!iCW&JDO$h*Dm!u+ZAaXuSy>IPBFJ(WjTiHsKk&X*=_fhse0a^ zFFz70c2(InI!5PZ*JyRX$vU!CGxR8E4RMOwQ@|xC{G1~~=x`FfL{*x{eDvk3o^k~R z+AsLN4IwS<3zAt=9wLkpQ`y#+-~K?WYh(UfVD=2WYUz=Ont-@tSq7%}>v2AFP9q@b zN>l>W$3Q%@CG0Q!g*&!J;2O#|L&!U3vT6Yzho{l;=9fMUvC>#K zCjf7y)iqk0t?_Oq;yBCptWZ(zSZOB{og>$<_y)+T$D$_j0Bwr1jNfy1eq5;8X%ubn z4~s@8l6$P;y@lWL5zQ1jD89|3NvRibWC1pXZdAq%@5!&f?q;QJv-bD?2T)4`1QY-Q z00;nicSbmexCa562><{K761SX0001TWnpA(Woj;Tcyy&$-ER}w6@M;L{)e+qBwA-| zCrh`0RP7|h!4RC(aY87i>Uex@4~%Er`LHn$)%uRKKoTcFpj1`WR%q4kvMN=DRQ)4iDp6HcYF~CGs;#zwx~li7A5T5!&Wt@y97x*`O_)39{?0kS^D%Soz&^mATv@XL ze-)V5EXP%JNa<#^+JGaLR%0+YpE@!GMbmaB4yB~C)p)H^S1cB<6$@vjvQyCq_6>AxuUclwQYz#_(P9j2v*?icVQ82xsEPp= zD`>W3X?fRSpgEuzg*ZA?F$-F;;UnRyYZRCTPMLwjtcne0QQS;s=3tT;%tB^n+`O)- zFr}%?uo)<*oL1~ID?mO#qCF|HV>Yk@QYJzxj%FH%fob^Mf*P}IyoZrcO8^-I)AC^k z6^HD%z^u~FAvC%HNPBm))SrW{s|C;u0bVw%=oC^*Zq_wjhdcwF|xBRL5z+jVlZaf4oRMn0TLt0WO6t;ns^;xZdUH5 z_6t*w3RbsGP-;kql1D8?%d8ygDX4nAE|m;dGObda$k18QiI=K+r-TOfc{Q))O?#KU zH$BID!yEUOLj724lHITe_I(8#0C>lmr#;MDRivHmSuy}mxwv$vq@{tf*Ih@xkrhJ`CXU;Yb!hkwq0@6CHDgq!p--h#&vXx_Vs zSF*#!>tY11t{Hod?PB!@ABvT zA-~0+tv+vEY|1M?;hRm@lf67@DxyTGS@W^HZ=&JCWZqu+#_A*fKJNPk{|FIoHOE4Y ztDh}Rp~f9S;ca36G4!D5jd{z6Rq__mmaJztPb1bR{9YFYy_O~xCID9-@GZJMna=nt z?UmBaD(UX=qTRC52gEoOLJUI~V^kd#y~m$*BQ+Rk8iJ_WbY?auPfhiT1s0&>=@9u0 z41XQ(BIsu#>gPq6-(1S9-C6lDdK#K@d*$7=JA9qi$rwzHxA_Ko^nl-@80^tFh|6=i z>Ajh_cx=U3`QpZJ;WVi}gCt%}Uv0m{_&&M1jmbTmJbQG444%&HZm!T5@Yz>4TD{?Y z2cP7<3~%$_@Lxvb*!x2$YsYU^qYj06xViYpAILWx+}_^Jfrwq9uuo%W=ao;dJ>9A0 zl~-PYYpqLvp#KCl6EuNN?6hgE_U-{O`uQ7+$`FohfAMh`!76d}D zGqfKDgSIvVeCx(>e!o*zA=t(>7fWGVX<~bblyqqD(sHCVY<3fL?M~}&*WN;79wXAP z_@k!0OFrEG{@vw&@(mvir9bvt3GLzS#mek0oo>i zgr2;&c#r=K5kErO*P|_BC)wfG9e%ha;tMmt*P-hkj7SN{jssR-&_7VsgV1Fv3#vzo zE8p_rmOt!E&N|X=Fa5oBk>5slp89=@KS9JN9UbiukFS%qz@b1V%Dwn6YI*BT z88?26>tC)sUAq&&Z3tuE$7fIY+n1iNofmB-SjAYp)4xIYNzz?v-H)w6dD4_ab_2PZ z$h*r(!aa^!;YipnG4981{2NpFepAN9Na3{>Fv7P*ia++tu7|=8`KJF0@-+mug?iep zhl0?kPuk5tH&f)f$fvaD(9_n#;BJkYYx8U*|JVAxBKPpB>3KEvyjOx2PX)Xke=qNu z?8J%b`H8*0X0|EVL${8m`hU}>Q>p*2QEx^X^%lR+@BI&ry4!4D?8R=)`ZNaMPxzIP z@fJP#%uY>|Z_A%GW$}U4{YZ(lS1QAKB_RXiWdNaAi(J`rBw&iuPas$Ljc%yB);`;)&Prce~S&53!I9Ua-;|J)5=m0uPY=Flrh7CAfF!!OdinZ#7hV*U_;M3;bzUgg_#@wbSWaUm zjM0pRlh;ZUo5|<=85oXMw52liMD~*~Nd_aI{)(zfZpD>s7XMz}wDHeSw-9mU@u%ew z4=0|pOm)Jiy(4|{;K742@oEs)q_~cV>!`TC7O_N=-FN%nNT0Q`2^P>g09x>>U_ zklw|=l-7TW=$nO+JnM-!xkseH5x=jV#b#@bChWm*Grv*Z8fv)8@}7bvH`#t99~~;v z3s#h$n7S#6DBZxC8E#&Sx~_8|I605xKr%VSP?7%(nrAQUJ*{Y9u36>rBlL;^r>w6Dk&c-mR8MfsNdlxb!!_< zpWbf0BngEa-l6R0S^8U15n0mG(3RCFZ#vA+Ig z?TvI4f$bb@W8ycl1`$NdsGM9VLRAMjL*2hEMy*O3#YtnsTu>WimlZW!DU4s`NQhMK z7J4gd^oQr&VArn7jrlE+_K3$lC=2o2#QIL<W-M;!YKFRge#o`sTheXF)_MTj(~N;<~&os=Ypz>iS5m z`}|ewjYJT@G-sd$jD!jRuuA=V3HK#nVrFb<`_B^Y5Ld%tz4cj#`2_*9XJyr*2-o8W z53g9=VRcFKfx3PDx+4Jvay(<61RVnR+0FJV9zfzc_JCzQ%{l=~G8y3c2<7{pjd(>j z9g;vmzDKiV*-3%eV*e%S`&_?0@abdryc}ZwbTyN3df@E2$XdGHG11w?bD@^&dCi)N zU>9G(F&;dyJHx-P4#!`xn==1w=;;K;KvzKX*spN#sMx7wuIrlD3b{|Z8cwK!z=XH= zv_5u!z6omA90;UDc6TPZJKpwSPI$SgjiwsoL)3WltkvU$pl#4_%HOL&( z5k59DA@aP%$86Rs%!T1ZK&BcuQr9mM%C>dj){>b7r z>3a6cB=&$~jBDwOi&K}{iGmGG31f&}dXl4A+;^4efhbR`Fw>z>_!K~mdntrFrzhUlHap8L1;9`P|X*r5zz%0dkP!Z=TU0XA` zxwzlgWwC3NY)I$`rAI%UyU_MY``F)kf4M7{RBj79i4``wV^t?JLbO7%;na}ayHo+6 zQ1bSjz`gKRm1<#2A%Pp7qxW|Njv^iII;&4HQJSk)^};lAfQg8RAy7pXzmFk`d2bATA27pr_@3{20wMyI9FCdo4Q$&zJDbw6O9zOS>^fh$M0jD~; zz6H9d&WAd_jgofgsN8RnkiAM+oBnB852f>1YrYQa>;_-PPRKs zhbiSoZ1%*Tp5a5_2lshN3+x;-8?@rSYgb;ui8F%NNq~gtK^&xUjct9uBvAHfS*xVm z;g2MY%`)g`Xz#_y5{}$rJ6A;z>7b1VMdcGNSS3yMN0BDPe_Df8q$<8k!2`Fs^mALp`H%pB1SPp9}NYjQ1N18ZQ9}Z~mv&XZdrg|Nvgfy#a z6eT_}QIObI>03Tc?zK|(a;p$ozr6V-u}`nyN{3T?_VFZV^< z7YSbZ4s0|648xfJV!Ce?lniju!A-c_%WHY)ZNvCp-A@Grm3m|As}_Kqg$`*#KWE?NW?}{mVLaHBRLWjTLe=Y3gNVyQcuYr^Yd#RzzAF{ zSKEgAEDWP8CXRp-LFW#wvJY_ zwG~T?HDXYn-z%)Ubr=}UByAqo-xiz6>}<@3DlCd>@_Bw*!ui(9TFe9M=REfFW?PG0 zZ9SSBf3w22`|b%X%1CCdjw4Tgb#vkD8D-NN#^|nh%I1Y>e0IeW`-}EXKyIeJw`CZt zd3mYC`b!O6Uv`ys^Yg+1W(B;XwDucgQNeMA!(fAuFN1JpEApk?&of z*if*gT0l&B+UfQ~%Ik8l!KVvs$xHt^A`fR&M)R zy?#mA+aRLZ!)rJ*x?mj;2So$5%SHx#Q$E8b&$~s-Px2c;2;97IOsQ*nXS__scVU@B zIKGN%a#aYTlEa6dTNNED4%@__{p_lV7W5I_8nJA7?u}=i416j0m1e8PvE7K)?Rr!dj*(X3bNHSDIu zX0HjtYzQToKyJpXh0iNmA?ZB_btE#?VxUOv)cp(nu157d$*p${WxS18UDDKqHQm&1 za}*3cqGt`>6{)Bk^uyoCqIfOO?hRi z8a6}`yJZXkwS${_kjw_1qMkBwVo~pt=G2Ri21S9!15a@e;2>$jxKj^_*z%;$7rOBi z@kOL+SLv0?nk8xR0V^Su8@Rcgfw(%LzdeHz0PDf|OBTFPb`yIH5wE;4(Um`}aaJ>V zImdpymx5=ja(b&$0Sfb%KI+z>gnz=%Al43qhl%B@1tqhbZ5VJo4>_#P{qm^XD9YxpmeNv!18KB-?|~Xh z>1d2|Zd?d!Er6z@(Pk`~9tf7ZbC`X~DS0PMO$TB%tbWC^oKN@WEL2q{`*FJuSmorsbN;SYAzNG$@bz?(?-`6pMUatpV|Eu z)6x`83r!9D2vh{Nv53Nw7*f0g2PI=-U#4B$DF00wJ~0GV1^*P84dkmeS?}8z zt=hF}?`=+YN$-xKf(64v&OLxetSuQWkLdLLc;hsfW<7^egfl9MFqOaRyefRUFjbV{ zv@C3bQSCdxSqT{l+7uo-;JyQb`{WZ-mXi0U{f+CAA}Ig@8sduJHo>n6U?3Q&x-%m=;~( zO=*?g&t{Q36UB>ukiGbw=Bm@L)PbV1H4UYQdZXrspImXF;-J5l}CZ*O)@V(oA*Uffw?De^e6 zE>y+yR~pBxi(U1~R!7%Uq*1XxqO6VAd~A2nS@L$GTzp!f;LCCn#PgzuJMihR(II-S zQx)VJG|0QMO|6==V1PIJELiH0BD6VjR-zU~3Yioyj{MT7p>mKc5M;P6=9|E*>j!DOD)Znrb+t0S z_QxI{nEPR+@zAA<5A>t(8tNXJZ=vdj{rTL*9SESf?U}2eFUaKJkl0!0gtna;s=Pl3 z#CcBc?v1>DM(qRTBd4Yp2eQ?wq1;K1cq8auZ;0z=yHpUA+zHDYtgAo}t|x(Q`wzth z&}3C~CQ&owdCa$DdrAp~3Kxng^REQ6nTaU881s;W!&EPj13ODZ&!p(I%gXD~-D}n) zGI`JqN6_svr`UY(Q-9K{%zmObgm@K^Uv4`7Je;SeZz(6&G5zQb2O1xn$W7K|z5D)C zzJremo#%&*fy#VniDQIqX>k(L7%VXyA7TJJ)vcM5%);X!*X&PHFEmgHcPb+}44eBl zvF(TrCYx5fh!q6CjNpd@G_db3N2=Cu6k zB)LeSSUuDAqTkU_Y+CiWAfpnM1Fn+jn^&7GJudpI)J`WyeuTulY8hv%-d;+eMH~&Z z443XxHoB@@dJkJVZlZt!nwF$~SG*e4&S9ZqoS+oMW2Pc4E@!fWRy2h0=3+?#LYk9x z`tSEV{B!K9V`GzsN{XS!T@|J)r*{v2j=Vv|f}B%`!a9SRWU{|!-vNfa?_u3xRe=2G z@a%y&_Q}FdIcGEZbL$qPm&{}0#&$CA1z?EjhaHL!oW7godz0hn^wR;EjX_w;sJ%v` z6y$-pV3v^1@2*gnDjuB^TC4Wtyp3T>gbwYd<*vU+17_~j12~45M~K*e*!4it$E6xA zR&cRCY zY5$}BEViw?K~{fjtSJ)5+cXt1y$RBuUJ5NhYv;}Zmz1%hO!Eo-r|{+35Yy0dvIrYv_}?RaIj6FXwFJ7=BFP8gh)NzG8!hZHB@; z2_H|gZsz=%yfsJU8E&4fM@^PH+VbX?XQ9X+)ab&*Qy~UZA-Wh4HaTBzXd~Gf^Nz+e$BO)D2iG8+aTS<_ek39d zaVDa)cwP%ah45ew8g91X^dqY^k1v73(GpMz)3?Z;Wj4!IqLnkxG#oIGN3q z-;cV(Uw)eK;K!6`S|x->tuV3VCc@47CnVluB5(^gb(Fot#kPkDSy5L;mM7I)_^dcg zcRg-;Y-}y6k6T`^0QpU}EF)c)qz+6kJJc+iu^~ zJgBJd^z__3RRo$pwJdL+U0t(cU@L1N@ujvRTU0Kno;Gox&pU7ML0_exfA3iTh{mfa z`)Xu`9GM_^&MaP<&aG*~La&cm+jkD&9bDSQZt*z(P^jS@+cG4mt;pNtXdc)`K6%hO zQYVO{W#}fFU0Z2f#>~m;=5FX;Lg9ybJRt!JiOw|^%66r)-@rvNYtS|_;S2Ayj9fh? z*VLD3*))@1^SDs$twgvcA*;Rr@n^v_&-9p1-fNiYWl|ucM@7JaoA?C+dSl)zU5(+wEg5%C-sh4QF%ikt1gUYV=X&_4^5bt24*SVwr8k2j2t!XkXtbrx&WFUdBD` z?}=ozQ~7L(H-pQuH^$A6=;>mBbuw>Y=b%^Ahv}Z5M`65UGrk*A;U#VJ;I!Cs|2EXK zp-cCx_5tx5ehWhULbZJJFnxL3*Wb*79{5lH!%C_$qd-bXSJT{8J>x#;i#gHMp585e zn}&(=N|*qGT95PXM5cPnbCd(6QH*z@8)|kpdOMt>Dj;xv6NHVYn5w9Eh>1zv5Jq!n zzpCk@VS5@{pPUY$bX&p~R_COudiGUf={X8P=>!$pM9<%B$_5qbzi(7wp6ntHW9RqT zO%eJtD`?Peoxo|6jkZlqfqFGCnP$9|H2eZU6@(Cy$B3!@zLj>YD{!~Wk!dlI;(Z!1 zjXY1GhcTsUYUIryG5o4ipd{XPhZ zBb|`r8*5S9dlW6J&?~3^vd@ezK1}E>@vhaRgQ@`Uhbm3s8m!lo~gTm_4F zrVQ^&S+h7z3~{ac)1BB$>M^X$HLe>;-VEfJsQAb$A(9q$Md&*7?}z-xz>$L|coiB* zky)V#cpj!&OMI)V2AhA}qfD+Vw?YF_6?9Dl^fS9 zsvo&!SwTZH&8B9A5xDFJ_Om zwVa9a0?+=vuHOtyqol#Oiu=xuM{{daq0&&4_o2Ujt?+rhD_CK-qrN@bmu#cnjY57c z>KOxSb3<5G54`B-fl67-)v_o?E;nhS9xTJ|4$g3(ZwQ*N-FBlFJ30s& zoGCWl&2UR@$N|Na#9SX33`w2+TP6uPMW=A7WKB3>c-I? zH9uNy6-^-=4T1?=B?a(;=c>c#KSc6?xU*1T6+?%UOPhT4+~>CsLP8#bkb{feT-?on zPbWRc6#a7?B)%cWpj%%YNTLD-EYq}y*%!yIB>d08FlQS);!ySXK9Ju|b&VmAnf`YDT*&ir zlG-LLE{(bxeY|DT%jmtJJ$>j2Er4eh&yT<^T{#)5`V%;6_dcF==~dC4oyHG<=ikoFXc*-nlHMq^iX z_bVC2F-@RS8M+N!*XhircgR5JMa61zT-i?XkD}jX0!O&?J<%BulYvEhdeMz9x_+dP zZH&>|YDUI|BXSZ<^e0P+3P>**wGdmTrxmnGH5{(-m{0rayiiK$(aDo4);a9D_(@|B zae;oAshbK)pi>MTLia#+9um`ck?W6F|H+igXrVLlYjn`f_&q08`WAbO#!$BlHtM0% z415>g*^#Y)&R}4TJi%=AjU{%uh^^F5;|FMsgqd}&??>49vh;Z0UeVC<+TqV)ml9sI z>zQF4BwRmhBFkGm)Ufbg(B&hA4M}QBqG8dt(VzPW+AMz1`c5zpZj#|eDcXp}IT17p zhjsUeCP`-eSo)Ju^-(-G8u+PI;>bdn1EMJX+)(~R(dJdB2mm8FlyMLBQket<+ zIkL0kI82`APDW^65oHQA&&ASAmMpr`(9Jx|a)P2gk6;6ze#OHe?6tZ#I`&UV$M}B? z-f6VE2nI^OR>@Ya>w4<6T*ZT#tIJb=Gm5W7%fX=Fq3(5F!-i;Bf%7fMw@Ve@jYaKO zxej(av|`x0WFo<`?F;#GQ;KZQRbqJ_zT=0&sD<3HO(b-L9w9}T=7o%crf)f@%;#Ci z&@ZIeJs8icm>U$`0nwA3g6JWA*EKg4&V1=q4&*|@QH)c<`KjSbh1kUJ{u89Cl+kZk z%q9z}aontIH2g>t-H)1&nn1Xzz5}4w3Z=02q+e0|b;i;B(Df!JU4TiDPXz(1K5~UY z!}|VeBn4g%rdvNJ-?>NC@T{sSfZ-17?YpziHLnKaNO6;NhAPcIpNh@UrO39LMz|;Y ztL{@|>G;WJvg0nU=fuMc?Rq6G_epz3HSfI^O`bSbMS1slf2ZZkH_EjjMa8!Krp-Mk z8y6zE+wd){Hy7kyXrXSZb9~h@WMlWsi_tb$6jd}{%D60%T%bv`W|Uix1hpc`Xl(}~2fgndl6+0( zW2x$TS9)A{l4mJy_v);9vqy1t0?nb|=1IDpqIRHWh|9%sUUX|buZDrYKl)n@=RRhj zm*f0w9?H%I43iI4OHwVuij%?#l-#FUbd%-|^)8}ETC^5z-P|8lUpgz``3AuFj$<~1 zj9fU4Tzb_*hkm*&?2vXgyH2i!@n2RdHQ;+GPx`Yjy5467xn3x{UbuRuq=MO$->lWI zug(8T<^OXdZa}7;nI^vwmUdl?T@z%&=aw>Q02anwB8Q-3*KQEXaWjj7gh3TJjeGC|mx%zM92~%4k5O;OeQmZB>*7Tz6HAHTQ1UP;8 zTE8^`M)(wxoDfpp$8s(Mrzac}R}N2>7vv$**JxhEA{a_B*|4xz z_-#AQuWfyD78mRV+9tj^!>G<;b#sn7$=9Z4lO02qzDF2RM7-_lEEtI)v|tv9ZOCO zBT@eqL@OQ=Z$#yQ0tUzEbGENB%9jv=Ou1qF3hDW1$;9m(bGRWGgyRyuJjpLy*{G?1 z*!he2q+^)I+Cu=N@v646eViGvI2oe{>qC_hPC6^cg4zKL1&gLZ3C@~XA)ZU>Wy!ka z)2vwyi8jYKV=XA)jc>@>wc@41IxzZUE~WF~!nb!;&EF2Z1t);j34K#S-hGQobgCSJ z7UdJKBR@9GJJN2Jj8ahmKOLWbC}Kn2d-Rt83D`Au6h~L2j*=b!l5F3GRboF6Bo3jx zysd3Z9RL^krR)2t!v+?q#s>e-8=Gzs?BX76MVS6gz?5j&E0Al0&7ck);*~wy#0vY|&r12w_vS^5G%}v`W z(kp=q(~1E2L2S_kI2GH^Woi5%@>@+v{t#dwwr)DVYoudpTl3%5hp&w;jGL}{k&|0jh){<1#-rO7K)X=zV4Arm3gQyi< zmRMBB45yakiZUHk%dB4?E@IPz^_=_UCg$x`ov5=*4cZ1rpQfswlOAR53cZ+d1*fP7 zd_ZZ zanA;_`2p|w?Hhu#V-p*$J^7r^Dci0?bqw)($yHx+sLgeyja$<9WM=kx-(H78Ls1@E zN4loCkSJ8I&XpJssSqtF6}8M0T(1Ma^jG-cHDB$OP&g$z&OlJ$&MmOZ$hsTgaq?kR zRi4{X5+;{CcZ%EFbnM;+h^x$ACoUJZIQvSFUhJOgoN5L!_qek=n%h6|Z*A7dD%!-7 z3&Qj=blR$ew%A|YMkOIzp*u(H{k`ZY2rhi6je*UGO4HAh_S0Df+Ux zATE#S#FtC*X=s_KqI^s)X3@l9E(-vCLWmdLAUK`pa;$}}O8kCa^ z!c45;s++atn;!;B)VQ3f7M_ZWy5@qYlH+vk7~h!3ulm`%$*^~tNRL%~0H}W`WDnM| z2sq{wOlnrrmy+AEsddL;2_y(_r~xMiC2$7tAR;8Ypkuih$%#eV0i*;!Ffx2*jfX^uj!1lV$tu(UAh8vBKuQ`)yTtTzlkE1<~rWHB2jz{eQ#riGIQ_SIQ#g^ zvZx3(E?-PFN83xzq$&USybspp?RFcqllxfGGD<)4MXsSZ(3| z>T9L{aK=~C)h>=FGsc>A4f*PTE0 zjL`3m1J@rvt6#XtTAwsXNE};>G`yJd7$ITXUShT9w9>wMQDH^vWOnz?V9&~YUn-~r zQ9s!~+dC-sOvNuwLFwEn3nw-|iEx!R<;0OLVO|(8?>1h2CnP`&anl0foF4Z$0Y3BC zo&R|&r}o^6{fvqI9E;`s$DdQ2k3)7|VL-hgu#~$u)Fu*;WqUY<~$1>rid;Ame|IGi+#(#_Q{u>PR zudHq@1N|-0`~SeN2ih|zhk$%H0w>)6f&b6^Z}@+AE&mP2{sZ(^5A)w_L~J9+pfBcs zMgTnm*2w?*82`IT=;X7Pe9{<4qGXiY4pN9Vz{J+ar{|g&n@^3@$q2mCerKM4qekN^Mx diff --git a/.cproject b/.cproject new file mode 100644 index 0000000..8d7bfa2 --- /dev/null +++ b/.cproject @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.directory b/.directory new file mode 100644 index 0000000..47f8216 --- /dev/null +++ b/.directory @@ -0,0 +1,4 @@ +[Dolphin] +Timestamp=2011,8,29,9,19,19 +Version=2 +ViewMode=2 diff --git a/.project b/.project new file mode 100644 index 0000000..5d4ed63 --- /dev/null +++ b/.project @@ -0,0 +1,78 @@ + + + lux + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + C:\Dev\lux\scripts\build.bat + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + false + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/.settings/org.eclipse.cdt.codan.core.prefs b/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 0000000..7031730 --- /dev/null +++ b/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,66 @@ +#Mon Aug 15 18:15:44 EEST 2011 +eclipse.preferences.version=1 +org.eclipse.cdt.codan.checkers.errnoreturn=Warning +org.eclipse.cdt.codan.checkers.errnoreturn.params={implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue=Error +org.eclipse.cdt.codan.checkers.errreturnvalue.params={} +org.eclipse.cdt.codan.checkers.noreturn=Error +org.eclipse.cdt.codan.checkers.noreturn.params={implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={no_break_comment\=>"no break",last_case_param\=>true,empty_case_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} diff --git a/.settings/org.eclipse.ltk.core.refactoring.prefs b/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 0000000..a12030a --- /dev/null +++ b/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,3 @@ +#Tue Aug 16 15:19:43 EEST 2011 +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/Build/bootload.bin b/Build/bootload.bin deleted file mode 100644 index a1ea4682e05c7c9ec288c0ef6aecf05a3823ce2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 512 zcmYLGL1@!p7=3@LtEM*F9K<<9{)31+7@8h>@U${IK?coeiVQYtu!LF#>L<9cNGJ@E|BuCM+gU@H@Tl@!t1+yl=3B`E;BnQOcZk_0{I??$%u%{~5MAM#1W|yB-PweT=9&t?9YXY}JnCn~CeFoxz&V@1j9vIV! zB_0oB)415L^XtUNGpO@*vZWF0yln=J6T>u44W|tl-#)wU-_Bd&ymG|@@wiPfygP|u zEQB|k6CUOf7~`<56T<0a7mSl}8{8ziV3t0G&@ss4U+to7aTK>)q8 zOa92(`Ok6X%c_J`;IPvr&fY}}HgDe?MV(5=A11tDy{N;Zx4e!BA{)Nc{m&!#52(t-Ak(CE@Uar2()3U76=cRI; OmBNZFs{#vTKKuj2jJ7KP diff --git a/Build/lib-conio.o b/Build/lib-conio.o deleted file mode 100644 index 8e403c2b0e2187fd177d5e540ab1879f0add0870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7944 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 K2))D_h5rY-32>kQ diff --git a/Build/lib-ctype.o b/Build/lib-ctype.o deleted file mode 100644 index a09ec3273d93f18266a257f6ea7a765691c1666c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcmcgru}%U(6x{O=&<3GVW8oE=K$H^`D6}F$L=$31EeBqL5jeu_MX4kqR%+rW@D;|^ z@CR1bR<_0u&^LR#$C1$3IAnL;%zL}b?t|NM^;pw1rl2vMO%-GBQshNJnk};!yFc2B z3|~ZIppQO{?+Kj5^AoJmNAdB*xO+>KUnf{YoBPlKC8ivW&mtE<`gMWg9QXxef#Dn= zAHIvY!hcVdQt8l0*BV}zdwbQ(uGM#pyh)$ze%=#qAtQ_eW2QUkaH~Pg`#!f+)VJFv zw{JKzFDz~`v*EhTY&xBe-6gNz26=UEj$)+1K%K;{ABq_{j04HSr0D@> z2udc&Q)eQLy3;vzs9y;AEm|}tjW>wV!1u%bp~L&dDPfSOpw3lVaoCTruOH=uXa9lF z;S-?M>-ekmpnFO$2E9s=m7*8Iy#?stB<-+90=ZSeWH$MrXPZsN9k183`|Mm8B-_q4 MN&G%EYS_BuU*<|-jsO4v diff --git a/Build/loader.o b/Build/loader.o index f9ab80736873133c089cbd18691ad11707976286..b125264426c4677cdaaab3874e4ea04e8e3b8c90 100644 GIT binary patch literal 1472 zcmb7EON$dh5Uxq$Yf%ss*9YjxBJLuL2p-f^ve~@YWFs4+;3Z5py-CPSCd~BuIEkwu zUPQ!`7x4!udloMqyt?91FMIIdH6Vy0j9<-kJIT?4?)tu}>gt}Z>bX~_77fE7Ee542 zVMJNwxESeqnxS1f^uILc@MIgaC-^Ks>#N_OX#LUG$M4@! zmgxR3_|9$YZhZd}hG8D$BD?|61c_~yK@x|Ug5Z7wcYQ&lFKjZTccA_+sN7u(rLKikfN zS*@1aE(^{>mK1j+S%HunBeL2-0Ne|tFYPwaT{qT>`@&K2jN&!XCR3BXcQ$5d%=`b7 z>CWeSC~#-RY4 z8}yJ-R#Et$112vrMK8gRYBx^u1~`7ZY)sKx%$p1&Nzn%lBb}y?(E9E17k&m$-c_2u zOvPu2-=P-ndwy?Pn4i@Int5`Tm_M2FJchdbEO8=a-~Y1^5sH) zxzVgqjk|df-K^TKaV-Z&TSfHW(VEd-=Nav;7qlr0OS6@WNCJ3cotGmoLTB(bOjNR}pn3B9Dm6b1m3 C_#OQK diff --git a/Build/main.o b/Build/main.o index 183423c78e17148c4d69b70b827fb10b2c4e3e46..596f6bd21cb00be95664e0454470f3c6d53c2253 100644 GIT binary patch literal 1208 zcmah|%W4!s6umt&#+djRAB%tsTZl42Q_(m|5JaUDlR)Ao4!R39Glgl=k62wJjvy{{ z6U5K(OI(OMKf#UQ!iDaI@t*FgNv8$9P<8IP_tfiF)$5gw2cGAVGmq+Yz=&Fwv~xj= zrfJeibL{MYd-G%FQ)3qF`|r_cbkMywmy6K5mC60aY@YZ_`S~N=k0M_y*&hmj%Sdg) zjrQkeI>3Mwm#Q`fYJjEY2?t@?d+e;6x%D#zuA-jV^G< zd0Iuns27GrUm8iGn`I<)3Ig?Y(I(ML<5(puNm8T4>ch@_W@K;o(3$^5E^rbho3NsL zjDht5P3xa$JZ62sUV~`O#xR~~Ug=AW;B{`Ww*`!Q=wMg4;b#7)yT%&Kx5y2K`7Y*O z(P2L1?^=W&_JJGLa0U$;_6&6P#W@yT?lg0^H>99@0>_%u0c$SE_?1bMgZv2c^I?BY zZm3;(zMo89am<;U&vA$4c!Pe8TpW1#<%5@30C&|cM%C#^c{t~fR`|sDw*;Iy!<9N! zQs5ltDtxZOZ&mnmg>O}OzrvqYIK?tdM2~j2;n229`n0LyR1Y7icyB!kO(>)ArJ|tt zfI+0BrZpLrQp-Agu5`AZ@YjeUJG_*)Lm%tVjOW?JYHYYSkGqqMHNModz-gix;PK)u Y)=m&z1!vI>Mvu$91kS~~1LVT}0X|KioB#j- literal 1488 zcma)6&rcIU6n>=zE20*{!5<_xu^NoBVuS;t2}qHU02cz7V65AALN|1G&F(CM5INKf zsTlniyy#gkUOXro?jAh&7nnd|)RT!xec$d5EgOx#X6Ad}dvD&GeKXVb(TN+eSd5g! zC{A@o^e7~Ken2<1(g79fW@%_O(8nFRFhLPV7PB&zX^L=aQiI#yY2Bd?{hnk1PR_~Cte`?YEF z;X0*g2%&zJR8Yk)(7eC0U!?LrHGey|RoU&TW-}R;yS|AhoANB}{N&w^jf`ALchBTK zOL`Y43`=+Hbf3n*o=bh6Z|y(l8~TYfcg2)?o>4jhmXzj*vL?l{B(11RowU5`l2))y zQ&?=XY$>#{shJ*E>V-u#>3`)E2jW;-!UaQ&A446G3iXqW2SXijle@CanB;-=I3Va} zLLO&?bcSahupkclc^-)WS6na0AO#SDd=~=MpW(w82+=q4Gz4RVDB8|8RTFN+jsGDI z@l6f(E?#tpjpzYxExs4M0dLH=#*WWyQ=;lBuCURbpl>y02kw70;Eff)QN1qlz0(V9 zaccH^3-*#n2Y2Xb;PPkeyEDR%M|e8I8+(rRgAxB!gcl;*V~)L~d0;63nn*MtfkFfviDViin()_P;)@tx7#S_x?YQ4#VE zyah_{H^>v9JV6jeO6QwnCtjc+W6gf^eLFk5JGVaB+THd%kHkD0q&|acNv%v+pb8Ds z<>s7!xi>djsdgp&^K;gc>e;W}3pyRg{KdUAPrrL7W#;*fXVJHKYH^@@*CpE7*jSrc zs7Ia5bXIngOy%vFT7cj3yIQAISKpMvDp61zr$$9Uliy=gBBQ?;3Swmx1yNB@&}gTr z&Y)#&ql2A~_2t5-#wWS+|KPN3#js80e(XC7eH+gLxn+Zvf43+gd9NXi!k^1qLJrq^ z3uohctcmd)J31nts+{^!j{Sji*j~bAPv)Gr#ep@+V;m3>*kl5c&pZO>dsN{SxLdCY zat%#P>IoNgb)Rl~qBA~vf#B{*c;4NS`H;ID+%M0_;y8Q~2j}m{@r30oz*q1o%ijYR z;bWH9f!tHRFRxF4>kj{lnENL4-w=Or_!VNV!6)bSbQJ5Lfic8G%#TAA$DuMNPolmS z>(&#k&?Y>{RjT`Ghfk%X2#<1I@EiZP1GG+|^9MpLb+$vo=RCoGr{xsa8T0V4)s9q) F{sOZ_n#BMB diff --git a/Build/mmngr-lib-pte.o b/Build/mmngr-lib-pte.o deleted file mode 100644 index d516b2f1a25247cd1750b6c8a08d5bfdbe258860..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 934 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 E1$2?HcK`qY diff --git a/Build/mmngr-virt.o b/Build/mmngr-virt.o deleted file mode 100644 index 134b7d8e8fb7f08291af30cd4b2381e90c1089c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3000 zcma)8TWl0n82-0iu#m>(5>3?=)?^xMENcymQR9Vh5lsjWV&S2c$#i!p1AEKtEVPD% zlx0IEn?|1W!557$#2DiviKJ;+un*n>@xl0rKGXmKd1xXM*YBG-XFFZ1ayDna^Iy(? zzW+bx%RKz%ekDw?erpBWV7qq9Qf(lnW;qk&eg`|&-vWv0(K;$p zr!uGvR&AHu_m;L}>TA|+>M!nmb@nTG&H6vJgJjOm$ImVckqMbh*F@HBM^15HX{MS% zpg$34wt5k#APG(HKNn{;yP{-HE|Jldj^?HPqdGrt#G^9DpOR+q@YP|#ZZPX$H-dw6 zV^wgrYL^E`4w>)b3=R6AiE5<$lZJty1C4Er(l}{k=59Z_7@vt%N7UAarxJUK#97c~ z`{1knnNH5=6!h`d^tDXtdfZ6PO#LEvS}pL;%q^_#zn>6^@!|~ymHn?9!vZ(J99)eC zm?NpC$ex`$Urr4Sk5!9a^|`%H(Q-?vOd7u}&u6NEcH1+70(qt@lLgNj1A1kvcgeF$~XwD>F}`v0Hb5PTS)$i{es;V^j8 z#{QDRK#9kwUPvkE!?qq>uSuDHZ*icS_9OC6==LHCvALf6Zk4R_keO1 zxEo#DPh)%(o#%q~4}n~jeZAameFiL}zlKixMWAl1%MV%rQoi0HFGBtToqNgo2^1t6 ze_NzLoc}uHpMg&+|AQU&Ly-Ad)^-=;0raiPzlO1HjQ2r@e7-}z2zdm(iB5jsci69Y z$cr8Fn#dX8dYd3`!Zu#TnDL}gD2}`4aVMRX4nNBfhPjuMwrP8r# z*~Fc9C)=i+0*GAjso*tH7q(kd&LGcC_^oiRDVlN6hjH>vDmm#mzCRVwS6l@qSx z*=E+=ssk-WFtd5va;0Dwz@TjoD;k)2W)}E#B$l)D9a%U<$8)T_ z^WI7osYp4eN)pMxt&5aNZN4?`6vr`xXF&5WSmlta2w&rOvC}3 z1=4Nkqu|D$x_Ut0=Cj`#u*FM=J!$3)&HJ}#0aBJNRz6U3y*mqg6_R^fue zjX2L-cQX+@4k-DElFt#J1V4qJ6E}gUl7CeAtJ2>BlJ{LA^0-Gm_^-yD>B2{9E0Fr# bl)*Dk1g}#>tn&20*`k=rqraSx^%N-`AvIA_x1+R)`L>~$~7PzjDlSy4aLccJ(EBOJEj#qc5Z8Psc#9S%^(yS;bB{4FO5 z5KFz0-@PcVjCKV!5pMq^b_F(*3tNaaEJ9sFJ^SA7ccg^w&=%6|-9)-~ZzkP=qL^9N zQK6cdb+t_`jq#~WH7e)Uthje}+=>!)T)kl^kPqg>{O+vy{&^75hXOoyaSvv;|#KGL8s^>}mQFocTr18&f7zO?l5tD3hd zkyc>#UQ2V6VcS+CYKyAlw7%gm`^Mg5+wt;OT4>2f6AKUmpgXwaiGw|dH|c?D(jqkw zmau!PiPXa8R#w}>B%3zTFcJ~NbRsZto{2glu41pUui)S={XR%XrXUp`l zKL%tfEu)K5`c9jgo1+Ow3!D@uOI4HV7S%_nK1$QXkoh(2_htMSZp&T4J95|ab27)M z)4aSial7&e>2H%I9f-a@L@5yZ=@rvtdvTq?eQ+itLZTME{`Ud;;wwvjknR` z!q*huuhc{$wUOtPeXX&RttS+E{6wp=I`R;IcyAo<=s14zn9?3oUT=@Z;%{mpr7qUm z(V>J-p2DD0iq@_~T3>5#*Fqkbi+AK7FMgx`2wqYU+&kjmfNX zg_RX4-Xr{Y1$LqwdQZY9-d3c#_pHSKm=#0KGCNb~hfE-|vEWlo>f!Iex80m?cb7xd zfC(7}o%m^h=hv%6l#sA^qS^a~6TN+4$~fQ|Zeaxm-}<&sA(scCok(Q>I+4WxrzA(L z|9gT!4L|lJIgvCk1IWO3*|yz#7LV?`_*fSI`T6W1KSqA3IKQ`F|+idURG4tG84vDXLNZ|pB|G0hw`=@3) diff --git a/FONT.TXT b/FONT.TXT deleted file mode 100644 index 6799ab6..0000000 --- a/FONT.TXT +++ /dev/null @@ -1,955 +0,0 @@ -1 8 0 0 0 0 0 0 0 0 -1 8 0 0 0 0 0 0 0 -1 -1 8 0 0 0 0 0 0 0 -2 -1 8 0 0 0 0 0 0 0 -3 -1 8 0 0 0 0 0 0 0 -4 -1 8 0 0 0 0 0 0 0 -5 -1 8 0 0 0 0 0 0 0 -6 -1 8 0 0 0 0 0 0 0 -7 -1 8 0 0 0 0 0 0 0 -8 -1 8 0 0 0 0 0 0 0 -9 -1 8 0 0 0 0 0 0 0 -10 -1 8 0 0 0 0 0 0 0 -11 -1 8 0 0 0 0 0 0 0 -12 -1 8 0 0 0 0 0 0 0 -13 -1 8 0 0 0 0 0 0 0 -14 -1 8 0 0 0 0 0 0 0 -15 -1 8 0 0 0 0 0 0 0 -16 -1 8 0 0 0 0 0 0 0 -17 -1 8 0 0 0 0 0 0 0 -18 -1 8 0 0 0 0 0 0 0 -19 -1 8 0 0 0 0 0 0 0 -20 -1 8 0 0 0 0 0 0 0 -21 -1 8 0 0 0 0 0 0 0 -22 -1 8 0 0 0 0 0 0 0 -23 -1 8 0 0 0 0 0 0 0 -24 -1 8 0 0 0 0 0 0 0 -25 -1 8 0 0 0 0 0 0 0 -26 -1 8 0 0 0 0 0 0 0 -27 -1 8 0 0 0 0 0 0 0 -28 -1 8 0 0 0 0 0 0 0 -29 -1 8 0 0 0 0 0 0 0 -30 -1 8 0 0 0 0 0 0 0 -31 - -5 8 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 - -1 8 -1 1 1 1 1 0 1 0 - -3 8 -0 1 0 1 -0 1 0 1 -0 0 0 0 -0 0 0 0 -0 0 0 0 -0 0 0 0 -0 0 0 0 -0 0 0 0 - -7 8 -0 0 1 0 1 0 0 -0 0 1 0 1 0 0 -1 1 1 1 1 1 1 -0 0 1 0 1 0 0 -1 1 1 1 1 1 1 -0 0 1 0 1 0 0 -0 0 1 0 1 0 0 -0 0 0 0 0 0 0 - -5 8 -0 0 1 0 0 -0 1 1 1 1 -1 0 1 0 0 -0 1 1 1 0 -0 0 1 0 1 -1 1 1 1 0 -0 0 1 0 0 -0 0 0 0 0 - -5 8 -0 0 0 0 0 -1 1 0 0 1 -1 1 0 1 0 -0 0 1 0 0 -0 1 0 1 1 -1 0 0 1 1 -0 0 0 0 0 -0 0 0 0 0 - -6 8 -0 0 1 1 0 0 -0 1 0 1 0 0 -0 0 1 0 0 0 -0 1 0 1 0 0 -1 0 0 0 1 1 -1 0 0 0 1 0 -0 1 1 1 0 1 -0 0 0 0 0 0 - -1 8 -1 1 0 0 0 0 0 0 - -3 8 -0 0 1 -0 1 0 -1 0 0 -1 0 0 -1 0 0 -0 1 0 -0 0 1 -0 0 0 - -3 8 -1 0 0 -0 1 0 -0 0 1 -0 0 1 -0 0 1 -0 1 0 -1 0 0 -0 0 0 - -7 8 -0 0 0 1 0 0 0 -1 0 0 1 0 0 1 -0 1 0 1 0 1 0 -0 0 1 1 1 0 0 -0 1 0 1 0 1 0 -1 0 0 1 0 0 1 -0 0 0 1 0 0 0 -0 0 0 0 0 0 0 - -7 8 -0 0 0 1 0 0 0 -0 0 0 1 0 0 0 -0 0 0 1 0 0 0 -1 1 1 1 1 1 1 -0 0 0 1 0 0 0 -0 0 0 1 0 0 0 -0 0 0 1 0 0 0 -0 0 0 0 0 0 0 - -2 8 -0 0 -0 0 -0 0 -0 0 -1 1 -1 1 -0 1 -1 0 - -6 8 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -1 1 1 1 1 1 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 - -2 8 -0 0 -0 0 -0 0 -0 0 -1 1 -1 1 -0 0 -0 0 - -7 8 -0 0 0 0 0 0 1 -0 0 0 0 0 1 0 -0 0 0 0 1 0 0 -0 0 0 1 0 0 0 -0 0 1 0 0 0 0 -0 1 0 0 0 0 0 -1 0 0 0 0 0 0 -0 0 0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -1 0 1 0 1 -1 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -3 8 -0 1 0 -1 1 0 -0 1 0 -0 1 0 -0 1 0 -0 1 0 -1 1 1 -0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -0 0 0 0 1 -0 0 0 1 0 -0 0 1 0 0 -0 1 0 0 0 -1 1 1 1 1 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -0 0 0 0 1 -0 0 1 1 0 -0 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -6 8 -0 0 0 1 1 0 -0 0 1 0 1 0 -0 1 0 0 1 0 -1 0 0 0 1 0 -1 1 1 1 1 1 -0 0 0 0 1 0 -0 0 0 0 1 0 -0 0 0 0 0 0 - -5 8 -1 1 1 1 1 -1 0 0 0 0 -1 0 0 0 0 -1 1 1 1 0 -0 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 0 -1 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -5 8 -1 1 1 1 1 -0 0 0 0 1 -0 0 0 1 0 -0 0 1 0 0 -0 1 0 0 0 -0 1 0 0 0 -0 1 0 0 0 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -0 1 1 1 1 -0 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -2 8 -0 0 -1 1 -1 1 -0 0 -1 1 -1 1 -0 0 -0 0 - -2 8 -0 0 -1 1 -1 1 -0 0 -1 1 -1 1 -0 1 -1 0 - -4 8 -0 0 0 1 -0 0 1 0 -0 1 0 0 -1 0 0 0 -0 1 0 0 -0 0 1 0 -0 0 0 1 -0 0 0 0 - -5 8 -0 0 0 0 0 -0 0 0 0 0 -1 1 1 1 1 -0 0 0 0 0 -1 1 1 1 1 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 - -4 8 -1 0 0 0 -0 1 0 0 -0 0 1 0 -0 0 0 1 -0 0 1 0 -0 1 0 0 -1 0 0 0 -0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -0 0 0 0 1 -0 0 0 1 0 -0 0 1 0 0 -0 0 0 0 0 -0 0 1 0 0 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 1 1 1 -1 0 1 0 1 -1 0 1 1 1 -1 0 0 0 0 -0 1 1 1 1 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -1 1 1 1 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -0 0 0 0 0 - -5 8 -1 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -1 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -1 1 1 1 1 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -5 8 -1 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 1 1 1 0 -0 0 0 0 0 - -5 8 -1 1 1 1 1 -1 0 0 0 0 -1 0 0 0 0 -1 1 1 1 0 -1 0 0 0 0 -1 0 0 0 0 -1 1 1 1 1 -0 0 0 0 0 - -5 8 -1 1 1 1 1 -1 0 0 0 0 -1 0 0 0 0 -1 1 1 1 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 0 -1 0 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -5 8 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 1 1 1 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -0 0 0 0 0 - -3 8 -1 1 1 -0 1 0 -0 1 0 -0 1 0 -0 1 0 -0 1 0 -1 1 1 -0 0 0 - -5 8 -0 0 1 1 1 -0 0 0 1 0 -0 0 0 1 0 -0 0 0 1 0 -0 0 0 1 0 -1 0 0 1 0 -0 1 1 0 0 -0 0 0 0 0 - -5 8 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 1 0 -1 1 1 0 0 -1 0 0 1 0 -1 0 0 0 1 -1 0 0 0 1 -0 0 0 0 0 - -5 8 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 1 -1 1 1 1 1 -0 0 0 0 0 - -7 8 -1 0 0 0 0 0 1 -1 1 0 0 0 1 1 -1 0 1 0 1 0 1 -1 0 0 1 0 0 1 -1 0 0 0 0 0 1 -1 0 0 0 0 0 1 -1 0 0 0 0 0 1 -0 0 0 0 0 0 0 - -5 8 -1 0 0 0 1 -1 0 0 0 1 -1 1 0 0 1 -1 0 1 0 1 -1 0 0 1 1 -1 0 0 0 1 -1 0 0 0 1 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -4 8 -1 1 1 0 -1 0 0 1 -1 0 0 1 -1 1 1 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 1 1 - -5 8 -1 1 1 0 0 -1 0 0 1 0 -1 0 0 1 0 -1 1 1 0 0 -1 0 1 0 0 -1 0 0 1 0 -1 0 0 0 1 -0 0 0 0 0 - -5 8 -0 1 1 1 0 -1 0 0 0 1 -1 0 0 0 0 -0 1 1 1 0 -0 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -5 8 -1 1 1 1 1 -0 0 1 0 0 -0 0 1 0 0 -0 0 1 0 0 -0 0 1 0 0 -0 0 1 0 0 -0 0 1 0 0 -0 0 0 0 0 - -5 8 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -0 1 1 1 0 -0 0 0 0 0 - -5 8 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -0 1 0 1 0 -0 0 1 0 0 -0 0 0 0 0 - -7 8 -1 0 0 0 0 0 1 -1 0 0 0 0 0 1 -1 0 0 0 0 0 1 -0 1 0 1 0 1 0 -0 1 0 1 0 1 0 -0 0 1 0 1 0 0 -0 0 1 0 1 0 0 -0 0 0 0 0 0 0 - -5 8 -1 0 0 0 1 -1 0 0 0 1 -0 1 0 1 0 -0 0 1 0 0 -0 1 0 1 0 -1 0 0 0 1 -1 0 0 0 1 -0 0 0 0 0 - -5 8 -1 0 0 0 1 -1 0 0 0 1 -0 1 0 1 0 -0 0 1 0 0 -0 0 1 0 0 -0 0 1 0 0 -0 1 1 1 0 -0 0 0 0 0 - -5 8 -1 1 1 1 1 -0 0 0 0 1 -0 0 0 1 0 -0 0 1 0 0 -0 1 0 0 0 -1 0 0 0 0 -1 1 1 1 1 -0 0 0 0 0 - -3 8 -1 1 1 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 1 1 -0 0 0 - -7 8 -1 0 0 0 0 0 0 -0 1 0 0 0 0 0 -0 0 1 0 0 0 0 -0 0 0 1 0 0 0 -0 0 0 0 1 0 0 -0 0 0 0 0 1 0 -0 0 0 0 0 0 1 -0 0 0 0 0 0 0 - -3 8 -1 1 1 -0 0 1 -0 0 1 -0 0 1 -0 0 1 -0 0 1 -1 1 1 -0 0 0 - -5 8 -0 0 1 0 0 -0 1 0 1 0 -1 0 0 0 1 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 - -5 8 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -0 0 0 0 0 -1 1 1 1 1 - -2 8 -1 0 -0 1 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 - - -6 8 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 1 1 1 0 0 -0 0 0 0 1 0 -0 1 1 1 1 0 -1 0 0 0 1 0 -0 1 1 1 0 1 -0 0 0 0 0 0 - -4 8 -1 0 0 0 -1 0 0 0 -1 1 1 0 -1 0 0 1 -1 0 0 1 -1 0 0 1 -1 1 1 0 -0 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -0 1 1 0 -1 0 0 1 -1 0 0 0 -1 0 0 1 -0 1 1 0 -0 0 0 0 - -4 8 -0 0 0 1 -0 0 0 1 -0 1 1 1 -1 0 0 1 -1 0 0 1 -1 0 0 1 -0 1 1 1 -0 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -0 1 1 0 -1 0 0 1 -1 1 1 1 -1 0 0 0 -0 1 1 1 -0 0 0 0 - -4 -0 0 1 0 -0 1 0 1 -0 1 0 0 -1 1 1 0 -0 1 0 0 -0 1 0 0 -0 1 0 0 -0 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -0 1 1 0 -1 0 0 1 -1 0 0 1 -0 1 1 1 -0 0 0 1 -1 1 1 1 - -4 8 -1 0 0 0 -1 0 0 0 -1 1 1 0 -1 0 0 1 -1 0 0 1 -1 0 0 1 -1 0 0 1 -0 0 0 0 - -1 8 -1 0 1 1 1 1 1 0 - -3 8 -0 0 1 -0 0 0 -0 0 1 -0 0 1 -0 0 1 -0 0 1 -0 0 1 -1 1 0 - -4 8 -1 0 0 0 -1 0 0 0 -1 0 0 1 -1 0 1 0 -1 1 0 0 -1 0 1 0 -1 0 0 1 -0 0 0 0 - -2 8 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 1 -0 0 - -7 8 -0 0 0 0 0 0 0 -0 0 0 0 0 0 0 -0 1 1 0 1 1 0 -1 0 0 1 0 0 1 -1 0 0 1 0 0 1 -1 0 0 0 0 0 1 -1 0 0 0 0 0 1 -0 0 0 0 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -1 1 1 0 -1 0 0 1 -1 0 0 1 -1 0 0 1 -1 0 0 1 -0 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -0 1 1 0 -1 0 0 1 -1 0 0 1 -1 0 0 1 -0 1 1 0 -0 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -1 1 1 0 -1 0 0 1 -1 0 0 1 -1 1 1 0 -1 0 0 0 -1 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -0 1 1 1 -1 0 0 1 -1 0 0 1 -0 1 1 1 -0 0 0 1 -0 0 0 1 - -4 8 -0 0 0 0 -0 0 0 0 -1 0 1 1 -1 1 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -0 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -0 1 1 1 -1 0 0 0 -0 1 1 0 -0 0 0 1 -1 1 1 0 -0 0 0 0 - -4 8 -0 1 0 0 -0 1 0 0 -1 1 1 1 -0 1 0 0 -0 1 0 0 -0 1 0 1 -0 0 1 0 -0 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -1 0 0 1 -1 0 0 1 -1 0 0 1 -1 0 0 1 -0 1 1 0 -0 0 0 0 - -5 8 -0 0 0 0 0 -0 0 0 0 0 -1 0 0 0 1 -1 0 0 0 1 -1 0 0 0 1 -0 1 0 1 0 -0 0 1 0 0 -0 0 0 0 0 - -7 8 -0 0 0 0 0 0 0 -0 0 0 0 0 0 0 -1 0 0 0 0 0 1 -1 0 0 0 0 0 1 -1 0 0 1 0 0 1 -0 1 0 1 0 1 0 -0 0 1 0 1 0 0 -0 0 0 0 0 0 0 - -5 8 -0 0 0 0 0 -0 0 0 0 0 -1 0 0 0 1 -0 1 0 1 0 -0 0 1 0 0 -0 1 0 1 0 -1 0 0 0 1 -0 0 0 0 0 - -4 8 -0 0 0 0 -0 0 0 0 -1 0 0 1 -1 0 0 1 -1 0 0 1 -0 1 1 1 -0 0 0 1 -1 1 1 1 - -4 8 -0 0 0 0 -0 0 0 0 -1 1 1 1 -0 0 0 1 -0 1 1 0 -1 0 0 0 -1 1 1 1 -0 0 0 0 - -3 8 -0 0 1 -0 1 0 -0 1 0 -1 0 0 -0 1 0 -0 1 0 -0 0 1 -0 0 0 - -1 8 -1 1 1 1 1 1 1 0 - -3 8 -1 0 0 -0 1 0 -0 1 0 -0 0 1 -0 1 0 -0 1 0 -1 0 0 -0 0 0 - -7 8 -0 0 0 0 0 0 0 -0 0 0 0 0 0 0 -0 1 1 0 0 0 0 -1 0 0 1 0 0 1 -0 0 0 0 1 1 0 -0 0 0 0 0 0 0 -0 0 0 0 0 0 0 -0 0 0 0 0 0 0 diff --git a/Kernel/debug/commands.c b/Kernel/debug/commands.c new file mode 100644 index 0000000..06ea81d --- /dev/null +++ b/Kernel/debug/commands.c @@ -0,0 +1,255 @@ +#include +#include +#include +#include +#include "../hal/mouse/mouse.h" +#include "../drivers/floppy/floppy.h" + +string ConsoleCommands[] = +{ + "osver", + "time", + "cls", + "help", + "dump", + "mem", + "crash", + "mouse", + "read", + "reboot", + "restart", +}; + +int32 ConsoleCommandsCount = 11; + +/***************************************** + * osver - get os info * + *****************************************/ +void CommandOsver() +{ + ConsoleWrite ("%#%s%# 32bit operating system\n", Color(0,ColorYellow), OS_STRING, Color(0,ColorLightGray)); + + int32 i = 0; + for (i = 0; i < 30; i++) + ConsoleWrite ("%#%c", ColorDarkGray, 205); + + ConsoleWrite ("\n%#OS version: %#%s\n", ColorDarkGray, ColorLightGray, OS_VERSION); + ConsoleWrite ("%#Build: %#%s ", ColorDarkGray, ColorLightGray, OS_BUILD); + ConsoleWrite ("%#built on %#%s %#at %#%s\n", ColorDarkGray, ColorLightGray, OS_BUILD_DATE, ColorDarkGray, ColorLightGray, OS_BUILD_TIME); + ConsoleWrite ("%#(c) Copyright %#CTA Systems Inc.\n", ColorDarkGray ,ColorLightGray); +} + + +/***************************************** + * time - get date and time * + *****************************************/ +void CommandTime() +{ + const char* Months[] = { + "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + }; + + const char* Weekdays[] = { + "", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + }; + + + Time time = TimeConvertToTime(TimeGetInternalTime()); + + ConsoleWrite ("Current time: "); + ConsoleWrite ("%#%d:%d%d:%d%d.%d%d%d\n", Color(0,ColorLightGreen) ,(int)time.Hour, + time.Minute/10, time.Minute%10, time.Second/10, time.Second%10, time.Milisecond/100, (time.Milisecond/10)%10, time.Milisecond%10); + + ConsoleWrite ("Date: %#%s, %s %d, %d\n", Color(0,ColorLightGreen), Weekdays[time.WeekDay], + Months[time.Month], time.Day, time.Year); + +} + + +/***************************************** + * help - help provider * + *****************************************/ +void CommandHelp(string params[], int32 count) +{ + if (count <= 1) + { + ConsoleWrite ("Available commands:\n"); + + int i; + for (i = 0; i < ConsoleCommandsCount; i++) + ConsoleWrite(" > %#%s\n", Color(0,ColorWhite), ConsoleCommands[i]); + + return; + } + + ConsoleWrite("%#! Help for %s command is not implemented yet.\n", Color(0,ColorLightRed), params[1]); +} + + +/***************************************** + * dump - dumps memory content * + *****************************************/ +inline char hex (int32 digit) +{ + return (digit < 10) ? (digit + '0') : (digit - 10 + 'A'); +} + +void CommandDump (string argv[], int32 argc) +{ + unsigned pause = 1, i = 0; + + // Verify correct number of arguments + if (argc < 3) { + ConsoleWrite("%#! Correct syntax: %#dump %#[start_address] [end_address]\n", + ColorLightRed, ColorWhite, ColorLightGray); + ConsoleWrite("%#Start %#and %#end %#addresses are in hex.\n", + ColorLightGray, ColorDarkGray, ColorLightGray, ColorDarkGray); + return; + } + + // Disable pause + if (argc==4 && strcmp(argv[3], "!p") == 0) + pause = 0; + + // Dump memory + unsigned char *start, *end; + start = (unsigned char *) ConvertStringToIntHex(argv[1]); + end = (unsigned char *) ConvertStringToIntHex(argv[2]); + unsigned char* count; + + while (start <= end) { + // Write address + ConsoleWrite("%#%x%#: ", Color(0,ColorLightMagenta), (unsigned int)start, Color(0,ColorLightGray)); + + // Write hex data + for (count = start; count < start+16; count++) { + if (*count == 0) ConsoleWrite ("%#00 ", Color(0,ColorDarkGray)); + else ConsoleWrite ("%#%c%c ", Color(0,ColorWhite), hex(*count/16), hex(*count%16)); + } + + // Write ASCII data + ConsoleWrite(" "); + for (count = start; count < start+16; count++) { + if (*count < 32) ConsoleWrite("."); + else ConsoleWrite("%#%c", Color(0,ColorLightGreen), *count); + } + + // New line + ConsoleWrite("\n\r"); + start+=16; i++; + + // Pause + if ((i%22 == 0) && (pause==1)) { + ConsoleWrite("\n\r%#Press %#any key %#to continue scrolling, %#Esc %#to exit.", + 0x8, 0x7, 0x8, 0x7, 0x8); + Key k = ReadKey(); + if (k.Scancode == KeyboardKeyEscape) return; + ConsoleWrite("\n\n\r"); + } + } +} + + +#define _CommandMemTotalRows 10 +void _CommandMemPrintMemmap() +{ + uint8 color = Color(ColorGreen, ColorRed); + uint32 total = MemoryGetFramesTotal(); + + char c = ' '; + + // Print memory map + int32 i, old = 0, n = 0, blocks, used; + for (i = 0; i < 80; i++) + ConsoleWrite("%#%c", ColorLightGray, 220); + + for (i = 1; i <= 80*_CommandMemTotalRows; i++, old++) + { + n = (total * i) / (80 * _CommandMemTotalRows); + + blocks = n - old; + used = 0; + for (; old < n; old++) + used += (MemPhGetFrame(old) != 0); + + if (used <= blocks / 5) c = ' '; + else if (used > 4 * blocks / 5) c = 219; + else if (used <= 2 * blocks / 5) c = 176; + else if (used <= 3 * blocks / 5) c = 177; + else c = 178; + + ConsoleWrite("%#%c", color, c); + } + + for (i = 0; i < 80; i++) + ConsoleWrite("%#%c", ColorDarkGray, 223); +} + +void CommandMem (string argv[], int32 argc) +{ + if (argc < 2) + { + ConsoleWrite ("Physical memory map:\n"); + + _CommandMemPrintMemmap(); + + ConsoleWrite ("Free space: %#%ukb (%u frames)\n", ColorLightMagenta, MemoryGetFree(), MemoryGetFramesFree()); + ConsoleWrite ("Used space: %#%ukb (%u frames)\n\n", ColorLightMagenta, MemoryGetUsed(), MemoryGetFramesUsed()); + ConsoleWrite ("Total space: %#%ukb (%u frames)\n", ColorLightMagenta, MemoryGetTotal(), MemoryGetFramesTotal()); + + return; + } + + if (strcmp(argv[1], "alloc") == 0) + { + uint32 addr = 0; + if (argc < 3) addr = (uint32)kmalloc(0x4); + else addr = (uint32)kmalloc(ConvertStringToUInt(argv[2])); + + ConsoleWrite("Returned address: %#0x%x\n", ColorWhite, addr); + } + + else if (strcmp(argv[1], "free") == 0) + { + if (argc < 3) { + ConsoleWrite ("%#! Missing parameter: address to free.", ColorRed); + return; + } + + kfree((void*)ConvertStringToIntHex(argv[2])); + ConsoleWrite("Done.\n"); + } + + else ConsoleWrite("%#! Invalid command. Available commands are: alloc, free.", ColorLightRed); +} + +void CommandCrash() +{ + int a = 10, b = 0; + ConsoleWrite ("%d", a/b); +} + +void CommandMouse() +{ + MouseState s = MouseGetState(); + ConsoleWrite("X=%d Y=%d Buttons=", s.Position.X, s.Position.Y); + + if (!s.Buttons) ConsoleWrite(""); + if (s.Buttons & 1) ConsoleWrite(""); + if (s.Buttons & 2) ConsoleWrite(""); + if (s.Buttons & 4) ConsoleWrite(""); + + ConsoleWrite("\n"); +} + +void CommandRead(string argv[], int32 argc) +{ + if (argc < 2) + { + ConsoleWrite("%#! Missing parameter - sector!\n", ColorLightRed); + return; + } + + uint32 sector = ConvertStringToUInt(argv[1]); + ConsoleWrite("Returned value: 0x%x\n", FloppyRead(0, sector)); +} diff --git a/Kernel/debug/commands.c~ b/Kernel/debug/commands.c~ new file mode 100644 index 0000000..3c95cd3 --- /dev/null +++ b/Kernel/debug/commands.c~ @@ -0,0 +1,255 @@ +#include +#include +#include +#include +#include "../hal/mouse/mouse.h" +#include "../drivers/floppy/floppy.h" + +string ConsoleCommands[] = +{ + "osver", + "time", + "cls", + "help", + "dump", + "mem", + "crash", + "mouse", + "read", + "reboot", + "restart", +}; + +int32 ConsoleCommandsCount = 11; + +/***************************************** + * osver - get os info * + *****************************************/ +void CommandOsver() +{ + ConsoleWrite ("%#%s%# 32bit operating system\n", Color(0,ColorYellow), OS_STRING, Color(0,ColorLightGray)); + + int32 i = 0; + for (i = 0; i < 30; i++) + ConsoleWrite ("%#%c", ColorDarkGray, 205); + + ConsoleWrite ("\n%#OS version: %#%s\n", ColorDarkGray, ColorLightGray, OS_VERSION); + ConsoleWrite ("%#Build: %#%s ", ColorDarkGray, ColorLightGray, OS_BUILD); + ConsoleWrite ("%#built on %#%s %#at %#%s\n", ColorDarkGray, ColorLightGray, OS_BUILD_DATE, ColorDarkGray, ColorLightGray, OS_BUILD_TIME); + ConsoleWrite ("%#(c) Copyright %#CTA Systems Inc.\n", ColorDarkGray ,ColorLightGray); +} + + +/***************************************** + * time - get date and time * + *****************************************/ +void CommandTime() +{ + const char* Months[] = { + "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + }; + + const char* Weekdays[] = { + "", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + }; + + + Time time = TimeConvertToTime(TimeGetInternalTime()); + + ConsoleWrite ("Current time: "); + ConsoleWrite ("%#%d:%d%d:%d%d.%d%d%d\n", Color(0,ColorLightGreen) ,(int)time.Hour, + time.Minute/10, time.Minute%10, time.Second/10, time.Second%10, time.Milisecond/100, (time.Milisecond/10)%10, time.Milisecond%10); + + ConsoleWrite ("Date: %#%s, %s %d, %d\n", Color(0,ColorLightGreen), Weekdays[time.WeekDay], + Months[time.Month], time.Day, time.Year); + +} + + +/***************************************** + * help - help provider * + *****************************************/ +void CommandHelp(string params[], int32 count) +{ + if (count <= 1) + { + ConsoleWrite ("Available commands:\n"); + + int i; + for (i = 0; i < ConsoleCommandsCount; i++) + ConsoleWrite(" > %#%s\n", Color(0,ColorWhite), ConsoleCommands[i]); + + return; + } + + ConsoleWrite("%#! Help for %s command is not implemented yet.\n", Color(0,ColorLightRed), params[1]); +} + + +/***************************************** + * dump - dumps memory content * + *****************************************/ +inline char hex (int32 digit) +{ + return (digit < 10) ? (digit + '0') : (digit - 10 + 'A'); +} + +void CommandDump (string argv[], int32 argc) +{ + unsigned pause = 1, i = 0; + + // Verify correct number of arguments + if (argc < 3) { + ConsoleWrite("%#! Correct syntax: %#dump %#[start_address] [end_address]\n", + ColorLightRed, ColorWhite, ColorLightGray); + ConsoleWrite("%#Start %#and %#end %#addresses are in hex.\n", + ColorLightGray, ColorDarkGray, ColorLightGray, ColorDarkGray); + return; + } + + // Disable pause + if (argc==4 && strcmp(argv[3], "!p") == 0) + pause = 0; + + // Dump memory + unsigned char *start, *end; + start = (unsigned char *) ConvertStringToIntHex(argv[1]); + end = (unsigned char *) ConvertStringToIntHex(argv[2]); + unsigned char* count; + + while (start <= end) { + // Write address + ConsoleWrite("%#%x%#: ", Color(0,ColorLightMagenta), (unsigned int)start, Color(0,ColorLightGray)); + + // Write hex data + for (count = start; count < start+16; count++) { + if (*count == 0) ConsoleWrite ("%#00 ", Color(0,ColorDarkGray)); + else ConsoleWrite ("%#%c%c ", Color(0,ColorWhite), hex(*count/16), hex(*count%16)); + } + + // Write ASCII data + ConsoleWrite(" "); + for (count = start; count < start+16; count++) { + if (*count < 32) ConsoleWrite("."); + else ConsoleWrite("%#%c", Color(0,ColorLightGreen), *count); + } + + // New line + ConsoleWrite("\n\r"); + start+=16; i++; + + // Pause + if ((i%22 == 0) && (pause==1)) { + ConsoleWrite("\n\r%#Press %#any key %#to continue scrolling, %#Esc %#to exit.", + 0x8, 0x7, 0x8, 0x7, 0x8); + Key k = ReadKey(); + if (k.Scancode == KeyboardKeyEscape) return; + ConsoleWrite("\n\n\r"); + } + } +} + + +#define _CommandMemTotalRows 10 +void _CommandMemPrintMemmap() +{ + uint8 color = Color(ColorGreen, ColorRed); + uint32 total = MemoryGetFramesTotal(); + + char c = ' '; + + // Print memory map + int32 i, old = 0, n = 0, blocks, used; + for (i = 0; i < 80; i++) + ConsoleWrite("%#%c", ColorLightGray, 220); + + for (i = 1; i <= 80*_CommandMemTotalRows; i++, old++) + { + n = (total * i) / (80 * _CommandMemTotalRows); + + blocks = n - old; + used = 0; + for (; old < n; old++) + used += (MemPhGetFrame(old) != 0); + + if (used <= blocks / 5) c = ' '; + else if (used > 4 * blocks / 5) c = 219; + else if (used <= 2 * blocks / 5) c = 176; + else if (used <= 3 * blocks / 5) c = 177; + else c = 178; + + ConsoleWrite("%#%c", color, c); + } + + for (i = 0; i < 80; i++) + ConsoleWrite("%#%c", ColorDarkGray, 223); +} + +void CommandMem (string argv[], int32 argc) +{ + if (argc < 2) + { + ConsoleWrite ("Memory map:\n"); + + _CommandMemPrintMemmap(); + + ConsoleWrite ("Free space: %#%ukb (%u frames)\n", ColorLightMagenta, MemoryGetFree(), MemoryGetFramesFree()); + ConsoleWrite ("Used space: %#%ukb (%u frames)\n\n", ColorLightMagenta, MemoryGetUsed(), MemoryGetFramesUsed()); + ConsoleWrite ("Total space: %#%ukb (%u frames)\n", ColorLightMagenta, MemoryGetTotal(), MemoryGetFramesTotal()); + + return; + } + + if (strcmp(argv[1], "alloc") == 0) + { + uint32 addr = 0; + if (argc < 3) addr = (uint32)kmalloc(0x4); + else addr = (uint32)kmalloc(ConvertStringToUInt(argv[2])); + + ConsoleWrite("Returned address: %#0x%x\n", ColorWhite, addr); + } + + else if (strcmp(argv[1], "free") == 0) + { + if (argc < 3) { + ConsoleWrite ("%#! Missing parameter: address to free.", ColorRed); + return; + } + + kfree((void*)ConvertStringToIntHex(argv[2])); + ConsoleWrite("Done.\n"); + } + + else ConsoleWrite("%#! Invalid command. Available commands are: alloc, free.", ColorLightRed); +} + +void CommandCrash() +{ + int a = 10, b = 0; + ConsoleWrite ("%d", a/b); +} + +void CommandMouse() +{ + MouseState s = MouseGetState(); + ConsoleWrite("X=%d Y=%d Buttons=", s.Position.X, s.Position.Y); + + if (!s.Buttons) ConsoleWrite(""); + if (s.Buttons & 1) ConsoleWrite(""); + if (s.Buttons & 2) ConsoleWrite(""); + if (s.Buttons & 4) ConsoleWrite(""); + + ConsoleWrite("\n"); +} + +void CommandRead(string argv[], int32 argc) +{ + if (argc < 2) + { + ConsoleWrite("%#! Missing parameter - sector!\n", ColorLightRed); + return; + } + + uint32 sector = ConvertStringToUInt(argv[1]); + ConsoleWrite("Returned value: 0x%x\n", FloppyRead(0, sector)); +} diff --git a/Kernel/debug/console-base.c b/Kernel/debug/console-base.c new file mode 100644 index 0000000..1eee06a --- /dev/null +++ b/Kernel/debug/console-base.c @@ -0,0 +1,131 @@ +#include +#include +#include + +uint8* VideoPtr = (uint8*) 0xb8000; + +Point ConsoleCursor = {0, 0}; +UPoint ConsoleSize = {80, 25}; + +uint8 ConsoleDefaultColor = CONSOLE_DEFAULT_COLOR; + +/************************************** + * Basic console operations * + **************************************/ +void ConsoleClear() +{ + uint32 temp; + + for (temp = 0; temp < ConsoleSize.X * ConsoleSize.Y; temp++) + { + VideoPtr[2 * temp] = 0; + VideoPtr[2 * temp + 1] = ConsoleDefaultColor; + } + + ConsoleCursor.X = ConsoleCursor.Y = 0; + ConsoleCursorUpdateHardware(); +} + +void ConsoleScroll (uint32 lines) +{ + // Sanity check, don't scroll too much + if (lines > ConsoleSize.Y) lines = ConsoleSize.Y; + + uint32 x, y; + for (y = 0; y < ConsoleSize.Y - lines; y++) + for (x = 0; x < 2*ConsoleSize.X; x++) + VideoPtr[y * ConsoleSize.X * 2 + x] = VideoPtr[(y+lines)*ConsoleSize.X*2 + x]; + + for (y = ConsoleSize.Y - lines; y < ConsoleSize.Y; y++) + for (x = 0; x < ConsoleSize.X; x++) + { + VideoPtr[2 * (y * ConsoleSize.X + x)] = 0; + VideoPtr[2 * (y * ConsoleSize.X + x) + 1] = ConsoleDefaultColor; + } + + ConsoleCursor.Y -= lines; +} + + +/************************************** + * Cursor position * + **************************************/ +Point ConsoleGetCursor() +{ + return ConsoleCursor; +} + +extern void ConsoleSetCursor(Point p) +{ + ConsoleCursor = p; +} + +void ConsoleCursorIncreasePos (int32 delta) +{ + // Increase X, Y positions + ConsoleCursor.Y += delta / ConsoleSize.X; + ConsoleCursor.X += delta % ConsoleSize.X; + + // Next line if X > Screen width + while (ConsoleCursor.X >= (int32)ConsoleSize.X) + { + ConsoleCursor.Y++; + ConsoleCursor.X -= ConsoleSize.X; + } + + // Previous line if X < 0 + while (ConsoleCursor.X < 0) + { + ConsoleCursor.Y--; + ConsoleCursor.X += ConsoleSize.X; + } + + // Scroll if Y > Screen height + if (ConsoleCursor.Y >= (int32)ConsoleSize.Y) + ConsoleScroll(1); +} + +void ConsoleCursorNewline() +{ + ConsoleCursor.X = 0; + + if (++ConsoleCursor.Y >= (int32)ConsoleSize.Y) + ConsoleScroll(1); +} + +void ConsoleCursorUpdateHardware() +{ + uint16 temp = (uint16) (ConsoleCursor.Y * ConsoleSize.X + ConsoleCursor.X); + uint16* port = (uint16*) 0x463 ; + + outportb(*port, 14); + outportb(*port + 1, (temp >> 8) & 0xff); + outportb(*port, 15); + outportb(*port + 1, temp & 0xff); +} + +uint8 Color (uint8 back, uint8 fore) +{ + return ((back<<4) | fore); +} + +void ConsoleSetDefaultColor(uint8 color) +{ + ConsoleDefaultColor = color; +} + +uint8 ConsoleGetDefaultColor () +{ + return ConsoleDefaultColor; +} + +UPoint ConsoleGetSize() +{ + return ConsoleSize; +} + +void ConsoleCursorGoto(Point p) +{ + if (p.X >= 0 && p.X < (int32)ConsoleSize.X) ConsoleCursor.X = p.X; + if (p.Y >= 0 && p.Y < (int32)ConsoleSize.Y) ConsoleCursor.Y = p.Y; +} diff --git a/Kernel/debug/console-in.c b/Kernel/debug/console-in.c new file mode 100644 index 0000000..d997ec7 --- /dev/null +++ b/Kernel/debug/console-in.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include "../hal/keyboard/keyboard.h" + +// extern uint8* VideoPtr; +extern UPoint ConsoleCursor; +// extern UPoint ConsoleSize; +// extern uint8 ConsoleDefaultColor; + +extern void _write_char (char c); +extern void _write_string (string s); + +int _next_word_index (string s, int32 direction, int32 current, int32 len) +{ + int32 tmp = current; + + if (direction < 0) { + --tmp; + while ((isspace((unsigned char)s[tmp]) || ispunct((unsigned char)s[tmp])) && tmp > 0) --tmp; + while (isalnum((unsigned char)s[tmp]) && tmp > 0) --tmp; + + if (tmp != 0) tmp++; + } + + else { + ++tmp; + while (isalnum((unsigned char)s[tmp]) && tmp < len) ++tmp; + while ((isspace((unsigned char)s[tmp]) || ispunct((unsigned char)s[tmp])) && tmp < len) ++tmp; + } + + return tmp; +} + +void _string_crop (string s, int32 start, int32 end, int32* len) +{ + int32 i; + for (i = end; i < *len; i++) + s[i-(end-start)] = s[i]; + + *len = *len - (end - start); + s[*len] = 0; +} + +void _string_insert (string s, char what, int32 position, int32* len) +{ + int32 i; + for (i = *len; i > position; i--) + s[i] = s[i-1]; + + s[position] = what; + *len = *len + 1; + + s[*len] = 0; +} + +void ConsoleReadString (string s, int32 buffer_size, char end_char) +{ + Key key; + int32 cursor=0, length = 0, old_length = 0; + UPoint cursor_original = ConsoleCursor; + + s[0] = 0; + + do { + // Read a key from keyboard + key = ReadKey(); + + // Process scancode + switch (key.Scancode) + { + // Left arrow + case KeyboardKeyLeft: + if (cursor > 0) + { + if (KeyboardGetKeyStatus(KeyboardKeyRightCtrl) || KeyboardGetKeyStatus(KeyboardKeyLeftCtrl)) + cursor = _next_word_index(s, -1, cursor, length); + else --cursor; + } + break; + + // Right arrow + case KeyboardKeyRight: + if (cursor < length) + { + if (KeyboardGetKeyStatus(KeyboardKeyRightCtrl) || KeyboardGetKeyStatus(KeyboardKeyLeftCtrl)) + cursor = _next_word_index(s, 1, cursor, length); + else ++cursor; + } + break; + + // Delete key + case KeyboardKeyDelete: + { + if (cursor == length) break; + + int32 start_d = cursor, end_d; + if (KeyboardGetKeyStatus(KeyboardKeyRightCtrl) || KeyboardGetKeyStatus(KeyboardKeyLeftCtrl)) + end_d = _next_word_index(s, 1, cursor, length); + else end_d = cursor + 1; + + _string_crop(s, start_d, end_d, &length); + + break; + } + + // Backspace key + case KeyboardKeyBackspace: + { + if (cursor == 0) break; + + int32 end = cursor; + if (KeyboardGetKeyStatus(KeyboardKeyRightCtrl) || KeyboardGetKeyStatus(KeyboardKeyLeftCtrl)) + cursor = _next_word_index(s, -1, cursor, length); + else cursor --; + + _string_crop(s, cursor, end, &length); + + break; + } + + // Home key + case KeyboardKeyHome: + cursor = 0; break; + + // End key + case KeyboardKeyEnd: + cursor = length; break; + + // Rest of keys + default: + // Ignore non-character keys + if (key.Character == 0 || iscntrl(key.Character)) break; + + _string_insert(s, key.Character, cursor, &length); + ++cursor; + + break; + } + + // Redraw string + ConsoleCursor = cursor_original; + + // Remove old string if still there + int32 i; + if (old_length > length) + for (i = 0; i < old_length; i++) + _write_char(' '); + + old_length = length; + ConsoleCursor = cursor_original; + _write_string(s); + + ConsoleCursor = cursor_original; + ConsoleCursorIncreasePos(cursor); + ConsoleCursorUpdateHardware(); + + } while (key.Character != end_char && length < buffer_size); + + ConsoleWriteChar('\n'); +} + diff --git a/Kernel/debug/console-out.c b/Kernel/debug/console-out.c new file mode 100644 index 0000000..94de0a2 --- /dev/null +++ b/Kernel/debug/console-out.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include + +extern uint8* VideoPtr; + +extern UPoint ConsoleCursor; +extern UPoint ConsoleSize; + +extern uint8 ConsoleDefaultColor; + +/************************************** + * Write operations* + **************************************/ +void _write_char(char c) +{ + switch (c) + { + case '\n': + ConsoleCursorNewline(); break; + + case '\r': + ConsoleCursor.X = 0; break; + + case '\t': + ConsoleCursorIncreasePos(6 - ConsoleCursor.X % 6); break; + + case '\b': + ConsoleCursorIncreasePos(-1); + VideoPtr[2 * (ConsoleCursor.Y * ConsoleSize.X + ConsoleCursor.X)] = 0; + break; + + default: + VideoPtr[2 * (ConsoleCursor.Y * ConsoleSize.X + ConsoleCursor.X)] = c; + VideoPtr[2 * (ConsoleCursor.Y * ConsoleSize.X + ConsoleCursor.X) + 1] = ConsoleDefaultColor; + + ConsoleCursorIncreasePos(1); + break; + } +} + +void _write_string (string s) +{ + int32 len = strlen(s), i; + + for (i = 0; i < len; i++) + _write_char(s[i]); +} + + +void ConsoleWriteChar (char c) +{ + _write_char(c); + ConsoleCursorUpdateHardware(); +} + +void ConsoleWriteString (string s) +{ + _write_string(s); + ConsoleCursorUpdateHardware(); +} + +int32 ConsoleWrite (string format, ...) +{ + if (!format || !*format) return 0; + + va_list args; + va_start (args, format); + uint32 i, len = strlen(format); + + uint8 temp_color = ConsoleDefaultColor; + + for (i = 0; i < len; i++) + if (format[i] != '%') _write_char(format[i]); + else + { + ++i; + switch (format[i]) { + // Character + case 'c': { + char c = va_arg (args, char); + _write_char(c); + break; + } + + // String + case 's': { + int32* c = (int32*) va_arg (args, string); + _write_string((string)c); + break; + } + + // Integers + case 'd': + case 'i': { + int32 c = va_arg(args, int32); char temp[32]; + ConvertIntToString(temp, c, 10); + _write_string(temp); + break; + } + + // Integers - hex + case 'X': + case 'x': { + int32 c = va_arg(args, int32); char temp[32]; + ConvertUIntToString(temp, c, 16); + _write_string(temp); + break; + } + + // Integers - unsigned + case 'u': { + int32 c = va_arg(args, uint32); char temp[32]; + ConvertUIntToString (temp, c, 10); + _write_string(temp); + break; + } + + // Colors + case '#': { + uint8 c = va_arg(args, uint8); + ConsoleDefaultColor = c; + break; } + + default: va_end(args); return 1; + }; + } + + va_end(args); + + ConsoleDefaultColor = temp_color; + ConsoleCursorUpdateHardware(); + return i; +} + +void ConsoleSetChar(Point pos, char c) +{ + VideoPtr[2 * (pos.Y * ConsoleSize.X + pos.X)] = c; +} + +void ConsoleSetColor(Point pos, uint8 color) +{ + VideoPtr[2 * (pos.Y * ConsoleSize.X + pos.X) + 1] = color; +} + +char ConsoleGetChar(Point pos) +{ + return (char)VideoPtr[2 * (pos.Y * ConsoleSize.X + pos.X)]; +} + +uint8 ConsoleGetColor (Point pos) +{ + return VideoPtr[2 * (pos.Y * ConsoleSize.X + pos.X) + 1]; +} diff --git a/Kernel/debug/console.c b/Kernel/debug/console.c new file mode 100644 index 0000000..b98ba17 --- /dev/null +++ b/Kernel/debug/console.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include "commands.c" + +void _process_command (string params[16], int32 count); +void _command_does_not_exist(string command); + +void ConsoleMain() +{ + char buffer[512]; + string params[CONSOLE_MAX_PARAMS]; + + CommandOsver(); + + for (;;) + { + // Read a string + ConsoleWrite("\n%#] ", Color(ColorBlack, ColorYellow)); + ConsoleReadString(buffer, 512, '\n'); + + // Split buffer in params + params[0] = buffer; + + int32 i=0, len = strlen(buffer), param_count = 0; + + while (i < len && param_count < CONSOLE_MAX_PARAMS) + { + // Skip spaces before + while (i < len && isspace(buffer[i])) buffer[i++] = 0; + if (i == len) break; + + params[param_count++] = &buffer[i]; + + // Skip non-spaces + while (i < len && !isspace(buffer[i])) i++; + } + + // Send command to processing + _process_command(params, param_count); + } + +} + +void _process_command (string params[CONSOLE_MAX_PARAMS], int32 count) +{ + int32 Cmd = -1; + + if (count == 0) + { + ConsoleWrite ("%#! You must enter a command!\n", Color(0, ColorLightRed)); + return; + } + + // Lookup command in list + int32 i; + for (i = 0; i < ConsoleCommandsCount && Cmd == -1; i++) + if (strcmp(params[0], ConsoleCommands[i]) == 0) Cmd = i; + + switch (Cmd) + { + case -1: _command_does_not_exist(params[0]); break; + case 0: CommandOsver(); break; + case 1: CommandTime(); break; + case 2: ConsoleClear(); break; + case 3: CommandHelp(params, count); break; + case 4: CommandDump (params, count); break; + case 5: CommandMem(params, count); break; + case 6: CommandCrash(); break; + case 7: CommandMouse(); break; + case 8: CommandRead(params, count); break; + case 9: + case 10: SystemReboot(); break; + + default: ConsoleWrite ("%#! Command %#%s%# was not implemented (yet)!\n", + Color(0,ColorLightRed), Color(0,ColorWhite), params[0], Color(0,ColorLightRed)); break; + } + + +} + +void _command_does_not_exist(string command) +{ + if (strlen(command) > 20) + { + command[18] = command[19] = command[20] = '.'; + command[21] = null; + } + + ConsoleWrite ("%#! Command %#%s%# does not exist!\n", + Color(0,ColorLightRed), Color(0,ColorWhite), command, Color(0,ColorLightRed)); + +} diff --git a/Kernel/drivers/cmos/cmos.c b/Kernel/drivers/cmos/cmos.c new file mode 100644 index 0000000..0a0a7bc --- /dev/null +++ b/Kernel/drivers/cmos/cmos.c @@ -0,0 +1,63 @@ +#include +#include +#include "cmos.h" + +uint8 CmosRead (uint8 address) +{ + outportb(0x70, address); iowait(); + return inportb(0x71); +} + +void CmosWrite (uint8 address, uint8 val) +{ + outportb(0x70, address); iowait(); + outportb(0x71, val); +} + +void CmosSetRTC (const Time* time) +{ + unsigned char BCD = ((CmosRead(0x0b)&4)==0) ? 1 : 0; + unsigned char ampm = ((CmosRead(0x0b)&2)==0) ? 1 : 0; + + uint8 year = time->Year % 100; + uint8 century = time->Year / 100; + + CmosWrite (0, (BCD) ? (time->Second%10) | (time->Second/10*16) : time->Second); // Seconds + CmosWrite (2, (BCD) ? (time->Minute%10) | (time->Minute/10*16) : time->Minute); // Minutes + + if (ampm && time->Hour > 12) // Hours + CmosWrite (4, (BCD) ? (((time->Hour - 12) % 10) | ((time->Hour - 12)/10*16) | 0x80) : (time->Hour | 0x80) ); + + else if (ampm && time->Hour == 0) // Midnight convention: 12 PM = 00:00 + CmosWrite (4, (BCD) ? 0x92 : 0x8C); + + else CmosWrite (4, (BCD) ? (time->Hour%10) | (time->Hour/10*16) : time->Hour); // 24h / AM + + CmosWrite (7, (BCD) ? (time->Day%10) | (time->Day/10*16) : time->Day); // Day + CmosWrite (8, (BCD) ? (time->Month%10) | (time->Month/10*16) : time->Month); // Month + CmosWrite (9, (BCD) ? (year%10) | (year/10*16) : year); // Year + CmosWrite (0x32, (BCD) ? (century%10) | (century/10*16) : century); // Century +} + +void CmosGetRTC(Time* tim) +{ + unsigned char BCD = ((CmosRead(0x0b)&4)==0) ? 1 : 0; + unsigned char am_pm = ((CmosRead(0x0b)&2)==0) ? 1 : 0; + + tim->Second = (BCD) ? (CmosRead(0x00)%16) + 10*(CmosRead(0x00)/16): CmosRead(0x00); + tim->Minute = (BCD) ? (CmosRead(0x02)%16) + 10*(CmosRead(0x02)/16): CmosRead(0x02); + + // Time is PM + if (am_pm && (CmosRead(0x04)&80)) { + tim->Hour = (BCD) ? ((CmosRead(0x04)-0x80)%16) + 10*((CmosRead(0x04)-0x80)/16): CmosRead(0x04)-0x80; + tim->Hour += 12; + } + // 24Hour format, or AM + else tim->Hour = (BCD) ? (CmosRead(0x04)%16) + 10*(CmosRead(0x04)/16): CmosRead(0x04); + + tim->WeekDay = (BCD) ? (CmosRead(0x06)%16) + 10*(CmosRead(0x06)/16): CmosRead(0x06); + tim->Day = (BCD) ? (CmosRead(0x07)%16) + 10*(CmosRead(0x07)/16): CmosRead(0x07); + tim->Month = (BCD) ? (CmosRead(0x08)%16) + 10*(CmosRead(0x08)/16): CmosRead(0x08); + tim->Year = (BCD) ? (CmosRead(0x09)%16) + 10*(CmosRead(0x09)/16): CmosRead(0x09); + tim->Year += 100 * ((BCD) ? (CmosRead(0x32)%16) + 10*(CmosRead(0x32)/16): CmosRead(0x32)); +} diff --git a/Kernel/drivers/cmos/cmos.h b/Kernel/drivers/cmos/cmos.h new file mode 100644 index 0000000..f6f2685 --- /dev/null +++ b/Kernel/drivers/cmos/cmos.h @@ -0,0 +1,12 @@ +#ifndef __CMOS__H +#define __CMOS__H + +#include +#include + +extern uint8 CmosRead (uint8 address); +extern void CmosWrite (uint8 address, uint8 val); +extern void CmosSetRTC (const Time* time); +extern void CmosGetRTC(Time* tim); + +#endif \ No newline at end of file diff --git a/Kernel/drivers/dma/dma.c b/Kernel/drivers/dma/dma.c new file mode 100644 index 0000000..0c389eb --- /dev/null +++ b/Kernel/drivers/dma/dma.c @@ -0,0 +1,111 @@ +/* + * dma.c + * + * Created on: Aug 20, 2011 + * Author: Tiberiu + */ + +#include +#include "dma.h" + +void DmaSetAddress (uint8 channel, uint8 low, uint8 high) +{ + uint16 port = 0; + + switch (channel) + { + case 0: port = DmaRegisterChannel0Address; break; + case 1: port = DmaRegisterChannel1Address; break; + case 2: port = DmaRegisterChannel2Address; break; + case 3: port = DmaRegisterChannel3Address; break; + case 4: port = DmaRegisterChannel4Address; break; + case 5: port = DmaRegisterChannel5Address; break; + case 6: port = DmaRegisterChannel6Address; break; + case 7: port = DmaRegisterChannel7Address; break; + default: return; + } + + outportb(port, low); iowait(); + outportb(port, high); +} + +void DmaSetCount (uint8 channel, uint8 low, uint8 high) +{ + uint16 port = 0; + + switch (channel) + { + case 0: port = DmaRegisterChannel0Count; break; + case 1: port = DmaRegisterChannel1Count; break; + case 2: port = DmaRegisterChannel2Count; break; + case 3: port = DmaRegisterChannel3Count; break; + case 4: port = DmaRegisterChannel4Count; break; + case 5: port = DmaRegisterChannel5Count; break; + case 6: port = DmaRegisterChannel6Count; break; + case 7: port = DmaRegisterChannel7Count; break; + default: return; + } + + outportb(port, low); iowait(); + outportb(port, high); +} + +void DmaSetExternalPageRegisters (uint8 channel, uint8 val) +{ + uint16 port = 0; + + switch (channel) + { + case 1: port = DmaRegisterChannel1PageAddress; break; + case 2: port = DmaRegisterChannel2PageAddress; break; + case 3: port = DmaRegisterChannel3PageAddress; break; + case 5: port = DmaRegisterChannel5PageAddress; break; + case 6: port = DmaRegisterChannel6PageAddress; break; + case 7: port = DmaRegisterChannel7PageAddress; break; + default: return; + } + + outportb(port, val); +} + +void DmaResetFlipFlop (uint8 channel) +{ + uint16 port = (channel < 4) ? DmaRegisterFlipFlopReset : 2*DmaRegisterFlipFlopReset+0xC0; + outportb(port, 0); +} + +void DmaReset () +{ + outportb(DmaRegisterMasterReset, 0); +} + +void DmaUnmaskAll() +{ + outportb(DmaRegisterMaskReset, 0); +} + +void DmaMaskChannel(uint8 channel) +{ + if (channel >= 8) return; + uint16 port = (channel < 4) ? (DmaRegisterSingleChannelMask) : (2*DmaRegisterSingleChannelMask + 0xC0); + + outportb(port, channel%4 | 4); +} + +void DmaUnmaskChannel (uint8 channel) +{ + if (channel >= 8) return; + uint16 port = (channel < 4) ? (DmaRegisterSingleChannelMask) : (2*DmaRegisterSingleChannelMask + 0xC0); + + outportb(port, channel%4); +} + +void DmaSetMode (uint8 channel, uint8 mode) +{ + if (channel >= 8) return; + uint16 port = (channel < 4) ? (DmaRegisterMode) : (2*DmaRegisterMode + 0xC0); + + DmaMaskChannel(channel); + outportb(port, (channel%4) | mode ); + DmaUnmaskAll(); +} diff --git a/Kernel/drivers/dma/dma.h b/Kernel/drivers/dma/dma.h new file mode 100644 index 0000000..f4840de --- /dev/null +++ b/Kernel/drivers/dma/dma.h @@ -0,0 +1,80 @@ +/* + * dma.h + * + * Created on: Aug 20, 2011 + * Author: Tiberiu + */ + +#ifndef DMA_H_ +#define DMA_H_ + +#include + +enum DmaRegisters +{ + DmaRegisterStatus = 0x08, + DmaRegisterCommand = 0x08, + DmaRegisterRequest = 0x09, + DmaRegisterSingleChannelMask = 0x0A, + DmaRegisterMode = 0x0B, + DmaRegisterFlipFlopReset = 0x0C, + DmaRegisterIntermediate = 0x0D, + DmaRegisterMasterReset = 0x0D, + DmaRegisterMaskReset = 0x0E, + DmaRegisterMultichannelMask = 0x0F, + + DmaRegisterChannel0Address = 0x00, + DmaRegisterChannel1Address = 0x02, + DmaRegisterChannel2Address = 0x04, + DmaRegisterChannel3Address = 0x06, + DmaRegisterChannel4Address = 0xC0, + DmaRegisterChannel5Address = 0xC4, + DmaRegisterChannel6Address = 0xC8, + DmaRegisterChannel7Address = 0xCC, + + DmaRegisterChannel0Count = 0x01, + DmaRegisterChannel1Count = 0x03, + DmaRegisterChannel2Count = 0x05, + DmaRegisterChannel3Count = 0x07, + DmaRegisterChannel4Count = 0xC2, + DmaRegisterChannel5Count = 0xC6, + DmaRegisterChannel6Count = 0xCA, + DmaRegisterChannel7Count = 0xCE, + + DmaRegisterChannel1PageAddress = 0x83, + DmaRegisterChannel2PageAddress = 0x81, + DmaRegisterChannel3PageAddress = 0x82, + DmaRegisterChannel5PageAddress = 0x8B, + DmaRegisterChannel6PageAddress = 0x89, + DmaRegisterChannel7PageAddress = 0x8A +}; + +enum DmaModes +{ + DmaModeChannelMask = 0x3, + + DmaModeSelfTest = 0, + DmaModeWrite = 0x8, + DmaModeRead = 0x4, + DmaModeAutoReinit = 0x10, + DmaModeDown = 0x20, + + DmaModeTransferOnDemand = 0, + DmaModeTransferSingleDma = 0x40, + DmaModeTransferBlockDma = 0x80, + DmaModeTransferCascade = 0xC0 +}; + +extern void DmaSetAddress (uint8 channel, uint8 low, uint8 high); +extern void DmaSetCount (uint8 channel, uint8 low, uint8 high); +extern void DmaSetExternalPageRegisters (uint8 channel, uint8 val); +extern void DmaSetMode (uint8 channel, uint8 mode); + +extern void DmaResetFlipFlop (uint8 channel); +extern void DmaReset (); + +extern void DmaMaskChannel(uint8 channel); +extern void DmaUnmaskChannel (uint8 channel); +extern void DmaUnmaskAll (); + +#endif /* DMA_H_ */ diff --git a/Kernel/drivers/drivers.c b/Kernel/drivers/drivers.c new file mode 100644 index 0000000..2f03bae --- /dev/null +++ b/Kernel/drivers/drivers.c @@ -0,0 +1,34 @@ +#include "drivers.h" +#include "cmos/cmos.h" +#include "pit/pit.h" +#include "floppy/floppy.h" +#include "time.h" +#include "../hal/cpu/irq.h" +#include + +void DriversInstall_Clock() +{ + // Set up PIT + PitSetFrequency(PIT_FREQUENCY); + + // Update internal clock + Time time; + CmosGetRTC(&time); + + TimeSetInternalTime(TimeConvertToTimeSystem(time)); + + Log("%#[Drivers] %#Read RTC time: ", ColorWhite, ColorLightGray); + Log("%#%u/%u/%u %u:%u:%u.%u\n", ColorLightCyan, time.Month, time.Day, + time.Year, time.Hour, time.Minute, time.Second, time.Milisecond); +} + + +void DriversInstall() +{ + // Install clock + DriversInstall_Clock(); + + // Install fdc + IrqInstallHandler(6, FloppyIrqHandler); + FloppyInitialize(); +} diff --git a/Kernel/drivers/drivers.h b/Kernel/drivers/drivers.h new file mode 100644 index 0000000..0037418 --- /dev/null +++ b/Kernel/drivers/drivers.h @@ -0,0 +1,6 @@ +#ifndef __DRIVERS__H +#define __DRIVERS__H + +extern void DriversInstall(); + +#endif diff --git a/Kernel/drivers/floppy/floppy.c b/Kernel/drivers/floppy/floppy.c new file mode 100644 index 0000000..caa5999 --- /dev/null +++ b/Kernel/drivers/floppy/floppy.c @@ -0,0 +1,384 @@ +/* + * floppy.c + * + * Created on: Aug 20, 2011 + * Author: Tiberiu + */ + +#include +#include +#include +#include +#include +#include "floppy.h" +#include "../dma/dma.h" +#include "../cmos/cmos.h" + +FloppyType fdTypes[] = { +/* Sectors + * | Sectors per track + * | | Heads + * | | | Tracks + * | | | | Gap1 + * | | | | | Data rate + * | | | | | | Spec1 + * | | | | | | | SRT HLT HUT Motor Spinup time + * | | | | | | | | | | | Motor Spindown time + * | | | | | | | | | | | | Interrupt timeout + * | | | | | | | | | | | | | Disk type name string*/ + { 0, 0,0, 0,0x00,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, "none"}, + { 720, 9,2,40,0x2A,0x01,0xDF,0x0C,0x04,0x00,1000,1000,3000, "5.25\" 360k"}, + { 2400,15,2,80,0x1B,0x00,0xDF,0x0A,0x08,0x00, 400,1000,3000, "5.25\" 1.2M"}, + { 1440, 9,2,80,0x2A,0x02,0xDF,0x0F,0x04,0x00,1000,1000,3000, "3.5\" 720k"}, + { 2880,18,2,80,0x1B,0x00,0xCF,0x0C,0x08,0x00, 400,1000,3000, "3.5\" 1.44M"}, + //{ 2880,18,2,80,0x1B,0x00,0xCF,0x0C,0x08,0x00,2000,3000,3000, "3.5\" 1.44M"}, + { 5760,36,2,80,0x1B,0x03,0xAF,0x0A,0x0F,0x00, 400,1000,3000, "3.5\" 2.88M AMI BIOS"}, + { 5760,36,2,80,0x1B,0x03,0xAF,0x0A,0x0F,0x00, 400,1000,3000, "3.5\" 2.88M"}, +}; + +int8 fd0, fd1; + +/************************************** + * IRQ handler etc * + **************************************/ +volatile uint8 FloppyIrqFired; +void FloppyIrqHandler(_RegsStack32* UNUSED(r)) +{ + FloppyIrqFired = 1; +} + +void FloppyWaitIrq() +{ + TimerStart(fdTypes[4].InterruptTimeout); + + while (!FloppyIrqFired && !TimerIsDone()); + + if (!FloppyIrqFired) { + Error("%#[Floppy] %#Irq timeout [%ums] !\n", ColorBrown, ColorLightRed, fdTypes[4].InterruptTimeout); + } +} + + +/************************************** + * Installation * + **************************************/ +void FloppyInitialize() +{ + // Detect drives + uint8 fd = CmosRead(0x10); + fd0 = fd >> 4; + fd1 = fd & 0xf; + + if (fd0 > 6) fd0 = 0; + if (fd1 > 6) fd1 = 0; + + if (!fd0 && !fd1) { + Error("%#[Floppy] %#No supported floppy drives found.", ColorBrown, ColorLightRed); + outportb(FloppyRegisterDigitalOutput, 0); + return; + } + + Log("%#[Floppy] %#Detected floppy drives:", ColorBrown, ColorLightGray); + if (fd0) Log(" %#fd0=%#%s", ColorLightCyan, Color(ColorCyan, ColorWhite), fdTypes[fd0].Name); + if (fd1) Log(" %#fd1=%#%s", ColorLightCyan, Color(ColorCyan, ColorWhite), fdTypes[fd1].Name); + Log("\n"); + + + // Reset floppy controller + FloppyReset(); + + // Configure and lock + FloppyConfigure(); + FloppySendCommand(FloppyCommandLock | 0x80); + FloppyReadData(); + + // Enable perpendicular mode for 3.5" ED floppies + if (fd0 > 4) + { + FloppySendCommand(FloppyCommandPerpendicularMode); + FloppySendCommand(1); + } + if (fd1 > 4) + { + FloppySendCommand(FloppyCommandPerpendicularMode); + FloppySendCommand(2); + } + + // Initialize DMA + FloppyInitDma(); +} + +void FloppyInitDma() +{ + DmaMaskChannel(2); + DmaResetFlipFlop(2); + DmaSetAddress(2, 0, 0x10); + DmaResetFlipFlop(2); + DmaSetCount(2, 0xff, 0x23); + DmaSetExternalPageRegisters(2,0); + DmaUnmaskChannel(2); +} + + +/************************************** + * Controller reset * + **************************************/ +void FloppyReset() +{ + FloppyIrqFired = 0; int32 i = 0; + + Log("%#[Floppy] %#Resetting...\n", ColorBrown, ColorLightGray); + + // Clear reset bit from DOR + outportb(FloppyRegisterDigitalOutput, 0); + for (i = 0; i < 1000; i++); + outportb(FloppyRegisterDigitalOutput, 4|8); + + // Wait for IRQ6 + FloppyWaitIrq(fd0); + + // Recalibrate every drive + if (fd0) + { + FloppyMotor(0,1); + FloppySelectDrive(0); + FloppyRecalibrate(0); + FloppyMotor(0,0); + } + + if (fd1) + { + FloppyMotor(1,1); + FloppySelectDrive(1); + FloppyRecalibrate(1); + FloppyMotor(1,0); + } + +} + +/************************************** + * Configure floppy controller * + **************************************/ +void FloppyConfigure() +{ + FloppySendCommand(FloppyCommandConfigure); + FloppySendCommand(0); + FloppySendCommand(1<<6 | 7); + FloppySendCommand(0); +} + +/************************************** + * Base commands * + **************************************/ +void FloppySendCommand (uint8 command) +{ + int32 t; + for (t = 0; t < 5000 && ((inportb(FloppyRegisterMainStatus) & FloppyMsrRQM) == 0); t++) ; + + outportb (FloppyRegisterFIFO, command); + +} + +uint8 FloppyReadData () +{ + int32 t; + for (t = 0; t < 5000 && ((inportb(FloppyRegisterMainStatus) & FloppyMsrRQM) == 0); t++) ; + + return inportb (FloppyRegisterFIFO); +} + +/************************************** + * Sense interrupt * + **************************************/ +void FloppySenseInterrupt(uint8 *st0, uint8 *cyl) +{ + FloppySendCommand(FloppyCommandSenseInterrupt); + *st0 = FloppyReadData(); + *cyl = FloppyReadData(); +} + +/************************************** + * Specify * + **************************************/ +void FloppySpecify (uint8 fd) +{ + FloppySendCommand(FloppyCommandSpecify); + FloppySendCommand((fdTypes[fd].SRT << 4) | fdTypes[fd].HUT); + FloppySendCommand(fdTypes[fd].HLT << 1); +} + +/************************************** + * Motor on/off * + **************************************/ +void FloppyMotor (uint8 fd_number, uint8 status) +{ + if (fd_number >= 2) return; + + uint8 fd = (fd_number == 0) ? fd0 : fd1; + uint8 temp = inportb(FloppyRegisterDigitalOutput); + + // Turn motor on/off + if (status) temp |= 0x1<<(4+fd_number); + else temp &= ~(0x1<<(4+fd_number)); + outportb(FloppyRegisterDigitalOutput, temp); + + // Wait for spinup/spindown + if (status) TimerStart(fdTypes[fd].Spinup); + else TimerStart(fdTypes[fd].Spindown); + + Log("%#[Floppy] %#Waiting for motor...\n", ColorBrown, ColorLightGray); + while (!TimerIsDone()); +} + +/************************************** + * Select drive * + **************************************/ +void FloppySelectDrive(uint8 number) +{ + if (number >= 2) return; + uint8 fd = (number == 0) ? fd0 : fd1; + + // Set CCR + outportb(FloppyRegisterConfigurationControl, fdTypes[fd].DataRate); + + // Specify + FloppySpecify(fd); + + // Select drive + uint8 dor = inportb(FloppyRegisterDigitalOutput); + dor = (dor & ~0xFF) | number; +} + +/************************************** + * RECALIBRATE * + * motor must be on, drive selected * + **************************************/ +void FloppyRecalibrate(uint8 fd_number) +{ + if (fd_number >= 2) return; + + uint8 st0, cyl, timeout = 10; + do { + Log("%#[Floppy] %#Recalibrating: attempt %u/10\n", ColorBrown, ColorLightGray, 11-timeout); + FloppyIrqFired = 0; + FloppySendCommand(FloppyCommandRecalibrate); + FloppySendCommand(fd_number); + FloppyWaitIrq(); + + FloppySenseInterrupt(&st0, &cyl); + + timeout--; + } while((st0 & 0x20) == 0 && timeout > 0); +} + +/************************************** + * SEEK * + * motor must be on, drive selected * + **************************************/ +void FloppySeek(uint8 fd_number, uint8 cylinder, uint8 head) +{ + if (fd_number >= 2) return; + + uint8 st0, cyl, timeout = 10; + do { + Log("%#[Floppy] %#Seeking: attempt %u/10\n", ColorBrown, ColorLightGray, 11-timeout); + FloppyIrqFired = 0; + FloppySendCommand(FloppyCommandSeek); + FloppySendCommand(head<<2 | fd_number); + FloppySendCommand(cylinder); + FloppyWaitIrq(); + + FloppySenseInterrupt(&st0, &cyl); + + timeout--; + } while(cyl != cylinder && timeout > 0); + +} + +/************************************** + * READ/WRITE * + * motor must be on, drive selected * + **************************************/ +void FloppyRW(uint8 isWrite, uint8 fd_number, uint8 head, uint8 cylinder, uint8 sector) +{ + if (fd_number >= 2) return; + uint8 fd = (fd_number == 0) ? fd0 : fd1; + + uint8 timeout = 10; + uint8 result[7], i, error; + do + { + error = 0; + Log("%#[Floppy] %#Read/write operation: attempt %u/10\n", ColorBrown, ColorLightGray, 11-timeout); + FloppyIrqFired = 0; + + if (isWrite) FloppySendCommand(FloppyCommandWriteData | FloppyModeMultitrack | FloppyModeMagneticEncoding); + else FloppySendCommand(FloppyCommandReadData | FloppyModeMultitrack | FloppyModeMagneticEncoding); + + FloppySendCommand(head<<2 | fd_number); + FloppySendCommand(cylinder); + FloppySendCommand(head); + FloppySendCommand(sector); + FloppySendCommand(2); + FloppySendCommand(fdTypes[fd].SectorsPerTrack); + FloppySendCommand(fdTypes[fd].Gap); + FloppySendCommand(0xff); + + FloppyWaitIrq(); + + for (i = 0; i < 7; i++) + result[i] = FloppyReadData(); + + // Disk is write protected, don't try again + if (result[1] & 2) + { + Error("%#[Floppy] %#Error: disk is write protected!\n", ColorBrown, ColorLightRed); + return; + } + + // Any other error - try again + if (result[0] & 0xC8) error = 1; + if (result[1] & 0xB5) error = 1; + if (result[2] & 0x77) error = 1; + if (result[6] & 0x02) error = 1; + + timeout--; + } while (timeout > 0 && !error); +} + +uint32 FloppyRead(uint8 drive, uint32 lba) +{ + if (drive >= 2) return 0; + uint8 fd = (drive == 0) ? fd0 : fd1; + + // Convert LBA to CHS + uint32 cyl=0, head=0, sect=1; + ConvertLbaToChs(fdTypes[fd].SectorsPerTrack, lba, &cyl, &head, §); + Log("%#[Floppy] %#Converted LBA=%u to Cyl=%u Head=%u Sect=%u\n", ColorBrown, ColorLightGray, lba, cyl, head, sect); + + FloppyInitDma(); + + // Reset drive if necessary + if ((inportb(FloppyRegisterMainStatus) & 0xC0) != 0x80) + FloppyReset(); + + // Start motor, select drive + FloppyMotor(drive, 1); + FloppySelectDrive(drive); + + // Seek to correct location + FloppySeek(drive, cyl, head); + + // Start DMA read + DmaMaskChannel(2); + DmaSetMode(2, 0x46); + DmaUnmaskChannel(2); + + FloppyRW(0, drive, head, cyl, sect); + + FloppyMotor(drive, 0); + + return 0x1000; +} + +// Log("%#[Drivers] %#Initializing blah blah %d...", ColorWhite, ColorLightGray,PIT_FREQUENCY); diff --git a/Kernel/drivers/floppy/floppy.h b/Kernel/drivers/floppy/floppy.h new file mode 100644 index 0000000..1f1e8c7 --- /dev/null +++ b/Kernel/drivers/floppy/floppy.h @@ -0,0 +1,86 @@ +/* + * floppy.h + * + * Created on: Aug 20, 2011 + * Author: Tiberiu + */ + +#ifndef FLOPPY_H_ +#define FLOPPY_H_ + +#include + +enum FloppyRegisters +{ + FloppyRegisterStatusA = 0x3F0, // read-only + FloppyRegisterStatusB = 0x3F1, // read-only + FloppyRegisterDigitalOutput = 0x3F2, + FloppyRegisterTapeDrive = 0x3F3, + FloppyRegisterMainStatus = 0x3F4, // read-only + FloppyRegisterDatarateSelect = 0x3F4, // write-only + FloppyRegisterFIFO = 0x3F5, + FloppyRegisterDigitalInput = 0x3F7, // read-only + FloppyRegisterConfigurationControl = 0x3F7 // write-only +}; + +enum FloppyCommands +{ + FloppyCommandReadTrack = 2, // generates IRQ6 + FloppyCommandSpecify = 3, // * set drive parameters + FloppyCommandSenseDriveStatus = 4, + FloppyCommandWriteData = 5, // * write to the disk + FloppyCommandReadData = 6, // * read from the disk + FloppyCommandRecalibrate = 7, // * seek to cylinder 0 + FloppyCommandSenseInterrupt = 8, // * ack IRQ6, get status of last command + FloppyCommandWriteDeletedData = 9, + FloppyCommandReadID = 10, // generates IRQ6 + FloppyCommandReadDeletedData = 12, + FloppyCommandFormatTrack = 13, // * + FloppyCommandSeek = 15, // * seek both heads to cylinder X + FloppyCommandVersion = 16, // * used during initialization, once + FloppyCommandScanEqual = 17, + FloppyCommandPerpendicularMode = 18, // * used during initialization, once, maybe + FloppyCommandConfigure = 19, // * set controller parameters + FloppyCommandLock = 20, // * protect controller params from a reset + FloppyCommandVerify = 22, + FloppyCommandScanLowOrEqual = 25, + FloppyCommandScanHighOrEqual = 29, + + FloppyModeMultitrack = 0x80, + FloppyModeMagneticEncoding = 0x40, // always set for read/write/verify/format + FloppyModeSkip = 0x20 +}; + +enum FloppyMSRMasks +{ + FloppyMsrRQM = 0x80, + FloppyMsrDIO = 0x40, + FloppyMsrNDMA = 0x20, + FloppyMsrBusy = 0x10 +}; + +typedef struct { + uint32 Size, SectorsPerTrack, Heads, Tracks; + uint8 Gap, DataRate, Spec1, SRT, HLT, HUT; + uint32 Spinup, Spindown, InterruptTimeout; + string Name; +} FloppyType; + +extern void FloppyInitialize(); +extern void FloppyIrqHandler(_RegsStack32 *r); +extern void FloppyWaitIrq(); +extern void FloppyInitDma(); + +extern void FloppyReset(); +extern void FloppyConfigure(); +extern void FloppySendCommand (uint8 command); +extern uint8 FloppyReadData (); +extern void FloppySenseInterrupt(uint8 *st0, uint8 *cyl); +extern void FloppySpecify (uint8 fd); +extern void FloppyMotor (uint8 fd_number, uint8 status); +extern void FloppySelectDrive(uint8 number); +extern void FloppyRecalibrate(uint8 fd_number); +extern void FloppyRW(uint8 isWrite, uint8 fd_number, uint8 head, uint8 cylinder, uint8 sector); +extern uint32 FloppyRead(uint8 drive, uint32 lba); + +#endif /* FLOPPY_H_ */ diff --git a/Kernel/drivers/pit/pit.c b/Kernel/drivers/pit/pit.c new file mode 100644 index 0000000..763685a --- /dev/null +++ b/Kernel/drivers/pit/pit.c @@ -0,0 +1,13 @@ +#include +#include +#include "pit.h" + +void PitSetFrequency(uint32 frequency) +{ + uint32 divisor = 1193180 / frequency; // Calculate the divisor + outportb(0x43, 0x36); // Set our command byte 0x36 + outportb(0x40, divisor & 0xff); // Set low byte + outportb(0x40, divisor>>8); // Set high byte + + TimeSetInternalFrequency(frequency); +} diff --git a/Kernel/drivers/pit/pit.h b/Kernel/drivers/pit/pit.h new file mode 100644 index 0000000..60cf309 --- /dev/null +++ b/Kernel/drivers/pit/pit.h @@ -0,0 +1,7 @@ +#ifndef __PIT__H +#define __PIT__H + +extern void PitSetFrequency(uint32 frequency); + + +#endif \ No newline at end of file diff --git a/Kernel/hal/clock/clock.c b/Kernel/hal/clock/clock.c new file mode 100644 index 0000000..1d59115 --- /dev/null +++ b/Kernel/hal/clock/clock.c @@ -0,0 +1,19 @@ +#include +#include "clock.h" + +#define MILISECONDS_IN_DAY 86400000 + +volatile TimeSystem _internal_time; +uint32 _internal_frequency_hz; + +void TimeHandler(_RegsStack32* UNUSED(r)) +{ + if (_internal_frequency_hz == 0) return; + + _internal_time.Time += 1000/_internal_frequency_hz; + if (_internal_time.Time >= MILISECONDS_IN_DAY) + { + _internal_time.Date++; + _internal_time.Time-=MILISECONDS_IN_DAY; + } +} diff --git a/Kernel/hal/clock/clock.h b/Kernel/hal/clock/clock.h new file mode 100644 index 0000000..45eaef0 --- /dev/null +++ b/Kernel/hal/clock/clock.h @@ -0,0 +1,9 @@ +#ifndef __CLOCK__H +#define __CLOCK__H + +#include + +extern void TimeHandler(_RegsStack32 *r); + + +#endif \ No newline at end of file diff --git a/SysCore/drivers/cpu/gdt/gdt.asm b/Kernel/hal/cpu/gdt-asm.asm similarity index 64% rename from SysCore/drivers/cpu/gdt/gdt.asm rename to Kernel/hal/cpu/gdt-asm.asm index d3ce6f7..a8a1b49 100644 --- a/SysCore/drivers/cpu/gdt/gdt.asm +++ b/Kernel/hal/cpu/gdt-asm.asm @@ -1,14 +1,17 @@ +; GLOBAL DESCRIPTOR TABLE +; +; + bits 32 ; !!! GDT !!! ; This will set up our new segment registers. We need to do ; something special in order to set CS. We do what is called a ; far jump. A jump that includes a segment as well as an offset. -; This is declared in C as 'extern void gdt_flush();' -global _i86_GdtFlush ; Allows the C code to link to this -extern _gp ; Says that '_gp' is in another file -_i86_GdtFlush: - lgdt [_gp] ; Load the GDT with our '_gp' which is a special pointer +global GdtFlush ; Allows the C code to link to this +extern gp ; Says that 'gp' is in another file +GdtFlush: + lgdt [gp] ; Load the GDT with our 'gp' which is a special pointer mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment mov ds, ax mov es, ax diff --git a/SysCore/drivers/cpu/gdt/gdt.c b/Kernel/hal/cpu/gdt.c similarity index 81% rename from SysCore/drivers/cpu/gdt/gdt.c rename to Kernel/hal/cpu/gdt.c index dd21fdd..ade2a8b 100644 --- a/SysCore/drivers/cpu/gdt/gdt.c +++ b/Kernel/hal/cpu/gdt.c @@ -5,15 +5,13 @@ #define MAX_DESCRIPTORS 5 #include "gdt.h" -extern void i86_GdtInstall(); - /* Our GDT, with 3 entries, and finally our special GDT pointer */ struct GdtEntry gdt[MAX_DESCRIPTORS]; struct GdtPointer gp; /* Setup a descriptor in the Global Descriptor Table */ -void i86_GdtSetGate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) +void GdtSetGate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) { /* Sanity check */ if (num >= MAX_DESCRIPTORS) return; @@ -32,45 +30,45 @@ void i86_GdtSetGate(int num, unsigned long base, unsigned long limit, unsigned c gdt[num].access = access; } -/*struct gdt_entry* i86_GdtGetGate(int num) +struct GdtEntry* GdtGetGate(int num) { if (num>MAX_DESCRIPTORS) return 0; return &gdt[num]; -}*/ +} /* Should be called by main. This will setup the special GDT * pointer, set up the first 3 entries in our GDT, and then * finally call gdt_flush() in our assembler file in order * to tell the processor where the new GDT is and update the * new segment registers */ -void i86_GdtInstall() +void GdtInstall() { /* Setup the GDT pointer and limit */ gp.limit = (sizeof(struct GdtEntry) * 3) - 1; gp.base = (unsigned int)&gdt; /* Our NULL descriptor */ - i86_GdtSetGate(0, 0, 0, 0, 0); + GdtSetGate(0, 0, 0, 0, 0); /* The second entry is our Code Segment. The base address * is 0, the limit is 4GBytes, it uses 4KByte granularity, * uses 32-bit opcodes, and is a Code Segment descriptor. * Please check the table above in the tutorial in order * to see exactly what each value means */ - i86_GdtSetGate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); + GdtSetGate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); /* The third entry is our Data Segment. It's EXACTLY the * same as our code segment, but the descriptor type in * this entry's access byte says it's a Data Segment */ - i86_GdtSetGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + GdtSetGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); /* User mode Code segment*/ - i86_GdtSetGate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); + GdtSetGate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); /* User mode data segment*/ - i86_GdtSetGate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); + GdtSetGate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); /* Flush out the old GDT and install the new changes! */ - i86_GdtFlush(); + GdtFlush(); } - \ No newline at end of file + diff --git a/SysCore/drivers/cpu/gdt/gdt.h b/Kernel/hal/cpu/gdt.h similarity index 81% rename from SysCore/drivers/cpu/gdt/gdt.h rename to Kernel/hal/cpu/gdt.h index 48fecf5..4068792 100644 --- a/SysCore/drivers/cpu/gdt/gdt.h +++ b/Kernel/hal/cpu/gdt.h @@ -30,9 +30,9 @@ struct GdtPointer /* This will be a function in start.asm. We use this to properly * reload the new segment registers */ -extern void i86_GdtInstall(); -extern void i86_GdtFlush(); -extern void i86_GdtSetGate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran); -//extern struct GdtEntry* i86_GdtGetGate(int num); +extern void GdtInstall(); +extern void GdtFlush(); +extern void GdtSetGate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran); +extern struct GdtEntry* GdtGetGate(int num); #endif \ No newline at end of file diff --git a/SysCore/drivers/cpu/idt/idt.asm b/Kernel/hal/cpu/idt-asm.asm similarity index 51% rename from SysCore/drivers/cpu/idt/idt.asm rename to Kernel/hal/cpu/idt-asm.asm index 1841ef5..c7bbd04 100644 --- a/SysCore/drivers/cpu/idt/idt.asm +++ b/Kernel/hal/cpu/idt-asm.asm @@ -2,8 +2,8 @@ bits 32 ; !!! IDT !!! ; Loads the IDT defined in '_idtp' -global _i86_IdtLoad -extern _idtp -_i86_IdtLoad: - lidt [_idtp] +global IdtLoad +extern idtp +IdtLoad: + lidt [idtp] ret diff --git a/SysCore/drivers/cpu/idt/idt.c b/Kernel/hal/cpu/idt.c similarity index 83% rename from SysCore/drivers/cpu/idt/idt.c rename to Kernel/hal/cpu/idt.c index 240cd35..106fd45 100644 --- a/SysCore/drivers/cpu/idt/idt.c +++ b/Kernel/hal/cpu/idt.c @@ -2,17 +2,17 @@ * idt.h - INTERRUPT DESCRIPTOR TABLE * * Contains structures and function declarations for IDT * ******************************************************************/ -#include +#include #include "idt.h" -extern void i86_IdtLoad(); +extern void IdtLoad(); /* Declare an IDT of 256 entries. */ struct IdtEntry idt[256]; struct IdtPointer idtp; /* Use this function to set an entry in the IDT. Alot simpler * than twiddling with the GDT ;) */ -void i86_IdtSetGate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags) +void IdtSetGate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags) { /* The interrupt routine's base address */ idt[num].base_lo = (base & 0xFFFF); @@ -25,13 +25,13 @@ void i86_IdtSetGate(unsigned char num, unsigned long base, unsigned short sel, u idt[num].flags = flags; } -struct IdtEntry* i86_IdtGetGate(unsigned char num) +struct IdtEntry* IdtGetGate(unsigned char num) { return &idt[num]; } /* Installs the IDT */ -void i86_IdtInstall() +void IdtInstall() { /* Sets the special IDT pointer up, just like in 'gdt.c' */ idtp.limit = (sizeof (struct IdtEntry) * 256) - 1; @@ -41,5 +41,5 @@ void i86_IdtInstall() memset (&idt, 0, sizeof(struct IdtEntry) * 256); /* Points the processor's internal register to the new IDT */ - i86_IdtLoad(); + IdtLoad(); } diff --git a/SysCore/drivers/cpu/idt/idt.h b/Kernel/hal/cpu/idt.h similarity index 76% rename from SysCore/drivers/cpu/idt/idt.h rename to Kernel/hal/cpu/idt.h index 96067ed..dda72b2 100644 --- a/SysCore/drivers/cpu/idt/idt.h +++ b/Kernel/hal/cpu/idt.h @@ -24,8 +24,8 @@ struct IdtPointer /* This exists in 'start.asm', and is used to load our IDT */ -extern void i86_IdtSetGate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags); -extern struct IdtEntry* i86_IdtGetGate(unsigned char num); -extern void i86_IdtInstall(); +extern void IdtSetGate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags); +extern struct IdtEntry* IdtGetGate(unsigned char num); +extern void IdtInstall(); #endif \ No newline at end of file diff --git a/SysCore/drivers/cpu/irq/irq.asm b/Kernel/hal/cpu/irq-asm.asm similarity index 76% rename from SysCore/drivers/cpu/irq/irq.asm rename to Kernel/hal/cpu/irq-asm.asm index b7fe235..b63337e 100644 --- a/SysCore/drivers/cpu/irq/irq.asm +++ b/Kernel/hal/cpu/irq-asm.asm @@ -1,25 +1,25 @@ bits 32 ; !!! IRQ !!! -global _i86_irq0 -global _i86_irq1 -global _i86_irq2 -global _i86_irq3 -global _i86_irq4 -global _i86_irq5 -global _i86_irq6 -global _i86_irq7 -global _i86_irq8 -global _i86_irq9 -global _i86_irq10 -global _i86_irq11 -global _i86_irq12 -global _i86_irq13 -global _i86_irq14 -global _i86_irq15 +global Irq_0 +global Irq_1 +global Irq_2 +global Irq_3 +global Irq_4 +global Irq_5 +global Irq_6 +global Irq_7 +global Irq_8 +global Irq_9 +global Irq_10 +global Irq_11 +global Irq_12 +global Irq_13 +global Irq_14 +global Irq_15 ; 32: IRQ0 -_i86_irq0: +Irq_0: cli push byte 0 push byte 32; Note that these don't push an error code on the stack: @@ -27,113 +27,113 @@ _i86_irq0: jmp irq_common_stub ; 33: IRQ1 -_i86_irq1: +Irq_1: cli push byte 0 push byte 33 jmp irq_common_stub ; 34: IRQ2 -_i86_irq2: +Irq_2: cli push byte 0 push byte 34 jmp irq_common_stub ; 35: IRQ3 -_i86_irq3: +Irq_3: cli push byte 0 push byte 35 jmp irq_common_stub ; 36: IRQ4 -_i86_irq4: +Irq_4: cli push byte 0 push byte 36 jmp irq_common_stub ; 37: IRQ5 -_i86_irq5: +Irq_5: cli push byte 0 push byte 37 jmp irq_common_stub ; 38: IRQ6 -_i86_irq6: +Irq_6: cli push byte 0 push byte 38 jmp irq_common_stub ; 39: IRQ7 -_i86_irq7: +Irq_7: cli push byte 0 push byte 39 jmp irq_common_stub ; 40: IRQ8 -_i86_irq8: +Irq_8: cli push byte 0 push byte 40 jmp irq_common_stub ; 41: IRQ9 -_i86_irq9: +Irq_9: cli push byte 0 push byte 41 jmp irq_common_stub ; 42: IRQ10 -_i86_irq10: +Irq_10: cli push byte 0 push byte 42 jmp irq_common_stub ; 43: IRQ11 -_i86_irq11: +Irq_11: cli push byte 0 push byte 43 jmp irq_common_stub ; 44: IRQ12 -_i86_irq12: +Irq_12: cli push byte 0 push byte 44 jmp irq_common_stub ; 45: IRQ13 -_i86_irq13: +Irq_13: cli push byte 0 push byte 45 jmp irq_common_stub ; 46: IRQ14 -_i86_irq14: +Irq_14: cli push byte 0 push byte 46 jmp irq_common_stub ; 47: IRQ15 -_i86_irq15: +Irq_15: cli push byte 0 push byte 47 jmp irq_common_stub -extern _i86_IrqHandler +extern IrqHandler ; This is a stub that we have created for IRQ based ISRs. This calls -; '_i86_irq_handler' in our C code. We need to create this in an 'irq.c' +; 'Irq__handler' in our C code. We need to create this in an 'irq.c' irq_common_stub: pusha push ds @@ -147,7 +147,7 @@ irq_common_stub: mov gs, ax mov eax, esp push eax - mov eax, _i86_IrqHandler + mov eax, IrqHandler call eax pop eax pop gs diff --git a/Kernel/hal/cpu/irq.c b/Kernel/hal/cpu/irq.c new file mode 100644 index 0000000..eed2efb --- /dev/null +++ b/Kernel/hal/cpu/irq.c @@ -0,0 +1,91 @@ +#include +#include "pic.h" +#include "irq.h" +#include "idt.h" + +/* These are own ISRs that point to our special IRQ handler +* instead of the regular 'fault_handler' function */ +extern void Irq_0(); +extern void Irq_1(); +extern void Irq_2(); +extern void Irq_3(); +extern void Irq_4(); +extern void Irq_5(); +extern void Irq_6(); +extern void Irq_7(); +extern void Irq_8(); +extern void Irq_9(); +extern void Irq_10(); +extern void Irq_11(); +extern void Irq_12(); +extern void Irq_13(); +extern void Irq_14(); +extern void Irq_15(); + +/* This array is actually an array of function pointers. We use +* this to handle custom IRQ handlers for a given IRQ */ +void *IrqRoutines[16] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* This installs a custom IRQ handler for the given IRQ */ +void IrqInstallHandler (int irq, void (*handler)(_RegsStack32 *r)) +{ + IrqRoutines[irq] = handler; +} + +void IrqUninstallHandler (int irq) +{ + IrqRoutines[irq] = 0; +} + + + +/* We first remap the interrupt controllers, and then we install +* the appropriate ISRs to the correct entries in the IDT. This +* is just like installing the exception handlers */ +void IrqInstall() +{ + PicRemap(32,40); + + IdtSetGate(32, (unsigned)Irq_0, 0x08, 0x8E); + IdtSetGate(33, (unsigned)Irq_1, 0x08, 0x8E); + IdtSetGate(34, (unsigned)Irq_2, 0x08, 0x8E); + IdtSetGate(35, (unsigned)Irq_3, 0x08, 0x8E); + IdtSetGate(36, (unsigned)Irq_4, 0x08, 0x8E); + IdtSetGate(37, (unsigned)Irq_5, 0x08, 0x8E); + IdtSetGate(38, (unsigned)Irq_6, 0x08, 0x8E); + IdtSetGate(39, (unsigned)Irq_7, 0x08, 0x8E); + IdtSetGate(40, (unsigned)Irq_8, 0x08, 0x8E); + IdtSetGate(41, (unsigned)Irq_9, 0x08, 0x8E); + IdtSetGate(42, (unsigned)Irq_10, 0x08, 0x8E); + IdtSetGate(43, (unsigned)Irq_11, 0x08, 0x8E); + IdtSetGate(44, (unsigned)Irq_12, 0x08, 0x8E); + IdtSetGate(45, (unsigned)Irq_13, 0x08, 0x8E); + IdtSetGate(46, (unsigned)Irq_14, 0x08, 0x8E); + IdtSetGate(47, (unsigned)Irq_15, 0x08, 0x8E); +} + +// Default IRQ handler, launches other handler if installed. +// Also sends end-of-interrupt messages to PIC +void IrqHandler (_RegsStack32 *r) +{ + /* This is a blank function pointer */ + void (*handler)(_RegsStack32 *r); + + /* Find out if we have a custom handler to run for this + * IRQ, and then finally, run it */ + handler = IrqRoutines[r->int_no - 32]; + if (handler) handler(r); + + /* If the IDT entry that was invoked was greater than 40 + * (meaning IRQ8 - 15), then we need to send an EOI to + * the slave controller */ + if (r->int_no >=40) outportb(0xA0, 0x20); + + /* In either case, we need to send an EOI to the master + * interrupt controller too */ + outportb(0x20, 0x20); +} diff --git a/Kernel/hal/cpu/irq.h b/Kernel/hal/cpu/irq.h new file mode 100644 index 0000000..70be7ee --- /dev/null +++ b/Kernel/hal/cpu/irq.h @@ -0,0 +1,10 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#include + +extern void IrqInstallHandler (int irq, void (*handler)(_RegsStack32 *r)); +extern void IrqUninstallHandler (int irq); +extern void IrqInstall(); + +#endif \ No newline at end of file diff --git a/SysCore/drivers/cpu/isrs/isrs.asm b/Kernel/hal/cpu/isrs-asm.asm similarity index 68% rename from SysCore/drivers/cpu/isrs/isrs.asm rename to Kernel/hal/cpu/isrs-asm.asm index d876d89..b96ab5d 100644 --- a/SysCore/drivers/cpu/isrs/isrs.asm +++ b/Kernel/hal/cpu/isrs-asm.asm @@ -1,196 +1,196 @@ bits 32 ; !!! ISRs !!! -global _i86_isr0 -global _i86_isr1 -global _i86_isr2 -global _i86_isr3 -global _i86_isr4 -global _i86_isr5 -global _i86_isr6 -global _i86_isr7 -global _i86_isr8 -global _i86_isr9 -global _i86_isr10 -global _i86_isr11 -global _i86_isr12 -global _i86_isr13 -global _i86_isr14 -global _i86_isr15 -global _i86_isr16 -global _i86_isr17 -global _i86_isr18 -global _i86_isr19 -global _i86_isr20 -global _i86_isr21 -global _i86_isr22 -global _i86_isr23 -global _i86_isr24 -global _i86_isr25 -global _i86_isr26 -global _i86_isr27 -global _i86_isr28 -global _i86_isr29 -global _i86_isr30 -global _i86_isr31 +global isr_exception_0 +global isr_exception_1 +global isr_exception_2 +global isr_exception_3 +global isr_exception_4 +global isr_exception_5 +global isr_exception_6 +global isr_exception_7 +global isr_exception_8 +global isr_exception_9 +global isr_exception_10 +global isr_exception_11 +global isr_exception_12 +global isr_exception_13 +global isr_exception_14 +global isr_exception_15 +global isr_exception_16 +global isr_exception_17 +global isr_exception_18 +global isr_exception_19 +global isr_exception_20 +global isr_exception_21 +global isr_exception_22 +global isr_exception_23 +global isr_exception_24 +global isr_exception_25 +global isr_exception_26 +global isr_exception_27 +global isr_exception_28 +global isr_exception_29 +global isr_exception_30 +global isr_exception_31 -_i86_isr0: +isr_exception_0: cli push byte 0; A normal ISR stub that pops a dummy error code to keep a ; uniform stack frame push byte 0 jmp isr_common_stub -_i86_isr1: +isr_exception_1: cli push byte 0 push byte 1 jmp isr_common_stub -_i86_isr2: +isr_exception_2: cli push byte 0 push byte 2 jmp isr_common_stub -_i86_isr3: +isr_exception_3: cli push byte 0 push byte 3 jmp isr_common_stub -_i86_isr4: +isr_exception_4: cli push byte 0 push byte 4 jmp isr_common_stub -_i86_isr5: +isr_exception_5: cli push byte 0 push byte 5 jmp isr_common_stub -_i86_isr6: +isr_exception_6: cli push byte 0 push byte 6 jmp isr_common_stub -_i86_isr7: +isr_exception_7: cli push byte 0 push byte 7 jmp isr_common_stub -_i86_isr8: +isr_exception_8: cli push byte 8 jmp isr_common_stub -_i86_isr9: +isr_exception_9: cli push byte 0 push byte 9 jmp isr_common_stub -_i86_isr10: +isr_exception_10: cli push byte 10 jmp isr_common_stub -_i86_isr11: +isr_exception_11: cli push byte 11 jmp isr_common_stub -_i86_isr12: +isr_exception_12: cli push byte 12 jmp isr_common_stub -_i86_isr13: +isr_exception_13: cli push byte 13 jmp isr_common_stub -_i86_isr14: +isr_exception_14: cli push byte 14 jmp isr_common_stub -_i86_isr15: +isr_exception_15: cli push byte 0 push byte 15 jmp isr_common_stub -_i86_isr16: +isr_exception_16: cli push byte 0 push byte 16 jmp isr_common_stub -_i86_isr17: +isr_exception_17: cli push byte 0 push byte 17 jmp isr_common_stub -_i86_isr18: +isr_exception_18: cli push byte 0 push byte 18 jmp isr_common_stub -_i86_isr19: +isr_exception_19: cli push byte 0 push byte 19 jmp isr_common_stub -_i86_isr20: +isr_exception_20: cli push byte 0 push byte 20 jmp isr_common_stub -_i86_isr21: +isr_exception_21: cli push byte 0 push byte 21 jmp isr_common_stub -_i86_isr22: +isr_exception_22: cli push byte 0 push byte 22 jmp isr_common_stub -_i86_isr23: +isr_exception_23: cli push byte 0 push byte 23 jmp isr_common_stub -_i86_isr24: +isr_exception_24: cli push byte 0 push byte 24 jmp isr_common_stub -_i86_isr25: +isr_exception_25: cli push byte 0 push byte 25 jmp isr_common_stub -_i86_isr26: +isr_exception_26: cli push byte 0 push byte 26 jmp isr_common_stub -_i86_isr27: +isr_exception_27: cli push byte 0 push byte 27 jmp isr_common_stub -_i86_isr28: +isr_exception_28: cli push byte 0 push byte 28 jmp isr_common_stub -_i86_isr29: +isr_exception_29: cli push byte 0 push byte 29 jmp isr_common_stub -_i86_isr30: +isr_exception_30: cli push byte 0 push byte 30 jmp isr_common_stub -_i86_isr31: +isr_exception_31: cli push byte 0 push byte 31 jmp isr_common_stub -extern _i86_FaultHandler +extern IsrsFaultHandler isr_common_stub: pusha @@ -205,7 +205,7 @@ isr_common_stub: mov gs, ax mov eax, esp ; Push us the stack push eax - mov eax, _i86_FaultHandler + mov eax, IsrsFaultHandler call eax ; A special call, preserves the 'eip' register pop eax pop gs diff --git a/Kernel/hal/cpu/isrs.c b/Kernel/hal/cpu/isrs.c new file mode 100644 index 0000000..78f0cf0 --- /dev/null +++ b/Kernel/hal/cpu/isrs.c @@ -0,0 +1,114 @@ +#include + +#include "isrs.h" +#include "idt.h" + +// Assembly coded +extern void isr_exception_0(); +extern void isr_exception_1(); +extern void isr_exception_2(); +extern void isr_exception_3(); +extern void isr_exception_4(); +extern void isr_exception_5(); +extern void isr_exception_6(); +extern void isr_exception_7(); +extern void isr_exception_8(); +extern void isr_exception_9(); +extern void isr_exception_10(); +extern void isr_exception_11(); +extern void isr_exception_12(); +extern void isr_exception_13(); +extern void isr_exception_14(); +extern void isr_exception_15(); +extern void isr_exception_16(); +extern void isr_exception_17(); +extern void isr_exception_18(); +extern void isr_exception_19(); +extern void isr_exception_20(); +extern void isr_exception_21(); +extern void isr_exception_22(); +extern void isr_exception_23(); +extern void isr_exception_24(); +extern void isr_exception_25(); +extern void isr_exception_26(); +extern void isr_exception_27(); +extern void isr_exception_28(); +extern void isr_exception_29(); +extern void isr_exception_30(); +extern void isr_exception_31(); + + +void* IdtFaultHandlers[32] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; + +void IsrsInstall() +{ + IdtSetGate(0, (unsigned)isr_exception_0, 0x08, 0x8E); + IdtSetGate(1, (unsigned)isr_exception_1, 0x08, 0x8E); + IdtSetGate(2, (unsigned)isr_exception_2, 0x08, 0x8E); + IdtSetGate(3, (unsigned)isr_exception_3, 0x08, 0x8E); + IdtSetGate(4, (unsigned)isr_exception_4, 0x08, 0x8E); + IdtSetGate(5, (unsigned)isr_exception_5, 0x08, 0x8E); + IdtSetGate(6, (unsigned)isr_exception_6, 0x08, 0x8E); + IdtSetGate(7, (unsigned)isr_exception_7, 0x08, 0x8E); + IdtSetGate(8, (unsigned)isr_exception_8, 0x08, 0x8E); + IdtSetGate(9, (unsigned)isr_exception_9, 0x08, 0x8E); + IdtSetGate(10, (unsigned)isr_exception_10, 0x08, 0x8E); + IdtSetGate(11, (unsigned)isr_exception_11, 0x08, 0x8E); + IdtSetGate(12, (unsigned)isr_exception_12, 0x08, 0x8E); + IdtSetGate(13, (unsigned)isr_exception_13, 0x08, 0x8E); + IdtSetGate(14, (unsigned)isr_exception_14, 0x08, 0x8E); + IdtSetGate(15, (unsigned)isr_exception_15, 0x08, 0x8E); + IdtSetGate(16, (unsigned)isr_exception_16, 0x08, 0x8E); + IdtSetGate(17, (unsigned)isr_exception_17, 0x08, 0x8E); + IdtSetGate(18, (unsigned)isr_exception_18, 0x08, 0x8E); + IdtSetGate(19, (unsigned)isr_exception_19, 0x08, 0x8E); + IdtSetGate(20, (unsigned)isr_exception_20, 0x08, 0x8E); + IdtSetGate(21, (unsigned)isr_exception_21, 0x08, 0x8E); + IdtSetGate(22, (unsigned)isr_exception_22, 0x08, 0x8E); + IdtSetGate(23, (unsigned)isr_exception_23, 0x08, 0x8E); + IdtSetGate(24, (unsigned)isr_exception_24, 0x08, 0x8E); + IdtSetGate(25, (unsigned)isr_exception_25, 0x08, 0x8E); + IdtSetGate(26, (unsigned)isr_exception_26, 0x08, 0x8E); + IdtSetGate(27, (unsigned)isr_exception_27, 0x08, 0x8E); + IdtSetGate(28, (unsigned)isr_exception_28, 0x08, 0x8E); + IdtSetGate(29, (unsigned)isr_exception_29, 0x08, 0x8E); + IdtSetGate(30, (unsigned)isr_exception_30, 0x08, 0x8E); + IdtSetGate(31, (unsigned)isr_exception_31, 0x08, 0x8E); +} + + +void IsrsInstallHandler(int interr, void (*function)(_RegsStack32 *r)) +{ + if (interr < 32) IdtFaultHandlers[interr] = function; +} + + +void IsrsUninstallHandler(int interr) +{ + if (interr < 32) IdtFaultHandlers[interr] = 0; +} + + +extern void CrashMessage(_RegsStack32 *r); +// Default fault handler; calls other handlers, or displays error message. +void IsrsFaultHandler(_RegsStack32 *r) +{ + /* Is this a fault whose number is from 0 to 31? */ + if (r->int_no < 32) + { + void (*func)(_RegsStack32 *r); + func = IdtFaultHandlers[r->int_no]; + + // Halt system if unhandled + if (!func) { + CrashMessage(r); + asm ("cli"); + asm ("hlt"); + } + + else (*func)(r); + } +} diff --git a/Kernel/hal/cpu/isrs.h b/Kernel/hal/cpu/isrs.h new file mode 100644 index 0000000..257a0fd --- /dev/null +++ b/Kernel/hal/cpu/isrs.h @@ -0,0 +1,10 @@ +#ifndef __ISRS_H_ +#define __ISRS_H_ + +#include + +extern void IsrsInstall(); +extern void IsrsInstallHandler(int interr, void (*function)(_RegsStack32 *r)); +extern void IsrsUninstallHandler(int interr); + +#endif \ No newline at end of file diff --git a/SysCore/drivers/cpu/irq/pic.c b/Kernel/hal/cpu/pic.c similarity index 86% rename from SysCore/drivers/cpu/irq/pic.c rename to Kernel/hal/cpu/pic.c index 4800b51..63a961b 100644 --- a/SysCore/drivers/cpu/irq/pic.c +++ b/Kernel/hal/cpu/pic.c @@ -1,7 +1,7 @@ -#include +#include #include "pic.h" -void i86_PicRemap(int pic1, int pic2) +void PicRemap(int pic1, int pic2) { // Send ICW1 outportb(0x20, 0x11); diff --git a/Kernel/hal/cpu/pic.h b/Kernel/hal/cpu/pic.h new file mode 100644 index 0000000..e464fcc --- /dev/null +++ b/Kernel/hal/cpu/pic.h @@ -0,0 +1,6 @@ +#ifndef _PIC_H +#define _PIC_H + +extern void PicRemap(int pic1, int pic2); + +#endif \ No newline at end of file diff --git a/Kernel/hal/crash.c b/Kernel/hal/crash.c new file mode 100644 index 0000000..fcaa4a0 --- /dev/null +++ b/Kernel/hal/crash.c @@ -0,0 +1,96 @@ +/* + * crash.c + * + * Created on: Aug 19, 2011 + * Author: Tiberiu + */ + +#include + +string errorCodes[] = +{ + "Division by zero", //0 + "Debugger", //1 + "Non maskable interrupt", //2 + "Breakpoint", //3 + "Overflow", //4 + "Bounds", //5 + "Invalid opcode", //6 + "Coprocessor not available", //7 + "Double fault", //8 + "Coprocessor segment overrun",//9 + "Invalid task state segment", //A + "Segment not present", //B + "Stack fault", //C + "General protection fault", //D + "Page fault", //E + "", //F + "Math fault", //10 + "Alignment check", //11 + "Machine check", //12 + "SIMD floating-point exception" //13 +}; + +void CrashMessage(_RegsStack32 *r) +{ + ConsoleSetDefaultColor(ColorLightRed); + ConsoleWrite("\n"); uint32 i; + for (i = 0; i < 80; i++) ConsoleWrite("%c", 205); + + ConsoleWrite("%#\t\t\t\tSomething went terribly wrong :(\n\n", ColorWhite); + ConsoleWrite("There was an unhandled exception: "); + + if (r->int_no < 20) + ConsoleWrite("%#%s (INT%u)", ColorWhite, errorCodes[r->int_no], r->int_no); + else ConsoleWrite("%#INT%u", ColorWhite, r->int_no); + + ConsoleWrite("\nTo protect your computer, it had to be halted.\n\n"); + ConsoleWrite("Here, this might help find the problem:\n"); + + Point a = {4, -1}, b = {22, -1}, c = {40, -1}, d = {58, -1}; + + ConsoleSetDefaultColor(ColorWhite); + ConsoleCursorGoto(a); ConsoleWrite("eax=0x%x", r->eax); + ConsoleCursorGoto(b); ConsoleWrite("ebx=0x%x", r->ebx); + ConsoleCursorGoto(c); ConsoleWrite("ecx=0x%x", r->ecx); + ConsoleCursorGoto(d); ConsoleWrite("edx=0x%x\n", r->edx); + + ConsoleCursorGoto(a); ConsoleWrite("edi=0x%x", r->edi); + ConsoleCursorGoto(b); ConsoleWrite("esi=0x%x", r->esi); + ConsoleCursorGoto(c); ConsoleWrite("ebp=0x%x", r->ebp); + ConsoleCursorGoto(d); ConsoleWrite("esp=0x%x\n", r->esp); + + ConsoleCursorGoto(a); ConsoleWrite("gs=0x%x", r->gs); + ConsoleCursorGoto(b); ConsoleWrite("fs=0x%x", r->fs); + ConsoleCursorGoto(c); ConsoleWrite("es=0x%x", r->es); + ConsoleCursorGoto(d); ConsoleWrite("ds=0x%x\n", r->ds); + + ConsoleCursorGoto(a); ConsoleWrite("eip=0x%x", r->eip); + ConsoleCursorGoto(b); ConsoleWrite("cs=0x%x", r->cs); + ConsoleCursorGoto(c); ConsoleWrite("eflags=0x%x", r->eflags); + ConsoleCursorGoto(d); ConsoleWrite("useresp=0x%x\n", r->useresp); + + ConsoleCursorGoto(a); ConsoleWrite("gs=0x%x", r->ss); + ConsoleCursorGoto(b); ConsoleWrite("fs=0x%x", r->int_no); + ConsoleCursorGoto(c); ConsoleWrite("err_code=0x%x", r->err_code); + + // Useful info about page fault + if (r->int_no == 0xE) + { + uint32 faulting_address; + asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); + + ConsoleCursorGoto(d); ConsoleWrite("address=0x%x\n", faulting_address); + ConsoleCursorGoto(a); ConsoleWrite("reason: "); + + if (!(r->err_code & 1)) ConsoleWrite("%#PAGE_NOT_PRESENT; ", ColorLightGray); + if (r->err_code & 2) ConsoleWrite("%#WRITE_OPERATION; ", ColorLightGray); + if (r->err_code & 4) ConsoleWrite("%#CPU_IN_USER_MODE; ", ColorLightGray); + if (r->err_code & 8) ConsoleWrite("%#CPU_RESERVED_PAGE_ENTRY_OVERWRITTEN; ", ColorLightGray); + if (r->err_code & 0x10) ConsoleWrite("%#INSTRUCTION_FETCH; ", ColorLightGray); + } + + ConsoleSetDefaultColor(ColorLightRed); + ConsoleWrite("\n"); + for (i = 0; i < 80; i++) ConsoleWrite("%c", 205); +} diff --git a/Kernel/hal/crash.c~ b/Kernel/hal/crash.c~ new file mode 100644 index 0000000..e6044d0 --- /dev/null +++ b/Kernel/hal/crash.c~ @@ -0,0 +1,97 @@ +/* + * crash.c + * + * Created on: Aug 19, 2011 + * Author: Tiberiu + */ + +#include + +string errorCodes[] = +{ + "Division by zero", //0 + "Debugger", //1 + "Non maskable interrupt", //2 + "Breakpoint", //3 + "Overflow", //4 + "Bounds", //5 + "Invalid opcode", //6 + "Coprocessor not available", //7 + "Double fault", //8 + "Coprocessor segment overrun",//9 + "Invalid task state segment", //A + "Segment not present", //B + "Stack fault", //C + "General protection fault", //D + "Page fault", //E + "", //F + "Math fault", //10 + "Alignment check", //11 + "Machine check", //12 + "SIMD floating-point exception" //13 +}; + +void CrashMessage(_RegsStack32 *r) +{ + ConsoleSetDefaultColor(ColorLightRed); + + ConsoleWrite("\n"); uint32 i; + for (i = 0; i < 80; i++) ConsoleWrite("%c", 205); + + ConsoleWrite("%#\t\t\t\tSomething went terribly wrong :(\n\n", ColorWhite); + ConsoleWrite("There was an unhandled exception: "); + + if (r->int_no < 20) + ConsoleWrite("%#%s (INT%u)", ColorWhite, errorCodes[r->int_no], r->int_no); + else ConsoleWrite("%#INT%u", ColorWhite, r->int_no); + + ConsoleWrite("\nTo protect your computer, it had to be halted.\n\n"); + ConsoleWrite("Here, this might help find the problem:\n"); + + Point a = {4, -1}, b = {22, -1}, c = {40, -1}, d = {58, -1}; + + ConsoleSetDefaultColor(ColorWhite); + ConsoleCursorGoto(a); ConsoleWrite("eax=0x%x", r->eax); + ConsoleCursorGoto(b); ConsoleWrite("ebx=0x%x", r->ebx); + ConsoleCursorGoto(c); ConsoleWrite("ecx=0x%x", r->ecx); + ConsoleCursorGoto(d); ConsoleWrite("edx=0x%x\n", r->edx); + + ConsoleCursorGoto(a); ConsoleWrite("edi=0x%x", r->edi); + ConsoleCursorGoto(b); ConsoleWrite("esi=0x%x", r->esi); + ConsoleCursorGoto(c); ConsoleWrite("ebp=0x%x", r->ebp); + ConsoleCursorGoto(d); ConsoleWrite("esp=0x%x\n", r->esp); + + ConsoleCursorGoto(a); ConsoleWrite("gs=0x%x", r->gs); + ConsoleCursorGoto(b); ConsoleWrite("fs=0x%x", r->fs); + ConsoleCursorGoto(c); ConsoleWrite("es=0x%x", r->es); + ConsoleCursorGoto(d); ConsoleWrite("ds=0x%x\n", r->ds); + + ConsoleCursorGoto(a); ConsoleWrite("eip=0x%x", r->eip); + ConsoleCursorGoto(b); ConsoleWrite("cs=0x%x", r->cs); + ConsoleCursorGoto(c); ConsoleWrite("eflags=0x%x", r->eflags); + ConsoleCursorGoto(d); ConsoleWrite("useresp=0x%x\n", r->useresp); + + ConsoleCursorGoto(a); ConsoleWrite("gs=0x%x", r->ss); + ConsoleCursorGoto(b); ConsoleWrite("fs=0x%x", r->int_no); + ConsoleCursorGoto(c); ConsoleWrite("err_code=0x%x", r->err_code); + + // Useful info about page fault + if (r->int_no == 0xE) + { + uint32 faulting_address; + asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); + + ConsoleCursorGoto(d); ConsoleWrite("address=0x%x\n", faulting_address); + ConsoleCursorGoto(a); ConsoleWrite("reason: "); + + if (!(r->err_code & 1)) ConsoleWrite("%#PAGE_NOT_PRESENT; ", ColorLightGray); + if (r->err_code & 2) ConsoleWrite("%#WRITE_OPERATION; ", ColorLightGray); + if (r->err_code & 4) ConsoleWrite("%#CPU_IN_USER_MODE; ", ColorLightGray); + if (r->err_code & 8) ConsoleWrite("%#CPU_RESERVED_PAGE_ENTRY_OVERWRITTEN; ", ColorLightGray); + if (r->err_code & 0x10) ConsoleWrite("%#INSTRUCTION_FETCH; ", ColorLightGray); + } + + ConsoleSetDefaultColor(ColorLightRed); + ConsoleWrite("\n"); + for (i = 0; i < 80; i++) ConsoleWrite("%c", 205); +} diff --git a/Kernel/hal/hal.c b/Kernel/hal/hal.c new file mode 100644 index 0000000..db51fe8 --- /dev/null +++ b/Kernel/hal/hal.c @@ -0,0 +1,35 @@ +// HARDWARE ABSTRACTION LAYER +#include "cpu/gdt.h" +#include "cpu/idt.h" +#include "cpu/isrs.h" +#include "cpu/irq.h" + +#include "clock/clock.h" +#include "keyboard/keyboard.h" +#include "mouse/mouse.h" + +#include + +void HalInitialize() +{ + // Initialize cpu + GdtInstall(); Log("%#[HAL] %#Installed GDT\n", ColorYellow, ColorLightGreen); + IdtInstall(); Log("%#[HAL] %#Installed IDT\n", ColorYellow, ColorLightGreen); + IsrsInstall(); Log("%#[HAL] %#Installed ISRs\n", ColorYellow, ColorLightGreen); + IrqInstall(); Log("%#[HAL] %#Installed IRQs\n", ColorYellow, ColorLightGreen); + + // Start interrupts + asm volatile ("sti"); + Log("%#[HAL] %#Interrupts are started...\n", ColorYellow, ColorLightMagenta); + + // Install keyboard + IrqInstallHandler(0, TimeHandler); + IrqInstallHandler(1, KeyboardHandler); + IrqInstallHandler(12, MouseHandler); + + KeyboardInstallA(); Log("%#[HAL] %#Installing keyboard... %#[1/2] ", ColorYellow, ColorLightGray, ColorLightGreen); + KeyboardInstallB(); Log("%#[2/2]\n", ColorLightGreen); + + // Install mouse driver + MouseInstall(); Log("%#[HAL] %#Installed mouse driver\n", ColorYellow, ColorLightGreen); +} diff --git a/Kernel/hal/hal.h b/Kernel/hal/hal.h new file mode 100644 index 0000000..081bb2d --- /dev/null +++ b/Kernel/hal/hal.h @@ -0,0 +1,6 @@ +#ifndef __HAL__H +#define __HAL__H + +extern void HalInitialize(); + +#endif \ No newline at end of file diff --git a/Kernel/hal/keyboard/keyboard.c b/Kernel/hal/keyboard/keyboard.c new file mode 100644 index 0000000..64980e7 --- /dev/null +++ b/Kernel/hal/keyboard/keyboard.c @@ -0,0 +1,327 @@ +#include +#include "keyboard.h" + +#define KeybCmdWriteLED 0xed +#define KeybCmdEcho 0xee +#define KeybCmdSetScancodeSet 0xf0 +#define KeybCmdGetID 0xf2 +#define KeybCmdSetRepeatDelay 0xf3 +#define KeybCmdEnable 0xf4 +#define KeybCmdSetDefaultDisable 0xf5 +#define KeybCmdSetDefault 0xf6 +#define KeybCmdResend 0xfe +#define KeybCmdReset 0xff + +volatile uint8 KeyState[16]; +volatile uint8 KeyboardLastStatus; +volatile uint8 KeyboardLastScancode; + +uint8 KeyboardScancodeSet = 2; + +// Byte map: +// 0 If set, next code is break +// 1 'Gray' key +// 2 'Weird' key (Pause/Break) +// 3 Scroll +// 4 Num +// 5 Caps +// 6 If set, LEDs changed +uint8 KeyboardModifiers; + +const char KeyboardMap[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t', '`', 0, + 0, 0, 0, 0, 0, 'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2', 0, + 0, 'c', 'x', 'd', 'e', '4', '3', 0, 0, ' ', 'v', 'f', 't', 'r', '5', 0, + 0, 'n', 'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j', 'u', '7', '8', 0, + 0, ',', 'k', 'i', 'o', '0', '9', 0, 0, '.', '/', 'l', ';', 'p', '-', 0, + 0, 0, '\'', 0, '[', '=', 0, 0, 0, 0, '\n', ']', 0, '\\', 0, 0, + 0, 0, 0, 0, 0, 0, '\b', 0, 0, '1', '/', '4', '7', '\n', 0, 0, + '0', '.', '2', '5', '6', '8', 0, 0, 0, '+', '3', '-', '*', '9', 0, 0 + }; + +const char KeyboardMapShift[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t', '~', 0, + 0, 0, 0, 0, 0, 'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@', 0, + 0, 'C', 'X', 'D', 'E', '$', '#', 0, 0, ' ', 'V', 'F', 'T', 'R', '%', 0, + 0, 'N', 'B', 'H', 'G', 'Y', '^', 0, 0, 0, 'M', 'J', 'U', '&', '*', 0, + 0, '<', 'K', 'I', 'O', ')', '(', 0, 0, '>', '?', 'L', ':', 'P', '_', 0, + 0, 0, '\"', 0, '{', '+', 0, 0, 0, 0, '\n', '}', 0, '|', 0, 0, + 0, 0, 0, 0, 0, 0, '\b', 0, 0, '1', '/', '4', '7', '\n', 0, 0, + '0', '.', '2', '5', '6', '8', 0, 0, 0, '+', '3', '-', '*', '9', 0, 0 + }; + + +void KeyboardSetKeyStatus (uint8 scancode, uint8 status) +{ + int32 index = scancode>>3, pos = scancode & 0x7; + + if (status) KeyState[index] |= 1<>3, pos = scancode & 0x7; + + return KeyState[index] & (1< 0); + status |= (num > 0) << 1; + status |= (caps > 0) << 2; + + KeyboardWaitOutport(); + outportb (0x60, KeybCmdWriteLED); + + KeyboardWaitOutport(); + outportb (0x60, status); +} + + +/*************************************** + * Set repeat rate/delay * + *************************************** + Values for inter-character delay (bits 4-0) + (characters per second; default is 10.9) + | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 + ----+----+----+----+----+----+----+----+---- + 0 |30.0|26.7|24.0|21.8|20.0|18.5|17.1|16.0 + 8 |15.0|13.3|12.0|10.9|10.0|9.2 |8.6 |8.0 + 16 |7.5 |6.7 |6.0 |5.5 |5.0 |4.6 |4.3 |4.0 + 24 |3.7 |3.3 |3.0 |2.7 |2.5 |2.3 |2.1 |2.0 + + Values for delay: + (miliseconds; default is 500) + 0 | 1 | 2 | 3 + -----+-----+-----+----- + 250 | 500 | 750 | 1000 + + ***************************************/ +void KeyboardSetRepeatRate(uint8 rate, uint8 delay) +{ + if (rate>3 || delay>31) return; + + uint8 out = rate<<5 | delay; + + KeyboardWaitOutport(); + outportb(0x60, KeybCmdSetRepeatDelay); + + KeyboardWaitOutport(); + outportb(0x60, out); +} + +/*************************************** + * Set scancode set * + *************************************** + 1 Set to scancode set 1 + 2 Set to scancode set 2 + 3 Set to scancode set 3 + ***************************************/ +void KeyboardSetScancodeSet(uint8 set) +{ + if (set>3 || set <= 0) return; + + KeyboardWaitOutport(); + outportb (0x60, KeybCmdSetScancodeSet); + + KeyboardWaitOutport(); + outportb (0x60, set); + + KeyboardScancodeSet = set; +} + + +void KeyboardWaitOutport() +{ + int fail_safe=200000; + while ((inportb(0x64)&2)!=0 && fail_safe>0) fail_safe--; +} + +void KeyboardWaitInport() +{ + int fail_safe=200000; + while ((inportb(0x64)&1)==0 && fail_safe>0) fail_safe--; +} + + +void KeyboardInstallA() +{ + KeyboardWaitOutport(); + outportb(0x60, KeybCmdReset); // Reset kb + + // Initialize variables + KeyboardLastStatus = 0; + KeyboardModifiers = 0; + + int32 i; + for (i = 0; i < 16; i++) + KeyState[i] = 0; +} + + +void KeyboardInstallB() +{ + // Wait for BAT test results + KeyboardWaitInport(); + + unsigned char temp; + do temp = inportb(0x60); + while (temp!=0xAA && temp!=0xFC); + + // Error + if (temp == 0xFC) return; + + // Set new repeat rate + KeyboardSetRepeatRate(1, 11); + + // Set scancode set 2 + KeyboardSetScancodeSet(2); // Set new scancode set + + KeyboardWaitOutport(); + outportb(0x64, 0x20); // Get "Command unsigned char" + + do { temp = inportb(0x60); + } while (temp==0xFA || temp==0xAA); + + temp &= ~(1<<6); // Unset bit6: disable conversion + KeyboardWaitOutport(); + outportb(0x64, 0x60); // Function to write cmd unsigned char + + KeyboardWaitOutport(); + outportb(0x60, temp); // Send it +} diff --git a/Kernel/hal/keyboard/keyboard.h b/Kernel/hal/keyboard/keyboard.h new file mode 100644 index 0000000..7d3805f --- /dev/null +++ b/Kernel/hal/keyboard/keyboard.h @@ -0,0 +1,52 @@ +#ifndef __KEYBOARD__H +#define __KEYBOARD__H + +#include + +extern const char KeyboardMap[0x80]; +extern const char KeyboardMapShift[0x80]; +extern volatile uint8 KeyboardLastStatus; +extern volatile uint8 KeyboardLastScancode; + +extern void KeyboardSetKeyStatus (uint8 scancode, uint8 status); +extern uint8 KeyboardGetKeyStatus (uint8 scancode); +extern void KeyboardHandler (_RegsStack32 *r); +extern void KeyboardSetLEDs (uint8 scroll, uint8 num, uint8 caps); +/*************************************** + * Set repeat rate/delay * + *************************************** + Values for inter-character delay (bits 4-0) + (characters per second; default is 10.9) + | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 + ----+----+----+----+----+----+----+----+---- + 0 |30.0|26.7|24.0|21.8|20.0|18.5|17.1|16.0 + 8 |15.0|13.3|12.0|10.9|10.0|9.2 |8.6 |8.0 + 16 |7.5 |6.7 |6.0 |5.5 |5.0 |4.6 |4.3 |4.0 + 24 |3.7 |3.3 |3.0 |2.7 |2.5 |2.3 |2.1 |2.0 + + Values for delay: + (miliseconds; default is 500) + 0 | 1 | 2 | 3 + -----+-----+-----+----- + 250 | 500 | 750 | 1000 + + ***************************************/ +extern void KeyboardSetRepeatRate(uint8 rate, uint8 delay); + +/*************************************** + * Set scancode set * + *************************************** + 1 Set to scancode set 1 + 2 Set to scancode set 2 + 3 Set to scancode set 3 + ***************************************/ +extern void KeyboardSetScancodeSet(uint8 set); + +extern void KeyboardWaitOutport(); +extern void KeyboardWaitInport(); + +extern void KeyboardInstallA(); +extern void KeyboardInstallB(); + +#endif + diff --git a/Kernel/hal/mouse/mouse.c b/Kernel/hal/mouse/mouse.c new file mode 100644 index 0000000..c5f4070 --- /dev/null +++ b/Kernel/hal/mouse/mouse.c @@ -0,0 +1,116 @@ +#include +#include +#include "mouse.h" +#include "../keyboard/keyboard.h" + +uint8 MouseCycle = 0; +uint8 MouseCycleExpected = 3; +uint8 Packets[4]; + +Point MousePosition = {0,0}; +Point MouseMinimumPosition = {0,0}, MouseMaximumPosition = {80, 25}; +Point Prev = {0,0}; + +#define SpeedLimit 0x8 + +// IRQ12 +void MouseHandler (_RegsStack32* UNUSED(r)) +{ + uint8 data = inportb(0x60); + Point delta; + + if (MouseCycle == 0 && (data == 0 || data == 0xFA || data == 0xFF || data == 0xAA)) return; + Packets[MouseCycle++] = data; + + // Cycle ended + if (MouseCycle >= MouseCycleExpected) + { + MouseCycle = 0; + if (Packets[0] & 0xC0) return; // Discard packet + + // Update X position + if (Packets[0] & 0x10) delta.X = (int32) (Packets[1] | 0xFFFFFF00); + else delta.X = (int32) Packets[1]; + + // Update Y position + if (Packets[0] & 0x20) delta.Y = -1 * (int32) (Packets[2] | 0xFFFFFF00); + else delta.Y = -1 * (int32)Packets[2]; + + if (delta.X >= SpeedLimit) delta.X = SpeedLimit; + if (delta.X <= -SpeedLimit) delta.X = -SpeedLimit; + if (delta.Y >= SpeedLimit) delta.Y = SpeedLimit; + if (delta.Y <= -SpeedLimit) delta.Y = -SpeedLimit; + + MousePosition.X += delta.X; + MousePosition.Y += delta.Y; + + // Check limits + if (MousePosition.X < MouseMinimumPosition.X) MousePosition.X = MouseMinimumPosition.X; + if (MousePosition.Y < MouseMinimumPosition.Y) MousePosition.Y = MouseMinimumPosition.Y; + if (MousePosition.X >= MouseMaximumPosition.X) MousePosition.X = MouseMaximumPosition.X - 1; + if (MousePosition.Y >= MouseMaximumPosition.Y) MousePosition.Y = MouseMaximumPosition.Y - 1; + + /* TESTING ONLY */ + ConsoleSetColor(Prev, 0xFF - ConsoleGetColor(Prev)); + ConsoleSetColor(MousePosition, 0xFF - ConsoleGetColor(MousePosition)); + Prev = MousePosition; + + } +} + +void MouseSendCommand(uint8 command) +{ + KeyboardWaitOutport(); + outportb(0x64, 0xD4); + KeyboardWaitOutport(); + outportb(0x60, command); +} + +uint8 MouseReadData () +{ + KeyboardWaitInport(); + return inportb(0x60); +} + +void MouseInstall() +{ + KeyboardWaitOutport(); + outportb(0x64, 0xA8); + + // Enable interrupts + KeyboardWaitOutport(); + outportb(0x64, 0x20); + + KeyboardWaitInport(); + uint8 temp = inportb(0x60) | 2; + temp &= ~0x20; + + KeyboardWaitOutport(); + outportb(0x64, 0x60); + + KeyboardWaitOutport(); + outportb(0x60, temp); + + // Reset mouse, and enable it + MouseSendCommand(MouseCommandReset); + MouseReadData(); MouseReadData(); + + MouseSendCommand(MouseCommandSetDefaults); + MouseReadData(); // Read ack + + MouseSendCommand(MouseCommandEnableDataReporting); + MouseReadData(); // Read ack + +} + +void MouseSetLimits (Point min_pos, Point max_pos) +{ + MouseMinimumPosition = min_pos; + MouseMaximumPosition = max_pos; +} + +MouseState MouseGetState() +{ + MouseState ret = { Packets[0] & 0x7, MousePosition}; + return ret; +} diff --git a/Kernel/hal/mouse/mouse.h b/Kernel/hal/mouse/mouse.h new file mode 100644 index 0000000..b71114b --- /dev/null +++ b/Kernel/hal/mouse/mouse.h @@ -0,0 +1,36 @@ +#ifndef __MOUSE__H +#define __MOUSE__H + +#include + +typedef struct +{ + uint8 Buttons; + Point Position; +} MouseState; + +enum MouseCommands +{ + MouseCommandReset = 0xFF, + MouseCommandResend = 0xFE, + MouseCommandSetDefaults = 0xF6, + MouseCommandDisableDataReporting = 0xF5, + MouseCommandEnableDataReporting = 0xF4, + MouseCommandSetSampleRate = 0xF3, + MouseCommandGetDeviceID = 0xF2, + MouseCommandSetRemoteMode = 0xF0, + MouseCommandSetWrapMode = 0xEE, + MouseCommandReadData = 0xEB, + MouseCommandSetStreamMode = 0xEA, + MouseCommandStatusRequest = 0xE9, + MouseCommandSetResolution = 0xE8, + MouseCommandSetScaling_2_1 = 0xE7, + MouseCommandSetScaling_1_1 = 0xE6 +}; + +extern void MouseInstall(); +extern void MouseHandler (_RegsStack32 *r); +extern void MouseSetLimits (Point min_pos, Point max_pos); +extern MouseState MouseGetState(); + +#endif diff --git a/Kernel/hal/sysinfo.c b/Kernel/hal/sysinfo.c new file mode 100644 index 0000000..8529f4c --- /dev/null +++ b/Kernel/hal/sysinfo.c @@ -0,0 +1,27 @@ +/* + * sysinfo.c + * + * Provides information about system, and useful utilities + * + * Created on: Aug 17, 2011 + * Author: Tiberiu + */ + +#include +#include +#include +#include + +#include <../drivers/cmos/cmos.h> + +#include "keyboard/keyboard.h" +void SystemReboot() +{ + Log("Rebooting system...\n"); + + KeyboardWaitOutport(); + outportb (0x64, 0xFE); + + asm("cli"); + asm("hlt"); +} diff --git a/Kernel/hal/vfs.c b/Kernel/hal/vfs.c new file mode 100644 index 0000000..23000df --- /dev/null +++ b/Kernel/hal/vfs.c @@ -0,0 +1,40 @@ +#include +#include + +#define MAX_FS_COUNT 64 + +uint32 FsRead(FsNode *node, uint32 offset, uint32 size, uint8 *buffer) +{ + if (node->Read != NULL) return node->Read(node, offset, size, buffer); + return NULL; +} + +uint32 FsWrite(FsNode *node, uint32 offset, uint32 size, uint8 *buffer) +{ + if (node->Write != NULL) return node->Write(node, offset, size, buffer); + return NULL; +} + +void FsOpen(FsNode *node, uint8 read, uint8 write) +{ + if (node->Open != NULL) return node->Open(node, read, write); +} + +void FsClose(FsNode *node) +{ + if (node->Close != NULL) return node->Close(); +} + +DirectoryEntry *FsReadDir(FsNode *node, uint32 index) +{ + if (node->ReadDir != NULL && (node->Flags&7) == FsDirectory) + return node->ReadDir(node, index); + return NULL; +} + +FsNode *FsFindDir(FsNode *node, char *name) +{ + if (node->FindDir != NULL && (node->Flags&7) == FsDirectory) + return node->FindDir(node, name); + return NULL; +} diff --git a/SysCore/include/ctype.h b/Kernel/include/ctype.h similarity index 98% rename from SysCore/include/ctype.h rename to Kernel/include/ctype.h index 3881116..ac70a3c 100644 --- a/SysCore/include/ctype.h +++ b/Kernel/include/ctype.h @@ -1,5 +1,5 @@ #ifndef __CTYPE_H -#define __CTYPE_H +#define __CTYPE_H extern unsigned char _ctype[]; diff --git a/Kernel/include/debugio.h b/Kernel/include/debugio.h new file mode 100644 index 0000000..54c6518 --- /dev/null +++ b/Kernel/include/debugio.h @@ -0,0 +1,88 @@ +#ifndef __DEBUGIO__H +#define __DEBUGIO__H + +#include +#include +#include + +enum Colors +{ + ColorBlack = 0x0, + ColorBlue = 0x1, + ColorGreen = 0x2, + ColorCyan = 0x3, + ColorRed = 0x4, + ColorMagenta = 0x5, + ColorBrown = 0x6, + ColorLightGray = 0x7, + ColorDarkGray = 0x8, + ColorLightBlue = 0x9, + ColorLightGreen = 0xA, + ColorLightCyan = 0xB, + ColorLightRed = 0xC, + ColorLightMagenta = 0xD, + ColorYellow = 0xE, + ColorWhite = 0xF +}; + +extern uint8 Color (uint8 back, uint8 fore); + +// Cursor position +extern Point ConsoleGetCursor(); +extern void ConsoleSetCursor(Point p); +extern void ConsoleCursorGoto(Point p); + +extern void ConsoleCursorIncreasePos (int32 delta); +extern void ConsoleCursorNewline(); +extern void ConsoleCursorUpdateHardware(); + +// Get/set properties +extern void ConsoleSetDefaultColor(uint8 color); +extern uint8 ConsoleGetDefaultColor (); +extern UPoint ConsoleGetSize(); + +extern void ConsoleSetChar(Point pos, char c); +extern void ConsoleSetColor(Point pos, uint8 color); +extern char ConsoleGetChar(Point pos); +extern uint8 ConsoleGetColor (Point pos); + + +// Basic console operations +extern void ConsoleClear(); +extern void ConsoleScroll (uint32 lines); + +// Console write operations +extern void ConsoleWriteChar (char c); +extern void ConsoleWriteString (string s); +extern int32 ConsoleWrite (string format, ...); + +// Console read operations +extern void ConsoleReadString (string s, int32 buffer_size, char end_char); + +// Console main loop +extern void ConsoleMain(); + +// Debug print +#if VERBOSE_MODE==1 +#define Log(...) ConsoleWrite(__VA_ARGS__) +#else +#define Log(...) +#endif + +// Error print +#if VERBOSE_ERROR==1 +#define Error(...) ConsoleWrite(__VA_ARGS__) +#else +#define Error(...) +#endif + +// Panic +#if VERBOSE_PANIC==1 +#define Panic(...) { ConsoleWrite("%#[PANIC] KERNEL PANIC: ", ColorLightRed); \ + ConsoleWrite(__VA_ARGS__); \ + asm volatile ("cli\nhlt"); } +#else +#define Panic(...) +#endif + +#endif diff --git a/Kernel/include/fileio.h b/Kernel/include/fileio.h new file mode 100644 index 0000000..0858ea9 --- /dev/null +++ b/Kernel/include/fileio.h @@ -0,0 +1,70 @@ +/* + * fileio.h + * + * Created on: Aug 23, 2011 + * Author: Tiberiu + */ + +#ifndef FILEIO_H_ +#define FILEIO_H_ + +#include + +enum FsFlags +{ + FsFile = 0x1, + FsDirectory = 0x2, + FsCharDevice = 0x3, + FsBlockDevice = 0x4, + FsPipe = 0x5, + FsSymbolLink = 0x6, + FsMountPoint = 0x8 +}; + +typedef uint32 (*ReadRoutine)(struct _FsNode*, uint32, uint32, uint8*); +typedef uint32 (*WriteRoutine)(struct _FsNode*, uint32, uint32, uint8*); +typedef void (*OpenRoutine)(struct _FsNode*); +typedef void (*CloseRoutine)(struct _FsNode*); +typedef struct _DirectoryEntry (*ReadDirRoutine)(struct _FsNode*,uint32); +typedef struct _FsNode* (*FindDirRoutine)(struct _FsNode*,char *name); + +typedef struct _FsNode +{ + char Name[128]; // The filename. + uint32 Permissions; // The permissions mask. + uint32 UserId; // The owning user. + uint32 GroupId; // The owning group. + uint32 Flags; // Includes the node type. See enum above. + uint32 INode; // This is device-specific - provides a way for a filesystem to identify files. + uint32 Length; // Size of the file, in bytes. + uint32 Implementation; // An implementation-defined number. + ReadRoutine Read; + WriteRoutine Write; + OpenRoutine Open; + CloseRoutine Close; + ReadDirRoutine ReadDir; + FindDirRoutine FindDir; + struct _FsNode *Ptr; // Used by mountpoints and symlinks. +} FsNode; + + +typedef struct _DirectoryEntry +{ + char Name[128]; + uint32 INode; +} DirectoryEntry; + + +extern uint32 FsRead(FsNode *node, uint32 offset, uint32 size, uint8 *buffer); +extern uint32 FsWrite(FsNode *node, uint32 offset, uint32 size, uint8 *buffer); +extern void FsOpen(FsNode *node, uint8 read, uint8 write); +extern void FsClose(FsNode *node); +extern DirectoryEntry *FsReadDir(FsNode *node, uint32 index); +extern FsNode *FsFindDir(FsNode *node, char *name); + +#ifdef NEVER +void VfsRegisterFilesys(); +void VfsMount(); +#endif + +#endif /* FILEIO_H_ */ diff --git a/Kernel/include/memory-add.h b/Kernel/include/memory-add.h new file mode 100644 index 0000000..e423cff --- /dev/null +++ b/Kernel/include/memory-add.h @@ -0,0 +1,97 @@ +/* + * memory-add.h + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ + +#ifndef MEMORY_ADD_H_ +#define MEMORY_ADD_H_ + +#include +#include +#include + +/*************************************************** + * Paging * + ***************************************************/ +typedef uint32 Page; + +enum PageFlags +{ + PagePresent = 0x1, + PageWriteable = 0x2, + PageUser = 0x4, + PageWriteThough = 0x8, + PageNotCacheable = 0x10, + PageAccessed = 0x20, + PageDirty = 0x40, + PagePAT = 0x80, + PageCpuGlobal = 0x100, + PageLvl4Global = 0x200, + PageFrame = 0xFFFFF000 +}; + + + +typedef struct { + Page Pages[1024]; +} PageTable; + +typedef struct { + PageTable* Tables[1024]; + uint32 TablesPhysical[1024]; + uint32 PhysicalAddr; +} PageDirectory; + +extern PageDirectory* CurrentDirectory; +extern PageDirectory* KernelDirectory; + +extern void PagingInitialize(uint32 SystemMemory); +extern void PagingSwitchPageDirectory (PageDirectory* dir); +extern Page* PagingGetPage(uint32 addr, uint8 make, PageDirectory* dir); + + +/*************************************************** + * Physical memory manager * + ***************************************************/ +extern uint32 TotalFrames; +extern uint32 TotalMemory; +extern uint32 UsedFrames; + +void MemPhInitialize(uint32 SystemMemoryKb); +extern void MemPhSetFrame (uint32 frame, uint8 value); +uint32 MemPhGetFrame (uint32 frame); +uint32 MemPhFindFreeFrame(); +void MemPhAllocFrame(Page* page, uint8 isKernel, uint8 isWriteable); +void MemPhFreeFrame(Page* page); +void MemPhReserveFrames (uint32 address, uint32 length); + + +/*************************************************** + * Memory heap * + ***************************************************/ +typedef struct +{ + OrderedArray Index; + uint32 StartAddress, EndAddress, MaxAddress; + // bit 0: supervisor-only bit 1: read-only + uint8 Flags; +} MemHeap; + +extern MemHeap* KernelHeap; + +extern uint32 MemHeapFindSmallestHole (uint32 size, uint8 page_align, MemHeap* heap); +extern int32 MemHeapCompare (uint32 a, uint32 b); +extern MemHeap* MemHeapCreate(uint32 start, uint32 end, uint32 max, uint8 flags); +extern void MemHeapExpand(uint32 newsz, MemHeap* heap, PageDirectory* pd); +extern uint32 MemHeapContract(uint32 newsz, MemHeap* heap, PageDirectory* pd); +extern uint32 MemHeapAlloc (uint32 size, uint8 isPageAligned, MemHeap* heap, PageDirectory* pd); +extern void MemHeapFree (uint32 address, MemHeap* heap, PageDirectory* pd); + + +#define LogMem(...) { Log("%#[Mem] ", ColorLightCyan); Log(__VA_ARGS__); } +#define ErrorMem(...) { Error("%#[Mem] ", ColorLightCyan); Error(__VA_ARGS__); } + + +#endif /* MEMORY_ADD_H_ */ diff --git a/Kernel/include/memory-add.h~ b/Kernel/include/memory-add.h~ new file mode 100644 index 0000000..acd3a39 --- /dev/null +++ b/Kernel/include/memory-add.h~ @@ -0,0 +1,96 @@ +/* + * memory-add.h + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ + +#ifndef MEMORY_ADD_H_ +#define MEMORY_ADD_H_ + +#include +#include +#include + +/*************************************************** + * Paging * + ***************************************************/ +typedef uint32 Page; + +enum PageFlags +{ + PagePresent = 0x1, + PageWriteable = 0x2, + PageUser = 0x4, + PageWriteThough = 0x8, + PageNotCacheable = 0x10, + PageAccessed = 0x20, + PageDirty = 0x40, + PagePAT = 0x80, + PageCpuGlobal = 0x100, + PageLvl4Global = 0x200, + PageFrame = 0xFFFFF000 +}; + + + +typedef struct { + Page Pages[1024]; +} PageTable; + +typedef struct { + PageTable* Tables[1024]; + uint32 TablesPhysical[1024]; + uint32 PhysicalAddr; +} PageDirectory; + +extern PageDirectory* CurrentDirectory; +extern PageDirectory* KernelDirectory; + +extern void PagingInitialize(uint32 SystemMemory); +extern void PagingSwitchPageDirectory (PageDirectory* dir); +extern Page* PagingGetPage(uint32 addr, uint8 make, PageDirectory* dir); + + +/*************************************************** + * Physical memory manager * + ***************************************************/ +extern uint32 TotalFrames; +extern uint32 TotalMemory; + +void MemPhInitialize(uint32 SystemMemoryKb); +extern void MemPhSetFrame (uint32 frame, uint8 value); +uint32 MemPhGetFrame (uint32 frame); +uint32 MemPhFindFreeFrame(); +void MemPhAllocFrame(Page* page, uint8 isKernel, uint8 isWriteable); +void MemPhFreeFrame(Page* page); +void MemPhReserveFrames (uint32 address, uint32 length); + + +/*************************************************** + * Memory heap * + ***************************************************/ +typedef struct +{ + OrderedArray Index; + uint32 StartAddress, EndAddress, MaxAddress; + // bit 0: supervisor-only bit 1: read-only + uint8 Flags; +} MemHeap; + +extern MemHeap* KernelHeap; + +extern uint32 MemHeapFindSmallestHole (uint32 size, uint8 page_align, MemHeap* heap); +extern int32 MemHeapCompare (uint32 a, uint32 b); +extern MemHeap* MemHeapCreate(uint32 start, uint32 end, uint32 max, uint8 flags); +extern void MemHeapExpand(uint32 newsz, MemHeap* heap, PageDirectory* pd); +extern uint32 MemHeapContract(uint32 newsz, MemHeap* heap, PageDirectory* pd); +extern uint32 MemHeapAlloc (uint32 size, uint8 isPageAligned, MemHeap* heap, PageDirectory* pd); +extern void MemHeapFree (uint32 address, MemHeap* heap, PageDirectory* pd); + + +#define LogMem(...) { Log("%#[Mem] ", ColorLightCyan); Log(__VA_ARGS__); } +#define ErrorMem(...) { Error("%#[Mem] ", ColorLightCyan); Error(__VA_ARGS__); } + + +#endif /* MEMORY_ADD_H_ */ diff --git a/Kernel/include/memory.h b/Kernel/include/memory.h new file mode 100644 index 0000000..0630375 --- /dev/null +++ b/Kernel/include/memory.h @@ -0,0 +1,29 @@ +#ifndef __MEMORY__H +#define __MEMORY__H + +#include +#include +#include + +/*************************************************** + * Basic memory operations: alloc, free * + ***************************************************/ +extern void* kmalloc (uint32 size); +extern void* kmalloc_a (uint32 size); +extern void* kmalloc_p (uint32 size, uint32* phys); +extern void* kmalloc_ap (uint32 size, uint32* phys); +extern void kfree (void* addr); + +extern void MemoryTempInitialize (uint32 kernel_end); +extern void MemoryInitialize (MultibootInfo* info); + +extern uint32 MemoryGetTotal(); +extern uint32 MemoryGetFree(); // Returns total free physical memory in kilobytes +extern uint32 MemoryGetUsed(); // Total used physical memory in kbytes +extern uint32 MemoryGetFrameSize(); // Same as above functions, but in frames +extern uint32 MemoryGetFramesTotal(); +extern uint32 MemoryGetFramesUsed(); +extern uint32 MemoryGetFramesFree(); + + +#endif diff --git a/Kernel/include/memory.h~ b/Kernel/include/memory.h~ new file mode 100644 index 0000000..35992b7 --- /dev/null +++ b/Kernel/include/memory.h~ @@ -0,0 +1,29 @@ +#ifndef __MEMORY__H +#define __MEMORY__H + +#include +#include +#include + +/*************************************************** + * Basic memory operations: alloc, free * + ***************************************************/ +extern void* kmalloc (uint32 size); +extern void* kmalloc_a (uint32 size); +extern void* kmalloc_p (uint32 size, uint32* phys); +extern void* kmalloc_ap (uint32 size, uint32* phys); +extern void kfree (void* addr); + +extern void MemoryTempInitialize (uint32 kernel_end); +extern void MemoryInitialize (MultibootInfo* info); + +extern uint32 MemoryGetTotal(); +extern uint32 MemoryGetFree(); // Returns total free physical memory in bytes +extern uint32 MemoryGetUsed(); // Total used physical memory in bytes +extern uint32 MemoryGetFrameSize(); // Same as above functions, but in frames +extern uint32 MemoryGetFramesTotal(); +extern uint32 MemoryGetFramesUsed(); +extern uint32 MemoryGetFramesFree(); + + +#endif diff --git a/Kernel/include/multiboot.h b/Kernel/include/multiboot.h new file mode 100644 index 0000000..51a5589 --- /dev/null +++ b/Kernel/include/multiboot.h @@ -0,0 +1,119 @@ +/* + * multiboot.h + * + * Created on: Aug 17, 2011 + * Author: Tiberiu +*/ + +#ifndef MULTIBOOT_H_ +#define MULTIBOOT_H_ + +#include + +// Flags to be set in the 'flags' member of the multiboot info structure. +#define MultibootInfo_MEMORY 0x00000001 // is there basic lower/upper memory information? +#define MultibootInfo_BOOTDEV 0x00000002 // is there a boot device set? +#define MultibootInfo_CMDLINE 0x00000004 // is the command-line defined? +#define MultibootInfo_MODS 0x00000008 // are there modules to do something with? + +// These next two are mutually exclusive +#define MultibootInfo_AOUT_SYMS 0x00000010 // is there a symbol table loaded? +#define MultibootInfo_ELF_SHDR 0X00000020 // is there an ELF section header table? + + +#define MultibootInfo_MEM_MAP 0x00000040 // is there a full memory map? +#define MultibootInfo_DRIVE_INFO 0x00000080 // Is there drive info? +#define MultibootInfo_CONFIG_TABLE 0x00000100 // Is there a config table? +#define MultibootInfo_BOOT_LOADER_NAME 0x00000200 // Is there a boot loader name? +#define MultibootInfo_APM_TABLE 0x00000400 // Is there a APM table? +#define MultibootInfo_VIDEO_INFO 0x00000800 // Is there video information? + + +// The symbol table for a.out. +typedef struct +{ + uint32 TableSize; + uint32 StrSize; + uint32 Address; + uint32 Reserved; +} MultibootAoutSymbolTable; + + +// The section header table for ELF. +typedef struct +{ + uint32 Number; + uint32 Size; + uint32 Address; + uint32 Shndx; +} MultibootElfSectionHeaderTable; + + +typedef struct +{ + uint32 Flags; // Multiboot info version number + + uint32 MemoryLower; // Available memory from BIOS + uint32 MemoryUpper; + + uint32 BootDevice; // "root" partition + + uint32 CommandLine; // Kernel command line + + uint32 ModulesCount; // Boot-Module list + uint32 ModulesAddress; + + union + { + MultibootAoutSymbolTable AoutSymbols; + MultibootElfSectionHeaderTable ElfSectionHeaderTable; + } Symbols; + + uint32 MemoryMapLength; // Memory Mapping buffer + uint32 MemoryMapAddress; + + uint32 DrivesLength; // Drive Info buffer + uint32 DrivesAddress; + + uint32 ConfigurationTable; // ROM configuration table + + uint32 BootLoaderName; // Boot Loader Name + + uint32 ApmTable; // APM table + + uint32 VbeControlInfo; // Video + uint32 VbeModeInfo; + uint16 VbeMode; + uint16 VbeInterfaceSegment; + uint16 VbeInterfaceOffset; + uint16 VbeInterfaceLength; +} MultibootInfo; + + +typedef struct +{ + uint32 Size; + uint64 Address; + uint64 Length; + + #define MULTIBOOT_MEMORY_AVAILABLE 1 + #define MULTIBOOT_MEMORY_RESERVED 2 + + uint32 Type; +} __attribute__((packed)) MultibootMemoryMapEntry; + +typedef struct +{ + // the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive + uint32 ModuleStart; + uint32 ModuleEnd; + + // Module command line + uint32 CommandLine; + + // padding to take it to 16 bytes (must be zero) + uint32 _Padding; +} MultibootModule; + + +#endif diff --git a/Kernel/include/settings.h b/Kernel/include/settings.h new file mode 100644 index 0000000..4c0382a --- /dev/null +++ b/Kernel/include/settings.h @@ -0,0 +1,38 @@ +/* + * settings.h + * + * Created on: Aug 16, 2011 + * Author: Tiberiu + */ + +#ifndef SETTINGS_H_ +#define SETTINGS_H_ + +// OS info +#define OS_STRING "lux" +#define OS_VERSION "0.1 [pre-Alpha]" +#define OS_BUILD_DATE __DATE__ +#define OS_BUILD_TIME __TIME__ + +#include + +// Logger +#define VERBOSE_MODE 1 +#define VERBOSE_ERROR 1 +#define VERBOSE_PANIC 1 + + +// Clock +#define PIT_FREQUENCY 100 + +// Console +#define CONSOLE_MAX_PARAMS 32 +#define CONSOLE_DEFAULT_COLOR 0x7 + +// Memory manager +#define KERNEL_HEAP_START 0xC0000000 +#define KERNEL_HEAP_INITIAL_SIZE 0x100000 +#define KERNEL_HEAP_END (KERNEL_HEAP_START + KERNEL_HEAP_INITIAL_SIZE) + + +#endif /* SETTINGS_H_ */ diff --git a/Kernel/include/settings.h~ b/Kernel/include/settings.h~ new file mode 100644 index 0000000..30491f7 --- /dev/null +++ b/Kernel/include/settings.h~ @@ -0,0 +1,37 @@ +/* + * settings.h + * + * Created on: Aug 16, 2011 + * Author: Tiberiu + */ + +#ifndef SETTINGS_H_ +#define SETTINGS_H_ + +// OS info +#define OS_STRING "lux" +#define OS_VERSION "0.1 [pre-Alpha]" +#define OS_BUILD_DATE __DATE__ +#define OS_BUILD_TIME __TIME__ + +#include + +// Logger +#define VERBOSE_MODE 1 +#define VERBOSE_ERROR 1 +#define VERBOSE_PANIC 1 + + +// Clock +#define PIT_FREQUENCY 100 + +// Console +#define CONSOLE_MAX_PARAMS 32 +#define CONSOLE_DEFAULT_COLOR 0x7 + +// Memory manager +#define KERNEL_HEAP_START 0xC0000000 +#define KERNEL_HEAP_END 0xCFFFF000 +#define KERNEL_HEAP_INITIAL_SIZE 0x100000 + +#endif /* SETTINGS_H_ */ diff --git a/SysCore/include/stdarg.h b/Kernel/include/stdarg.h similarity index 72% rename from SysCore/include/stdarg.h rename to Kernel/include/stdarg.h index 257f25b..4e3b41c 100644 --- a/SysCore/include/stdarg.h +++ b/Kernel/include/stdarg.h @@ -1,17 +1,9 @@ -#ifndef __STDARG_H -#define __STDARG_H +#ifndef __STDARG__H +#define __STDARG__H - -/****************************** - * [filename] * - * - [description] * - ******************************/ - -// INTERFACE REQUIRED HEADERS #include -// INTERFACE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS #ifdef __cplusplus extern "C" { diff --git a/Kernel/include/stdio.h b/Kernel/include/stdio.h new file mode 100644 index 0000000..59a37dc --- /dev/null +++ b/Kernel/include/stdio.h @@ -0,0 +1,29 @@ +#ifndef __STDIO__H +#define __STDIO__H + +#include + +#define inb(port) inportb(port) +#define outb(port) outportb(port) + +extern uint8 inportb (uint16 _port); + +static inline void outportb (uint16 _port, uint8 _data) { + asm volatile ("outb %1, %0" : : "dN" (_port), "a" (_data)); +} + +static inline void iowait() { + asm volatile ("outb %al, $0x80"); +} + +static inline void MagicBreakpoint() +{ + asm volatile ("xchg %bx, %bx"); +} + +extern void SystemReboot(); + +extern Key ReadKey(); +extern KeyEvent ReadKeyEvent(); + +#endif diff --git a/Kernel/include/stdlib.h b/Kernel/include/stdlib.h new file mode 100644 index 0000000..4239b52 --- /dev/null +++ b/Kernel/include/stdlib.h @@ -0,0 +1,69 @@ +#ifndef __STDLIB__H +#define __STDLIB__H + +#include + +#define IsDigit(c) (c >= '0' && c <= '9') +#define IsHexDigit(c) ( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) +#define IsUpper(c) (c >= 'A' && c <= 'Z') +#define IsLower(c) (c >= 'a' && c <= 'z') + +#define IsAlpha(c) (IsLower(c) || IsUpper(c)) +#define IsAlphaNum(c) (IsAlpha(c) || IsDigit(c)) + +#define ToLower(c) ((IsUpper(c)) ? (c - 'A' + 'a') : c) +#define ToUpper(c) ((IsLower(c)) ? (c - 'a' + 'A') : c) + +#define Max(a,b) ((a > b) ? (a) : (b)) +#define Min(a,b) ((a < b) ? (a) : (b)) +#define Abs(a) ((a < 0) ? (a * -1) : (a)) + +/*************************************************** + * String operations: len, cmp, cpy * + ***************************************************/ +extern uint32 strlen (string s); +extern int32 strcmp (string a, string b); +extern string strcpy (string s1, const string s2); + +/*************************************************** + * Number operations: len * + ***************************************************/ +extern uint32 numlen (int32 number, int32 base); +extern uint32 unumlen (uint32 number, int32 base); + +/*************************************************** + * Memory operations: cpy, cmp, set * + ***************************************************/ +void* memcpy (void *dest, const void *src, uint32 count); +int32 memcmp (const void *s1, const void *s2, uint32 count); +void* memset (void *dest, uint8 val, uint32 count); + +/*************************************************** + * Conversion operations: num-str/str-num * + ***************************************************/ +extern int32 ConvertIntToString (string buffer, int32 number, int32 base); +extern uint32 ConvertUIntToString (string buffer, uint32 number, int32 base); +extern int32 ConvertStringToInt (string buffer); +extern uint32 ConvertStringToUInt (string buffer); +extern uint32 ConvertStringToIntHex (string buffer); + +/*************************************************** + * Ordered array implementation * + ***************************************************/ +typedef int (*ComparePredicate) (uint32, uint32); +typedef struct { + uint32* Data; + uint32 Size; + uint32 SizeLimit; + ComparePredicate Compare; +} OrderedArray; + +extern OrderedArray OrderedArrayCreate (uint32 maxSize, ComparePredicate p); +extern OrderedArray OrderedArrayPlace (uint32 addr, uint32 maxSize, ComparePredicate p); +extern void OrderedArrayDispose (OrderedArray* arr); +extern uint32 OrderedArraySearch (uint32 key, OrderedArray* arr, ComparePredicate predicate); +extern void OrderedArrayInsert (uint32 item, OrderedArray* arr); +extern uint32 OrderedArrayLookup (uint32 index, OrderedArray* arr); +extern void OrderedArrayDeleteIndex (uint32 index, OrderedArray* arr); + +#endif diff --git a/Kernel/include/stdlib.h~ b/Kernel/include/stdlib.h~ new file mode 100644 index 0000000..7b0451a --- /dev/null +++ b/Kernel/include/stdlib.h~ @@ -0,0 +1,69 @@ +#ifndef __STDLIB__H +#define __STDLIB__H + +#include + +#define IsDigit(c) (c >= '0' && c <= '9') +#define IsHexDigit(c) ( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) +#define IsUpper(c) (c >= 'A' && c <= 'Z') +#define IsLower(c) (c >= 'a' && c <= 'z') + +#define IsAlpha(c) (IsLower(c) || IsUpper(c)) +#define IsAlphaNum(c) (IsAlpha(c) || IsDigit(c)) + +#define ToLower(c) ((IsUpper(c)) ? (c - 'A' + 'a') : c) +#define ToUpper(c) ((IsLower(c)) ? (c - 'a' + 'A') : c) + +#define Max(a,b) ((a > b) ? (a) : (b)) +#define Min(a,b) ((a < b) ? (a) : (b)) +#define Abs(a) ((a < 0) ? (a * -1) : (a)) + +/*************************************************** + * String operations: len, cmp, cpy * + ***************************************************/ +extern uint32 strlen (string s); +extern int32 strcmp (string a, string b); +extern string strcpy (string s1, const string s2); + +/*************************************************** + * Number operations: len * + ***************************************************/ +extern uint32 numlen (int32 number, int32 base); +extern uint32 unumlen (uint32 number, int32 base); + +/*************************************************** + * Memory operations: cpy, cmp, set * + ***************************************************/ +void* memcpy (void *dest, const void *src, uint32 count); +int32 memcmp (const void *s1, const void *s2, uint32 count); +void* memset (void *dest, uint8 val, uint32 count); + +/*************************************************** + * Conversion operations: num-str/str-num * + ***************************************************/ +extern int32 ConvertIntToString (string buffer, int32 number, int32 base); +extern uint32 ConvertUIntToString (string buffer, uint32 number, int32 base); +extern int32 ConvertStringToInt (string buffer); +extern uint32 ConvertStringToUInt (string buffer); +extern uint32 ConvertStringToIntHex (string buffer); + +/*************************************************** + * Ordered array implementation * + ***************************************************/ +typedef int (*ComparePredicate) (uint32, uint32); +typedef struct { + uint32* Data; + uint32 Size; + uint32 SizeLimit; + ComparePredicate Compare; +} OrderedArray; + +extern OrderedArray OrderedArrayCreate (uint32 maxSize, ComparePredicate p); +extern OrderedArray OrderedArrayPlace (uint32 addr, uint32 maxSize, ComparePredicate p); +extern void OrderedArrayDispose (OrderedArray* arr); +extern uint32 OrderedArraySearch (uint32 key, OrderedArray* arr, ComparePredicate predicate); +extern void OrderedArrayInsert (uint32 item, OrderedArray* arr); +extern uint32 OrderedArrayLookup (uint32 index, OrderedArray* arr); +extern void OrderedArrayDeleteIndex (uint32 index, OrderedArray* arr); + +#endif diff --git a/Kernel/include/storage.h b/Kernel/include/storage.h new file mode 100644 index 0000000..dde42b1 --- /dev/null +++ b/Kernel/include/storage.h @@ -0,0 +1,65 @@ +/* + * storage.h + * + * Created on: Aug 23, 2011 + * Author: Tiberiu + */ + +#ifndef STORAGE_H_ +#define STORAGE_H_ + +#include + +// Storage device +typedef struct { + + char MountPointName[32];// E.g. "fd0"; you should avoid spaces, or special chars, or otherwise get weird paths like "Mom's floppy\virus.exe" + uint32 DeviceID; // Autocompleted by VFS + + uint32 BlockSize; // E.g. sector size + uint32 BlockCount; // How many blocks are loaded in memory per read + + /******************************************************** + * READ DATA * + * Params: * + * > offset: read starting from block ~ * + * Returns: address to data, NULL for error * + ********************************************************/ + uint32 (*ReadData) (uint32 offset); + + /******************************************************** + * WRITE DATA * + * Params: * + * > offset: write starting from block ~ * + * > address: where to write from * + * Returns: NULL for error * + ********************************************************/ + uint32 (*WriteData) (uint32 offset, uint32 address); + + uint32 FileSystemID; // Autocompleted by 'mount'... at least should be + +} StorageDevice; + + +typedef struct { + uint32 FileSystemID; // Autocompleted by VFS + + /******************************************************** + * DETECT IF THIS IS THE FS ON STORAGE DEVICE * + * Params: * + * > *s: Pointer to device info & routines * + * Returns: positive if match, NULL otherwise * + ********************************************************/ + uint32 (*Detect) (StorageDevice *s); + + uint32 (*Open) (StorageDevice *s, string path); + uint32 (*CreateNode) (StorageDevice *s, string path); + uint32 (*DeleteNode) (StorageDevice *s, string path); + +} FileSystem; + + + +extern void ConvertLbaToChs(uint32 SectorsPerTrack, uint32 lba, uint32 *cyl, uint32 *head, uint32 *sector); + +#endif /* STORAGE_H_ */ diff --git a/Kernel/include/time.h b/Kernel/include/time.h new file mode 100644 index 0000000..2bdc562 --- /dev/null +++ b/Kernel/include/time.h @@ -0,0 +1,37 @@ +#ifndef __TIME__H +#define __TIME__H + +#include + +// User friendly time structure +struct _Time +{ + int32 Year; + uint8 Month, WeekDay, Day; // Day starts monday + uint8 Hour, Minute, Second; + uint16 Milisecond; +} __attribute__((packed)); + +// System time structure +struct _TimeSystem { + uint32 Date, Time; +} __attribute__((packed)); + +typedef struct _Time Time; +typedef struct _TimeSystem TimeSystem; + + +extern TimeSystem TimeConvertToTimeSystem (Time t); +extern Time TimeConvertToTime (TimeSystem InternalTime); +extern uint16 TimeCalculateWeekday (Time t); + +extern TimeSystem TimeGetInternalTime(); +extern uint32 TimeGetInternalFrequency (); + +extern void TimeSetInternalTime(TimeSystem t); +extern void TimeSetInternalFrequency (uint32 f); + +extern void TimerStart (uint32 ms); +extern uint8 TimerIsDone (); + +#endif diff --git a/Kernel/include/types.h b/Kernel/include/types.h new file mode 100644 index 0000000..1860f54 --- /dev/null +++ b/Kernel/include/types.h @@ -0,0 +1,267 @@ +#ifndef __TYPES__H +#define __TYPES__H + +// Get rid of annoying unused params warnings +#ifdef UNUSED +#elif defined(__GNUC__) +# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) +#elif defined(__LCLINT__) +# define UNUSED(x) /*@unused@*/ x +#else +# define UNUSED(x) x +#endif + +/**************************************** + * NULL constant * + ****************************************/ +#define null 0 +#define NULL 0 + +/**************************************** + * Int definitions * + ****************************************/ +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned uint32; +typedef long long int64; +typedef unsigned long long uint64; + + +/**************************************** + * Limits definitions * + ****************************************/ +#define INT8_MIN (-128) +#define INT16_MIN (-32768) +#define INT32_MIN (-2147483647 - 1) +#define INT64_MIN (-9223372036854775807LL - 1) + +#define INT8_MAX 127 +#define INT16_MAX 32767 +#define INT32_MAX 2147483647 +#define INT64_MAX 9223372036854775807LL + +#define UINT8_MAX 0xff /* 255U */ +#define UINT16_MAX 0xffff /* 65535U */ +#define UINT32_MAX 0xffffffff /* 4294967295U */ +#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ + + +/**************************************** + * Registers * + ****************************************/ +// 32 bit registers +typedef struct { + uint32 eax, ebx, ecx, edx, esi, edi, ebp, esp, eflags; + uint8 cflag; +} _R32BIT; + +// 16 bit registers +typedef struct { + uint16 ax, bx, cx, dx, si, di, bp, sp, es, cs, ss, ds, flags; + uint8 cflag; +} _R16BIT ; + +// 16 bit registers expressed in 32 bit registers +typedef struct { + uint16 ax, axh, bx, bxh, cx, cxh, dx, dxh; + uint16 si, di, bp, sp, es, cs, ss, ds, flags; + uint8 cflags; +} _R16BIT32 ; + +// 8 bit registers +typedef struct { + uint8 al, ah, bl, bh, cl, ch, dl, dh; +} _R8BIT; + +// 8 bit registers expressed in 32 bit registers +typedef struct { + uint8 al, ah; uint16 axh; + uint8 bl, bh; uint16 bxh; + uint8 cl, ch; uint16 cxh; + uint8 dl, dh; uint16 dxh; +} _R8BIT32; + +// 8 and 16 bit registers union +typedef union { + _R16BIT x; + _R8BIT h; +}_INTR16; + +// 32 bit, 16 bit and 8 bit registers union +typedef union { + _R32BIT x; + _R16BIT32 l; + _R8BIT32 h; +} _INTR32; + +/* This defines what the stack looks like after an ISR was running */ +typedef struct +{ + uint32 gs, fs, es, ds; /* pushed the segs last */ + uint32 edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */ + uint32 int_no, err_code; /* our 'push byte #' and ecodes do this */ + uint32 eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */ +} _RegsStack32; + + +/**************************************** + * Keyboard data types * + ****************************************/ +enum KeyboardKeys { + + KeyboardKeyF9 = 0x01, + KeyboardKeyF7 = 0x02, + KeyboardKeyF5 = 0x03, + KeyboardKeyF3 = 0x04, + KeyboardKeyF1 = 0x05, + KeyboardKeyF2 = 0x06, + KeyboardKeyF12 = 0x07, + KeyboardKeyMediaNext = 0x08, + KeyboardKeyF10 = 0x09, + KeyboardKeyF8 = 0x0A, + KeyboardKeyF6 = 0x0B, + KeyboardKeyF4 = 0x0C, + KeyboardKeyTab = 0x0D, + KeyboardKeyTilda = 0x0E, + KeyboardKeyMediaPrevious = 0x0F, + KeyboardKeyMediaStop = 0x10, + KeyboardKeyLeftAlt = 0x11, + KeyboardKeyLeftShift = 0x12, + KeyboardKeyMediaPause = 0x13, + KeyboardKeyLeftCtrl = 0x14, + KeyboardKeyQ = 0x15, + KeyboardKey1 = 0x16, + KeyboardKeyMediaVolUp = 0x17, + KeyboardKeyMediaVolDown = 0x18, + KeyboardKeyMediaSelect = 0x19, + KeyboardKeyZ = 0x1A, + KeyboardKeyS = 0x1B, + KeyboardKeyA = 0x1C, + KeyboardKeyW = 0x1D, + KeyboardKey2 = 0x1E, + KeyboardKeyLeftWin = 0x1F, + KeyboardKeyMediaEmail = 0x20, + KeyboardKeyC = 0x21, + KeyboardKeyX = 0x22, + KeyboardKeyD = 0x23, + KeyboardKeyE = 0x24, + KeyboardKey4 = 0x25, + KeyboardKey3 = 0x26, + KeyboardKeyRightWin = 0x27, + KeyboardKeyMediaCalculator = 0x28, + KeyboardKeySpace = 0x29, + KeyboardKeyV = 0x2A, + KeyboardKeyF = 0x2B, + KeyboardKeyT = 0x2C, + KeyboardKeyR = 0x2D, + KeyboardKey5 = 0x2E, + KeyboardKeyMenu = 0x2F, + KeyboardKeyMediaComputer = 0x30, + KeyboardKeyN = 0x31, + KeyboardKeyB = 0x32, + KeyboardKeyH = 0x33, + KeyboardKeyG = 0x34, + KeyboardKeyY = 0x35, + KeyboardKey6 = 0x36, + KeyboardKeyPower = 0x37, + KeyboardKeyMediaWebSearch = 0x38, + KeyboardKeyMediaWebHome = 0x39, + KeyboardKeyM = 0x3A, + KeyboardKeyJ = 0x3B, + KeyboardKeyU = 0x3C, + KeyboardKey7 = 0x3D, + KeyboardKey8 = 0x3E, + KeyboardKeySleep = 0x3F, + KeyboardKeyWake = 0x40, + KeyboardKeyComma = 0x41, + KeyboardKeyK = 0x42, + KeyboardKeyI = 0x43, + KeyboardKeyO = 0x44, + KeyboardKey0 = 0x45, + KeyboardKey9 = 0x46, + KeyboardKeyMediaWebBack = 0x47, + KeyboardKeyMediaWebForward = 0x48, + KeyboardKeyPeriod = 0x49, + KeyboardKeySlash = 0x4A, + KeyboardKeyL = 0x4B, + KeyboardKeySemicolon = 0x4C, + KeyboardKeyP = 0x4D, + KeyboardKeyDash = 0x4E, + KeyboardKeyMediaWebStop = 0x4F, + KeyboardKeyMediaWebRefresh = 0x50, + KeyboardKeyMediaWebFavorites = 0x51, + KeyboardKeyApostrophe = 0x52, + KeyboardKeyRightAlt = 0x53, + KeyboardKeyLeftBracket = 0x54, + KeyboardKeyEqual = 0x55, + KeyboardKeyPrintScreen = 0x56, + KeyboardKeyPause = 0x57, + KeyboardKeyCapsLock = 0x58, + KeyboardKeyRightShift = 0x59, + KeyboardKeyReturn = 0x5A, + KeyboardKeyRightBracket = 0x5B, + KeyboardKeyRightCtrl = 0x5C, + KeyboardKeyBackSlash = 0x5D, + KeyboardKeyInsert = 0x5E, + KeyboardKeyDelete = 0x5F, + KeyboardKeyHome = 0x60, + KeyboardKeyEnd = 0x61, + KeyboardKeyPageUp = 0x62, + KeyboardKeyPageDown = 0x63, + KeyboardKeyLeft = 0x64, + KeyboardKeyDown = 0x65, + KeyboardKeyBackspace = 0x66, + KeyboardKeyRight = 0x67, + KeyboardKeyUp = 0x68, + KeyboardKeyNumpad1 = 0x69, + KeyboardKeyNumpadSlash = 0x6A, + KeyboardKeyNumpad4 = 0x6B, + KeyboardKeyNumpad7 = 0x6C, + KeyboardKeyNumpadEnter = 0x6D, + KeyboardKeyMediaMute = 0x6E, + KeyboardKeyNumpad0 = 0x70, + KeyboardKeyNumpadColon = 0x71, + KeyboardKeyNumpad2 = 0x72, + KeyboardKeyNumpad5 = 0x73, + KeyboardKeyNumpad6 = 0x74, + KeyboardKeyNumpad8 = 0x75, + KeyboardKeyEscape = 0x76, + KeyboardKeyNumLock = 0x77, + KeyboardKeyF11 = 0x78, + KeyboardKeyNumpadPlus = 0x79, + KeyboardKeyNumpad3 = 0x7A, + KeyboardKeyNumpadMinus = 0x7B, + KeyboardKeyNumpadAsterisk = 0x7C, + KeyboardKeyNumpad9 = 0x7D, + KeyboardKeyScrollLock = 0x7E +}; + +typedef struct { + char Character; + uint8 Scancode; +} Key; + +typedef struct { + uint8 Pressed; + char Character; + uint8 Scancode; +} KeyEvent; + +/**************************************** + * Other data types * + ****************************************/ +typedef struct { + int32 X, Y; +} Point; + +typedef struct +{ + uint32 X, Y; +} UPoint; + +typedef char* string; + +#endif diff --git a/Kernel/include/va_list.h b/Kernel/include/va_list.h new file mode 100644 index 0000000..71a45a9 --- /dev/null +++ b/Kernel/include/va_list.h @@ -0,0 +1,17 @@ +#ifndef __VA_LIST__H +#define __VA_LIST__H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* va list parameter list */ +typedef unsigned char *va_list; + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Kernel/include/version.h b/Kernel/include/version.h new file mode 100644 index 0000000..e987952 --- /dev/null +++ b/Kernel/include/version.h @@ -0,0 +1 @@ +#define OS_BUILD "0.1.0.450" diff --git a/Kernel/include/version.h~ b/Kernel/include/version.h~ new file mode 100644 index 0000000..2c68073 --- /dev/null +++ b/Kernel/include/version.h~ @@ -0,0 +1 @@ +-e #define OS_BUILD "0.1.0.418" diff --git a/SysCore/lib/ctype.c b/Kernel/library/ctype.c similarity index 100% rename from SysCore/lib/ctype.c rename to Kernel/library/ctype.c diff --git a/Kernel/library/memory/memory_alloc.c b/Kernel/library/memory/memory_alloc.c new file mode 100644 index 0000000..f630d70 --- /dev/null +++ b/Kernel/library/memory/memory_alloc.c @@ -0,0 +1,84 @@ +/* + * memory_alloc.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ + +#include + +extern uint32 mem_kernel_end; +extern uint8 mem_initialized; + +// Used prior to proper initialization +uint32 _malloc_init1 (uint32 size, uint8 page_aligned) +{ + uint32 ret = mem_kernel_end; + + if (page_aligned && (ret & 0xfff)) ret = (ret & 0xfffff000) + 0x1000; + mem_kernel_end = size + ret; + + LogMem("%#Allocated %u bytes (%spage aligned) at end of kernel (0x%x).\n", ColorLightMagenta, size, ((page_aligned) ? "" : "not "), ret); + return (ret); +} + +uint32 _malloc_init2 (uint32 size, uint8 page_aligned, uint32* phys) +{ + uint32 ret = MemHeapAlloc(size, page_aligned, KernelHeap, KernelDirectory); + + if (phys) + { + Page *pg = PagingGetPage(ret, 0, KernelDirectory); + *phys = (*pg & PageFrame) + (ret & 0xFFF); + + LogMem("%#Allocated %u bytes (%spage aligned) at address 0x%x (phys=%x).\n", ColorLightMagenta, size, ((page_aligned) ? "" : "not "), ret, *phys); + } + + else { + LogMem("%#Allocated %u bytes (%spage aligned) at address 0x%x.\n", ColorLightMagenta, size, ((page_aligned) ? "" : "not "), ret); + } + + return ret; +} + +// Allocate 'size' bytes +void* kmalloc (uint32 size) +{ + if (!mem_initialized) return 0; + if (mem_initialized == 1) return (void*)_malloc_init1(size, 0); + + return (void*)_malloc_init2(size,0,0); +} + +// Allocate 'size' bytes, page aligned +void* kmalloc_a(uint32 size) +{ + if (!mem_initialized) return 0; + if (mem_initialized == 1) return (void*)_malloc_init1(size, 1); + + return (void*)_malloc_init2(size,1,0); +} + +void* kmalloc_p(uint32 size, uint32* phys) +{ + if (!mem_initialized) return 0; + if (mem_initialized == 1) { + *phys = _malloc_init1(size,0); + return (void*)(*phys); + } + + return (void*)_malloc_init2(size,0,phys); +} + +void* kmalloc_ap(uint32 size, uint32* phys) +{ + if (!mem_initialized) return 0; + + uint32 ret; + if (mem_initialized == 1) { + *phys = ret = _malloc_init1(size,1); + } + + else ret = _malloc_init2(size,1,phys); + return (void*)ret; +} diff --git a/Kernel/library/memory/memory_alloc.c~ b/Kernel/library/memory/memory_alloc.c~ new file mode 100644 index 0000000..3969298 --- /dev/null +++ b/Kernel/library/memory/memory_alloc.c~ @@ -0,0 +1,87 @@ +/* + * memory_alloc.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ + +#include + +extern uint32 mem_kernel_end; +extern uint8 mem_initialized; + +// Used prior to proper initialization +uint32 _malloc_init1 (uint32 size, uint8 page_aligned) +{ + uint32 ret = mem_kernel_end; + + if (page_aligned && (ret & 0xfff)) ret = (ret & 0xfffff000) + 0x1000; + mem_kernel_end = size + ret; + + LogMem("%#Allocated %u bytes (%spage aligned) at end of kernel (0x%x).\n", ColorLightMagenta, size, ((page_aligned) ? "" : "not "), ret); + return (ret); +} + +uint32 _malloc_init2 (uint32 size, uint8 page_aligned, uint32* phys) +{ + uint32 ret = MemHeapAlloc(size, page_aligned, KernelHeap, KernelDirectory); + + if (phys) + { + Page *pg = PagingGetPage(ret, 0, KernelDirectory); + *phys = (*pg & PageFrame) + (ret & 0xFFF); + + LogMem("%#Allocated %u bytes (%spage aligned) at address 0x%x (phys=%x).\n", ColorLightMagenta, size, ((page_aligned) ? "" : "not "), ret, *phys); + } + + else { + LogMem("%#Allocated %u bytes (%spage aligned) at address 0x%x.\n", ColorLightMagenta, size, ((page_aligned) ? "" : "not "), ret); + } + + return ret; +} + +// Allocate 'size' bytes +void* kmalloc (uint32 size) +{ + if (!mem_initialized) return 0; + if (mem_initialized == 1) return (void*)_malloc_init1(size, 0); + + return (void*)_malloc_init2(size,0,0); +} + +// Allocate 'size' bytes, page aligned +void* kmalloc_a(uint32 size) +{ + if (!mem_initialized) return 0; + if (mem_initialized == 1) return (void*)_malloc_init1(size, 1); + + return (void*)_malloc_init2(size,1,0); +} + +void* kmalloc_p(uint32 size, uint32* phys) +{ + if (!mem_initialized) return 0; + if (mem_initialized == 1) { + *phys = _malloc_init1(size,0); + return (void*)(*phys); + } + + return (void*)_malloc_init2(size,0,phys); +} + +void* kmalloc_ap(uint32 size, uint32* phys) +{ + if (!mem_initialized) return 0; + + uint32 ret; + if (mem_initialized == 1) { + *phys = ret = _malloc_init1(size,1); + } + + else ret = _malloc_init2(size,1,phys); + + LogMem("%#kmalloc_ap requested, returned 0x%x, phys = 0x%x.\n", ColorMagenta, ret, *phys); + + return (void*)ret; +} diff --git a/Kernel/library/memory/memory_free.c b/Kernel/library/memory/memory_free.c new file mode 100644 index 0000000..a61b9fc --- /dev/null +++ b/Kernel/library/memory/memory_free.c @@ -0,0 +1,20 @@ +/* + * memory_free.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ + +#include + +extern uint8 mem_initialized; + +void kfree(void* addr) +{ + if (mem_initialized < 2) { + ErrorMem("%#Tried to free at address 0x%x when memory manager is uninitialized.\n", ColorLightRed, (uint32)addr); + return; + } + + MemHeapFree((uint32)addr, KernelHeap, KernelDirectory); +} diff --git a/Kernel/library/memory/memory_info.c b/Kernel/library/memory/memory_info.c new file mode 100644 index 0000000..fbcf54a --- /dev/null +++ b/Kernel/library/memory/memory_info.c @@ -0,0 +1,48 @@ +/* + * memory_info.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ + +#include +// MemoryGetFree(), MemoryGetTotal(), MemoryGet blah blah... + +// Returns total physical memory in bytes +uint32 MemoryGetTotal() +{ + return (TotalMemory); +} + +// Returns total free physical memory in bytes +uint32 MemoryGetFree() +{ + return (TotalFrames - UsedFrames) * 0x4; +} + +// Total used physical memory in bytes +uint32 MemoryGetUsed() +{ + return UsedFrames * 0x4; +} + +// Same as above functions, but in frames +uint32 MemoryGetFrameSize() +{ + return 0x4; +} + +uint32 MemoryGetFramesTotal() +{ + return TotalFrames; +} + +uint32 MemoryGetFramesUsed() +{ + return UsedFrames; +} + +uint32 MemoryGetFramesFree() +{ + return (TotalFrames - UsedFrames); +} \ No newline at end of file diff --git a/Kernel/library/memory/memory_info.c~ b/Kernel/library/memory/memory_info.c~ new file mode 100644 index 0000000..e035707 --- /dev/null +++ b/Kernel/library/memory/memory_info.c~ @@ -0,0 +1,48 @@ +/* + * memory_info.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ + +#include +// MemoryGetFree(), MemoryGetTotal(), MemoryGet blah blah... + +// Returns total physical memory in bytes +uint32 MemoryGetTotal() +{ + return (TotalMemory); +} + +// Returns total free physical memory in bytes +uint32 MemoryGetFree() +{ + return (TotalFrames - UsedFrames) * 0x4; +} + +// Total used physical memory in bytes +uint32 MemoryGetUsed() +{ + return UsedFrames * 0x4; +} + +// Same as above functions, but in frames +uint32 MemoryGetFrameSize() +{ + return 0x1000; +} + +uint32 MemoryGetFramesTotal() +{ + return TotalFrames; +} + +uint32 MemoryGetFramesUsed() +{ + return UsedFrames; +} + +uint32 MemoryGetFramesFree() +{ + return (TotalFrames - UsedFrames); +} \ No newline at end of file diff --git a/Kernel/library/memory/memory_init.c b/Kernel/library/memory/memory_init.c new file mode 100644 index 0000000..1fd66dc --- /dev/null +++ b/Kernel/library/memory/memory_init.c @@ -0,0 +1,88 @@ +/* + * memory-init.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ +#include +#include +#include +#include "../../drivers/cmos/cmos.h" +#include + + +uint32 mem_kernel_end = 0; +uint8 mem_initialized = 0; + +uint32 _memory_get_total_mem(MultibootInfo* info) +{ + // Grub was nice enough to give us info + if (info->Flags & MultibootInfo_MEMORY) return (1024 + info->MemoryUpper); + + // No? Get info from CMOS + uint8 low, high; + uint32 total; + + low = CmosRead(0x30); + high = CmosRead(0x31); + total = (uint32)(low | high<<8) + 1024; + + ErrorMem("%#Missing memory info from bootloader. Reading from CMOS: %ukb\n", ColorLightRed, total); + + return total; +} + +void _memory_reserve_system(MultibootInfo* info) +{ + MagicBreakpoint(); + if ((info->Flags & MultibootInfo_MEM_MAP) != 0) + { + MultibootMemoryMapEntry* location = (MultibootMemoryMapEntry*)info->MemoryMapAddress; + + while ((uint32)location < (info->MemoryMapAddress + info->MemoryMapLength)) + { + if (location->Type > 1) + MemPhReserveFrames((uint32)location->Address, (uint32)location->Length); + + location = (MultibootMemoryMapEntry*) ((uint32)location + location->Size + sizeof(uint32)); + } + } + + else + { + ErrorMem("%#Missing %#memory map%# info from bootloader.\n", ColorLightRed, ColorWhite, ColorLightRed); + + // Standard memory hole at 15mb + MemPhReserveFrames(0x00F00000, 0x00100000); + } + + // Standard reserved memory areas + MemPhReserveFrames(0x0, 0x400 + 256); // Real mode IVT, BDA + MemPhReserveFrames(0x1000, 0x2400); // DMA buffer + MemPhReserveFrames(0x9FC00, 385*1024); // EBDA, Video memory, ROM area +} + + +void MemoryInitialize (MultibootInfo* info) +{ + uint32 totalSystemMemory = _memory_get_total_mem(info); + + MemPhInitialize(totalSystemMemory); + PagingInitialize(0x200000); + + _memory_reserve_system(info); + + KernelHeap = MemHeapCreate(KERNEL_HEAP_START, KERNEL_HEAP_START + + KERNEL_HEAP_INITIAL_SIZE, 0xCFFFF000, 3); // is kernel, writeable + + LogMem("Done initializing memory!"); + + mem_initialized = 2; +} + +void MemoryTempInitialize (uint32 kernel_end) +{ + mem_initialized = 1; + mem_kernel_end = kernel_end; + LogMem("Initialized temporary memory manager, allocating from %#0x%x.\n", kernel_end); +} diff --git a/Kernel/library/memory/memory_init.c~ b/Kernel/library/memory/memory_init.c~ new file mode 100644 index 0000000..0cf2f18 --- /dev/null +++ b/Kernel/library/memory/memory_init.c~ @@ -0,0 +1,92 @@ +/* + * memory-init.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ +#include +#include +#include +#include "../../drivers/cmos/cmos.h" +#include + + +uint32 mem_kernel_end = 0; +uint8 mem_initialized = 0; + +uint32 _memory_get_total_mem(MultibootInfo* info) +{ + // Grub was nice enough to give us info + if (info->Flags & MultibootInfo_MEMORY) return (1024 + info->MemoryUpper); + + // No? Get info from CMOS + uint8 low, high; + uint32 total; + + low = CmosRead(0x30); + high = CmosRead(0x31); + total = (uint32)(low | high<<8) + 1024; + + ErrorMem("%#Missing memory info from bootloader. Reading from CMOS: %ukb\n", ColorLightRed, total); + + return total; +} + +void _memory_reserve_system(MultibootInfo* info) +{ + MagicBreakpoint(); + if ((info->Flags & MultibootInfo_MEM_MAP) != 0) + { + MultibootMemoryMapEntry* location = (MultibootMemoryMapEntry*)info->MemoryMapAddress; + + while ((uint32)location < (info->MemoryMapAddress + info->MemoryMapLength)) + { + if (location->Type > 1) + MemPhReserveFrames((uint32)location->Address, (uint32)location->Length); + + location = (MultibootMemoryMapEntry*) ((uint32)location + location->Size + sizeof(uint32)); + } + } + + else + { + ErrorMem("%#Missing %#memory map%# info from bootloader.\n", ColorLightRed, ColorWhite, ColorLightRed); + + // Standard memory hole at 15mb + MemPhReserveFrames(0x00F00000, 0x00100000); + } + + // Standard reserved memory areas + MemPhReserveFrames(0x0, 0x400 + 256); // Real mode IVT, BDA + MemPhReserveFrames(0x1000, 0x2400); // DMA buffer + MemPhReserveFrames(0x9FC00, 385*1024); // EBDA, Video memory, ROM area +} + + +void MemoryInitialize (MultibootInfo* info) +{ + uint32 totalSystemMemory = _memory_get_total_mem(info); + + MemPhInitialize(totalSystemMemory); + PagingInitialize(0x200000); + + LogMem("Reserving important areas...\n"); + + _memory_reserve_system(info); + + LogMem("Allocating kernel heap...\n"); + + KernelHeap = MemHeapCreate(KERNEL_HEAP_START, KERNEL_HEAP_START + + KERNEL_HEAP_INITIAL_SIZE, 0xCFFFF000, 3); // is kernel, writeable + + LogMem("Done initializing memory!"); + + mem_initialized = 2; +} + +void MemoryTempInitialize (uint32 kernel_end) +{ + mem_initialized = 1; + mem_kernel_end = kernel_end; + LogMem("Initialized temporary memory manager, allocating from %#0x%x.\n", kernel_end); +} diff --git a/Kernel/library/stdio.c b/Kernel/library/stdio.c new file mode 100644 index 0000000..2279459 --- /dev/null +++ b/Kernel/library/stdio.c @@ -0,0 +1,44 @@ +#include +#include "../hal/keyboard/keyboard.h" + +uint8 inportb (uint16 _port) { + uint8 rv; + __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +Key ReadKey() +{ + Key key; + + do { + KeyboardLastScancode = 0xFF ; + while (KeyboardLastScancode == 0xFF) ; + + key.Scancode = KeyboardLastScancode; + + } while (KeyboardLastStatus & 1); + + if (KeyboardGetKeyStatus(KeyboardKeyLeftShift) || KeyboardGetKeyStatus(KeyboardKeyRightShift)) + key.Character = KeyboardMapShift[key.Scancode]; + else key.Character = KeyboardMap[key.Scancode]; + + return key; +} + +KeyEvent ReadKeyEvent() +{ + KeyEvent key; + + KeyboardLastScancode = 0xFF ; + while (KeyboardLastScancode == 0xFF) ; + + key.Scancode = KeyboardLastScancode; + key.Pressed = 1 - (KeyboardLastStatus & 1); + + if (KeyboardGetKeyStatus(KeyboardKeyLeftShift) || KeyboardGetKeyStatus(KeyboardKeyRightShift)) + key.Character = KeyboardMapShift[key.Scancode]; + else key.Character = KeyboardMap[key.Scancode]; + + return key; +} diff --git a/Kernel/library/stdlib/convert_ops.c b/Kernel/library/stdlib/convert_ops.c new file mode 100644 index 0000000..2d9c448 --- /dev/null +++ b/Kernel/library/stdlib/convert_ops.c @@ -0,0 +1,100 @@ +/* + * convert_ops.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ +#include + +const string _Numbers = "0123456789abcdefghijklmnopqrstuvwxyz"; + +int32 ConvertIntToString (string buffer, int32 number, int32 base) +{ + if (base > 36 || base < 2) return 0; + + int32 len = numlen (number, base), beg = 0, i; + uint32 n = (uint32) number; + + // If number is negative and in base 10, we put a '-' in front + if (number < 0 && base == 10) buffer[beg++] = '-'; + + // Put every digit in string + for (i = len-1; i>=beg; i--) + { + buffer[i] = _Numbers[n % base]; + n /= base; + } + + buffer[len] = 0; + return number; +} + +uint32 ConvertUIntToString (string buffer, uint32 number, int32 base) +{ + if (base > 36 || base < 2) return 0; + + int32 len = unumlen (number, base), i; + + // Put every digit in string + for (i = len-1; i >= 0; i--) + { + buffer[i] = _Numbers[number % base]; + number /= base; + } + + buffer[len] = 0; + return number; +} + +int32 ConvertStringToInt (string buffer) +{ + int8 negative = (buffer[0] == '-'); + int32 pos = (buffer[0] == '-' ); + + int32 number = 0; + + while (IsDigit(buffer[pos])) + { + number = number*10 + (buffer[pos] - '0'); + pos++; + } + + if (negative) return -number; + return number; +} + +uint32 ConvertStringToUInt (string buffer) +{ + int32 pos = 0; + int32 number = 0; + + while (IsDigit(buffer[pos])) + { + number = number*10 + (buffer[pos] - '0'); + pos++; + } + + return number; +} + +uint32 ConvertStringToIntHex (string buffer) +{ + int32 pos = 0; + uint32 number = 0; + + // Skip first 2 digits if it is in format 0xXXXX... + if (buffer[1] == 'x' || buffer[1] == 'X') pos = 2; + + while (IsHexDigit(buffer[pos])) + { + number = number*0x10; + + if (IsDigit(buffer[pos])) number += buffer[pos] - '0'; + else if (buffer[pos] >= 'a' && buffer[pos] <= 'f') number += 10 + buffer[pos] - 'a'; + else if (buffer[pos] >= 'A' && buffer[pos] <= 'F') number += 10 + buffer[pos] - 'A'; + + pos++; + } + + return number; +} diff --git a/Kernel/library/stdlib/mem_ops.c b/Kernel/library/stdlib/mem_ops.c new file mode 100644 index 0000000..61bb2c8 --- /dev/null +++ b/Kernel/library/stdlib/mem_ops.c @@ -0,0 +1,42 @@ +/* + * mem_ops.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ +#include + +void *memcpy(void *dest, const void *src, uint32 count) +{ + uint8* d = (uint8*) dest; + const uint8* s = (const uint8*) src; + + while (count-- != 0) + *d++ = *s++; + + return dest; +} + +int32 memcmp(const void *s1, const void *s2, uint32 count) +{ + const uint8 *us1 = (const uint8*) s1; + const uint8 *us2 = (const uint8*) s2; + + while (count-- != 0) + { + if (*us1 != *us2) return (*us1 < *us2) ? -1 : 1; + us1++; us2++; + } + + return 0; +} + + +void *memset(void *dest, uint8 val, uint32 count) +{ + uint8 *temp = (uint8 *)dest; + while (count-- != 0) + *temp++ = val; + + return dest; +} diff --git a/Kernel/library/stdlib/num_ops.c b/Kernel/library/stdlib/num_ops.c new file mode 100644 index 0000000..8ff7752 --- /dev/null +++ b/Kernel/library/stdlib/num_ops.c @@ -0,0 +1,39 @@ +/* + * num_ops.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ +#include + +uint32 numlen (int32 number, int32 base) +{ + // Sanity check + if (base < 2) return 0; + + uint32 len = (number < 0 && base == 10); // add minus sign + if (number == 0) return 1; + + while (number) { + number /= base; + ++len; + } + + return len; +} + +uint32 unumlen (uint32 number, int32 base) +{ + // Sanity check + if (base < 2) return 0; + + uint32 len = 0; + if (number == 0) return 1; + + while (number) { + number /= base; + ++len; + } + + return len; +} diff --git a/Kernel/library/stdlib/ord_arr.c b/Kernel/library/stdlib/ord_arr.c new file mode 100644 index 0000000..1c9758b --- /dev/null +++ b/Kernel/library/stdlib/ord_arr.c @@ -0,0 +1,112 @@ +/* + * ord-arr.c + * + * Created on: Aug 25, 2011 + * Author: Tiberiu + */ + + +/* + * memory.c + * + * Created on: Aug 24, 2011 + * Author: Tiberiu + */ + +#include +#include + +int StandardComparePredicate (uint32 a, uint32 b) +{ + if (a > b) return 1; + else if (a == b) return 0; + return -1; +} + +OrderedArray OrderedArrayCreate (uint32 maxSize, ComparePredicate p) +{ + OrderedArray ret; + ret.Data = (unsigned*) kmalloc(maxSize); + memset(ret.Data, 0, maxSize); + ret.Size = 0; + ret.SizeLimit = maxSize; + ret.Compare = (p == 0) ? StandardComparePredicate : p; + + return ret; +} + +OrderedArray OrderedArrayPlace (uint32 addr, uint32 maxSize, ComparePredicate p) +{ + OrderedArray ret; + ret.Data = (unsigned*)addr; + memset(ret.Data, 0, maxSize); + ret.Size = 0; + ret.SizeLimit = maxSize; + ret.Compare = (p == 0) ? StandardComparePredicate : p; + + return ret; +} + +void OrderedArrayDispose (OrderedArray* arr) +{ + kfree(arr->Data); +} + +uint32 OrderedArrayBinarySearch (uint32 key, uint32* array, uint32 length, ComparePredicate predicate) +{ + if (!predicate) return 0; + + uint32 left = 0, right = length, mid; + + while (left < right) + { + mid = left + (right-left) / 2; + + int r = (*predicate)(key, array[mid]); + + if (r > 0) left = mid + 1; + else if (r < 0) right = mid; + else return mid; + } + mid = left + (right-left) / 2; + + return mid; +} + +uint32 OrderedArraySearch (uint32 key, OrderedArray* arr, ComparePredicate predicate) +{ + uint32 r = OrderedArrayBinarySearch(key,arr->Data,arr->Size,predicate); + + if (arr->Data[r] != key) return 0xffffffff; + return r; +} + +void OrderedArrayInsert (uint32 item, OrderedArray* arr) +{ + if (arr->Size >= arr->SizeLimit) return; + + uint32 location = OrderedArrayBinarySearch(item, arr->Data, arr->Size, arr->Compare); + + uint32 i; + for (i = arr->Size; i > location && arr->Size > 0; i--) + arr->Data[i] = arr->Data[i-1]; + + arr->Data[location] = item; + arr->Size++; +} + +uint32 OrderedArrayLookup (uint32 index, OrderedArray* arr) +{ + if (index >= arr->Size) return 0; + return arr->Data[index]; +} + +void OrderedArrayDeleteIndex (uint32 index, OrderedArray* arr) +{ + if (index >= arr->Size) return; + + uint32 i; + for (i = index + 1; i < arr->Size; i++) + arr->Data[i - 1] = arr->Data[i]; + arr->Size--; +} diff --git a/Kernel/library/stdlib/str_ops.c b/Kernel/library/stdlib/str_ops.c new file mode 100644 index 0000000..e163210 --- /dev/null +++ b/Kernel/library/stdlib/str_ops.c @@ -0,0 +1,39 @@ +/* + * str_ops.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ +#include + +uint32 strlen (string s) +{ + string end = s; + while (*end != '\0') + end++; + + return (uint32)(end - s); +} + +int32 strcmp (string a, string b) +{ + unsigned char c1, c2; + + while (*a != '\0' && *b != '\0' && *a == *b) { + a++; b++; + } + + c1 = (*(unsigned char*) a); + c2 = (*(unsigned char*) b); + return ((c1 < c2) ? -1 : (c1 > c2)); +} + +string strcpy (string s1, const string s2) +{ + char *dst = s1; + const char *src = s2; + + while ((*dst++ = *src++) != '\0') ; + + return s1; +} diff --git a/Kernel/library/storage.c b/Kernel/library/storage.c new file mode 100644 index 0000000..64b66aa --- /dev/null +++ b/Kernel/library/storage.c @@ -0,0 +1,18 @@ +/* + * storage.c + * + * Created on: Aug 23, 2011 + * Author: Tiberiu + */ + +#include + +void ConvertLbaToChs(uint32 SectorsPerTrack, uint32 lba, uint32 *cyl, uint32 *head, uint32 *sector) +{ + // Avoid division by 0 + if (SectorsPerTrack == 0) return; + + *head = (lba % (SectorsPerTrack * 2)) / SectorsPerTrack; + *cyl = lba / (SectorsPerTrack * 2); + *sector = lba % SectorsPerTrack + 1; +} diff --git a/Kernel/library/time.c b/Kernel/library/time.c new file mode 100644 index 0000000..fa8aa23 --- /dev/null +++ b/Kernel/library/time.c @@ -0,0 +1,98 @@ +#include +extern volatile TimeSystem _internal_time; +extern uint32 _internal_frequency_hz; + +// Length of months (summed) +const int16 MonthLen[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; + + +TimeSystem TimeConvertToTimeSystem (Time t) +{ + TimeSystem sys = {0,0}; + + t.Year--; t.Month--; t.Day--; t.WeekDay--; + + sys.Time = (uint32)(t.Hour * 3600000) + (uint32)(t.Minute * 60000) + (uint32)(t.Second * 1000) + (uint32)t.Milisecond; + + if (t.Year < 0) return sys; + + sys.Date = (uint32)(t.Day) + (uint32)(MonthLen[t.Month]) + + (uint32)((t.Year/4) * (365*4 + 1)) + (uint32)(t.Year%4 * 365); + + return sys; +} + +Time TimeConvertToTime (TimeSystem InternalTime) +{ + Time t; + t.Milisecond = InternalTime.Time % 1000; + t.Second = (InternalTime.Time / 1000) % 60; + t.Minute = (InternalTime.Time / 60000) % 60; + t.Hour = (InternalTime.Time / 3600000); + + + uint32 DayOfYear = (InternalTime.Date % 1461) % 365; + t.Year = (InternalTime.Date / 1461)*4 + (InternalTime.Date % 1461)/365 + 1; + t.Month = 11; + while ((int32)DayOfYear < (MonthLen[t.Month] + (t.Year % 4 == 0 && t.Month>1))) t.Month--; + t.WeekDay = InternalTime.Date % 7; + t.Day = DayOfYear - MonthLen[t.Month] - (t.Year % 4 == 0 && t.Month>1); + + t.Month++; t.WeekDay++; t.Day++; + + return t; +} + +uint16 TimeCalculateWeekday (Time t) +{ + t.Year--; + uint32 d = (uint32)(t.Day-1) + (uint32)(MonthLen[t.Month-1]) + + + (uint32)((t.Year/4) * (365*4 + 1)) + (uint32)(t.Year%4 * 365); + + return 1 + (d%7); +} + + +TimeSystem TimeGetInternalTime() +{ + return _internal_time; +} + +void TimeSetInternalTime(TimeSystem t) +{ + _internal_time = t; +} + +uint32 TimeGetInternalFrequency () +{ + return _internal_frequency_hz; +} + +void TimeSetInternalFrequency (uint32 f) +{ + _internal_frequency_hz = f; +} + + +TimeSystem _timer; +#define MILISECONDS_IN_DAY 86400000 + +void TimerStart (uint32 ms) +{ + _timer = TimeGetInternalTime(); + _timer.Time += ms; + + if (_timer.Time >= MILISECONDS_IN_DAY) + { + _timer.Date++; + _timer.Time-=MILISECONDS_IN_DAY; + } +} + +uint8 TimerIsDone () +{ + TimeSystem now = TimeGetInternalTime(); + if (_timer.Date >= now.Date && _timer.Time > now.Time) return 0; + + return 1; +} diff --git a/Kernel/loader.asm b/Kernel/loader.asm new file mode 100644 index 0000000..119b3c7 --- /dev/null +++ b/Kernel/loader.asm @@ -0,0 +1,98 @@ +bits 32 + +global start + +; multiboot header +MODULEALIGN equ 1<<0 +MEMINFO equ 1<<1 +VIDEOINFO equ 1<<2 +FLAGS equ MODULEALIGN | MEMINFO | VIDEOINFO +MAGIC equ 0x1BADB002 +CHECKSUM equ -(MAGIC + FLAGS) + +align 4 +section .__mbHeader +MultiBootHeader: + dd MAGIC + dd FLAGS + dd CHECKSUM + +section .text + +STACKSIZE equ 0x4000 ; that's 16k. + +start: + XCHG BX, BX ; magic breakpoint + + mov ecx, eax + +; lgdt [trickgdt] +; mov ax, 0x10; +; mov ds, ax +; mov es, ax +; mov fs, ax +; mov gs, ax +; mov ss, ax + +; jmp 0x08:HigherHalf ; NOTE: Must be absolute jump! + +HigherHalf: + + ; Verify booted with multiboot compliant bootloader + mov esp, stack+STACKSIZE + + cmp ecx, 0x2BADB002 + jne .bad + + push ebx + + extern k_main + call k_main + +; Show error message, and halt system +.bad: + + extern ConsoleClear + extern ConsoleWrite + extern CommandOsver + + call ConsoleClear + call CommandOsver + + mov eax, [ErrorColor] + push eax + push ErrorString + call ConsoleWrite + + cli + hlt + + +; some variables +ErrorString db 0xA, "%#! Fatal error: Not booted with multiboot compliant bootloader (e.g. GRUB).", 0x0 +ErrorColor db 0x0C + + + +; tells the assembler to include this data in the '.setup' section +section .setup + +trickgdt: + dw gdt_end - gdt - 1 ; size of the GDT + dd gdt ; linear address of GDT + +gdt: + dd 0, 0 ; null gate + db 0xFF, 0xFF, 0, 0, 0, 10011010b, 11001111b, 0x40 ; code selector 0x08: base 0x40000000, limit 0xFFFFFFFF, type 0x9A, granularity 0xCF + db 0xFF, 0xFF, 0, 0, 0, 10010010b, 11001111b, 0x40 ; data selector 0x10: base 0x40000000, limit 0xFFFFFFFF, type 0x92, granularity 0xCF + +gdt_end: + + + + +; stack +section .bss +align 32 +stack: + resb STACKSIZE ; This reserves 64KBytes of memory here diff --git a/Kernel/loader.asm~ b/Kernel/loader.asm~ new file mode 100644 index 0000000..68763ef --- /dev/null +++ b/Kernel/loader.asm~ @@ -0,0 +1,99 @@ +bits 32 + +global start + +; multiboot header +MODULEALIGN equ 1<<0 +MEMINFO equ 1<<1 +VIDEOINFO equ 1<<2 +FLAGS equ MODULEALIGN | MEMINFO | VIDEOINFO +MAGIC equ 0x1BADB002 +CHECKSUM equ -(MAGIC + FLAGS) + + +section .__mbHeader +align 4 +MultiBootHeader: + dd MAGIC + dd FLAGS + dd CHECKSUM + +section .text + +STACKSIZE equ 0x4000 ; that's 16k. + +start: + XCHG BX, BX ; magic breakpoint + + mov ecx, eax + +; lgdt [trickgdt] +; mov ax, 0x10; +; mov ds, ax +; mov es, ax +; mov fs, ax +; mov gs, ax +; mov ss, ax + +; jmp 0x08:HigherHalf ; NOTE: Must be absolute jump! + +HigherHalf: + + ; Verify booted with multiboot compliant bootloader + mov esp, stack+STACKSIZE + + cmp ecx, 0x2BADB002 + jne .bad + + push ebx + + extern k_main + call k_main + +; Show error message, and halt system +.bad: + + extern ConsoleClear + extern ConsoleWrite + extern CommandOsver + + call ConsoleClear + call CommandOsver + + mov eax, [ErrorColor] + push eax + push ErrorString + call ConsoleWrite + + cli + hlt + + +; some variables +ErrorString db 0xA, "%#! Fatal error: Not booted with multiboot compliant bootloader (e.g. GRUB).", 0x0 +ErrorColor db 0x0C + + + +; tells the assembler to include this data in the '.setup' section +section .setup + +trickgdt: + dw gdt_end - gdt - 1 ; size of the GDT + dd gdt ; linear address of GDT + +gdt: + dd 0, 0 ; null gate + db 0xFF, 0xFF, 0, 0, 0, 10011010b, 11001111b, 0x40 ; code selector 0x08: base 0x40000000, limit 0xFFFFFFFF, type 0x9A, granularity 0xCF + db 0xFF, 0xFF, 0, 0, 0, 10010010b, 11001111b, 0x40 ; data selector 0x10: base 0x40000000, limit 0xFFFFFFFF, type 0x92, granularity 0xCF + +gdt_end: + + + + +; stack +section .bss +align 32 +stack: + resb STACKSIZE ; This reserves 64KBytes of memory here diff --git a/Kernel/main.c b/Kernel/main.c new file mode 100644 index 0000000..b8c764a --- /dev/null +++ b/Kernel/main.c @@ -0,0 +1,27 @@ +#include "hal/hal.h" +#include "drivers/drivers.h" +#include +#include +#include +#include +#include +#include + +extern uint32 _end; + +void k_main(MultibootInfo* info) +{ + uint32 KernelEnd = (uint32)&_end; + MemoryTempInitialize(KernelEnd); + + ConsoleClear(); + HalInitialize(); + DriversInstall(); + + // Set up memory manager + MemoryInitialize(info); + + Log("All ready. Starting console...\n\n"); + + ConsoleMain(); +} diff --git a/Kernel/main.c~ b/Kernel/main.c~ new file mode 100644 index 0000000..5d7d17f --- /dev/null +++ b/Kernel/main.c~ @@ -0,0 +1,27 @@ +#include "hal/hal.h" +#include "drivers/drivers.h" +#include +#include +#include +#include +#include +#include + +extern uint32 _end; + +void k_main(MultibootInfo* info) +{ + uint32 KernelEnd = (uint32)&_end; + MemoryTempInitialize(KernelEnd); + + ConsoleClear(); + HalInitialize(); + DriversInstall(); + + // Set up memory manager + MemoryInitialize(&info_new); + + Log("All ready. Starting console...\n\n"); + + ConsoleMain(); +} diff --git a/Kernel/memory/mem-heap.c b/Kernel/memory/mem-heap.c new file mode 100644 index 0000000..eac2d6e --- /dev/null +++ b/Kernel/memory/mem-heap.c @@ -0,0 +1,304 @@ +#include +#include +#include + +#define MEMHEAP_MAGIC 0x50DBE514 +#define MEMHEAP_INDEX_SIZE 0x20000 +#define MEMHEAP_MINIM_SIZE 0x70000 + +#define FlagsKernel 1 +#define FlagsWriteable 2 + +typedef struct +{ + uint32 Magic; + // bit 0: used bit 1: reserved + uint8 Used; + uint32 Size; +} MemHeapHeader; + +typedef struct +{ + uint32 Magic; + MemHeapHeader* Header; +} MemHeapFooter; + +MemHeap* KernelHeap; + +uint32 MemHeapFindSmallestHole (uint32 size, uint8 page_align, MemHeap* heap) +{ + uint32 i; + for (i = 0; i < heap->Index.Size; i++) + { + MemHeapHeader* head = (MemHeapHeader*) OrderedArrayLookup(i, &heap->Index); + + if (page_align) + { + uint32 location = (uint32)(head) + sizeof(MemHeapHeader); + + // page align it + uint32 offset = 0x1000 - (location & 0xfff); + offset &= 0xfff; + + if (head->Size - offset >= size) return i; + } + + else if (head->Size >= size) return i; + } + + return 0xffffffff; +} + +int32 MemHeapCompare (uint32 a, uint32 b) +{ + MemHeapHeader *ha = (MemHeapHeader*)a, *hb = (MemHeapHeader*)b; + + if (ha->Size > hb->Size) return 1; + else if (ha->Size == hb->Size) return 0; + return -1; +} + + +inline void MemHeapHeaderSetup (uint32 size, uint8 used, MemHeapHeader* head) +{ + head->Magic = MEMHEAP_MAGIC; + head->Used = used; + head->Size = size; +} + +inline void MemHeapFooterSetup (MemHeapHeader* head, MemHeapFooter* foot) +{ + foot->Magic = MEMHEAP_MAGIC; + foot->Header = head; +} + + +MemHeap* MemHeapCreate(uint32 start, uint32 end, uint32 max, uint8 flags) +{ + if ((start & 0xfff) || (end & 0xfff)) return NULL; + + MemHeap* heap = (MemHeap*) kmalloc(sizeof(MemHeap)); + heap->Index = OrderedArrayPlace(start, MEMHEAP_INDEX_SIZE, MemHeapCompare); + + start += sizeof(uint32) * MEMHEAP_INDEX_SIZE; + + if (start & 0xfff) start = (start & 0xFFFFF000) + 0x1000; + + heap->StartAddress = start; + heap->EndAddress = end; + heap->Flags = flags; + heap->MaxAddress = max; + + // One large hole + MemHeapHeader* hole = (MemHeapHeader*)start; + MemHeapHeaderSetup(end-start, 0, hole); + OrderedArrayInsert(start, &heap->Index); + + return heap; +} + + +void MemHeapExpand(uint32 newsz, MemHeap* heap, PageDirectory* pd) +{ + if (newsz <= heap->EndAddress - heap->StartAddress) return; + + if (newsz & 0xfff) newsz = (newsz & 0xfffff000) + 0x1000; + if (newsz + heap->StartAddress >= heap->MaxAddress) return; + + uint32 i; + for (i = heap->EndAddress - heap->StartAddress; i < heap->StartAddress + newsz; i+=0x1000) + MemPhAllocFrame(PagingGetPage(i, 1, pd), heap->Flags & FlagsKernel, heap->Flags & FlagsWriteable); + + heap->EndAddress = heap->StartAddress + newsz; +} + +uint32 MemHeapContract(uint32 newsz, MemHeap* heap, PageDirectory* pd) +{ + if (newsz >= heap->EndAddress - heap->StartAddress) return 0; + + if (newsz & 0xfff) newsz = (newsz & 0xfffff000) + 0x1000; // page align + newsz = Max(newsz, MEMHEAP_MINIM_SIZE); + + uint32 i; + for (i = heap->EndAddress - heap->StartAddress - 0x1000; i > newsz; i-=0x1000) + MemPhFreeFrame(PagingGetPage(i, 0, pd)); + + heap->EndAddress = heap->StartAddress + newsz; + return newsz; +} + + +uint32 MemHeapAlloc (uint32 size, uint8 isPageAligned, MemHeap* heap, PageDirectory* pd) +{ + // Sanity check + if (!size || !heap) return 0; + + // Find a good hole + uint32 newsize = size + sizeof(MemHeapHeader) + sizeof(MemHeapFooter); + uint32 i = MemHeapFindSmallestHole(newsize, isPageAligned, heap); + + // Didn't find? Expand heap + if (i == 0xffffffff) + { + uint32 oldLen = heap->EndAddress - heap->StartAddress; + uint32 oldEnd = heap->EndAddress; + MemHeapExpand(oldLen + newsize, heap, pd); + + uint32 newLen = heap->EndAddress - heap->StartAddress; + + // Find the last header + uint32 i = 0, index = 0, addr = 0; + for (; i < heap->Index.Size; i++) + { + uint32 tmp = OrderedArrayLookup(i, &heap->Index); + if (tmp > addr) { + addr = tmp; index = i; + } + } + + + MemHeapHeader* head; MemHeapFooter* foot; + + if (heap->Index.Size == 0) // No headers? Add one + { + head = (MemHeapHeader*)oldEnd; + MemHeapHeaderSetup(newLen - oldLen, 0, head); + OrderedArrayInsert(oldEnd, &heap->Index); + } + + else { // Modify last header + head = (MemHeapHeader*) OrderedArrayLookup(index, &heap->Index); + head->Size = newLen - oldLen; + } + + foot = (MemHeapFooter*)((uint32)head + head->Size - sizeof(MemHeapFooter)); + MemHeapFooterSetup(head, foot); + + // Try again + return MemHeapAlloc(size, isPageAligned, heap, pd); + } + + // Get info about hole + uint32 origAddr = OrderedArrayLookup(i, &heap->Index); + MemHeapHeader* origHead =(MemHeapHeader*) origAddr; + uint32 origSize = origHead->Size; + + // Should split in two? + if (origSize - newsize <= sizeof(MemHeapHeader) + sizeof(MemHeapFooter)) + { + size += origSize - newsize; + newsize = origSize; + } + + // Should be page aligned + if (isPageAligned && (origAddr&0xfffff000)) + { + uint32 newAddr = origAddr + 0x1000 - (origAddr&0xfff) - sizeof(MemHeapHeader); + MemHeapHeaderSetup(0x1000 - (origAddr&0xfff) - sizeof(MemHeapHeader), 0, origHead); + + MemHeapFooter* holeFooter = (MemHeapFooter*)(newAddr - sizeof(MemHeapFooter)); + MemHeapFooterSetup(origHead, holeFooter); + + origAddr = newAddr; + origSize -= origHead->Size; + } + + else OrderedArrayDeleteIndex(i, &heap->Index); + + // Create the new block + MemHeapHeader* bHead = (MemHeapHeader*)origAddr; + MemHeapFooter* bFoot = (MemHeapFooter*)(origAddr + sizeof(MemHeapHeader) + size); + MemHeapHeaderSetup(newsize, 1, bHead); + MemHeapFooterSetup(bHead, bFoot); + + // Create a new hole at the end of current block if necessary + if (origSize - newsize > 0) + { + // header + MemHeapHeader* hHead = (MemHeapHeader*)(origAddr + sizeof(MemHeapHeader) + + sizeof(MemHeapFooter) + size); + MemHeapHeaderSetup(origSize - newsize, 0, hHead); + + // footer + MemHeapFooter* hFoot = (MemHeapFooter*)((uint32)hHead + hHead->Size - sizeof(MemHeapFooter)); + if ((uint32)hFoot < heap->EndAddress) MemHeapFooterSetup(hHead, hFoot); + + // add it to index + OrderedArrayInsert((uint32)hHead, &heap->Index); + } + + return (uint32)bHead + sizeof(MemHeapHeader); +} + +void MemHeapFree (uint32 address, MemHeap* heap, PageDirectory* pd) +{ + // Sanity check + if (!address || !heap) return; + + MemHeapHeader* head = (MemHeapHeader*) (address - sizeof(MemHeapHeader)); + MemHeapFooter* foot = (MemHeapFooter*) ((uint32)head + head->Size - sizeof(MemHeapFooter)); + + if (head->Magic != MEMHEAP_MAGIC) return; + if (foot->Magic != MEMHEAP_MAGIC) return; + + // Clear used flag + head->Used = 0; + + uint8 AddToIndex = 1; + + // Unify left (if possible) + MemHeapFooter* testFoot = (MemHeapFooter*) ((uint32)head - sizeof(MemHeapFooter)); + if (testFoot->Magic == MEMHEAP_MAGIC && testFoot->Header->Used == 0) + { + uint32 temp = head->Size; + head = testFoot->Header; + foot->Header = head; + head->Size += temp; + + AddToIndex = 0; + } + + // Unify right (if possible) + MemHeapHeader* testHead = (MemHeapHeader*) ((uint32)foot + sizeof(MemHeapFooter)); + if ((uint32)testHead < heap->EndAddress && testHead->Magic == MEMHEAP_MAGIC && testHead->Used == 0) + { + head->Size += testHead->Size; + testFoot = (MemHeapFooter*) ((uint32)testHead + testHead->Size - sizeof(MemHeapFooter)); + foot = testFoot; + + uint32 i; + for (i = 0; i < heap->Index.Size && + (uint32)testHead != OrderedArrayLookup(i, &heap->Index); i++) ; + + if (i < heap->Index.Size) OrderedArrayDeleteIndex(i, &heap->Index); + } + + // Contract heap (if possible) + if ((uint32)foot + sizeof(MemHeapFooter) == heap->EndAddress) + { + uint32 old = heap->EndAddress - heap->StartAddress; + uint32 new = MemHeapContract((uint32)head + head->Size - sizeof(MemHeapFooter), heap,pd); + + // Last block still existent + if (head->Size > (old - new)) + { + head->Size -= old - new; + foot = (MemHeapFooter*) ((uint32)head + head->Size - sizeof(MemHeapFooter)); + MemHeapFooterSetup(head, foot); + } + + // Nope, not existent + else + { + uint32 i; + for (i=0; iIndex.Size && (uint32)testHead != OrderedArrayLookup(i,&heap->Index); i++) ; + + if (i < heap->Index.Size) OrderedArrayDeleteIndex(i,&heap->Index); + } + } + + // Lastly, insert hole in array + if (AddToIndex) OrderedArrayInsert((uint32)head, &heap->Index); +} + + diff --git a/Kernel/memory/mem-paging.c b/Kernel/memory/mem-paging.c new file mode 100644 index 0000000..6c4e3d8 --- /dev/null +++ b/Kernel/memory/mem-paging.c @@ -0,0 +1,74 @@ +/* + * memory-vi.c + * + * Created on: Aug 23, 2011 + * Author: Tiberiu + */ +#include +#include +/******************************* + * Data * + *******************************/ +PageDirectory* CurrentDirectory; +PageDirectory* KernelDirectory; + +/******************************* + * Useful routines * + *******************************/ +void PagingInitialize(uint32 kernel_used) +{ + LogMem("Virtual memory manager initialization started. End of kernel = 0x%x\n", kernel_used); + PageDirectory* kernelPd = (PageDirectory*) kmalloc_a(sizeof(PageDirectory)); + memset(kernelPd, 0, sizeof(PageDirectory)); + + CurrentDirectory = kernelPd; + KernelDirectory = kernelPd; + + uint32 i; + for (i = 0; i < kernel_used; i+=0x1000) + MemPhAllocFrame(PagingGetPage(i, 1, kernelPd), 0, 0); + + LogMem("Identity mapped first 0x%x bytes.\n", kernel_used); + + for (i = KERNEL_HEAP_START; i < KERNEL_HEAP_END; i+=0x1000) + MemPhAllocFrame(PagingGetPage(i, 1, kernelPd), 1, 1); + + LogMem("Mapped kernel space.\n"); + + PagingSwitchPageDirectory (kernelPd); +} + +void PagingSwitchPageDirectory (PageDirectory* dir) +{ + CurrentDirectory = dir; + asm volatile ("mov %0, %%cr3":: "r"(&dir->TablesPhysical)); + + uint32 cr0; + asm volatile ("mov %%cr0, %0": "=r"(cr0)); + cr0 |= 0x80000000; + asm volatile ("mov %0, %%cr0":: "r"(cr0)); + + LogMem("Enabled paging.\n"); +} + +Page* PagingGetPage(uint32 addr, uint8 make, PageDirectory* dir) +{ + addr >>= 12; + + uint32 tableIndex = addr >> 10; + + if (dir->Tables[tableIndex]) + return &dir->Tables[tableIndex]->Pages[addr&0x3ff]; + + else if (make) + { + uint32 temp; + dir->Tables[tableIndex] = (PageTable*)kmalloc_ap(sizeof(PageTable), &temp); + memset (dir->Tables[tableIndex], 0, 0x1000); + dir->TablesPhysical[tableIndex] = temp | 0x7; + return &dir->Tables[tableIndex]->Pages[addr&0x3ff]; + } + + else return 0; +} + diff --git a/Kernel/memory/mem-paging.c~ b/Kernel/memory/mem-paging.c~ new file mode 100644 index 0000000..40fbe2d --- /dev/null +++ b/Kernel/memory/mem-paging.c~ @@ -0,0 +1,75 @@ +/* + * memory-vi.c + * + * Created on: Aug 23, 2011 + * Author: Tiberiu + */ +#include +#include +/******************************* + * Data * + *******************************/ +PageDirectory* CurrentDirectory; +PageDirectory* KernelDirectory; + +/******************************* + * Useful routines * + *******************************/ +void PagingInitialize(uint32 kernel_used) +{ + LogMem("Virtual memory manager initialization started. End of kernel = 0x%x\n", kernel_used); + PageDirectory* kernelPd = (PageDirectory*) kmalloc_a(sizeof(PageDirectory)); + memset(kernelPd, 0, sizeof(PageDirectory)); + + CurrentDirectory = kernelPd; + KernelDirectory = kernelPd; + + uint32 i; + for (i = 0; i < kernel_used; i+=0x1000) + MemPhAllocFrame(PagingGetPage(i, 1, kernelPd), 0, 0); + + LogMem("Identity mapped first 0x%x bytes.\n", kernel_used); + + for (i = KERNEL_HEAP_START; i < KERNEL_HEAP_END; i+=0x1000) + MemPhAllocFrame(PagingGetPage(i, 1, kernelPd), 1, 1); + + LogMem("Mapped kernel space.\n"); + + PagingSwitchPageDirectory (kernelPd); +} + +void PagingSwitchPageDirectory (PageDirectory* dir) +{ + CurrentDirectory = dir; + asm volatile ("mov %0, %%cr3":: "r"(&dir->TablesPhysical)); + LogMem("Switched page directory to 0x%x.\n", (uint32)(&dir->TablesPhysical)); + + uint32 cr0; + asm volatile ("mov %%cr0, %0": "=r"(cr0)); + cr0 |= 0x80000000; + asm volatile ("mov %0, %%cr0":: "r"(cr0)); + + LogMem("Enabled paging.\n"); +} + +Page* PagingGetPage(uint32 addr, uint8 make, PageDirectory* dir) +{ + addr >>= 12; + + uint32 tableIndex = addr >> 10; + + if (dir->Tables[tableIndex]) + return &dir->Tables[tableIndex]->Pages[addr&0x3ff]; + + else if (make) + { + uint32 temp; + dir->Tables[tableIndex] = (PageTable*)kmalloc_ap(sizeof(PageTable), &temp); + memset (dir->Tables[tableIndex], 0, 0x1000); + dir->TablesPhysical[tableIndex] = temp | 0x7; + return &dir->Tables[tableIndex]->Pages[addr&0x3ff]; + } + + else return 0; +} + diff --git a/Kernel/memory/mem-phys.c b/Kernel/memory/mem-phys.c new file mode 100644 index 0000000..b19038b --- /dev/null +++ b/Kernel/memory/mem-phys.c @@ -0,0 +1,108 @@ +/* + * mem-phys.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ +#include + +uint32* FrameMap; +uint32 TotalFrames; +uint32 TotalMemory; +uint32 UsedFrames; + +inline void ConvertIndexToFrame (uint32 index, uint32* address, uint32* offset) +{ + *address = (index >> 5); + *offset = index & 0x1f; +} + +inline uint32 ConvertFrameToIndex (uint32 address, uint32 offset) +{ + return (address<<5) | offset; +} + +void MemPhSetFrame (uint32 frame, uint8 value) +{ + uint32 addr, off; + ConvertIndexToFrame(frame, &addr, &off); + + if (value) { + if ((FrameMap[addr] & (1<> 5; addr++) + if (FrameMap[addr] != 0xffffffff) + { + for (pos = 0; (FrameMap[addr] & (1<> 2; + TotalMemory = SystemMemoryKb; + + FrameMap = (uint32*) kmalloc(sizeof(uint32) * (1 + (TotalFrames>>5))); + memset(FrameMap, 0, sizeof(uint32) * (1 + (TotalFrames>>5))); + LogMem("%#Started physical memory manager ok!, found %ukb\n", ColorLightGreen, SystemMemoryKb); +} + +void MemPhReserveFrames (uint32 address, uint32 length) +{ + address >>= 12; + length = (length>>12) + ((length & 0xfff) > 0); + uint32 end = address + length; + + for (; address < end ; address++) + MemPhSetFrame(address, 1); +} diff --git a/Kernel/memory/mem-phys.c~ b/Kernel/memory/mem-phys.c~ new file mode 100644 index 0000000..484315b --- /dev/null +++ b/Kernel/memory/mem-phys.c~ @@ -0,0 +1,109 @@ +/* + * mem-phys.c + * + * Created on: Aug 27, 2011 + * Author: Tiberiu + */ +#include + +uint32* FrameMap; +uint32 TotalFrames; +uint32 TotalMemory; +uint32 UsedFrames; + +inline void ConvertIndexToFrame (uint32 index, uint32* address, uint32* offset) +{ + *address = (index >> 5); + *offset = index & 0x1f; +} + +inline uint32 ConvertFrameToIndex (uint32 address, uint32 offset) +{ + return (address<<5) | offset; +} + +void MemPhSetFrame (uint32 frame, uint8 value) +{ + uint32 addr, off; + ConvertIndexToFrame(frame, &addr, &off); + + if (value) { + if ((FrameMap[addr] & (1<> 5; addr++) + if (FrameMap[addr] != 0xffffffff) + { + for (pos = 0; (FrameMap[addr] & (1<> 2; + TotalMemory = SystemMemoryKb; + + FrameMap = (uint32*) kmalloc(sizeof(uint32) * (1 + (TotalFrames>>5))); + memset(FrameMap, 0, sizeof(uint32) * (1 + (TotalFrames>>5))); + LogMem("%#Started physical memory manager ok!, found %ukb\n", ColorLightGreen, SystemMemoryKb); +} + +void MemPhReserveFrames (uint32 address, uint32 length) +{ + address >>= 12; + length = (length>>12) + ((length & 0xfff) > 0); + uint32 end = address + length; + + for (; address < end ; address++) + MemPhSetFrame(address, 1); +} diff --git a/Makefile b/Makefile deleted file mode 100644 index e2d3ecd..0000000 --- a/Makefile +++ /dev/null @@ -1,270 +0,0 @@ -# User sets these -CC = gcc -ASM = nasm -CURDIR = /media/6C9EE8DF9EE8A336/ctaos - -# Other parameters & paths used -LSCRIPT = SysCore/objects/linker.ld -OBJ = Build - -CCPARAM = -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I./SysCore/include -c -ASMPARAMobj = -f aout -ASMPARAMbin = -f bin - -#.PHONY : FORCE -#FORCE :# -# @echo -e "\e[1;4m\e[36mC\e[31mT\e[32mA \e[37mOperating System v0.1\e[0" - -# Build final floppy image -ctaos.img : $(OBJ)bootload.bin $(OBJ)stage2.cta $(OBJ)kernel.bin - @echo -e "\e[1;32m[ 99%]\e[0m Making floppy image" - dd bs=512 count=2880 if=/dev/zero of=ctaos.img - mkfs.msdos ctaos.img - dd bs=512 count=1 conv=notrunc if=$(OBJ)bootload.bin of=ctaos.img - sudo mkdir /media/floppy1/ - sudo mount -o loop ctaos.img /media/floppy1/ - sudo cp $(OBJ)stage2.cta /media/floppy1 - sudo cp $(OBJ)kernel.bin /media/floppy1 - sudo umount /media/floppy1/ - sudo rm -r /media/floppy1/ - - -# Build Bootloader: Stage 1 -$(OBJ)bootload.bin : SysBoot/stage1/bootload.asm - echo -e "\e[1;32m[ 4%]\e[0m BOOTLOADER :: stage 1" - @$(ASM) $(ASMPARAMbin) SysBoot/stage1/bootload.asm -o $(OBJ)bootload.bin - -# Build Bootloader: Stage 2 -$(OBJ)stage2.cta : SysBoot/stage2/stage2.asm \ - SysBoot/stage2/a20.inc \ - SysBoot/stage2/bootinfo.inc \ - SysBoot/stage2/common.inc \ - SysBoot/stage2/fat12.inc \ - SysBoot/stage2/floppy16.inc \ - SysBoot/stage2/gdt.inc \ - SysBoot/stage2/getdata.inc \ - SysBoot/stage2/memory.inc \ - SysBoot/stage2/paging.inc \ - SysBoot/stage2/stdio.inc - @echo -e "\e[1;32m[ 8%]\e[0m BOOTLOADER :: stage 2" - @$(ASM) $(ASMPARAMbin) -I./SysBoot/stage2/ -o $(OBJ)stage2.cta SysBoot/stage2/stage2.asm - -# Build KERNEL: -$(OBJ)kernel.bin : $(OBJ)/loader.o \ - $(OBJ)/main.o \ - $(OBJ)/lib-conio.o \ - $(OBJ)/lib-ctype.o \ - $(OBJ)/mmngr-asm.o \ - $(OBJ)/mmngr-phys.o \ - $(OBJ)/mmngr-virt.o \ - $(OBJ)/mmngr-lib-pde.o \ - $(OBJ)/mmngr-lib-pte.o \ - $(OBJ)/shell.o \ - $(OBJ)/lib-stdlib.o \ - $(OBJ)/lib-string.o \ - $(OBJ)/lib-system.o \ - $(OBJ)/lib-time.o \ - $(OBJ)/driver-bsod.o \ - $(OBJ)/driver-cpu.o \ - $(OBJ)/driver-dma.o \ - $(OBJ)/driver-drivers.o \ - $(OBJ)/driver-floppy.o \ - $(OBJ)/driver-gdt.o \ - $(OBJ)/driver-gdt-asm.o \ - $(OBJ)/driver-idt.o \ - $(OBJ)/driver-idt-asm.o \ - $(OBJ)/driver-isrs.o \ - $(OBJ)/driver-isrs-asm.o \ - $(OBJ)/driver-irq.o \ - $(OBJ)/driver-irq-asm.o \ - $(OBJ)/driver-keyboard.o \ - $(OBJ)/driver-fat.o \ - $(OBJ)/driver-pic.o \ - $(OBJ)/driver-pit.o \ - $(OBJ)/video-vga03h.o - ld -T SysCore/link.ld - -# ---------- Kernel components ---------- # - -# Build assembly sources: -$(OBJ)/loader.o : SysCore/loader.asm - @ echo -e "\e[1;33m[ 9%]\e[0m Assembly kernel loader" - @$(ASM) $(ASMPARAMobj) -o $(OBJ)/loader.o SysCore/loader.asm - -$(OBJ)/driver-gdt-asm.o : SysCore/drivers/cpu/gdt/gdt.asm - @echo -e "\e[1;33m[ 10%]\e[0m Assembly code for GDT" - @$(ASM) $(ASMPARAMobj) -o $(OBJ)/driver-gdt-asm.o SysCore/drivers/cpu/gdt/gdt.asm - -$(OBJ)/driver-idt-asm.o : SysCore/drivers/cpu/idt/idt.asm - @echo -e "\e[1;33m[ 11%]\e[0m Assembly code for IDT" - @$(ASM) $(ASMPARAMobj) -o $(OBJ)/driver-idt-asm.o SysCore/drivers/cpu/idt/idt.asm - -$(OBJ)/driver-irq-asm.o : SysCore/drivers/cpu/irq/irq.asm - @echo -e "\e[1;33m[ 12%]\e[0m Assembly code for IRQ" - @$(ASM) $(ASMPARAMobj) -o $(OBJ)/driver-irq-asm.o SysCore/drivers/cpu/irq/irq.asm - -$(OBJ)/driver-isrs-asm.o : SysCore/drivers/cpu/isrs/isrs.asm - @echo -e "\e[1;33m[ 13%]\e[0m Assembly code for ISRs" - @$(ASM) $(ASMPARAMobj) -o $(OBJ)/driver-isrs-asm.o SysCore/drivers/cpu/isrs/isrs.asm - - -# Build MAIN function -$(OBJ)/main.o : SysCore/main.c SysCore/include/string.h \ - SysCore/include/system.h SysCore/include/conio.h \ - SysCore/drivers/drivers.h SysCore/include/time.h \ - SysCore/include/bootinfo.h SysCore/memory/mmngr_ph.h \ - SysCore/memory/mmngr_vi.h SysCore/video/vga03h.h - @echo -e "\e[1;32m[ 14%]\e[0m MAIN C Function" - @$(CC) $(CCPARAM) -o $(OBJ)/main.o SysCore/main.c - -# Build SHELL -$(OBJ)/shell.o : SysCore/shell/shell.c SysCore/shell/apps.h \ - SysCore/include/system.h SysCore/include/conio.h \ - SysCore/drivers/drivers.h SysCore/include/time.h \ - SysCore/memory/mmngr_ph.h SysCore/drivers/keyboard.h \ - SysCore/drivers/cpu/cpu.h SysCore/include/drivers/floppy.h \ - SysCore/drivers/filesys/fat.h - @echo -e "\e[1;34m[ 15%]\e[0m Shell" - @$(CC) $(CCPARAM) -o $(OBJ)/shell.o SysCore/shell/shell.c - -# Build LIBRARIES -$(OBJ)/lib-conio.o : SysCore/lib/conio.c \ - SysCore/include/drivers/keyboard.h SysCore/include/stdarg.h \ - SysCore/include/conio.h SysCore/include/stdlib.h \ - SysCore/include/string.h SysCore/include/ctype.h \ - SysCore/memory/mmngr_ph.h - @echo -e "\e[1;34m[ 16%]\e[0m Libraries: conio" - @$(CC) $(CCPARAM) -o $(OBJ)/lib-conio.o SysCore/lib/conio.c - -$(OBJ)/lib-ctype.o : SysCore/lib/ctype.c SysCore/include/ctype.h - @echo -e "\e[1;34m[ 17%]\e[0m Libraries: ctype" - @$(CC) $(CCPARAM) -o $(OBJ)/lib-ctype.o SysCore/lib/ctype.c - -$(OBJ)/lib-stdlib.o : SysCore/lib/stdlib.c SysCore/include/stdlib.h \ - SysCore/include/ctype.h - @echo -e "\e[1;34m[ 18%]\e[0m Libraries: stdlib" - @$(CC) $(CCPARAM) -o $(OBJ)/lib-stdlib.o SysCore/lib/stdlib.c - -$(OBJ)/lib-string.o : SysCore/lib/string.c SysCore/include/string.h - @echo -e "\e[1;32m[ 19%]\e[0m Libraries: string" - @$(CC) $(CCPARAM) -o $(OBJ)/lib-string.o SysCore/lib/string.c - -$(OBJ)/lib-system.o : SysCore/lib/system.c SysCore/include/system.h - @echo -e "\e[1;34m[ 20%]\e[0m Libraries: system" - @$(CC) $(CCPARAM) -o $(OBJ)/lib-system.o SysCore/lib/system.c - -$(OBJ)/lib-time.o : SysCore/lib/time.c SysCore/include/time.h \ - SysCore/include/system.h - @echo -e "\e[1;34m[ 21%]\e[0m Libraries: time" - @$(CC) $(CCPARAM) -o $(OBJ)/lib-time.o SysCore/lib/time.c - - -# Build Memory Manager -$(OBJ)/mmngr-asm.o : SysCore/memory/mmngr.asm - @echo -e "\e[1;36m[ 22%]\e[0m Memory manager assembly code" - @$(ASM) $(ASMPARAMobj) -o $(OBJ)/mmngr-asm.o SysCore/memory/mmngr.asm - -$(OBJ)/mmngr-phys.o : SysCore/memory/mmngr_ph.c SysCore/memory/mmngr_ph.h - @echo -e "\e[1;36m[ 22%]\e[0m Physical memory manager" - @$(CC) $(CCPARAM) -o $(OBJ)/mmngr-phys.o SysCore/memory/mmngr_ph.c - -$(OBJ)/mmngr-virt.o : SysCore/memory/mmngr_vi.c SysCore/memory/mmngr_vi.h \ - SysCore/memory/mmngr_ph.h - @echo -e "\e[1;36m[ 23%]\e[0m Virtual memory manager" - @$(CC) $(CCPARAM) -o $(OBJ)/mmngr-virt.o SysCore/memory/mmngr_vi.c - -$(OBJ)/mmngr-lib-pde.o : SysCore/memory/lib/pde.c SysCore/memory/lib/pde.h - @echo -e "\e[1;36m[ 24%]\e[0m Memory manager libraries: PDE" - @$(CC) $(CCPARAM) -o $(OBJ)/mmngr-lib-pde.o SysCore/memory/lib/pde.c - -$(OBJ)/mmngr-lib-pte.o : SysCore/memory/lib/pte.c SysCore/memory/lib/pte.h - @echo -e "\e[1;36m[ 25%]\e[0m Memory manager libraries: PTE" - @$(CC) $(CCPARAM) -o $(OBJ)/mmngr-lib-pte.o SysCore/memory/lib/pte.c - - -# Build drivers -$(OBJ)/driver-drivers.o : SysCore/drivers/drivers.c SysCore/include/system.h \ - SysCore/drivers/cpu/cpu.h SysCore/drivers/clock/clock.h \ - SysCore/drivers/floppy/floppy.h SysCore/include/drivers/keyboard.h - @echo -e "\e[1;35m[ 26%]\e[0m Driver manager" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-drivers.o SysCore/drivers/drivers.c - -$(OBJ)/driver-bsod.o : SysCore/drivers/BSOD.c SysCore/include/system.h \ - SysCore/include/conio.h - @echo -e "\e[1;35m[ 27%]\e[0m Kernel panic screen" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-bsod.o SysCore/drivers/BSOD.c - -$(OBJ)/driver-cpu.o : SysCore/drivers/cpu/cpu.c SysCore/include/system.h \ - SysCore/drivers/cpu/cpu.h SysCore/drivers/cpu/gdt/gdt.h \ - SysCore/drivers/cpu/idt/idt.h SysCore/drivers/cpu/irq/irq.h \ - SysCore/drivers/cpu/isrs/isrs.h - @echo -e "\e[1;35m[ 28%]\e[0m CPU modules" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-cpu.o SysCore/drivers/cpu/cpu.c - -$(OBJ)/driver-gdt.o : SysCore/drivers/cpu/gdt/gdt.c SysCore/drivers/cpu/gdt/gdt.h - @echo -e "\e[1;35m[ 29%]\e[0m Global descriptor table" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-gdt.o SysCore/drivers/cpu/gdt/gdt.c - -$(OBJ)/driver-idt.o : SysCore/drivers/cpu/idt/idt.c SysCore/drivers/cpu/idt/idt.h \ - SysCore/include/system.h - @echo -e "\e[1;35m[ 30%]\e[0m Interrupt descriptor table" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-idt.o SysCore/drivers/cpu/idt/idt.c - -$(OBJ)/driver-isrs.o : SysCore/drivers/cpu/isrs/isrs.c SysCore/drivers/cpu/isrs/isrs.h \ - SysCore/drivers/cpu/idt/idt.h SysCore/include/system.h \ - SysCore/include/conio.h - @echo -e "\e[1;35m[ 31%]\e[0m Interrupt service routines" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-isrs.o SysCore/drivers/cpu/isrs/isrs.c - - -$(OBJ)/driver-irq.o : SysCore/drivers/cpu/irq/irq.c SysCore/drivers/cpu/irq/irq.h \ - SysCore/include/system.h SysCore/drivers/cpu/idt/idt.h \ - SysCore/drivers/cpu/pic/pic.h - @echo -e "\e[1;35m[ 32%]\e[0m Interrupt requests" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-irq.o SysCore/drivers/cpu/irq/irq.c - -$(OBJ)/driver-pic.o : SysCore/drivers/cpu/irq/pic.c SysCore/drivers/cpu/irq/pic.h \ - SysCore/include/system.h - @echo -e "\e[1;35m[ 33%]\e[0m Programmable interrupt controller" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-pic.o SysCore/drivers/cpu/irq/pic.c - -$(OBJ)/driver-pit.o : SysCore/drivers/clock/pit.c SysCore/drivers/clock/clock.h \ - SysCore/include/system.h SysCore/include/time.h - @echo -e "\e[1;35m[ 34%]\e[0m Programmable interval timer" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-pit.o SysCore/drivers/clock/pic.c - -$(OBJ)/driver-keyboard.o : SysCore/drivers/keyboard/keyboard.c SysCore/include/system.h \ - SysCore/include/drivers/keyboard.h - @echo -e "\e[1;35m[ 35%]\e[0m Keyboard" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-pic.o SysCore/drivers/cpu/irq/pic.c - -$(OBJ)/driver-dma.o : SysCore/drivers/floppy/dma.c SysCore/drivers/floppy/dma.h \ - SysCore/include/system.h - @echo -e "\e[1;35m[ 36%]\e[0m DMA Controller" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-dma.o SysCore/drivers/floppy/dma.c - -$(OBJ)/driver-floppy.o : SysCore/drivers/floppy/floppy.c SysCore/drivers/floppy/dma.h \ - SysCore/include/system.h SysCore/include/time.h \ - SysCore/include/conio.h SysCore/drivers/floppy/storage.h \ - SysCore/drivers/floppy/floppy.h - @echo -e "\e[1;35m[ 37%]\e[0m FDC Controller" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-floppy.o SysCore/drivers/floppy/floppy.c - -# TODO: add SysCore/drivers/filesys/vfs.h -$(OBJ)/driver-fat.o : SysCore/drivers/filesys/fat.c SysCore/drivers/filesys/fat.h \ - SysCore/drivers/floppy/floppy.h SysCore/include/conio.h - @echo -e "\e[1;35m[ 38%]\e[0m File system" - @$(CC) $(CCPARAM) -o $(OBJ)/driver-fat.o SysCore/drivers/floppy/fat.c - -# TODO: add vfs.c - -# TODO: add colors -$(OBJ)/video-vga03h.o : SysCore/video/vga03h.c SysCore/include/conio.h \ - SysCore/include/system.h - @$(CC) $(CCPARAM) -o $(OBJ)/video-vga03h.o SysCore/video/vga03h.c - - -.PHONY : clean -clean: - - rm ctaos.img - rm $(OBJ)*.* diff --git a/SysBoot/makeall.bat b/SysBoot/makeall.bat deleted file mode 100644 index 0d28bf6..0000000 --- a/SysBoot/makeall.bat +++ /dev/null @@ -1,16 +0,0 @@ -@echo off -set nasm_path=C:\nasm -set djgpp_path=C:\DJGPP\bin - -@echo ***************** CTA Bootloader ***************** -@echo. - -:Stage1 - cd stage1 - call make.bat - cd.. - -:Stage2 - cd stage2 - call make.bat - cd.. \ No newline at end of file diff --git a/SysBoot/stage1/BOOTLOAD.BIN b/SysBoot/stage1/BOOTLOAD.BIN deleted file mode 100644 index 0735e886e54da8c62af04a9970fba004093952c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 512 zcmYLG!E4iS6n-ytb+#tk9K^Z9_#H&tCG^)r51v*==cUk$wrJTwI$KAlB$%ecj$O-W zQwWIvz`B8;2zn^kG3n9;kud^pryXZcaYYbhR3~<%6b%zX-i;cnzr|VO{d03~1jOW`9fKD0 z0X3n58dpXwvW^;m8?4FVb!u3XiOkZ&(up2mrKubM3PnVq#)%;QO&O8!@_bw5{Rhei$#)^*2vTR8c}7U PSI: 0 terminated string -;************************************************; -Print: - lodsb ; load next byte from string from SI to AL - or al, al ; Does AL=0? - jz PrintDone ; Yep, null terminator found-bail out - mov ah, 0eh ; Nope-Print the character - int 10h - jmp Print ; Repeat until null terminator found - PrintDone: - ret ; we are done, so return - -;************************************************; -; Reads a series of sectors -; CX=>Number of sectors to read -; AX=>Starting sector -; ES:BX=>Buffer to read to -;************************************************; - -ReadSectors: - .MAIN: - mov di, 0x0005 ; five retries for error - .SECTORLOOP: - push ax - push bx - push cx - call LBACHS ; convert starting sector to CHS - mov ah, 0x02 ; BIOS read sector - mov al, 0x01 ; read one sector - mov ch, BYTE [absoluteTrack] ; track - mov cl, BYTE [absoluteSector] ; sector - mov dh, BYTE [absoluteHead] ; head - mov dl, BYTE [bsDriveNumber] ; drive - int 0x13 ; invoke BIOS - jnc .SUCCESS ; test for read error - xor ax, ax ; BIOS reset disk - int 0x13 ; invoke BIOS - dec di ; decrement error counter - pop cx - pop bx - pop ax - jnz .SECTORLOOP ; attempt to read again - int 0x18 - .SUCCESS: - mov si, msgProgress - call Print - pop cx - pop bx - pop ax - add bx, WORD [bpbBytesPerSector] ; queue next buffer - inc ax ; queue next sector - loop .MAIN ; read next sector - ret - -;************************************************; -; Convert CHS to LBA -; LBA = (cluster - 2) * sectors per cluster -;************************************************; - -ClusterLBA: - sub ax, 0x0002 ; zero base cluster number - xor cx, cx - mov cl, BYTE [bpbSectorsPerCluster] ; convert byte to word - mul cx - add ax, WORD [datasector] ; base data sector - ret - -;************************************************; -; Convert LBA to CHS -; AX=>LBA Address to convert -; -; absolute sector = (logical sector / sectors per track) + 1 -; absolute head = (logical sector / sectors per track) MOD number of heads -; absolute track = logical sector / (sectors per track * number of heads) -; -;************************************************; - -LBACHS: - xor dx, dx ; prepare dx:ax for operation - div WORD [bpbSectorsPerTrack] ; calculate - inc dl ; adjust for sector 0 - mov BYTE [absoluteSector], dl - xor dx, dx ; prepare dx:ax for operation - div WORD [bpbHeadsPerCylinder] ; calculate - mov BYTE [absoluteHead], dl - mov BYTE [absoluteTrack], al - ret - -;********************************************* -; Bootloader Entry Point -;********************************************* - -main: - - ;---------------------------------------------------- - ; code located at 0000:7C00, adjust segment registers - ;---------------------------------------------------- - - cli ; disable interrupts - mov ax, 0x07C0 ; setup registers to point to our segment - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - ;---------------------------------------------------- - ; create stack - ;---------------------------------------------------- - - mov ax, 0x0000 ; set the stack - mov ss, ax - mov sp, 0xFFFF - sti ; restore interrupts - - ;---------------------------------------------------- - ; Display loading message - ;---------------------------------------------------- - - mov si, msgLoading - call Print - - ;---------------------------------------------------- - ; Load root directory table - ;---------------------------------------------------- - - LOAD_ROOT: - - ; compute size of root directory and store in "cx" - - xor cx, cx - xor dx, dx - mov ax, 0x0020 ; 32 byte directory entry - mul WORD [bpbRootEntries] ; total size of directory - div WORD [bpbBytesPerSector] ; sectors used by directory - xchg ax, cx - - ; compute location of root directory and store in "ax" - - mov al, BYTE [bpbNumberOfFATs] ; number of FATs - mul WORD [bpbSectorsPerFAT] ; sectors used by FATs - add ax, WORD [bpbReservedSectors] ; adjust for bootsector - mov WORD [datasector], ax ; base of root directory - add WORD [datasector], cx - - ; read root directory into memory (7C00:0200) - - mov bx, 0x0200 ; copy root dir above bootcode - call ReadSectors - - ;---------------------------------------------------- - ; Find stage 2 - ;---------------------------------------------------- - - ; browse root directory for binary image - mov cx, WORD [bpbRootEntries] ; load loop counter - mov di, 0x0200 ; locate first root entry - .LOOP: - push cx - mov cx, 0x000B ; eleven character name - mov si, ImageName ; image name to find - push di - rep cmpsb ; test for entry match - pop di - je LOAD_FAT - pop cx - add di, 0x0020 ; queue next directory entry - loop .LOOP - jmp FAILURE - - ;---------------------------------------------------- - ; Load FAT - ;---------------------------------------------------- - - LOAD_FAT: - - ; save starting cluster of boot image - - mov dx, WORD [di + 0x001A] - mov WORD [cluster], dx ; file's first cluster - - ; compute size of FAT and store in "cx" - - xor ax, ax - mov al, BYTE [bpbNumberOfFATs] ; number of FATs - mul WORD [bpbSectorsPerFAT] ; sectors used by FATs - mov cx, ax - - ; compute location of FAT and store in "ax" - - mov ax, WORD [bpbReservedSectors] ; adjust for bootsector - - ; read FAT into memory (7C00:0200) - - mov bx, 0x0200 ; copy FAT above bootcode - call ReadSectors - - ; read image file into memory (0050:0000) - - mov ax, 0x0050 - mov es, ax ; destination for image - mov bx, 0x0000 ; destination for image - push bx - - ;---------------------------------------------------- - ; Load Stage 2 - ;---------------------------------------------------- - - LOAD_IMAGE: - - mov ax, WORD [cluster] ; cluster to read - pop bx ; buffer to read into - call ClusterLBA ; convert cluster to LBA - xor cx, cx - mov cl, BYTE [bpbSectorsPerCluster] ; sectors to read - call ReadSectors - push bx - - ; compute next cluster - - mov ax, WORD [cluster] ; identify current cluster - mov cx, ax ; copy current cluster - mov dx, ax ; copy current cluster - shr dx, 0x0001 ; divide by two - add cx, dx ; sum for (3/2) - mov bx, 0x0200 ; location of FAT in memory - add bx, cx ; index into FAT - mov dx, WORD [bx] ; read two bytes from FAT - test ax, 0x0001 - jnz .ODD_CLUSTER - - .EVEN_CLUSTER: - - and dx, 0000111111111111b ; take low twelve bits - jmp .DONE - - .ODD_CLUSTER: - - shr dx, 0x0004 ; take high twelve bits - - .DONE: - - mov WORD [cluster], dx ; store new cluster - cmp dx, 0x0FF0 ; test for end of file - jb LOAD_IMAGE - - DONE: - push WORD 0x0050 - push WORD 0x0000 - retf - - FAILURE: - - mov si, msgFailure - call Print - mov ah, 0x00 - int 0x16 ; await keypress - int 0x19 ; warm boot computer - - absoluteSector db 0x00 - absoluteHead db 0x00 - absoluteTrack db 0x00 - - datasector dw 0x0000 - cluster dw 0x0000 - ImageName db "STAGE2 CTA" - msgLoading db 0x0D, "CTA OS v0.1", 0x0A, 0x0D, "(c) CTA 2010", 0x0A, 0x0D, "Loading", 0x00 - msgProgress db ".", 0x00 - msgFailure db 0x0D, 0x0A, "Error: Could not find stage2.bin. Press any key to reboot.", 0x0A, 0x00 - - TIMES 510-($-$$) db 0 - DW 0xAA55 diff --git a/SysBoot/stage1/make.bat b/SysBoot/stage1/make.bat deleted file mode 100644 index aa718bf..0000000 --- a/SysBoot/stage1/make.bat +++ /dev/null @@ -1,23 +0,0 @@ -@echo off -set nasm_path=C:\nasm -set djgpp_path=C:\DJGPP\bin - -goto build - -:error - @echo. - @echo There have been build errors. Building halted. - @pause - exit - -:build - @echo Compiling stage 1... - del bootload.bin - %nasm_path%\nasm.exe -f bin bootload.asm -o bootload.bin - -:check - if not exist bootload.bin goto error - -:copy - @echo Writing stage 1 to floppy boot sector... - debug bootload.bin <..\..\scripts\stage1d >nul \ No newline at end of file diff --git a/SysBoot/stage2/MAKE.BAT b/SysBoot/stage2/MAKE.BAT deleted file mode 100644 index fc0dc23..0000000 --- a/SysBoot/stage2/MAKE.BAT +++ /dev/null @@ -1,24 +0,0 @@ -@echo off -set nasm_path=C:\nasm -set djgpp_path=C:\DJGPP\bin - -goto build - -:error - @echo. - @echo There have been build errors. Building halted. - @pause - exit - -:build - - @echo Compiling stage 2... - del stage2.cta - %nasm_path%\nasm.exe -f bin stage2.asm -o stage2.cta - -:test - if not exist stage2.cta goto error - -:copy - @echo Copying stage 2 to floppy... - copy stage2.cta A:\stage2.cta >nul \ No newline at end of file diff --git a/SysBoot/stage2/STAGE2.CTA b/SysBoot/stage2/STAGE2.CTA deleted file mode 100644 index 091bc4b21701024949ef543e70deed1ef2269476..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1784 zcmb_dUrbw782@hDd)iB(Z8}z%iQCN{YJ9Nnnz&>>m^B7p*annMVa;OEakeFMm~v|} zV+^&K<3iG8d)(82X=XAF52%;1!G&uqWNQZVL6kTc-Jdh6a|X4nAlL5{79Z58(evoe|8t8O8wAji@Hp0kf|D8Y;2y~;D_*C8opQzp7RH^stDJMj}! zxn9`*owz#I83+&_-xoUrRiw9?m?I+8H#V?utpQuV&=smCU7i5x+FnJv0!w0cLwmVm zWH;0`N1GDU*=lt5&9map`3W;dlnLd!E<+)BTP$p!6;GYLB^H7UqMgi(eSRW%{N(VQ z%{c_X&R9;=ohZgSL>ujy7Y`dYr!vFd;kkxLqqf-Xxh;-BXr*D$4cd*D7e9DKt!PeV zm) z+CU>*8Ra_Flh_{{R^$lP#;Nut-A|iM)DPEH3V+Ay0z=@&j+OURU&l&^>drZ|@jn)1 z{ifc@DZM8Q)y>g_qXkZi+e#IKY9`f2sWwJ4z$T5gI`OX&wnFvj55Pt zFGDOTkB}Zq>JA8HQ*&uU`$~tptS_}xr@ApeQzFPqrI1521c!cob zW!Q#x_-!X%?Y0%Fc}_a{hq8QlkHk(F2Ot~BZYp|ZgQms>?^a{sfZGKz9VR6hvSa-q z@2*v+3`f%BP39MMJLdWTd+PQ%9$m$VPrX~Gk*5NSI*>>QOd^HvPbgZ<|9kI%>ONE? zJ()Hx0Z71hSeDgu5*O|L?D1Lr$`^7&xDfnjtPFEOMld$C(Z%=mx31nWN=h9*hXPyA T@|p#nbwTQLNAV{N|Ks=#DFJan diff --git a/SysBoot/stage2/a20.inc b/SysBoot/stage2/a20.inc deleted file mode 100644 index 2a35227..0000000 --- a/SysBoot/stage2/a20.inc +++ /dev/null @@ -1,60 +0,0 @@ -;***** memory.inc **************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Enable A20 address line * -;* ======================= * -;* * -;************************************************************ cta os */ - -%ifndef __A20_INC_CTA000__ -%define __A20_INC_CTA000__ - -bits 16 ; real mode 16 bit code - -_EnableA20: - - cli - - call a20wait - mov al,0xAD - out 0x64,al - - call a20wait - mov al,0xD0 - out 0x64,al - - call a20wait2 - in al,0x60 - push eax - - call a20wait - mov al,0xD1 - out 0x64,al - - call a20wait - pop eax - or al,2 - out 0x60,al - - call a20wait - mov al,0xAE - out 0x64,al - - call a20wait - sti - ret - -a20wait: - in al,0x64 - test al,2 - jnz a20wait - ret - - -a20wait2: - in al,0x64 - test al,1 - jz a20wait2 - ret - -%endif \ No newline at end of file diff --git a/SysBoot/stage2/bootinfo.inc b/SysBoot/stage2/bootinfo.inc deleted file mode 100644 index 8bd7f9f..0000000 --- a/SysBoot/stage2/bootinfo.inc +++ /dev/null @@ -1,39 +0,0 @@ -;***** bootinfo.inc ************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Multiboot information structure * -;* =============================== * -;* * -;************************************************************ cta os */ - -%ifndef __BOOTINFO_INC_CTA001__ -%define __BOOTINFO_INC_CTA001__ - -struc multiboot_info - .flags resd 1 - .memoryLo resd 1 - .memoryHi resd 1 - .bootDevice resd 1 - .cmdLine resd 1 - .mods_count resd 1 - .mods_addr resd 1 - .syms0 resd 1 - .syms1 resd 1 - .syms2 resd 1 - .mmap_length resd 1 - .mmap_addr resd 1 - .drives_length resd 1 - .drives_addr resd 1 - .config_table resd 1 - .bootloader_name resd 1 - .apm_table resd 1 - .vbe_control_info resd 1 - .vbe_mode_info resd 1 - .vbe_mode resw 1 - .vbe_interface_seg resw 1 - .vbe_interface_off resw 1 - .vbe_interface_len resw 1 -endstruc - - -%endif diff --git a/SysBoot/stage2/common.inc b/SysBoot/stage2/common.inc deleted file mode 100644 index aeb3768..0000000 --- a/SysBoot/stage2/common.inc +++ /dev/null @@ -1,24 +0,0 @@ -;***** common.inc **************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Common definitions, variables * -;* ============================= * -;* * -;************************************************************ cta os */ - -%ifndef _COMMON_INC_CTA002__ -%define _COMMON_INC_CTA002__ - -; where the kernel is to be loaded to in protected mode -%define IMAGE_PMODE_BASE 0xC0000000 - -; where the kernel is to be loaded to in real mode -%define IMAGE_RMODE_BASE 0x3000 - -; kernel name (Must be 11 bytes) -ImageName db "KERNEL CTA" - -; size of kernel image in bytes -ImageSize db 0 - -%endif diff --git a/SysBoot/stage2/fat12.inc b/SysBoot/stage2/fat12.inc deleted file mode 100644 index f494a8e..0000000 --- a/SysBoot/stage2/fat12.inc +++ /dev/null @@ -1,245 +0,0 @@ -;***** FAT12.inc ***************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Fat12 filesystem for 3.5" floppies * -;* ================================== * -;* * -;************************************************************ cta os */ - -%ifndef __FAT12_INC_CTA003__ -%define __FAT12_INC_CTA003__ - -bits 16 - -;%include "Floppy16.inc" ; the erm.. floppy driver - -%define ROOT_OFFSET 0x2e00 -%define FAT_SEG 0x2c0 -%define ROOT_SEG 0x2e0 - -;******************************************* -; LoadRoot () -; - Load Root Directory Table to 0x7e00 -;******************************************* - -LoadRoot: - - pusha ; store registers - push es - - ; compute size of root directory and store in "cx" - - xor cx, cx ; clear registers - xor dx, dx - mov ax, 32 ; 32 byte directory entry - mul WORD [bpbRootEntries] ; total size of directory - div WORD [bpbBytesPerSector] ; sectors used by directory - xchg ax, cx ; move into AX - - ; compute location of root directory and store in "ax" - - mov al, BYTE [bpbNumberOfFATs] ; number of FATs - mul WORD [bpbSectorsPerFAT] ; sectors used by FATs - add ax, WORD [bpbReservedSectors] - mov WORD [datasector], ax ; base of root directory - add WORD [datasector], cx - - ; read root directory into 0x7e00 - - push word ROOT_SEG - pop es - mov bx, 0 ; copy root dir - call ReadSectors ; read in directory table - pop es - popa ; restore registers and return - ret - -;******************************************* -; LoadFAT () -; - Loads FAT table to 0x7c00 -; -; Parm/ ES:DI => Root Directory Table -;******************************************* - -LoadFAT: - - pusha ; store registers - push es - - ; compute size of FAT and store in "cx" - - xor ax, ax - mov al, BYTE [bpbNumberOfFATs] ; number of FATs - mul WORD [bpbSectorsPerFAT] ; sectors used by FATs - mov cx, ax - - ; compute location of FAT and store in "ax" - - mov ax, WORD [bpbReservedSectors] - - ; read FAT into memory (Overwrite our bootloader at 0x7c00) - - push word FAT_SEG - pop es - xor bx, bx - call ReadSectors - pop es - popa ; restore registers and return - ret - -;******************************************* -; FindFile () -; - Search for filename in root table -; -; parm/ DS:SI => File name -; ret/ AX => File index number in directory table. -1 if error -;******************************************* - -FindFile: - - push cx ; store registers - push dx - push bx - mov bx, si ; copy filename for later - - ; browse root directory for binary image - - mov cx, WORD [bpbRootEntries] ; load loop counter - mov di, ROOT_OFFSET ; locate first root entry at 1 MB mark - cld ; clear direction flag - -.LOOP: - push cx - mov cx, 11 ; eleven character name. Image name is in SI - mov si, bx ; image name is in BX - push di - rep cmpsb ; test for entry match - pop di - je .Found - pop cx - add di, 32 ; queue next directory entry - loop .LOOP - -.NotFound: - pop bx ; restore registers and return - pop dx - pop cx - mov ax, -1 ; set error code - ret - -.Found: - pop ax ; return value into AX contains entry of file - pop bx ; restore registers and return - pop dx - pop cx - ret - -;******************************************* -; LoadFile () -; - Load file -; parm/ ES:SI => File to load -; parm/ EBX:BP => Buffer to load file to -; ret/ AX => -1 on error, 0 on success -;******************************************* - -LoadFile: - - xor ecx, ecx ; size of file in sectors - push ecx - -.FIND_FILE: - - push bx ; BX=>BP points to buffer to write to; store it for later - push bp - call FindFile ; find our file. ES:SI contains our filename - cmp ax, -1 - jne .LOAD_IMAGE_PRE - pop bp - pop bx - pop ecx - mov ax, -1 - ret - -.LOAD_IMAGE_PRE: - - sub edi, ROOT_OFFSET - sub eax, ROOT_OFFSET - - ; get starting cluster - - push word ROOT_SEG ;root segment loc - pop es - mov dx, WORD [es:di + 0x001A] ; DI points to file entry in root directory table. Refrence the table... - mov WORD [cluster], dx ; file's first cluster - pop bx ; get location to write to so we dont screw up the stack - pop es - push bx ; store location for later again - push es - call LoadFAT - -.LOAD_IMAGE: - - ; load the cluster - - mov ax, WORD [cluster] ; cluster to read - pop es ; bx:bp=es:bx - pop bx - call ClusterLBA - xor cx, cx - mov cl, BYTE [bpbSectorsPerCluster] - - call ReadSectors - - pop ecx - inc ecx - push ecx - - push bx - push es - - mov ax, FAT_SEG ;start reading from fat - mov es, ax - xor bx, bx - - ; get next cluster - - mov ax, WORD [cluster] ; identify current cluster - mov cx, ax ; copy current cluster - mov dx, ax ; copy current cluster - shr dx, 0x0001 ; divide by two - add cx, dx ; sum for (3/2) - - mov bx, 0 ;location of fat in memory - add bx, cx - mov dx, WORD [es:bx] - test ax, 0x0001 ; test for odd or even cluster - jnz .ODD_CLUSTER - -.EVEN_CLUSTER: - - and dx, 0000111111111111b ; take low 12 bits - jmp .DONE - -.ODD_CLUSTER: - - shr dx, 0x0004 ; take high 12 bits - -.DONE: - - mov WORD [cluster], dx - cmp dx, 0x0ff0 ; test for end of file marker - jb .LOAD_IMAGE - -.SUCCESS: - pop es - pop bx - pop ecx - xor ax, ax - ret - -%endif ;__FAT12_INC_67343546FDCC56AAB872_INCLUDED__ - - - - - diff --git a/SysBoot/stage2/floppy16.inc b/SysBoot/stage2/floppy16.inc deleted file mode 100644 index 3c08ac4..0000000 --- a/SysBoot/stage2/floppy16.inc +++ /dev/null @@ -1,120 +0,0 @@ -;***** floppy16.inc ************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Floppy drive interface routines * -;* =============================== * -;* * -;************************************************************ cta os */ - -%ifndef __FLOPPY16_INC_CTA004__ -%define __FLOPPY16_INC_CTA004__ - -bits 16 - -bpbOEM db "CTA OS " -bpbBytesPerSector: DW 512 -bpbSectorsPerCluster: DB 1 -bpbReservedSectors: DW 1 -bpbNumberOfFATs: DB 2 -bpbRootEntries: DW 224 -bpbTotalSectors: DW 2880 -bpbMedia: DB 0xf0 ;; 0xF1 -bpbSectorsPerFAT: DW 9 -bpbSectorsPerTrack: DW 18 -bpbHeadsPerCylinder: DW 2 -bpbHiddenSectors: DD 0 -bpbTotalSectorsBig: DD 0 -bsDriveNumber: DB 0 -bsUnused: DB 0 -bsExtBootSignature: DB 0x29 -bsSerialNumber: DD 0xa0a1a2a3 -bsVolumeLabel: DB "CTA OS " -bsFileSystem: DB "FAT12 " - -datasector dw 0x0000 -cluster dw 0x0000 - -absoluteSector db 0x00 -absoluteHead db 0x00 -absoluteTrack db 0x00 - -;************************************************; -; Convert CHS to LBA -; LBA = (cluster - 2) * sectors per cluster -;************************************************; - -ClusterLBA: - sub ax, 0x0002 ; zero base cluster number - xor cx, cx - mov cl, BYTE [bpbSectorsPerCluster] ; convert byte to word - mul cx - add ax, WORD [datasector] ; base data sector - ret - -;************************************************; -; Convert LBA to CHS -; AX=>LBA Address to convert -; -; absolute sector = (logical sector / sectors per track) + 1 -; absolute head = (logical sector / sectors per track) MOD number of heads -; absolute track = logical sector / (sectors per track * number of heads) -; -;************************************************; - -LBACHS: - xor dx, dx ; prepare dx:ax for operation - div WORD [bpbSectorsPerTrack] ; calculate - inc dl ; adjust for sector 0 - mov BYTE [absoluteSector], dl - xor dx, dx ; prepare dx:ax for operation - div WORD [bpbHeadsPerCylinder] ; calculate - mov BYTE [absoluteHead], dl - mov BYTE [absoluteTrack], al - ret - - -;************************************************; -; Reads a series of sectors -; CX=>Number of sectors to read -; AX=>Starting sector -; ES:EBX=>Buffer to read to -;************************************************; - -ReadSectors: - .MAIN: - mov di, 0x0005 ; five retries for error - .SECTORLOOP: - push ax - push bx - push cx - call LBACHS ; convert starting sector to CHS - mov ah, 0x02 ; BIOS read sector - mov al, 0x01 ; read one sector - mov ch, BYTE [absoluteTrack] ; track - mov cl, BYTE [absoluteSector] ; sector - mov dh, BYTE [absoluteHead] ; head - mov dl, BYTE [bsDriveNumber] ; drive - int 0x13 ; invoke BIOS - jnc .SUCCESS ; test for read error - xor ax, ax ; BIOS reset disk - int 0x13 ; invoke BIOS - dec di ; decrement error counter - pop cx - pop bx - pop ax - jnz .SECTORLOOP ; attempt to read again - int 0x18 - .SUCCESS: - pop cx - pop bx - pop ax - add bx, WORD [bpbBytesPerSector] ; queue next buffer - inc ax ; queue next sector - loop .MAIN ; read next sector - ret - - - - - -%endif ;__FLOPPY16_INC_67343546FDCC56AAB872_INCLUDED__ diff --git a/SysBoot/stage2/gdt.inc b/SysBoot/stage2/gdt.inc deleted file mode 100644 index 45b9c7a..0000000 --- a/SysBoot/stage2/gdt.inc +++ /dev/null @@ -1,68 +0,0 @@ -;***** gdt.inc ******************************************************* -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Global Descriptor Table routines * -;* ===================== * -;* * -;************************************************************ cta os */ - - -%ifndef __GDT_INC_CTA005__ -%define __GDT_INC_CTA005__ - -bits 16 - -;******************************************* -; InstallGDT() -; - Install our GDT -;******************************************* - -InstallGDT: - - cli ; clear interrupts - pusha ; save registers - lgdt [toc] ; load GDT into GDTR - sti ; enable interrupts - popa ; restore registers - ret ; All done! - -;******************************************* -; Global Descriptor Table (GDT) -;******************************************* - -gdt_data: - dd 0 ; null descriptor - dd 0 - -; gdt code: ; code descriptor - dw 0FFFFh ; limit low - dw 0 ; base low - db 0 ; base middle - db 10011010b ; access - db 11001111b ; granularity - db 0 ; base high - -; gdt data: ; data descriptor - dw 0FFFFh ; limit low (Same as code)10:56 AM 7/8/2007 - dw 0 ; base low - db 0 ; base middle - db 10010010b ; access - db 11001111b ; granularity - db 0 ; base high - -end_of_gdt: -toc: - dw end_of_gdt - gdt_data - 1 ; limit (Size of GDT) - dd gdt_data ; base of GDT - -; give the descriptor offsets names - -%define NULL_DESC 0 -%define CODE_DESC 0x8 -%define DATA_DESC 0x10 - -%endif ;__GDT_INC_67343546FDCC56AAB872_INCLUDED__ - - - - diff --git a/SysBoot/stage2/getdata.inc b/SysBoot/stage2/getdata.inc deleted file mode 100644 index 6a5d44d..0000000 --- a/SysBoot/stage2/getdata.inc +++ /dev/null @@ -1,98 +0,0 @@ - -gatherinfo: - pusha - push es - xor eax, eax - mov ebx, eax - mov ecx, eax - mov edx, eax -;Boot device - mov dword [multiboot_info_bootDevice], 0 ; drive 0 - -;Detect current video mode - mov ah, 0Fh - int 10h - mov byte [multiboot_info_video_mode], al - mov byte [multiboot_info_video_columns], ah - mov byte [multiboot_info_video_page], bh - -;Get VESA information - xor eax, eax - xor ebx, ebx - xor edx, edx - mov dword [TemporaryStorage], vbeControllerInfo - mov ax, word [TemporaryStorage] - mov dx, word [TemporaryStorage+2] - shl ax, 1 - mov es, ax - mov di, dx - mov ax, 0x4f00 - int 10h - cmp ax, 0x004F - - ; not correct - je vesa_00_ok - mov dword [multiboot_info_vbe_control_info], 0x0 ; failure - jmp vesa_00_done - - ; correct - vesa_00_ok: - mov dword [multiboot_info_vbe_control_info], vbeControllerInfo ; success - - vesa_00_done: -;Write VBE 2.0+ Interface pointers to 0 - mov word [multiboot_info_vbe_interface_seg], 0 - mov word [multiboot_info_vbe_interface_off], 0 - mov word [multiboot_info_vbe_interface_len], 0 - -;Get VESA Current mode - mov ax, 4f03h - int 10h - cmp ax, 004fh - je vesa_01_ok - - ; not ok: - mov word [multiboot_info_vbe_mode], 0 - jmp vesa_01_done - - vesa_01_ok: - mov word [multiboot_info_vbe_mode], bx - - vesa_01_done: - -;Get some info about current VESA mode - xor eax, eax - mov ebx, eax - mov edx, eax - - mov eax, vbeControllerInfo - push eax - and eax, 0fh - mov dx, ax - pop eax - - shr eax, 4 - - mov es, ax - mov di, dx - - - mov ax, 4f01h - mov cx, [multiboot_info_vbe_mode] - int 10h - - cmp ax, 004fh - je vesa_02_ok - - ; not ok: - mov word [multiboot_info_vbe_mode_info], 0 - jmp vesa_02_done - - vesa_02_ok: - mov word [multiboot_info_vbe_mode_info], vbeModeInfo - - vesa_02_done: - pop es - popa - ret - \ No newline at end of file diff --git a/SysBoot/stage2/memory.inc b/SysBoot/stage2/memory.inc deleted file mode 100644 index eeff590..0000000 --- a/SysBoot/stage2/memory.inc +++ /dev/null @@ -1,174 +0,0 @@ -;***** memory.inc **************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Basic memory routines * -;* ===================== * -;* * -;************************************************************ cta os */ - -%ifndef __MEMORY_INC_CTA006__ -%define __MEMORY_INC_CTA006__ - -bits 16 - -;-------------------------------------------- -; Memory map entry structure -;-------------------------------------------- - -struc MemoryMapEntry - .baseAddress resq 1 - .length resq 1 - .type resd 1 - .acpi_null resd 1 -endstruc - -;--------------------------------------------- -; Get memory map from bios -; /in es:di->destination buffer for entries -; /ret bp=entry count -;--------------------------------------------- - -BiosGetMemoryMap: - - xor ebx, ebx - xor bp, bp - mov edx, 0x0534D4150 ; Place "SMAP" into edx - mov eax, 0xe820 - mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry - mov ecx, 24 - int 0x15 - jc short .failed ; carry set on first call means "unsupported function" - mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register? - cmp eax, edx ; on success, eax must have been reset to "SMAP" - jne short .failed - test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless) - je short .failed - jmp short .jmpin -.e820lp: - mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call - mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry - mov ecx, 24 ; ask for 24 bytes again - int 0x15 - jc short .e820f ; carry set means "end of list already reached" - mov edx, 0x0534D4150 ; repair potentially trashed register -.jmpin: - jcxz .skipent ; skip any 0 length entries - cmp cl, 20 ; got a 24 byte ACPI 3.X response? - jbe short .notext - test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear? - je short .skipent -.notext: - mov ecx, [es:di + 8] ; get lower dword of memory region length - test ecx, ecx ; is the qword == 0? - jne short .goodent - mov ecx, [es:di + 12] ; get upper dword of memory region length - jecxz .skipent ; if length qword is 0, skip entry -.goodent: - inc bp ; got a good entry: ++count, move to next storage spot - add di, 24 -.skipent: - test ebx, ebx ; if ebx resets to 0, list is complete - jne short .e820lp -.e820f: - ret ; bp=entry count -.failed: - stc ; "function unsupported" error exit - ret - -;--------------------------------------------- -; Get memory size for >64M configuations (32 bit) -; ret\ ax=KB between 1MB and 16MB -; ret\ bx=number of 64K blocks above 16MB -; ret\ bx=0 and ax= -1 on error -;--------------------------------------------- - -BiosGetMemorySize64MB_32bit: - push ecx - push edx - xor ecx, ecx - xor edx, edx - mov eax, 0xe881 - int 0x15 - jc .error - jcxz .use_ax ;bios may have stored it in ax,bx or cx,dx. test if cx is 0 - mov eax, ecx ;its not, so it should contain mem size; store it - mov ebx, edx - -.use_ax: - pop edx ;mem size is in ax and bx already, return it - pop ecx - ret - -.error: - mov ax, -1 - mov bx, 0 - pop edx - pop ecx - ret - -;--------------------------------------------- -; Get memory size for >64M configuations -; ret\ ax=KB between 1MB and 16MB -; ret\ bx=number of 64K blocks above 16MB -; ret\ bx=0 and ax= -1 on error -;--------------------------------------------- - -BiosGetMemorySize64MB: - push ecx - push edx - xor ecx, ecx - xor edx, edx - mov ax, 0xe801 - int 0x15 - jc .error - cmp ah, 0x86 ;unsupported function - je .error - cmp ah, 0x80 ;invalid command - je .error - jcxz .use_ax ;bios may have stored it in ax,bx or cx,dx. test if cx is 0 - mov ax, cx ;its not, so it should contain mem size; store it - mov bx, dx - -.use_ax: - pop edx ;mem size is in ax and bx already, return it - pop ecx - ret - -.error: - mov ax, -1 - mov bx, 0 - pop edx - pop ecx - ret - -;--------------------------------------------- -; Get amount of contiguous KB from addr 0 -; ret\ ax=KB size from address 0 -;--------------------------------------------- - -BiosGetMemorySize: - int 0x12 - ret - -;--------------------------------------------- -; Get contiguous exetended memory size -; ret\ ax=KB size above 1MB; ax= -1 on error -;--------------------------------------------- - -BiosGetExtendedMemorySize: - mov ax, 0x88 - int 0x15 - jc .error - test ax, ax ; if size=0 - je .error - cmp ah, 0x86 ;unsupported function - je .error - cmp ah, 0x80 ;invalid command - je .error - ret -.error: - mov ax, -1 - ret - - -%endif diff --git a/SysBoot/stage2/paging.inc b/SysBoot/stage2/paging.inc deleted file mode 100644 index d9f4c03..0000000 --- a/SysBoot/stage2/paging.inc +++ /dev/null @@ -1,83 +0,0 @@ -;***** paging.inc **************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Basic paging for bootloader * -;* =========================== * -;* * -;************************************************************ cta os */ - -%ifndef __PAGING_INC_CTA007__ -%define __PAGING_INC_CTA007__ - -[bits 32] - -%define PAGE_DIR 0x9C000 ; page directory table -%define PAGE_TABLE_0 0x9D000 ; 0th page table. Address must be 4KB aligned -%define PAGE_TABLE_768 0x9E000 ; 768th page table. Address must be 4KB aligned -%define PAGE_TABLE_ENTRIES 1024 ; each page table has 1024 entries -%define PRIV 3 ; attributes (page is present;page is writable; supervisor mode) - - -;**************************************** -; Enable Paging -;**************************************** - -EnablePaging: - pusha ; save stack frame - - ;------------------------------------------ - ; idenitity map 1st page table (4MB) - ;------------------------------------------ - - mov eax, PAGE_TABLE_0 ; first page table - mov ebx, 0x0 | PRIV ; starting physical address of page - mov ecx, PAGE_TABLE_ENTRIES ; for every page in table... -.loop: - mov dword [eax], ebx ; write the entry - add eax, 4 ; go to next page entry in table (Each entry is 4 bytes) - add ebx, 4096 ; go to next page address (Each page is 4Kb) - loop .loop ; go to next entry - - ;------------------------------------------ - ; set up the entries in the directory table - ;------------------------------------------ - - mov eax, PAGE_TABLE_0 | PRIV ; 1st table is directory entry 0 - mov dword [PAGE_DIR], eax - - mov eax, PAGE_TABLE_768 | PRIV ; 768th entry in directory table - mov dword [PAGE_DIR+(768*4)], eax - - ;------------------------------------------ - ; install directory table - ;------------------------------------------ - - mov eax, PAGE_DIR - mov cr3, eax - - ;------------------------------------------ - ; enable paging - ;------------------------------------------ - - mov eax, cr0 - or eax, 0x80000000 - mov cr0, eax - - ;------------------------------------------ - ; map the 768th table to physical addr 1MB - ; the 768th table starts the 3gb virtual address - ;------------------------------------------ - - mov eax, PAGE_TABLE_768 ; first page table - mov ebx, 0x100000 | PRIV ; starting physical address of page - mov ecx, PAGE_TABLE_ENTRIES ; for every page in table... -.loop2: - mov dword [eax], ebx ; write the entry - add eax, 4 ; go to next page entry in table (Each entry is 4 bytes) - add ebx, 4096 ; go to next page address (Each page is 4Kb) - loop .loop2 ; go to next entry - - popa - ret - -%endif diff --git a/SysBoot/stage2/stage2.asm b/SysBoot/stage2/stage2.asm deleted file mode 100644 index 97055d0..0000000 --- a/SysBoot/stage2/stage2.asm +++ /dev/null @@ -1,264 +0,0 @@ -;***** stage2.asm **************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Stage 2 Bootloader * -;* ================== * -;* * -;************************************************************ cta os */ -bits 16 - -org 0x500 - -jmp main ; go to start - -;******************************************************* -; Preprocessor directives -;******************************************************* - -%include "stdio.inc" ; basic i/o routines -%include "gdt.inc" ; Gdt routines -%include "a20.inc" ; A20 enabling -%include "floppy16.inc" -%include "fat12.inc" ; FAT12 driver. Kinda :) -%include "common.inc" -;%include "bootinfo.inc" -%include "memory.inc" -%include "getdata.inc" - -;******************************************************* -; Data Section -;******************************************************* - -msgFailure db 0x0D, 0x0A, "FATAL ERROR: Kernel file KERNEL.CTA missing or corrupt. Press Any Key to Reboot.", 0x0D, 0x0A, 0x0A, 0x00 - -boot_info: - ; Memory - multiboot_info_memoryLo dd 0 - multiboot_info_memoryHi dd 0 - ; Boot device - multiboot_info_bootDevice dd 0 - ; Pointer to a char[] string. (not implemented) - multiboot_info_cmdLine dd 0 - ; Other modules loaded by bootloader. (not implemented - multiboot_info_mods_count dd 0 - multiboot_info_mods_addr dd 0 - ; Pointer to memory map - multiboot_info_mmap_length dd 0 - multiboot_info_mmap_addr dd 0 - ; TODO: - multiboot_info_drives_length dd 0 - multiboot_info_drives_addr dd 0 - ; BIOS ROM config table. TODO: - multiboot_info_config_table dd 0 - ; CTA bootloader name - multiboot_info_bootloader_name db "CTA", 0 - ; TODO: - multiboot_info_apm_table dd 0 - ; Returns VGA current video mode info - multiboot_info_video_mode db 0 - multiboot_info_video_columns db 0 - multiboot_info_video_page db 0 - ; Returns VESA information - multiboot_info_vbe_control_info dd 0 - multiboot_info_vbe_mode_info dd 0 - multiboot_info_vbe_mode dw 0 - multiboot_info_vbe_interface_seg dw 0 - multiboot_info_vbe_interface_off dw 0 - multiboot_info_vbe_interface_len dw 0 - - -vbeControllerInfo: - vbeControllerInfo_signature dd 0 ; "VESA", taken as 4 bytes - vbeControllerInfo_version dw 0 ; 0x0300 for VBE 3.0 - vbeControllerInfo_oemString dd 0 ; isa vbeFarPtr, taken as 2 shorts - vbeControllerInfo_capabilities dd 0 ; taken as 4 bytes - vbeControllerInfo_videomodes dd 0 ; isa vbeFarPtr, taken as 2 shorts - vbeControllerInfo_totalMemory dw 0 ; as # of 64k blocks - - -TemporaryStorage dd 0 ; temporary storage - -main: - - ;-------------------------------; - ; Setup segments and stack ; - ;-------------------------------; - - cli ; clear interrupts - xor ax, ax ; null segments - mov ds, ax - mov es, ax - mov ax, 0x0000 ; stack begins at 0x9000-0xffff - mov ss, ax - mov sp, 0xFFFF - sti ; enable interrupts - - call _EnableA20 - call InstallGDT - sti - - - ;-------------------------------; - ; Fill in the boot structure ; - ;-------------------------------; -; Memory Size - xor eax, eax - xor ebx, ebx - call BiosGetMemorySize64MB - - push eax - mov eax, 64 - mul ebx - mov ecx, eax - pop eax - add eax, ecx - add eax, 1024 ; the routine doesnt add the KB between 0-1MB; add it - - mov dword [multiboot_info_memoryHi], 0 - mov dword [multiboot_info_memoryLo], eax - -;Memory map - mov eax, 0x0 - mov ds, ax - mov di, 0x1000 - call BiosGetMemoryMap - - mov dword [multiboot_info_mmap_addr], 0x1000 ; address - xor eax, eax - mov ax, bp - mov dword [multiboot_info_mmap_length], eax ; length - - call gatherinfo - - call LoadRoot - mov ebx, 0 - mov ebp, IMAGE_RMODE_BASE - mov esi, ImageName - call LoadFile ; load our file - mov dword [ImageSize], ecx - cmp ax, 0 - je EnterStage3 - mov si, msgFailure - call Puts16 - mov ah, 0 - int 0x16 ; await keypress - int 0x19 ; warm boot computer - - ;-------------------------------; - ; Go into pmode ; - ;-------------------------------; - -EnterStage3: - - cli ; clear interrupts - mov eax, cr0 ; set bit 0 in cr0--enter pmode - or eax, 1 - mov cr0, eax - - jmp CODE_DESC:Stage3 ; far jump to fix CS. Remember that the code selector is 0x8! - - ; Note: Do NOT re-enable interrupts! Doing so will triple fault! - ; We will fix this in Stage 3. - -;****************************************************** -; ENTRY POINT FOR STAGE 3 -;****************************************************** - -bits 32 - -%include "paging.inc" - -BadImage db "FATAL ERROR: Kernel file KERNEL.CTA missing or corrupt. Press Any Key to Reboot.", 0 - -Stage3: - - ;-------------------------------; - ; Set registers ; - ;-------------------------------; - - mov ax, DATA_DESC ; set data segments to data selector (0x10) - mov ds, ax - mov ss, ax - mov es, ax - mov esp, 90000h ; stack begins from 90000h - - call EnablePaging - -CopyImage: - mov eax, dword [ImageSize] - movzx ebx, word [bpbBytesPerSector] - mul ebx - mov ebx, 4 - div ebx - cld - mov esi, IMAGE_RMODE_BASE - mov edi, IMAGE_PMODE_BASE - mov ecx, eax - rep movsd ; copy image to its protected mode address - - mov eax, 0xC0DEcC7A ; cta bootloader specific - mov ebx, 0 - -;edx=8 - - push dword boot_info - push dword [ImageSize] - - jmp CODE_DESC:IMAGE_PMODE_BASE ; Execute Kernel - add esp, 4 - - cli - hlt - - -vbeModeInfo: - vbeModeInfo_attributes dw 0 - vbeModeInfo_winA db 0 - vbeModeInfo_winB db 0 - vbeModeInfo_granularity dw 0 - vbeModeInfo_winsize dw 0 - vbeModeInfo_segmentA dw 0 - vbeModeInfo_segmentB dw 0 - vbeModeInfo_realFctPtr dd 0 - vbeModeInfo_pitc dw 0 ; // bytes per scanline - vbeModeInfo_Xres dw 0 - vbeModeInfo_Yres dw 0 - vbeModeInfo_Wchar db 0 - vbeModeInfo_Ychar db 0 - vbeModeInfo_planes db 0 - vbeModeInfo_bpp db 0 - vbeModeInfo_banks db 0 - vbeModeInfo_memory_model db 0 - vbeModeInfo_bank_size db 0 - vbeModeInfo_image_pages db 0 - vbeModeInfo_reserved0 db 0 - - ; VBE v1.2+ - vbeModeInfo_red_mask db 0 - vbeModeInfo_red_position db 0 - vbeModeInfo_green_mask db 0 - vbeModeInfo_green_position db 0 - vbeModeInfo_blue_mask db 0 - vbeModeInfo_blue_position db 0 - vbeModeInfo_rsv_mask db 0 - vbeModeInfo_rsv_position db 0 - vbeModeInfo_directcolor_attrib db 0 - - ; VBE v2.0+ - vbeModeInfo_physbase dd 0 - vbeModeInfo_start_offscreen_mem dd 0 - vbeModeInfo_size_offscreen_mem dw 0 - - ; VBE v3.0+ - vbeModeInfo_bytes_per_scanline dw 0 - vbeModeInfo_number_images_banked db 0 - vbeModeInfo_number_images_linear db 0 - vbeModeInfo_linear_red_mask db 0 - vbeModeInfo_linear_red_pos db 0 - vbeModeInfo_linear_green_mask db 0 - vbeModeInfo_linear_green_pos db 0 - vbeModeInfo_linear_blue_mask db 0 - vbeModeInfo_linear_blue_pos db 0 - vbeModeInfo_linear_res_mask db 0 - vbeModeInfo_linear_res_pos db 0 - vbeModeInfo_max_pixel_clock dd 0 diff --git a/SysBoot/stage2/stdio.inc b/SysBoot/stage2/stdio.inc deleted file mode 100644 index b86699f..0000000 --- a/SysBoot/stage2/stdio.inc +++ /dev/null @@ -1,296 +0,0 @@ -;***** stdio.inc ***************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Standard Input/Output routines * -;* ============================== * -;* * -;************************************************************ cta os */ - - -%ifndef __STDIO_INC_CTA008__ -%define __STDIO_INC_CTA008__ - - -;========================================================== -; -; 16 Bit Real Mode Routines -;========================================================== - - -;************************************************; -; Puts16 () -; -Prints a null terminated string -; DS=>SI: 0 terminated string -;************************************************; -tmpStr db " ", 0x0D, 0x0A, 0x00 - -bits 16 - -Puts16: - pusha ; save registers -.Loop1: - lodsb ; load next byte from string from SI to AL - or al, al ; Does AL=0? - jz Puts16Done ; Yep, null terminator found-bail out - mov ah, 0eh ; Nope-Print the character - int 10h ; invoke BIOS - jmp .Loop1 ; Repeat until null terminator found -Puts16Done: - popa ; restore registers - ret ; we are done, so return - - -PutINT: - pusha ; save registers - - mov cx, 0 - .init: - mov bx, cx - add bx, tmpStr - mov [bx], byte ' ' - inc cx - - cmp cx, 31 - jne .init - - - mov cx, 31 ; initialize counter - - .loop: - mov dx, 0 - mov bx, 0x0A - div bx ; ax = ax/10, dx = ax%10 - mov bx, cx - add bx, tmpStr - add dl, '0' - mov [bx], dl - - sub cx, 1 - - cmp ax, 0 ; when done, ax = 0; - je .done - - jmp .loop - - .done: - mov si, tmpStr - call Puts16 - popa - ret - -;========================================================== -; -; 32 Bit Protected Mode Routines -;========================================================== - - ;bits 32 - -;%define VIDMEM 0xB8000 ; video memory -;%define COLS 80 ; width and height of screen -;%define LINES 25 -;%define CHAR_ATTRIB 14 ; character attribute (White text on black background) - -;_CurX db 0 ; current x/y location -;_CurY db 0 - -;**************************************************; -; Putch32 () -; - Prints a character to screen -; BL => Character to print -;**************************************************; - -;Putch32: -; -; pusha -; mov edi, VIDMEM -; -; xor eax, eax ; clear eax -; -; ; y * screen width -; -; mov ecx, COLS*2 ; Mode 7 has 2 bytes per char, so its COLS*2 bytes per line -; mov al, byte [_CurY] ; get y pos -; mul ecx ; multiply y*COLS -; push eax ; save eax--the multiplication - - ; now add _CurX * 2 - -; mov al, byte [_CurX] ; multiply _CurX by 2 because it is 2 bytes per char -; mov cl, 2 -; mul cl -; pop ecx ; pop y*COLS result -; add eax, ecx - - ; add the position to draw to the base of vid memory - -; xor ecx, ecx -; add edi, eax ; add it to the base address -; - ; watch for new line - -; cmp bl, 0x0A ; is it a newline character? -; je .Row ; yep--go to next row -; - ; print the character - -; mov dl, bl ; Get character -; mov dh, CHAR_ATTRIB ; the character attribute -; mov word [edi], dx ; write to video display -; -; ; go to next location - -; inc byte [_CurX] ; go to next character -; jmp .done ; nope, bail out - -;.Row: -; mov byte [_CurX], 0 ; go back to col 0 -; inc byte [_CurY] ; go to next row - -;.done: -; popa -; ret - -;**************************************************; -; Puts32 () -; - Prints a null terminated string -; parm\ EBX = address of string to print -;**************************************************; - -;Puts32: - -; pusha -; push ebx ; copy the string address -; pop edi - -;.loop: - - ;-------------------------------; - ; Get character ; - ;-------------------------------; - -; mov bl, byte [edi] ; get next character -; cmp bl, 0 ; is it 0 (Null terminator)? -; je .done ; yep-bail out - - ;-------------------------------; - ; Print the character ; - ;-------------------------------; - -; call Putch32 ; Nope-print it out - - ;-------------------------------; - ; Go to next character ; - ;-------------------------------; - -; inc edi ; go to next character -; jmp .loop - -;.done: - - ;-------------------------------; - ; Update hardware cursor ; - ;-------------------------------; - -; mov bh, byte [_CurY] ; get current position -; mov bl, byte [_CurX] -; call MovCur ; update cursor - -; popa ; restore registers, and return -; ret - -;**************************************************; -; MoveCur () -; - Update hardware cursor -; parm/ bh = Y pos -; parm/ bl = x pos -;**************************************************; - - - -;bits 32 - -;MovCur: - -; pusha -; - ;-------------------------------; - ; Get current position ; - ;-------------------------------; - - ; location = _CurX + _CurY * COLS - -; xor eax, eax -; mov ecx, COLS -; mov al, bh ; get y pos -; mul ecx ; multiply y*COLS -; add al, bl ; Now add x -; mov ebx, eax -; - ;--------------------------------------; - ; Set low byte index to VGA register ; - ;--------------------------------------; - -; mov al, 0x0f -; mov dx, 0x03D4 -; out dx, al -; -; mov al, bl -; mov dx, 0x03D5 -; out dx, al ; low byte - - ;---------------------------------------; - ; Set high byte index to VGA register ; - ;---------------------------------------; - -; xor eax, eax - -; mov al, 0x0e -; mov dx, 0x03D4 -; out dx, al - -; mov al, bh -; mov dx, 0x03D5 -; out dx, al ; high byte - -; popa -; ret - -;**************************************************; -; ClrScr32 () -; - Clears screen -;**************************************************; -; -;bits 32 -; -;ClrScr32: -; -; pusha -; cld -; mov edi, VIDMEM -; mov cx, 2000 -; mov ah, CHAR_ATTRIB -; mov al, ' ' -; rep stosw -; mov byte [_CurX], 0 -; mov byte [_CurY], 0 -; popa -; ret - -;**************************************************; -; GotoXY () -; - Set current X/Y location -; parm\ AL=X position -; parm\ AH=Y position -;**************************************************; - -;bits 32 - -;GotoXY: -; pusha -; mov [_CurX], al -; mov [_CurY], ah -; popa -; ret - - -%endif ;__STDIO_INC_67343546FDCC56AAB872_INCLUDED__ diff --git a/SysCore/compile.bat b/SysCore/compile.bat deleted file mode 100644 index 8963f0a..0000000 --- a/SysCore/compile.bat +++ /dev/null @@ -1,20 +0,0 @@ -@echo off -rem The name of the loader assembly file (without extension, must be .asm): -set loader_name=loader - -rem NASM and DJGPP executable paths: -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin - -rem Compile loader -@echo on -%nasm_path%\nasm.exe -f aout -o ./objects/%loader_name%.o %loader_name%.asm -@echo off -@echo. -rem Compile main Kernel -@echo on -%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I./include -c -o ./objects/main.o main.c -@echo off -rem OTHER GCC/NASM SOURCES GO HERE - -@pause diff --git a/SysCore/debug/BIOS-bochs-latest b/SysCore/debug/BIOS-bochs-latest deleted file mode 100644 index 5e94170b38809d3ee4e020410e582db5e83a4b0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 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 S{{hE|TU*4bz)7^O2mcpn#^cif diff --git a/SysCore/debug/OSDev.log b/SysCore/debug/OSDev.log deleted file mode 100644 index da16f8e..0000000 --- a/SysCore/debug/OSDev.log +++ /dev/null @@ -1,195 +0,0 @@ -00000000000i[ ] Bochs x86 Emulator 2.4.5 -00000000000i[ ] Build from CVS snapshot, on April 25, 2010 -00000000000i[ ] System configuration -00000000000i[ ] processors: 1 (cores=1, HT threads=1) -00000000000i[ ] A20 line support: yes -00000000000i[ ] CPU configuration -00000000000i[ ] level: 6 -00000000000i[ ] SMP support: no -00000000000i[ ] APIC support: yes -00000000000i[ ] FPU support: yes -00000000000i[ ] MMX support: yes -00000000000i[ ] 3dnow! support: no -00000000000i[ ] SEP support: yes -00000000000i[ ] SSE support: sse2 -00000000000i[ ] XSAVE support: no -00000000000i[ ] AES support: no -00000000000i[ ] MOVBE support: no -00000000000i[ ] x86-64 support: yes -00000000000i[ ] 1G paging support: no -00000000000i[ ] MWAIT support: no -00000000000i[ ] VMX support: no -00000000000i[ ] Optimization configuration -00000000000i[ ] RepeatSpeedups support: yes -00000000000i[ ] Trace cache support: yes -00000000000i[ ] Fast function calls: yes -00000000000i[ ] Devices configuration -00000000000i[ ] ACPI support: yes -00000000000i[ ] NE2000 support: yes -00000000000i[ ] PCI support: yes, enabled=yes -00000000000i[ ] SB16 support: yes -00000000000i[ ] USB support: yes -00000000000i[ ] VGA extension support: vbe cirrus -00000000000i[MEM0 ] allocated memory at 02720020. after alignment, vector=02721000 -00000000000i[MEM0 ] 32.00MB -00000000000i[MEM0 ] mem block size = 0x00100000, blocks=32 -00000000000i[MEM0 ] rom at 0xe0000/131072 ('BIOS-bochs-latest') -00000000000i[MEM0 ] rom at 0xc0000/40448 ('VGABIOS-lgpl-latest') -00000000000i[CMOS ] Using local time for initial clock -00000000000i[CMOS ] Setting initial clock to: Sun Nov 07 17:10:07 2010 (time0=1289142607) -00000000000i[DMA ] channel 4 used by cascade -00000000000i[DMA ] channel 2 used by Floppy Drive -00000000000i[FDD ] fd0: 'ctaos.img' ro=0, h=2,t=80,spt=18 -00000000000i[PCI ] 440FX Host bridge present at device 0, function 0 -00000000000i[PCI ] PIIX3 PCI-to-ISA bridge present at device 1, function 0 -00000000000i[MEM0 ] Register memory access handlers: 0x000a0000 - 0x000bffff -00000000000i[WGUI ] Desktop Window dimensions: 1366 x 768 -00000000000i[WGUI ] Number of Mouse Buttons = 5 -00000000000i[WGUI ] IME disabled -00000000000i[MEM0 ] Register memory access handlers: 0xe0000000 - 0xe0ffffff -00000000000i[CLVGA] VBE Bochs Display Extension Enabled -00000000000i[CLVGA] interval=50000 -00000000000i[ ] init_dev of 'unmapped' plugin device by virtual method -00000000000i[ ] init_dev of 'biosdev' plugin device by virtual method -00000000000i[ ] init_dev of 'speaker' plugin device by virtual method -00000000000i[ ] init_dev of 'extfpuirq' plugin device by virtual method -00000000000i[ ] init_dev of 'gameport' plugin device by virtual method -00000000000i[ ] init_dev of 'pci_ide' plugin device by virtual method -00000000000i[PCI ] PIIX3 PCI IDE controller present at device 1, function 1 -00000000000i[ ] init_dev of 'acpi' plugin device by virtual method -00000000000i[PCI ] ACPI Controller present at device 1, function 3 -00000000000i[ ] init_dev of 'ioapic' plugin device by virtual method -00000000000i[IOAP ] initializing I/O APIC -00000000000i[MEM0 ] Register memory access handlers: 0xfec00000 - 0xfec00fff -00000000000i[ ] init_dev of 'keyboard' plugin device by virtual method -00000000000i[KBD ] will paste characters every 1000 keyboard ticks -00000000000i[ ] init_dev of 'harddrv' plugin device by virtual method -00000000000i[HD ] Using boot sequence floppy, none, none -00000000000i[HD ] Floppy boot signature check is enabled -00000000000i[ ] init_dev of 'serial' plugin device by virtual method -00000000000i[SER ] com1 at 0x03f8 irq 4 -00000000000i[ ] init_dev of 'parallel' plugin device by virtual method -00000000000i[PAR ] parallel port 1 at 0x0378 irq 7 -00000000000i[ ] register state of 'unmapped' plugin device by virtual method -00000000000i[ ] register state of 'biosdev' plugin device by virtual method -00000000000i[ ] register state of 'speaker' plugin device by virtual method -00000000000i[ ] register state of 'extfpuirq' plugin device by virtual method -00000000000i[ ] register state of 'gameport' plugin device by virtual method -00000000000i[ ] register state of 'pci_ide' plugin device by virtual method -00000000000i[ ] register state of 'acpi' plugin device by virtual method -00000000000i[ ] register state of 'ioapic' plugin device by virtual method -00000000000i[ ] register state of 'keyboard' plugin device by virtual method -00000000000i[ ] register state of 'harddrv' plugin device by virtual method -00000000000i[ ] register state of 'serial' plugin device by virtual method -00000000000i[ ] register state of 'parallel' plugin device by virtual method -00000000000i[SYS ] bx_pc_system_c::Reset(HARDWARE) called -00000000000i[CPU0 ] cpu hardware reset -00000000000i[APIC0] allocate APIC id=0 (MMIO enabled) to 0xfee00000 -00000000000i[CPU0 ] CPUID[0x00000000]: 00000003 756e6547 6c65746e 49656e69 -00000000000i[CPU0 ] CPUID[0x00000001]: 00000f20 00000800 00002000 078bfbff -00000000000i[CPU0 ] CPUID[0x00000002]: 00410601 00000000 00000000 00000000 -00000000000i[CPU0 ] CPUID[0x00000003]: 00000000 00000000 00000000 00000000 -00000000000i[CPU0 ] CPUID[0x00000004]: 00000000 00000000 00000000 00000000 -00000000000i[CPU0 ] CPUID[0x80000000]: 80000008 00000000 00000000 00000000 -00000000000i[CPU0 ] CPUID[0x80000001]: 00000000 00000000 00000101 2a100800 -00000000000i[CPU0 ] CPUID[0x80000002]: 20202020 20202020 20202020 6e492020 -00000000000i[CPU0 ] CPUID[0x80000003]: 286c6574 50202952 69746e65 52286d75 -00000000000i[CPU0 ] CPUID[0x80000004]: 20342029 20555043 20202020 00202020 -00000000000i[CPU0 ] CPUID[0x80000006]: 00000000 42004200 02008140 00000000 -00000000000i[CPU0 ] CPUID[0x80000007]: 00000000 00000000 00000000 00000000 -00000000000i[CPU0 ] CPUID[0x80000008]: 00003020 00000000 00000000 00000000 -00000000000i[ ] reset of 'unmapped' plugin device by virtual method -00000000000i[ ] reset of 'biosdev' plugin device by virtual method -00000000000i[ ] reset of 'speaker' plugin device by virtual method -00000000000i[ ] reset of 'extfpuirq' plugin device by virtual method -00000000000i[ ] reset of 'gameport' plugin device by virtual method -00000000000i[ ] reset of 'pci_ide' plugin device by virtual method -00000000000i[ ] reset of 'acpi' plugin device by virtual method -00000000000i[ ] reset of 'ioapic' plugin device by virtual method -00000000000i[ ] reset of 'keyboard' plugin device by virtual method -00000000000i[ ] reset of 'harddrv' plugin device by virtual method -00000000000i[ ] reset of 'serial' plugin device by virtual method -00000000000i[ ] reset of 'parallel' plugin device by virtual method -00000003305i[BIOS ] $Revision: 1.247 $ $Date: 2010/04/04 19:33:50 $ -00000200000i[WGUI ] dimension update x=720 y=400 fontheight=16 fontwidth=9 bpp=8 -00000318042i[KBD ] reset-disable command received -00000444800i[VBIOS] VGABios $Id: vgabios.c,v 1.69 2009/04/07 18:18:20 vruppert Exp $ -00000444871i[CLVGA] VBE known Display Interface b0c0 -00000444903i[CLVGA] VBE known Display Interface b0c5 -00000447828i[VBIOS] VBE Bios $Id: vbe.c,v 1.62 2009/01/25 15:46:25 vruppert Exp $ -00000760517i[BIOS ] Starting rombios32 -00000761014i[BIOS ] Shutdown flag 0 -00000761695i[BIOS ] ram_size=0x02000000 -00000762173i[BIOS ] ram_end=32MB -00000802745i[BIOS ] Found 1 cpu(s) -00000822014i[BIOS ] bios_table_addr: 0x000fbc18 end=0x000fcc00 -00000822117i[PCI ] 440FX PMC write to PAM register 59 (TLB Flush) -00001149814i[PCI ] 440FX PMC write to PAM register 59 (TLB Flush) -00001477742i[P2I ] PCI IRQ routing: PIRQA# set to 0x0b -00001477763i[P2I ] PCI IRQ routing: PIRQB# set to 0x09 -00001477784i[P2I ] PCI IRQ routing: PIRQC# set to 0x0b -00001477805i[P2I ] PCI IRQ routing: PIRQD# set to 0x09 -00001477815i[P2I ] write: ELCR2 = 0x0a -00001478700i[BIOS ] PIIX3/PIIX4 init: elcr=00 0a -00001486658i[BIOS ] PCI: bus=0 devfn=0x00: vendor_id=0x8086 device_id=0x1237 class=0x0600 -00001489220i[BIOS ] PCI: bus=0 devfn=0x08: vendor_id=0x8086 device_id=0x7000 class=0x0601 -00001491621i[BIOS ] PCI: bus=0 devfn=0x09: vendor_id=0x8086 device_id=0x7010 class=0x0101 -00001491851i[PIDE ] new BM-DMA address: 0xc000 -00001492555i[BIOS ] region 4: 0x0000c000 -00001494865i[BIOS ] PCI: bus=0 devfn=0x0b: vendor_id=0x8086 device_id=0x7113 class=0x0680 -00001495103i[ACPI ] new irq line = 11 -00001495117i[ACPI ] new irq line = 9 -00001495147i[ACPI ] new PM base address: 0xb000 -00001495161i[ACPI ] new SM base address: 0xb100 -00001495189i[PCI ] setting SMRAM control register to 0x4a -00001659283i[CPU0 ] Enter to System Management Mode -00001659293i[CPU0 ] RSM: Resuming from System Management Mode -00001823313i[PCI ] setting SMRAM control register to 0x0a -00001832484i[BIOS ] MP table addr=0x000fbcf0 MPC table addr=0x000fbc20 size=0xd0 -00001834543i[BIOS ] SMBIOS table addr=0x000fbd00 -00001836931i[BIOS ] ACPI tables: RSDP addr=0x000fbe20 ACPI DATA addr=0x01ff0000 size=0x988 -00001840169i[BIOS ] Firmware waking vector 0x1ff00cc -00001851282i[PCI ] 440FX PMC write to PAM register 59 (TLB Flush) -00001852126i[BIOS ] bios_table_cur_addr: 0x000fbe44 -00014041543i[BIOS ] Booting from 0000:7c00 -00026325033i[KBD ] setting typematic info -00026325046i[KBD ] setting delay to 500 mS (unused) -00026325046i[KBD ] setting repeat rate to 10.9 cps (unused) -00026325079i[KBD ] Switched to scancode set 2 -00026325154i[KBD ] keyboard: scan convert turned off -00026326238i[FDD ] controller reset in software -00026326585i[FDD ] io_write: config control register: 0x00 -00026326642e[FDD ] non DMA mode not fully implemented yet -00055764602e[FDD ] non DMA mode not fully implemented yet -00055764757e[FDD ] non DMA mode not fully implemented yet -00067767563p[FDD ] >>PANIC<< write 0x03f5: receiving new command 0x03, old one (0xc6) pending -00067767563i[CPU0 ] CPU is in protected mode (active) -00067767563i[CPU0 ] CS.d_b = 32 bit -00067767563i[CPU0 ] SS.d_b = 32 bit -00067767563i[CPU0 ] EFER = 0x00000000 -00067767563i[CPU0 ] | RAX=0000000000000003 RBX=0000000000000000 -00067767563i[CPU0 ] | RCX=0000000000000012 RDX=00000000000003f5 -00067767563i[CPU0 ] | RSP=000000000008fd68 RBP=00000000c000a21c -00067767563i[CPU0 ] | RSI=0000000000000000 RDI=0000000000000001 -00067767563i[CPU0 ] | R8=0000000000000000 R9=0000000000000000 -00067767563i[CPU0 ] | R10=0000000000000000 R11=0000000000000000 -00067767563i[CPU0 ] | R12=0000000000000000 R13=0000000000000000 -00067767563i[CPU0 ] | R14=0000000000000000 R15=0000000000000000 -00067767563i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df IF tf SF zf af pf cf -00067767563i[CPU0 ] | SEG selector base limit G D -00067767563i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D -00067767563i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1 -00067767563i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 -00067767563i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 -00067767563i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1 -00067767563i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 -00067767563i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 -00067767563i[CPU0 ] | MSR_FS_BASE:0000000000000000 -00067767563i[CPU0 ] | MSR_GS_BASE:0000000000000000 -00067767563i[CPU0 ] | RIP=00000000c00040be (00000000c00040bd) -00067767563i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000000000 -00067767563i[CPU0 ] | CR3=0x00001000 CR4=0x00000000 -00067767563i[CPU0 ] 0x00000000c00040bd>> out dx, al : EE -00067767563i[CMOS ] Last time is 1289142623 (Sun Nov 07 17:10:23 2010) -00067767563i[ ] restoring default signal behavior -00067767563i[CTRL ] quit_sim called with exit code 1 diff --git a/SysCore/debug/VGABIOS-lgpl-latest b/SysCore/debug/VGABIOS-lgpl-latest deleted file mode 100644 index a6c56a569ef143742fc019b059f1602564f9463b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40448 zcmd_Te_)i=l{bFpM+Fh<4X^yKDQd>#ObCZr!&pwyut(bq9h`UsDBbEiKfIKPt~S7!WapFwA^E=iK`| z^E{cvAKm@F?;ralndiCZo_p@O=bn4+IrrXYa`R7bNM*!m*ELJNCL#@MTC3;HUb24G z-5Ue9EWKjMJ?l3HMDXHys{+C5z!e)B19OAH1tsIe^eZo<$Lc`S-D?8ZEsb1fV6R@& zvZi7EhBb{F17BZr$A1Ct*YCcEiOs%c$yEWSh;-wchBbF=T(dgRyl(ZHMkcfL`kR?l z$v6}OC&&)8+_UkXroh6Iae<2icQ-X{SU7w3oy6S58`n2Cu38ga-+0%Wi`T7bG9zr- zwCUn?>(|}2uK8kQ&u+Qvjyur|rmEd~srHLYwdCJSos)d%Kw_rt$y$*R$tRbHO6};S z35WQ#Ptz{dUi+I@|9dRsZFXtpccgwPVwtn?IKLtFG#i?o=Y2nYVW=1n zcYQw{2)Xg_;P=y$LnV0V`hL39HMPD=Bp*7ct-kb*%Hn@`9sTVTiJaZ0?sj!|sJqi< zwI(NO#kjhv45=;yJg$|`$G?x ziSIrCL{3aBpKN!!ihbiJOe`y(G}$K5VRQw(-rT>pd<6CTY&PLq^%plp?*F>A{^_WH zPfkp>UN!**;%l5Y7xDXq4-DC(RQ~4s!2b>7N+}ooPxpTB`6qM2Eia#6UZuk8=Hk8* z?|=IKXF>csKB)f#W4!1;Lw}NzoYJ57a>8bJ(6Gzvk5^S#ME&O$wKghm^nboQ_5bIT zSCsyr-6H-{5hMPeH2ANT%xu~A&FS7%yTCuR&F=@0v<~;Y{&M?2zdXyYthjo?!bPFQ zm)F>YNq(}f|Gb~mG5+0djQ_h>{~ouD|FTLR|HI_xF~)zX$$s25lKuD+<^N3k6Zwh{ z8Ug)zPwLOu%SEm1%?}^^x9Q@r6Z%tQ{jv1_7b!oi{g(1HeyRS_{P?><)=&1cHZMO{ zv3pF(SkJgp?-jcK)k1$)SLyuUyK2>zZ%t`DChBGR+jiVKSKPW$AHQExe`kEj3v>C1 zm*l1J^GlMSF(PpQneq%VLkLjB2X5u^5ji8k%jv4YPdN(n6K?!CGW`DmeQE=mQZAr& z)R>wXqI`y^LBnRus39<=kjX7&7^9SnawuxKsHvGzUOuC|W=2gpq(?nCudJz|-}yC_vui3ZsIg|4pd)9@npHDrR?WOwH4A6e)X?w3npyK|X3eRwW|*KO zX9!VIEGkMxMY*V`px^QeQCcC2E36qN=*StRr4{2#E6PhN{G}BY^y{xEEw3mYUt!HK zK}XIgE324PR^czJIJ>N(f_~4gDDzj8O{%bFn4lwP2;p-IAACxW@WC_m2@mE6pK!uT znKMk#ku%(GUy0l2ar;W$J|F#-`rIC$yToVBFhNJo7(3SI8S5K2*5@7T^U<%@H+GzF ztjA}~FhNJoU^_6vN3M^ZfnvM+u*aOe`Mw|B_p3+m+q^kV}5u-d5sy^XAQr2ecgH!&@R(9ci%T$$D@T!TM}{kg$`4t_Zei}ruE!pZB1fiZ@e=yo3svD|X4)wN( z`uZf}`GfWK^+CVDpC8XcL_@hy6j{Mw1_b35qzsW?z(9t}1MFl>wDr99_P_^iBDf)l zDZumu zkE;g^8x-%hrQAP8i7dqpN1ZHq=T=uXHD{W;ixerOmJ**ouUz5C9r zyw@M&{MVwF3-mFH^$JK2SF4!n0h{3GgJ?r*L-Yf24C1*nniW0$+3Z_AJ)-A>fwy17 zy}F^Nr>CKs>#GMnRNs53wSv=BuC=#sLj|?-8A%t}xH429$Oi>Vzm@F=JrDscf`f%t zk?ncVKNt12qTc%YRzZ#Txa^{p6vW>OeFk#=$^}_A1ZefNp(Ty0lTn-4bQ`ta!o~Yzqc2rT(L0#0PF@KNRwvOZoJm+AR8?RX5X%`ZD#c^)xi@_1xQguecoQ z-rM^csNk36qu+@z(ttCcASmyYM!UQHAu=?w8Nh=zNG4%QsvA}xtN(!XrZqz&64D>) zdA;YQ(kcFs-+y2O+RN>!R{XI5sNM=ie~>#2gSYoc=1{K)H8flJ1cz`|z~YH)75{JHt3^5@{DgZ=ae zp&8d8KMnfnJ`dLb{-~lX-*xzai{Sc&T$LVhk@+Jy-Tj~fCE-ib_4_Ls?)Q^fq$|hu z0ggMT@j)O7uVgsUn@=C}<_BvCNz?>o`lOI_a^j@QCpf4weBQj145!)%k5F`cqED1^ zTyEYxqDx#<5>Uu`>8VEL6CQD;^Q*Uu_|B<|@agfGy1eQl80BHy9eVi?##L+YVDBJ$ zFw+aemxTB*6Ttpwdh3H^k1^{UIB;MC>^rWu`Xq{xNJNGVXKOISY7Ld3QPt4UkMZY+ z-Dst92M#Iqb>4LWK55@zO6OS-gu+ABQPgtgmD4jBe>X8>1U?j5f z7|1l1Sr1VQE-5^Ez@Hap=tx7TqLo`A#0C%~ZiEQo;)fAG$PZvgfOE+kV0S>`l2gFm z04H_VfD`Zr4j(>DBb_duWHI`TilnoE9Fn_o8B`A_$3f*O_kr`KmYzMA}&?UVG-4UR!C8s0G zdGI{g^_W7bww`+K*=kQu8|Tsogu%}S74)-C6CEb=xaag5kgMDi&dfV0GO1h@nV1g$ zW4e4KYhB&ermCZg+uEw(oQ-fn(6DPt7tk7VdGw2X8vX;o?{DkblWcQs?`czv6e4E|dx#1y z#%v?Fkw;IPT`rH*LCK-fB!18v#GH_`!Bp@8ZNM*I?1Z3>dQO3+2SpVbq~L-bN=jbj zw2Vp_GlL$4I|6@vZiQ^5oso#ce>zW1J#+_Pq6W zn}^rjIS(GDtO0rT7+|VbHg8^G;*5&XC8Z>v8`Kb>)LU<5+ZwnA_6TXPatgwO)zB>w zd56LJJxX6f)aSTl+hHd*R9BQL%MfBocs!Ih%x7e}@*{`AA;-B1NDhS@Ipj^k3q~L6 z*=;?^q-p~^OZfIWCJ@?svU(o87IHI{%#a7?5MB;jLeM0aQ^^cUR83-%ZE(3nsS6j{ zj6%RvUN}|HXa*(#N3w6d#U3f;k{gPPAMwH6WN=M+Z3Z`z7d5WfUCr~^*0Z5Pwa>>> zT5w*4P7_TqwU%n5cuij1fwKPqP(HnpM?;WYTe`Bnuu@XXOVOGQ_+wQf%fha%q{(o~ z=R$_p%PGV8@2FjrJ%>?X_~C_DFlh86sU%x^;7|M z3Q;ljG^pfLL?xf1iKv=dMa3{xnNx(B&+F;Y%?1#ua#DZtvQZ2+CmXGAt5-5Z3tQ&F zm03qL$=fD(8~!#f$(d=4ffqd`Inz_{c}!BGyu8d1k>QtntQ9>;{yr{g3sjaG#b{U* z8cNd@E?wo}tJ5XtdNq5%X&>C%`*v?Hk7>B>Jg<=ZE*qGaJoQ*!F4XvZ8z^Ps6FOn& zJf3wEMwRPMK0PZJi*!R?m?khG>XwLLG`Gk+PGS6UDw*u*JrJxvwB6&sTnL$pzV_JV zoXxsQbG0fsui-!gJN2B#bHf3C8eeDr(W3-;|Kld}4}?;94Vpl3{AEhH&ja$V7@%MR z7pJV4*1$rd>6m(uA)zwV011U8hbfOt)IF$bk~cGFe&ymzObQLmm+sz6=E=For4SUR zgc*SVC1tpP2gQpFPGmw4StJoXaFKa>_#*T4AVx2zsBoqXVDQM9GOWQP^J2}@LmZu^ zYLQGD;f}1MMnaj29{Na-(IQn&4})Ym6*S4(Et2pLlf053Tx`>&^CCfdv?T9(%p~us zkSf5pmO}>)Pz=RaTTiB^2eEK1Qm{c78@TXHmkg?;ozM2ba9|)QC6NIZjcC4Tdcc&E zlqnf($xh!)kv>HNoTV(C@-^7lz{l<9ys7ZUE+!VF&`8nUylk^Scth*s)H^~85tU(p^&km z5gd{@hlPj7umpXqFCQRIy*zvQRNWCA79+|90Mw|5iL^p3<3tV=G2hga7B*NSMQD&7 zEavGcdCKUK6hz8TsY*U%1jm-35kZ%}wypOgMp#yV#$8|QRv>HeNW6?1KB9z-AdT<@ zO*O}mKrn}q5T=YHO@XA~NV2|XyR2T1C6(I*f4g30s85Um@K&eR=Z6=@pz zdaSAABibZ_xFkPhZ1PTubiEOA8X>3RJkP#tNxr$v9$6y2ePn=)!77*h8ONv((WlYB zT%jodR1|82p>l@++1MoDOGcu+=xZSCL(+3ac^k9p#FsJGKBAJ*2~q+IE^) zc6UqLDD5iaqk4{6$xG4ume$i^EBfj$}MngU%JWtikaU2gP0$|Fe%VDLkk zPyiz>^~W0X8jg}4^{TL!44;g9m44}wuL^y6mDr%n4;(D&<}AOeBm-dVpjh~a?xDT; z{-h|;q94FFrzsjVr;S)RFAo{^$#7Ujoq75KX24t@(KDy9Cv4FV2+oowe5n#re|qu; zjT&!?j!_Y8s~#Wc17soAEt<0Vz@bf)pO2AckgWKn9#Z}0aEGcYu}TBHO-C~5vI@@0h%SaCSO?(uZ20fre|w}ee+Mv5jH)8 z^hnpB1!%<2M)Wx#gESRi!v(XXhvSbDaZ?!#v{uEs!&3u8r6rS;E<=3yr z-|R+F5jEEs_|_O4_)Hfc3d6uxa4WtMxf=2?N8|Y|M7=s|L{3|V27N}cM&(rApr`T; ze3pk1n-7o9jg<-mUoStreM+wStwv{+@vL#WzE#Ot3eOs=V?978#7OxqOugFS{bk6T zVkGmW=o=twD%$Eq%CXpfy(j_r-$ z-mtGQyz;_ek-sW!3GsQ0i`-|!rN%RixE|(PcWCwgL!_^V`s}}(gMDM~ma7{f-Ur+m zSc)ay)8%J9>c`$Lr>${6HhK>Xi~KR2erE8$YmZ}RcmJ-vj-Af_T`xLz+WWg&FI%Ra z4%gLn>n~DOU9);&K)sH1@v50EfjJk?TflEr%?@5VJ2*cur+OiN=LQ2Ujm;bI3RP3! zs@4sGs&OS^YNA#=bfC*8I*X^ho*Nes@#3y+VyCaYxa$G2vmUp0vGWveak2A8+}4Pl zW7>-=yF2V6sW*Q3y*q)|gbuuLuFxim7pjFePQ0*5XvN}%e-@febU%3Dp=A8zoL5fn z4<<9me|B>JH8&=Nqf6i&soN5^iCtqw{L^3ix^IsEsWUvGy)XEF>UYkL@Py#|5v{7I zt`3h?_ol0m7fgC;;^7JD#qv2w&vWE+fS#w#6phD1#ha!C-{0RC@4h(q^9tr!VhhR@QcdRU3wqvDlnUPU9Zp&U* zD(;+y%ZK4~^fl*O$5w z^uKJ$C%EKM$BvZ~^6Wn1r*{0ok!$gFggwlJY@wch;?A{9QY_nMZ`oU#^4KJT0=5I_Oq~=KU`ddG?^=P6F!0wx($vc55Y7w0p)S%Z z1z%L7HVEXB)Z>bR_F)j+`Zs#&kCfV~r}j~*Md%8%W2GC4Gb!H_PZO#1E$Oe%6yB|8 zqaMle_q*K{%lI6UvBkZh- zwTE+C_NKMT%eN()+%O>8A8sc5>8!f9Jq*j_go11HYwGIS!`Y5-Hk502#*cin8;`;F z6G}u=_9*bS$+I_;>-Bv5zGlfYGZJ5iL=J zPHqqPC)yR@#}e>SBCY`6lYpZg;iFaVtx4~;tDq*}=4l7je_!{2tz)T+Y)6kHqWzYT z$t=E%#LJW@z%5Rn+f`B$UpbVX(e;1$er{LCSW2JWb*+c)6Vg5?)E}TsZ{zP>{Cz;C zdm!}`)M!}E#ZoNW(X2(`fyQrih6mz%_V?NLIl@Db4zeSOSHMe%crh|-hviPS<_^!! zU5>)(3#eU0>lh{V#Czt%Ta-X8wcr-F#dz)K{;%dpa`uqDc^s51LR}uZ0BDInfYig6 z*VS>`($%?^fkYCZzabjKx(&2!-5pEMqt+14x?%N96fMa_89IzIZ`3)WM4g`4i^P0N z;Kk=i;zgt`iBVF~s5?u$T*>mPA0w_hU{`@9huK(9O}H*j=ca zwynwL^An;rk_Z%2w-0MnZj)2{mqj$mZbMmTXxzpsLI&c`T7o7{0Y^7V)eO-sk`pP| zODdv+CNqK?MLHDeB7$^%a@n%PPZVS<~Tsu2qAebQrtKmTN@tunPh2Tsld)6*2KTjh!VwfsLPeOQ>DH|HDe^A%);;)@3w?62G1&; zDSa%|5C8&*har6zyn;>$B1y4_ocV+AcV0hqGDS>vUO#v;<;h_>BauB)8~^>uls%k7 z$2h{r>*`>?jkagzgDSj%L@BlIgmx9x0!5URLF@#zpMYd72;)3TbO3|ePq`Bapj6|! z>yVGGWVMDd$Z9>PfQAfvo>}cVN}5Du=*UK51Xx_?uN4+~Vut8$R2cB#v)X#XF!T{# ziy?Hw9+eV)d-#)%@F(C^n>de*9x#vVKGKerS$OlAWh|wLR+D4aj$1ty8f@!~UitMr zYHN7Vuu%U*0PYpc--Dgk51dTx?;9q1h?mUb^{UgKK@m9b61fmHT?H0(-%a=0*h8bv z?7YEoGDZER+ss9hqoIUHs^?ZpqhpK?Bn4hizy!WGh1B~_N^}52SKu2Z0MsLfW}dtZ zOhV8~Hs_r|8AIGd99NNgVHA*Z(IdjaN2H=T*#e*_q72G$kB*c{6xkvPn)wf*LMNCG zpH5%d5vGZkNmBXKvb-aljU>e5Bfv8Z*M5a?qXg)+AcEV%aB1VeB#Iz)qTfdJjTU4K z;-(g$QfmtmMRr-ZMrZC!dJeY-OvuO*Wr#&gjMR3WMNLDbMDrzB!Qei#Fzji3$zbJU zijxdhK2wt2ZT2_)?GAdOmf)R;1!qia-_>4ru(ox>~ug@70`OMDAH#JL5J(F&Re7U97 z)}BF^$oA^pTF_o?2_jr~de-NZ(_5rXBy?-1ZZVjKVR56IrQwHkpndY$ut%Fw9QFv_ zeU9wWmN~;?Hp8fVoiL?QF)YtAg0b!Q!G4W52I_Q4)yE1=5lt~UDvMAvbsXbU%Iw1!LC>b?27Ne5PFE=fi&&g1)6qOfu`MTnD91QOVssFnQXT9Qa?tCp#m2}VusFI^}W~z*N z?;tRTY0kzisfWOc)SGlGkB$Ph`8*ahB3!@%YLYr)Vm5OUn4j6tZMoD(g-bq;_Am@P zjmu5aU~G`xcuzq$-dfO&SB=zh)QK52Wq)QT-j1bccd8C7Ww5AH!9w5P*B+)Rh&)WV z3#bu`cjQ^KjrkAj*^9q$&mJeS{{PXlPkrH@UH=7oHeHsUKr7poSz5JTm7&jXX4EVQ z?|<4%c>i1W9yeya_KSGdBZrJsea8%%_2Bai<-PFZ@WPMjUikB$NG}}Lpc8(u3UD&U z+*nQYhRu!h3C6uQROq}TiiDOZBX@>vK0E>Iqy~a=Qgej+DLx{99W0uO(MdXDkQ!rN_F1!0A$6yCe7aJCvq*KZh?T zl*R%qz!8yd>mXu6%FU*~tqgP`CgQ(;b5Q!PGPd`)CG9yxi`M_(jB7u+5DB(ZGQQ+R z)N{jUz|CZ0%gdHd;ywXfSK24nJh=3C34$7H)#|m|d;ex~kdUSuoG9=8k=(A=90_;s zDD3c2H0WqvDr#lVYC0jfW%q)O0i+b}h{=75m=V^!kydu~aV|z(UZBa27K! zS*&gO$N7o3PxS0UG* z(rWT>uH_6?(1%~uxjq+?mt61fW4;~3`3{VZ@fn;u8@F3I{|>lAc+5-UXe-V5A(Kjk zpdxkILKUFtFF&YguLE4d^Po;2T?_6j7z+}gw1N9x4vMeQEi-bzLVd9sgQ*Qx28Lz8 zj;{R;f=(J7Ph(FM`5cN2@34Q)t2wo)B_IDBGmPg~QJ#8A64xTr$as<|Ei|6A9;LPQ zbA87#noP#?jA1-aPXoPS#&d{ZY&>D0d5EYz8d~{S%gig|N$o=C4>z8u*=jsl?s73u z#;(V5EhV`Ye8NUrDj}o#E^jJ-f{s8Ix^N`N5dCi{*Rd4d#1LDuVQ_mI-UY>1>}HX_ z#r90<0zT3Dh<5!DIXicGfDnG`V6q zTT^X!WZ8{3?fQe`$gZSgr|54#Q04uJyUFf!_djimz2^h8{pJ2$yB$ZWj=B#Z)t}uR zJLPOXyfe_h;? z&a)e<6+a@vo!6J}dbAq^G+t(6rE^#D9_(j082hNS;oJgX}U4GN+h< z9}a*Yw${U9S_f(i!$wv)B0OUbz!RveGta66{Y3hSG3|5Eszw=5b1Q_*|l->*u3W zk%0RvWd|p?jPVVjvotZE55aTeD9G9Pvy_H)ENC2iqEJ4UR6d;>_b3W>F;z91f=#1V zCvOJ; zh70z=<#FU?U3ZF(;@jI_T82Z&9T&vjk9A!GfV;2jS|o3;><)=$d-@KX)3K+UF(txt z$G}QQUteIah^5EKE()~QH zK0@{XHrGA~8A(4b{w5fZuAp-I&TlVPd>q!xj^|pDp#yYB@TOfaJJ7scuQ--R+WY$3 zwSEvmGugr9tQ9w*nXfpwb@`8LnsrZdSj*6^=5bZ`CJz_82g&nHpB2&TEbCuh6>D}R z58Gphy-J|ujNY{CCE{Uu`(D&@WP4xaNc)RN+IQ<*aHito2(>N$VQ_KNt{x&mMd~z(mx-TeuC1SVJGG)+y-$Q z#BEX7<-NZ;$A<*hPO7UjPM>WgbQ+d;{Q&0)k0$KSqX}p6Q5@GlO1`nvE*I8Z&ZBu0 z2T<@wD7^?hY{@>mr=)%FPV%Oag>|?h-_hXJrHjtwP#&{c zQ6`7&6UyOa#5hxQ14y_M6C@8C@;uxC9;hz{i7xT?^?cqX%pX<(2dZl2QV1#;sG@zU zVzr1=%L|2aIWgW1v1>!w_VA}2;ZI@HBgQ(*^JP@Keh%*Mk%CCz^#QB%`V1Wri5REg zenhy2|2wGNN(U#Z&^9u*G=G4J(kiUBaT@DdDw4t(8z@n_j$b?=UWVjSF8SU#ZjS@2 zPZtq#mTRVWBjBy^+I5D5qlYJABBT>cQZW~WOB$ci&d^b$kgpK|0hQ3s$-*Vpk2Vcz zUC4F~;|*@+XuMrPOzojIT)2<7SCGy#MMsW0R}S9Sy<+k*98Lp!lCgma7RGQUw(&V_ zwPI`xmC`!SSlFuia%?RkHfUldL75rCaX`tC*TT@6LWX{&y@~E5NsURMly)j38G^~$ z>u5i;({U6=OWGZ6J21b5(3m^t2;BK}?xtC|dkJrdnEH{#^(*Z%gFBScZdcsVJJQ4z z_G!L@_XeP7&eWB*M4KRALHihljNJ_{+U!bfmN~yuIehZ!QzTreIktpHo=x6mE_Q%2 z6QwfeadWX3xY!UKPef1i4$4ym!iEW69$?BpV3gmPQQ9SnS4U}OlxNH+Yb44<9pz?5 z`D-)E5{Yt|jxv|h>GdX70up1Ij^SgBubD8iK4SKEgGN84(-+a;;CGY;Ebl1Y@U2t# z1lQiRwqx!8TDx!U@wH{&O8?fdP0c7OJ#mCSS?z~J$uJ$ujZC~nk<}icOsZrm9kPAs zK=32H%hlnHz2og#h1b2h9Afb^j%NFFw&j)G-BXv{)V@c)3l@i~MVJ@FhHOpcjbDik z*_-U?8CCase6jbB#d^mymsPD-PbF1HJu!ZE;|(!>Tde(p#Dobe;G{9h*t@pmyN*2J zs*~=0?ZpZMb#}v3h<#$)_a09cXW$9#arASxQ9gFuw(ngNg)=4!dL6(qVPs7hthG3H zN~iU9tQ^8#A$y!Veh1-TGYg^O1O$ROBE1DetglAzVde z>09WI^bL3o1*UMq)zD6#_C_gS{NjYO%8pR1+>-l@%ynZa2F98EYe|aFI!ClcA0yZ^ zt#keeJ6U~YMPAH*M7#v+Ly0KC2U zb_QYucU|knOGs`SN!set_z_Z6q-$##auY$OVh`dP{NZRea*CXSvmPCXEIQDyj+Ii@ zxiV`rW$CA(_anjcvAbxR%>EM~FcVbZdjL$j=Cg3@eZ>l%O9F z2&d8sG(&>g^W`p*kd{1Tri84fVql$$&5@uR^GI_gq=t}i&{1)EiG<$fQIptp*U_v= zhEHEq$rgo$f>1|e>n{tY6a=RgB*ck#2uOVlGFoUHAaLQdpX6{fPFb|yd(>!EE~kD- z^Lv291Hgh0*X!LHweyku-5&BrP#X5nrEQ_oXdToL=^^b&OYRy|E}v-JYRL|pv&q$6 zgKU1i;~R{J$&TlLuIVf@^8W#HwT0FY-ksDLK|qLxrZ2&GVV0{<)XA@NI4xy*Ol2S_ zw1MQc81HzzNDeo>Dv|<g-+@9M;lZi^`I$I9N-wyqVlH;$=}HU9qLE4BO_^tyRynZq+;I>1nH0T~GFW16 z(5{la{7l^8Nc)RumFn&Pr6W;yLqrO^SqEF7caI3YX+&tq1SN%oT6?!{uR|rR!&0!rw z_9Cg?Y;?Kl*!uU)=m|5rMKu~IGoR>&*wOLwWY}UrXnW63rFJ{`N3ziAi0&b-?A4m zp)%Y*wX-pBgEq}Wm|V$nKkGu>h_e9Vpu$~LB&cE1c3!I6PL0siINw0e=s`B6uTw%< zeiL&ro_lrU`Ol`Zmzv8yVk#@&a?5BB6HFSb5a=x)FPhE=6L3GY)h0SeiX;#4nqXnC zH4!o~0h{{EL@xwf=Blf!!b%6`F@C2mLocMlID7CmEsWX_zxh@~M07R=i9U(xRF1{e zW~uKFGIy{Db2&aAUY+r)I|7oClINF$i81ZGGSQsz0_?qs;He#>U9}rYY*$?Y3l2z zgj%do`Ri3abqd#I&5r2BiLd`{DsDx)P@$mSZ zI3E&D#FzR}I$Li) zV?qZ_GeMUb-K3s)+3yuq?7zqg^jC%A<`N2JKB17<^q0u4(~EI_Rs-Dl<}U-CqGfH=|45ggd_{@c-;iXxcLKTp<$ua48x4uq$ zhM{01PR!>*3pSmD8WjZz0OZ>c6>w=<}1+0R0~KDL1n#hTNEB@{4qB@_QM1r4w9Y zigQw6uhkI@>PcI_AF$Tp%uqBE@1FC@&xLl0po3)-@N}VAaG+`2mfi0AP6>Ns|C~3{ zzMuQ>{XPHmajyAzbhqYy8~^GXVAItnpJR3t43D-EY4kA-%#oK_u=`|cI1Rh4 zau^@0@vho(yW8h<+8mptTrM@+T zOGl^SlQhP2C;d(R20ytb=A6d!UoygQ=Kr^=1cKGI%dAU zQa~f-Q8c`Zh>sEE5ra(4;Hjh2@JSk`hATdph6!9*KqEOp@!?MJrWJ*hYlthOGc!@b}TT_ z1&!2^&3p`_ab*FGm`9D5M>g}}v(mV#kVcu( z(?G-}>?6{^462hRKEeewYHg}t+%_lmfa&U!&$Tua43A3-Xo$0vegsi@D`)!QfUv0?N6H3c-p7)8TdN&R9T7>Wigqy>EK=rnwihG}4! zX_&xYEuaw_r}*$+obOxN2t^|{PM3!SUspgwOi(lei}N`~f6y(M)_w&kx1X+TezMxbW2whYtL|5```ZAo%l z&gZ$o#Pld_X)C0GwlEF+ketDpPhVaIU z+5hk@B|gkdn{?d_ZZDt_o1|#?*XH@K^h;hpBsg9`LrhgP0z1gx(I+GGJU2BDCMq3; zG|EItt&4Q*JH&^X={_of3--ed?kuD+RnhSOGS7!B+b3_r;6tV#ETl1A(FhFXX;^JC z{%5M*M53bqn_pGKpLJWZe%0L@XGa>=v{ugx+_L1V=~rGDm>UdU61cmmX~V+Vvp3$+ za>u%LciesPy7lYsTGxE>`o_CvZ)jY`ehT%&*E@?5HP!R+9i*>f)o%(-mgrSlfz!TOEMk{U4?sJmz5hK4)7 zt&C`>@eaod}Z@`d}T9QaZdx`oWnRoW63@1HwOM3K2QfV z;;SNq*ylCd>-gDcqpu#1ZaIxZC0OCHbw}g-qF5=4?t0A@O%#df(dhE%uGek2e-vF2 zU9hJaXgA>B86<9?gVM34l9*96a^p?6+`9W+-+k{;_m0`W`yG4yWktzFl!(qp-sfJH z#2qHkvE^H`&Zfy*dWv`VJG}q;9Mq$x6rA=_Pxm?j-M1a*|U35_cHAU5$_&n7utN0 zuk)iw{D5}8SbjTW%u*QTjG@R7hErlN|2SW(_~*)yG`9|K!JBiDl)3kv7Ph9TV-7Y? zkMFxFg5CxX67!=K=;;aQ=vNh#3dHxkie7(JiOg*!iln*9G1gopWo~5IP4RB+NH*l$ zWZ$3Oop$W{4V`|Rc$Ch-<7~a`4wtnwl8QD7saQ{$`{|*J&2cpj9-}4N zckx94HuM`8znV~xG2!U)oyGl2j#T|>V6Uyo?y(Q-#Ys0$Z9h=}qdO<}@A|Fdh{w^d zp9z;I$UXG3B%SJ~GtjQ0qjWmj?!}2{8~UDW2)P?;L1ZV6mlFX{v>ZYA)anHGs;_lF z;&BtTokjh-UdN&7e?*ZL%b{x5UDs8-IleNRzOr*=wzG24N@sHr3*lICrqf2Gap|eZ z!P_wWB@PB~41im@>!@V@kxATlI+ttyITnxUV4yr9*7ZEjjnS70;Lu(oxl=ol(ca4} zPVQ`;ltaHO2Ze>Yro84CwDAXn(=+_7d@Oh?+N*Mq+Xv6=yrmt4c3#yE zGCP;GgUHS++Cc)<#<$yX1Glbh*S!zLA9H3QmF;fY|Jgoi$HB_4g3j$Nc-u#e~0B9qMS|$wPWd&;QMn9E{jm2b7`67amNeV8I8V# z#ku2!BWJV_JyG`@Kcn4#nhGphTGseA?JxN`!lV{$??1ESe;zxtXusW5;yc$Neb%Swk%gjn-DVZDK zl3dsBzm7lV&QYtek0`%79IR&--yoV*KTEdwWk|Pn;yu*Q=QS{PGTIiflb4OQ2U}0* zQ*2QciiBSU0c*~kwIrl=`c`RR#TJVg1Q(OAlLTX_;Q{BxH=akwA|u*;r|7gCzRW_t z&k)i6>PZ|SB&KnGoQ~b9lM5H&<#)XONw2ezaN~js*P(Fd$|0yz$k{w5u@+|$7NNKV zVY^!U$snh4o65Ai^~XtC6CSDfd0h8NkFA8iSycNJa4mfby_wjBQHOIjS{tN-)4nG? z^|bq~@Ah9$P|0MvjP(Yma9oQW0^51aIwYucY!RWd$>cM&+W#1wW)n?gx_03pb-cTI z48Na7M{iNEl3WM8Kf>MstQocj<=DRzMC91_zDL`ObdVTaq6+QcyP%KCF)HXAaaj}O zx3SAz%=AL+U*be$(?#Hk4as4Yki_=9tDhouYLA%d(AgYx0F@jgT3%2?1RSYK7ZC}t zF}&WX2FLdk2DoH{)l7-hp9DCP?O82zxdBJtK_(8oz{Guxz&cICSDJ4^-jhcTSdej? zhZ|R7LjK!4@+b6YP}arzM}q21?xO@;6||dcdl9psGyQc{?va9WKm7g3yGc!UjI}(^yz|q_!@b*_}czY<9q0V zT>bdVvD3Dus@Q3JldJJ;LXT+Ye;UlSzvn*KT(rB-@eA9WHqrav;8& zGc{zMd=GA44Zb*^2vXcImgtqKnqSs_`YEdK{*>$e*{AW{+DoXM#}%;Qq)J3B@M$dP zLd=nKH%}QC5Y3Kh|CZBEpLoutxjvm15KZ>y+&ahITMssm|5vyuFa7JY4?q9hcP~7p c=cw2Zq1Wn-fxFiPSpn#O@eh8+H1e}+H0--a5nwj-pmElW7o`&#k_DRxF*!Ohh_D4g0Pg-9JP95siz0}ut zZrGdhc*pQz-r?UD6m^99raXK2!b0iO?t}XQ=Z)x^A4YRf_M1Bq25=wlxupFS5P$E+u9Kd4etp3 z$P4=m)1AXl@E-HR*Zy#*xBb4*_3!+@pNp5?xN&#Pd+GK5+q}+&CnraJB{Zccvv{)i zf#IGlSe4#Z@7>q)BhQ=vz*jp~Tg`QE=(372`|3}D64B7Zn zI@(|0^}ZIdBsU&86m8zwRPQx;-jmxO3;Bt;<(Uiq$taw6w&QtXd!Ye8c)!e08k3;nvlweH*CKb^+G4aLMPURMlKGGZVjEZC3H$pXw3f5STB59EPO^?c--RfS*_s- zTf*n`gwNd{KF=$d5-a#rUBLy53odFcsM%6*Nl(G0`wKqpMW)9hGwUL=52XhR6H^Ev zfB*srAb{>cfU zW!X2wi6b@&#gFu5UZ9ZoUW-G2^1T-J{tNwO-)oV{SmvD+e<-wfQj98c@1!_XXz!#r zxyas0@pfVRs8fm_tSZXB`{Fn0;N2HhMIFOWF6y}Ol%kGN9~B<^?hE(Uis8a4_*SPUb-2(O+&$Ulm@tN*r7?nkfhRiSWH>Mw`EE=-N zKk%`=_u>zQ{*ZLzjg8ZlP|>!Y@O?c~ex>;XZ^7_FPo8<4*I-l@xz}JkG(_v1($klB z2ia?!@~bItG(J*4{i^wm+hV@wo!Pj1c11|Lqw$B8`h0q1^UayrHG31+Hg5h^d~Ry& zpNcv;i2Cvwtshpb9dhRTN+~}2%*M{EiW@gSo+!4dvfExRoV{^(rKhA4Kj{0gukqT( zd1f=^*~V=fl>x1B*vmzY$vut9=NfNnys=M$+8J(gAnvx1uZSaCKl*aKy!E5j_|TUl z$vvN3;OP;4+uAM3=;ogIP>Wq;u|t-q_H5&np2lQfW3sm~xubD+(Y6vRh7U!bE`RWq zlJ+zIP}2Sv2TCl?lwVo)b{7pTJ*+4X3@z;(HLUcR{rB}GU)bhd^K|*8*Ld+V&41M; z&|l)YX^XqN=q>m8j{AI1pW6yD3zY0GdQ;!~BVO{a8bjpL%qjK1H{ z*y~5!szTRv4u7*GSe=$m+0sQ?MXKb5TN_8|%pBtM!Z{9WYE{Xjw`fj_1H zABgRu9+}c(ua?QZR>og{)W7=Z(LmiF_OT$g)hTA<;g@Yc-Ow1?(^%+56tKJKApvM& zYj;Vbme-4E_C4m6`{(>ovz{vP$~9|BPttGPx~Ie+@v$HIs8QuefscBV^|}2^dYHm* z`lvBEylaTnm}T2lOdjacrbmA;=4I9ShhP4YZN}kuKH6?9k7>Fm+565vZu`Ph zzqR-7s8Z?{bNT{X<~5sJ>}}j>iyV2^=JNL+6zI43mzr+kgv`!yFIMumD*VX1_g{bA z{LY)J%iCU$Y^!@@bkDh7tJhP%Lhmoq*nj0h&+ELTb5T{>&f+GUeZ9ZtL>1$Z3UJrI zHmSU}?JQ57)b_>lP(n!*r(25CpYop^>B8IkD%-wT<|T^SzF6$VBQ@_NUQm?YH^W_< zHq<>a+N;+)lFB{*DkW&idnz3(JpV5&{hewHl=7m_ey*?W^~!X-I_57>LGtgpT{FKl zF<9-#_uJn>Z9v=WRUJ21PwTv^dTM99dUETfJ>8>wLWxTsn5=PfR&|-y`{*W3rxV_` zRvS-FkF3|YZD-lxz2mG?QlB?#LAAEGJV+&+7}I(*9Iv#EyI`3udck7*9J$6VUfy~% z6hB!X%@-?L;wnYE{<_@E)TN#0S{5>)$E;Bie{Ot#GVS&;wjId}EXT=9E&pvht7LME zP|7=JRmZkkCNxpKwL6#?zjaG6F>$M{SFwY6%ZVyop_6O~(SGdgBfS3P*YCUzIr z=~DvU?!sA_sTJY$1vZ_&z~=dX^Km-8tI*rx^@NmxK3Df?`AF~nNXLTe;1prUzC2=^t3vVp4U-P)bX{@8m~vM&eGTSca+A@+uU={ zIbCJLAM+G^c@XQ`k2@BO4&~xRzuvdGC;AUNKC|h$#BaJPiqu0@Ql;;2w3PNnH$ASe zif~`A#@k&oL5wTX9dn0=HvZnNs&{WDncgclJ(>7T|6eO|*Yr>}Tkn6#B^Liw&Az+O z%Vwu8lbvvWc9hPn>Vld+WoY`Q1=R(KUk+rcBk49Sv&Pc+w3@zqrn)TEWwI2?&r)eF zsooiz=2}vzqP7o0ZTr$~J0o@k=m1?%T`o+Ay7}3}xt#^_s@ZOj@5#5yi;tWaI#hqH zj+07%y>?czz?G}ep=3d7L}x)w?}oy*Bcb?^?bg7go?7(T{2et{J4!pr3PiiMsdIGK zj8Jk&%@g+w?~07-xFOwMdBx>5&)oH%A{4YohIbCx6)Doe>9S^(#~3RkmyEH})e_ro z#pW@aR)w;{OJ6uYJ<`hNOl7EM?7G*2?a{n}!q#@Fl}9h$;FcXIj%}A(GG4sSmA4<+ zS~6+Y2Wjfyb+fiuF|JQvnEq6HiguRj)4h#L$0FH z5r1=au?~PbJLa|VTeQ~pBGqs9rQW{G3AODCJCEONcu~h=S!h;u-DNd*RoC7Vtyx(; z`L0J(Z@KMC6>hWrHTamX*lG~&FgEG{phr{ngAUmPM^rR)tR8QhqU{@%thVd!+;+9( zZP#tut`(oyuFni?SH!Kfqp03C$#!n=-EEili3_&(t9pEWW@2)^LRZ@0?+sSyzg4E~ zdcD|kT4i&q{IS{q9l&inCuUloiWO?A2epUs>hWs4zoW`Wv4ZNQTr0O~WxT4Ds8&~9 z;2M|$S7EFl(K&3fc4Ak>(ByNMhn}c;;?BcCNX;)dR3v|P_;<+{Cp?jSt}b+>YieoD zTlc)1+;RBX-XmjA+uP}mznUEzMr)fU?Cq)x)%(k>n`wvT<;rK$tzoN`k=DDaqh9=U z!TqTt<;RCD%i1>A+i(q7d51FIdbA`yTOS*SwjM2xZvF@D)>KRD(Ndk(9UT_k{FnB9 zl-nUILfZ0DtBZG*_dllafjXwYTVFd}EBeEK{?@m?l{|F#_u9?Hsxr!Sh?Vue7VavW z7kYfcTV2zOT$ykw&a3wyagyb!=3o`xinRYvE~w1lZPS9rIa?K$r!LQKWc$8)SCytO ze9R7(^hMb?$5fXJw-TdrWP5W($e$CeGrGMmqoIyfv36p4N5Q6^xHh&dy1l2~-=}CZ zJ9GqDEiFv*1NHZPekTJzuYedD9wAw@y>wZJKa}{xo&u z>;Q2UxC+TwCFxE9bW{~9;uJ;fx~qCY*Ge^i3##ioA}805i*EKTxFysPIlp#!d}ZzO z4OO*EvJtP!fLnk-qI~+gX|2 z{gYK)T&@DDI?Mm&*+HdoSM@9}df&HoBD-4~WEs*pVqj@8TQg*x(q;shqC0aw*g6i?}{C}x;MRt6$uQyfM-m4UnJ9=L$Z+q>=)+58B_nxD- z<_3MzboJL45A%9n*YKo6D~;8ki>Qq#Pwwge zlG4<+M6y2pcPOAcbhda@21eVg{?BIO9X)EeX)reEfwv0T;JaB%_LH{ zA~cZ5VROw(WUD2jWn3cP(3eau?$xAnak48fw$Fk*Y_r98Ym-uiYK_aUQL`MGb4k3q z{H}9dan=Ucg^r4^uE6;2a^2VRj*3uwML}Ix#gLj`-2Ju|)LB)K-jB}Gai}hWQtYqP zDhD>9NZ)J|Mz082iLou1>(|)otpe2QRrSqOQjyDQj&3+DSh;$31x;%ADUo^Ha_jTVbeF{Dj4NW`RcfUy7pCzaK7MGN}lx_0xv!`Xgl-t{v zz1E=$Oa?*YyhG^?E@s>QP-Yy-j9W9~a9>`Y=4%DTog<6YU|o@Pqppg11tTlBb;u(A>5cOUbG|Pxg{Gr-L>YT);q(V4yYi3s(A%tTms3V9d+UM znc*2h%IRU2)FSI1*`DdV)YiH=9Y3S7^VCkaN>|7lYferScU%#^`08+cSY6wWf|}jy zQm$dO)2I2W;jLd++_9i~xb|k*w7rQFlKaNly%nA2>T|-L)G$|V2Nl(Xz1ixyR@=Hj z`?)^a^+0eWEKpyt-YU4UU6JrJA87B74>F=2N_AJHF0|J+Q1#R#+mN6#s;^VDO6`dH zuG)D8cU4zwazV%3>e0bTcJk>)t!9$Tk0Ms3hUnn0Y};L+JXc;>^J4TX-_nllxGdb* z8J(sS6T^~wT;y|HWS8*?zD{uWbVcTA`>MNUg~F-gE86^mniuc7qocU7bIr%ow7SIb z@)s3B#8?$8ce z5dBLF%(mPLjclz@Sy8Tvldhoj?l0~2%eIy)aH|!n-Gx?`?1;(q#3EJ)_P$xBWvi?$ zE9)HQO55YnP2X0m&U3ARCVh8whmIzzsyl87Z+uy$M>myv50p1{R_dF+mb_E*yLH1a zsj6-%*;Ncj2x(~X_wjmi0c%&ljR zIzu&Yt=rn>t~T6~J#Lck^d1~Icusx5w#02m<0X}eA<4HczFfzR%i{~{UVp?oq-{si z(XaQ|(er>Y_B~*3eGeF1-vgErUDQ(7#5y+qBJ~@3{jqBJU6-drjevid!Z!UXK4h3S zw$=JX>GTH0t@qD&os3-nXQIk@U2>oHjP}&5-q*^Ky}hZb_M59CT~klc5!UOMt1MQy z9J^y}jIF$Lq-Dg8xa96f%`M_$F+ zVY819c?>b|6lx-qvWbf^^!3o6eO z+HVZkZ8f26#Tl&7Rg#;Zjn{m#!Vat2Jf^}9n&2mTUn+OCOv&Ef{bjl9A~#o0-u$cR zrXL8s?Pw@bs(Y~MbpN;YHK?3*j9#y^yGPZJ%I-9EqBs0e*i|a6suXq5ss>;0s;%TM z9XYCW?XdZUTkoT)W<8f*YgJUIWUc^)dw;J(Y(ysRGjnQwnmBWI&2JKCYK1C4`^)N+ zhwRfoPfhWJ-*(Lj>6_IWBVCGh$sIMj*G7^*O?}fP-j=zVp;p%F3acjm7uw5kUh{ar z(hAOjVAXrY*?m#I@x#pQJ(}GW`I2jE|L0;puvZ;$cd)65mHVTu zI^5CiX%C+)j(PL_Iy;1S7Ox1+_s3|mJ0uBr(y3!m87X&hPfCuobQF}nV815(f7E$G zCTf`-*^(*OZP^obiqT|8yE?vp!KtpVW(WJ9i1GU|xfnVFvP-a4y2a7!YG+F>IG>sj zoQEm9mdQ3ZH&-iE`Li@Tx!b?gMnBPtRuuSO2$tBKj&8b1g+v#fHqFymwL+PlEzhyA zbbe;9_pb}GviXht;D!FDGdav{mRglce}Y0?xj zCtXI0ubc1xQd1ju8I6|N__62Jd5N9Y5A1POT9Clhdv{0f%`JYN|CM0zt~TAwsjI)v z|7%Oc-K4Zcjw+F!M32?f;vi?2c615$DfPVRidH74Fv7%730Q1e*b`{t9K8`=F;G4h`Y)d%v#RZx!nY>K#0urQA(Nl^ev6wb@2uLs@nv;B zEo0Tae(AW6bV)CyQe}<&`1$@_I*>ET+^ETH!E_a3u5+x3ac4}PbIq#Q`qhc%*s_L} z&rgggRkRG%vZmA>PoOeG1@Wmz6~= z4NK#zo9E7$ev9&der&$`+7esWygVLnST#w38(%NiC4wgVH)>YwwyPHP{tYhWvLNiV zu1(ctnpy8pcfsXtKd!bVLK{Zt@M^l#^1I><^C(YEu_Jp^bxgCv;uVOeZRJho)nGWYMU z81Cdd$K7e!)|%|(Ha{1yydLD@Ld%8DiY*Ie%0g3niL$R7tyOB@{EIKJTvWO*O|@eb z@-M-1Rx{myRm1J8o7cydtX;Bv<&s-hHUy0060s|1SP8g)!Rq*um9bluxzD%c=Go&; zuIwyqX;?NmGzg#5+>lF2sdTONW>^ZbmgQf_g}Vf9T_0~~DIHe7*||c zvH1^ae%sEN|M~1v6His>-`i53wV<8lk1SV+EduESoQ7Vc!XI4YY(&puB;>%aBy12xf*Pwswr#apdi#IjITHIkfDHCyFi~bd$ zi%awX(EXNli!!HFZ`Tp7j4ru#bt3K-TAe%Uvx_(0KWll*nw3k|2dOSiG&eV_Qsm{g zH|QS{S{7TTQa;Ic>9pywl{zZ*Oi#lSRT#~&hTCq7jc;kvpVdFhR$F}(H(vewL#tP5 zp_wZimNaKFyHrJN)g&*-n`M9P^5(e7-5!+arK?xzfRD#+ZHTW^%wP-GG%Q`-xV&Lm z>9CTL%t6-BGAX8Q%;kCcs+M?jVySIri`zL3OO`feF(=xyMz*q*%Uj~H)s2=;c2C7r zk*-oUV=dXWCICeq9twhuF8uwHm|-t*0^%@nlRS;@Bxuwbd>rxF`O1o6Ah*{ZU^}({l?U|#&mB3qKi$rsa zEj(lVYF9j$th_jO?zwC1ADvpWB%uRH1$Xtzl`7*CyiXoW-qJOR<;y(57^1Si#O0(R z(;(d9+2Lr1;kxB54J+3N1<=CAUoEr=ZnjoFdr^=b+Xz=$U6^Gp2x%TDXSwpDBg67N zy{X~OCCgO6ZeOy}B2RK@F3{d`X$(5(*W_9+Re9OXon$VSrJzi!#AM2gNu$;Cwbr@ZXwc4c9*i>tiMv~~PP%7LmNT~>4Vuc|ulE=xAN z(m8Ufn&+-rBTjAGe`vzauA8f)Z7(0%{OmmyuG8L_)IZ!6#L>O9x0>du0bCJQZ+prJ zYm3U;?k*0+%iLwa?bgnx7OARjI%KtR`2klEw_R#02;DQ$Jy-CUMN)kqeJs+Fo_gIM8?~UCpDw9;g$YJ)zr?kZqm9)dg|Z%rw40S&${@M zF}BEEFWJnge`m=zHQAD1)spIze8;9YYuYk% zGh0KWhI=)9Q^VsLUehpC^CxP!N`vKThoyE=kn#&QeNK>af16UZ2)+f5%8O8XOoYmq zBE0vC%bQD~U(?E4E`?f)@O)l`J;y}2!y^1^UW9)-Cc-9*@U^@MUp^+nQx@Tlya)}) zL^%C4MX1kshI(HVuEP;d>hPX!x~;LmDEQ zU#VfD1|6t6?7wX*e?wQIZKHpdInf-_^r!{@A`@&iP!QV%Kb8r8U~up^Gr=8$gTERC zr`853JY@;roe8@&2#cMeu;rPstAnrw7Pc@Gc5&X?r)R?K;*0X%Zt>2|gz0p`!XC1) zlY%f;8QAv{eOC?E)$p!6i*x5)GiT}{XI1m+sI7`Gx%1+ntDS8~=L9X+=Q7QbYf9%> zqdE{`4bjZ;Y9G{6O;Dw-*40zctZ{eh^CG2Z-=v1h#mB?$TgA>fzE$RpdQ5x=C9#;p`8k9_PqQ?kz20yj!gYbrt zw)HEuul=F>gFXC@DlKgvL=s~q)zqUo>6SA8W;@m2S-yK#b+Kma!Mu2}O>5HX(sWD2 zAE__NUAnTXXGZ;E`x4x9tl1U4*Di!S8pJKWu4$*O?eBh^ir?S8YaNW`%Z*-z8n&)NkQ$ z{MKc}CG%vi#Jr%;+1s{uPI~0q^qK}D^efovF-Xv;u4)a7Kaj3E&d@(<)2(C z5uK@4*83yQH&eTzJ$!Bae2X*fY{h8{)}#l>BF$CFkNfw0tTkuz-5AX5|3ccblYMx! z%)fJ=eJ|6sf(5IWEm?0Tb=v!L#4JUv7IoTtJw*o9UB{8pR0oC|5O)7 z)Vr#CH0S}9H4Qyit4;mda;E2+6=lBvYwZX%2)@-D&uC7vs@gwIR{*r*wL|M-@ga{` zflrmW(TvvG6JzlYyUI>XmQ{CM5vtjg`}+sDy+e)X73HFTMZr>;Y3c+~SB)6u5&x-ORM!risMEnOD9 z_antkS3f#!lGXbw^|?{Qmo?n4;cqqkcMadsuv5c}8s5{8)^N^wUe8DkR_rQl+u!_^ zZF_nDn<|U`w}#8;Te`B+zu&$d(FMZ(U)aYe)!kVs@Bf!U zp(h0w+xov@OPwEFPpog6YU})BW}RQOSzmfn3EnYi(Z%laReArSL7{&YT=D6j9fX=u z)1{WuG%HN(@H^3n!(I^@o3+?k7a`|8B1xMvrw8oYrkcf1!Hg`&^szpRl%-+NM8-qMN><($egZo~X~K@+UEXBf z5vbVw`1+A;e=JSt$(G&^#!l&-(EFH<057ERgh0QjZPD{9lq+ zyTPX07#(4Ecc{JBUAGUOY%fn-sAun%{m7nZ4;&-DhS6;q1d=vU9gtU3Q|| z_YBI)`C9e$E*CDy{Oi*{x3g;1 z;YE5jYJB2VO%=K>kv*GJ<_-ZJjqX;UdKyQ@9=@x(EO~7t8A|TavnzjQmi+Z3gbt~4 zJ)=^w`Te*q^XsppqM*GZR9ADT`8`v~TxzK8oL$z|lexgKpgO9{3~^m%c_3m}=bx9sV><&|XO zsm{dC)UYcH?*8>9x9pF8WmB-!b=PN?+3-s8mRC9zSuwAArRJ*r8&+%YIpTds(H+ey~v%RMcKp9&C{%x;IhOIeUL{ z_Fm=wmHx@^V>yCi>5*Ww$57lka!^SkJ|I z-sCCge`@Ll7hW{2X8Meovu4k^?DEfCapl~ruD+&TziwWz@Ve`7xbddE=5*lxvvqQY z)V0=zy~KyEiqef1E1|Br=%^a4S|GZ;Y}AYid+cd~#2Z$VsabZ4(b3rZT5-qa1>>LD+uv1jLXSNw{&Pk2#y`{kgbQzfLMaq<)JIy6R3(PC z-dPw{hp;X(rcc4aBOe`?7he3;E$S_=Jxen}9rcBpRoHr@Z0+b>b%pv~r0+$oN0zP~ zva7Dh`?zjM-xW(%C6+X=_vSR*+UzE-TGG6<$(z2WdHG83swL~aD-x?3^s#ciH$8Ei zdeGkdhBdmCc&n~BU!(haHokiG+8|(7!_r`4eqxo*GrX%-yU~I~LyLXAzG2y_U}`~A zqS*z_X=Lq)O<-7ABSI23(^n>bkza zE-%V8x+$ZRsu}7%>Sn;eqS^C|Yt}4Xy{sW`#?`B1Ggq%^UcI!TrDb)qH*0mmvNUH& zVrBlC^P=dUi-qX{4@0kiFyrs;mDiaA0JqD}i)o9wU%4WWQlXm<}E!lQ7mgu+O=Rc=ADUaO7E#X=sVH@OkGx&rc?bKt%Q6$Y z3MYS0KX=YO_o*LrX1A>BNA;T3HMO<(K)7SpslgShF0Kwwl~-hewB8uo@O{jqeq^8 z>Zzv=zhpn}syg2nys1%Fq^_%~GBwQqwZ14?q}xl4 z*kZd>2ghr{&eg9$9Ey9O!n)?}LRfUO9lO>Cx;puG?`!3WMDz!JAwBC=p7^}~Z+ghc z3Ub(As3{dW+XBDcLU-!G+FhTyMy3eMb*UvA;kF<`^6luuyXrR{(36bbb&9e&h@u^& zANeVYf3ZID9&}Pn*L_0b9uzrd^tsfXJ~(*C zJ`_CPq4H7MUEp@@!Bk1MT>NsIE6NoQ_r4U4KD;tq*0CTwyuG4&a1wXqk~pdN50Q<3 zIHYxVM5^2NM@#%;Q+%Q;@^JLwshe+6b_S<%PA-*GHoj^E0YvEilEZq8_}FyzWKZ4P z-cji)&y*^69oLnr7j@anE_UnbKzDRmP4={kPur7aI!kKbS8^yQLso0JA0ubZ0<(KR zbIf;_9rPcrb|vTEG|H5m68}Mcsp(r=o-H*8Gt0RPP42Qwe~-4p3b{KFuMDoDIq2fd z=8VWe_q(649!>52kuErUsnC_VV$s@!Up#JGqcSo|SCR4hZ`D!PdZ`sHFFwni6YGFl5lX(3 zDbRjg^>b2}S1&5^JUd5D9tuk0x))Lv{#L19t>-hNn@?6c{U^D4KR8_uo>tnelHP7N z586jA(>ipM;6W>R9m8ymZs)l=b-NW}ofEenDQNv=TAzt4cSRFASL^3Ab@r~-#TwP`YQ0e-EqarE>;JFXNHw*I%axvDT6)Dn zdeI;~jV!$pL3(v+<%0B13DR3RIK9-Btw#zIbCg&?keFgy=1vU~)5sF54iak}bxdLl z1}E0mQ_=Rp_~_;Wv9&u9UA`&wuXZh>)d9Ma^_cCY;8Mw_a=ZDLZ@b2HP>CBpP~z+~ zDJX4)$#+tZ50tnEvdbN>#BIvX%xh291YrY(P3=i=GG{-)E>C8DV46J=rXMGXbN_4- z6-oC)VgDvofY-F8RgkW*g7g>q2oBnbssLxHOLn<_!&#;AT#d(ST(9vMjjL3FmF&=$ zQ|*qJVYwqT=rToGd-sR!8d0VZt{!7Qwy{^MxaS^qN6&&KbX6cuZshs-r_TAG`*+nkMEpmceK-+QZK}9+_Z=q-Hd;UV+ zCl?xP3!QY#LMP=f^rRk>Rc2Kha%-xxg({C(s4{<{Z+vp0F}Bd?V-^~nztEE0LecJU zj$u^ZBE~SvehaHc@%wftKBU6CIk-Q_A=MO9kec8KSt z^@8q51lt^S%c|cRypCgFhq!|#Z;}6=TSPtMV1?h$>*l=h{ove0`{|S)>Q<6Bp*LG< zP9B&%X<)K)U~=@pf-1X7Q29lVYNg~&`cxF!9$3qeulYahBUi4BS zm5Ry1m1S4gb$d0>M8EuyI#N1%hqebV4zh#QH9+Z4lF|CJtt-D^n-I_qRg_$FC zaC^Bcxbvi(m30qEz8&<1Qp2*9;tTfnu-s<+O)hdt@@?(#p?N){7ySqI^Jn!Y^$7F8 zZn#fhj<*|J^_-fJOZn5el!tT|D;ud?N8s1}&uBxEsnm0y=m?Z%7dl?G{6_HPvNmj> zBk;>0?9X%revn&Ax6(7+hppMLL~Nil@U&^$MaD}1Ty+$JPUz|SjbTJ(G!l(&zRx;V zxi}>j$96}ym*#I#?=GmhV^)yI>Lah_)>%P8ruIHX&~x?u)J*MNWk;Io=Tb#c@R)4< zt>A*7gR4qHaSPg>D6>jmz1^TTk7SR_Dyz-QEdIr=bKK$zs_P>DK#wrnZ-CX6(Y96j z-?2{6%ZC*Aypnwby~F&5;Gll0oNWjusU99w%<|fTo88mVR^3Lsf0C;N^Q(2M1Wyj0 zsK^zJGjmJjDrr~WezImCT&@qkmaXV=%eiLcla>46ejmKtJ)d08H75C$ zyfs^+j@iCBx#e6omcHHU{&Llf{C?|wW`FLjljSf4!!XwlI_{0 zatGyCm448RDCv%>wpQ(&yK?ekavf~SO4?POY(ifr5V>;8wdt-6j8Nj>w4w&gq7#e%jaFROo@owL3o z*F>}iVfhX}OTCrzT9R92pwL_ugbl#y6v0*BHM6RxCL+3$bb?wF*W;;(ZoX5k$-qy@ z{H5BNLE~|$H68=q{#xCs)#FF;>IKO|LFFE8Td3k;KkU0oW9?zR?#7MBXU6W5O!DoZ zx22!|YO7TH&-1SfT30n^H|s4pe^hLD%&Rw2(G~ex(4UwCwy3XQ*+T+P2f)c9Ff&H{Sn+yKtmNCVuNiHG`f#WAu9NG-h&rwh5e; zo2s)HZcGgF`$b)Lo4N5PwgtMusJGeN9KCmffQ4!&Kd!xx`IiR$fmES8Osu;WyxAsb zzH5)s|FSk#hI&8OrZ4`P9nh&Lxt;Ly%r1B?X#BFfvgKSWQLdei>S^apJH5~^(Vo&> z03F&dAIfi~gFW|NcF%Rq`nDJBwu;=E^u&wyTUGLpf2v?;H{GD!r2b^Eo7#`Fo67Qc z(?qwM#t+&})hZWxyQ$hgPnS1b1!BK*{P%ay)L{3V?#}Y6TnTd_3;qAD2ZnQdtUTCb zQ-VEK<@VS@|GuDsOxdHK^;QD4G4^pk{iF;q9c6dx(sA?6l0^6VC^=Rpa znnzkyMD-eq9pU89dfzNh9&NvQN2IsEvVHE3A&tq2J5;kKQ+n>N?d536JDOLdt8fJx z7iKR>Yg-$47j`R^(Rw}C_cgW@-FvU>-B+HUP}ZC5VdbX3)yImodm+|h1-9)RAB2A` z8y@yA&qY3x4J`0Kl^^--Y!#f4Y+datR<_9yNKMMEPkTlueMy>IVpKVE1rzP0Q9 zdKjbFwK!6VZ0oV8$+Eq@{d!Zv+`UEisD@31cg@=Cp6V!XpS!nk;1!)+k)PNix)ffn z?eF=aUI#X0ci|3=Ex5^!QvC$cru`4}Jg=`u^^{5dd^7hK4UMtI`ZUA+sorq!ok><~ z9ZC&}Dv219mg`Vd3D>NHaVL_++_B>%;#8WNw z48JEY;&=^?lAk{s**hFERtwEnMTrcUqwQfBIm{yQ^M)%~k7Q{(#W4wWr&X8%o@ zsk8d+Ahxja{c|!?6Z)-*v9PoI?P{@2ozrg(oJ~#a*R=pQb#A|%6E0Wn|0DXqkg-cP?o>hb?C`WYB+~Z5*bPIiAgT~H zWecGTR7tb|ix~V4TF(xgZ4WTd4jv%TU3`0hVBxAJ{mM~4Ueyn=vUm2!f9C21;}R3B z)zVQ_-Z_1;Qe1adXRr#rqvAwWYxPYZ3E7W+&*1eyfg)d&#Ci)Y_WxU6#2YNA#BU!Q@m32h^_%k|uCSn?{^tfqY_`xc|1)_J zzhFVb{0j$1{E~$Z_hWexJ1i*b4;viuuPwCPKdgJP*{%M23p&An#oeCGZS^-TbcFxY zyoleopcDNc4UYI@3$5_~F)!jS3mWNvZE(cB7COqmD=*@U7Bt#lJ~-kl7Fy}g&x?4_ zf==@521oqBLQnS3&WjknMM0T+D(5g)VAQ~iAk&GMXW zL1X=&xQG+`?zbb&>pxo^Ae##H$1+pl{!y8!g8s71RHQ$gnJVo6K!=bmQPh7hGc~0D z6*pDf|LaUhN&mBMsBL-}RFSKbM&|0IQMo#4bgoXS%+*OJZGxM zu1=bA<8kUF-SN;hn)3D?J+Bq$b%DRPH}X_?@#>&g|D$rfG+j3tPjuG;o_jU6}t*8(R9a18?_!u$KUH1W|JKw_p1Hw7;{LUdJ|E>`#TEaC$v8q+%1bf{I6>o z^fY-iFW}HJz3}6m_8SUZC+db!d%50fWi9n*?WJd`1bL?N&jT5eVJI{_~2M}yHrnjtedQwREd2r8%+;g96GQ#2>gEr0^9c;Slm7)rp?N& z$5II5#RuYbzmZ+|a|404uv;v5qt<$u6}I{dl85xO9=jT+OiUbDr2Cz0I->^ydtWXr z`EAm&=kC?o#@d35{dZn)6t&-qM`}Mxq-sBk*IQS3sH**>dV$$%brDVbzf>cyE|9(S zD_HnpE$m(bSbHS?hLY&_AGRoq4=i(?7F|Ku|5zsfdayxj+nimS-d_~a3r@eauBrBh z=%!YkL)G4}Zc^xGlQ*H4A*%z8r~enrZ7ivaY)J_j(-t_v=b)_eVEB zu6e1cwFje{#@XCM(ak@wkU6ym~lAs??RuKg(br3V!1zo33f_qzuc_kXBNY}v2k z*|sP2ppE-q9SDg8AwM4o2?rs4*$|byv)tl(R42N{3VYk0$b&XcO%1;8KN@@;cWkuc zAbeOR+F|!~SE1!WH=6(43POWd@bRBmLEYdLJT_;E#hAus5V; zH|C5jR_nAKiacoJ;LGcJ6OoEyz3Uul1GC)ks1ydvMdBlZiQ;%kW^QWYu}OxHm*ndK zQ8vjfxg^7hY*s?YTkfI3%h^9{(H-s>Y31Pk9r~@y7zK3IKiqocQ_*|v)!;$pt~bCg zTWZhPO;e58_`fjJ{x2+Bmsxg}#+M(H&Rl)3*RUWHeuKt0XQuP>yEqdzRpVtEx{Fhj zx>uym?!GZ~X7^`Pr+0rYb!zwG)XCjTQlq+WO^xVYni}4{ELGawkSglFO|MvL%36gJ z`hlp*Z)O+&?t`EVTi1C-aFMOveSD z^v!C1_0aW>Wu3NKd+1Mp)>fgjovw%U{M0djC5wZAJEmy-g_b4jbdIw0&Sec#KjnF` zwT@5StxdPBzfkjUUy-ecIS zg9e?BOgV4rMVgvC>HG^W)MDN_pE~z!EjH+{MAzc%@7mM!antKT_`cH?I?|Een%o_V(F$SXf{%>JDohI&hjky#uG^T@JY4ejQT$$gii4@G=(&lYQM69+;`N)n0t~L9s@|UU$#Y zKHzI)*-4JHsXq6;?*W_Xt{QZXoU9$#Ic%yvljX_FBkEpkIb?IK+jC&efmV%+58PqT z@oB2cLi8-(eS3o)u2$2fShv+u4^}qP63@L|U*~Mrwl>*n{AF%2cb*npan7 zGed(CD-II7GNfIVN$vd|;oyb%r8T8vQBd02f7umDc9r$&Gh0G;Xb($2)HA-X5&lcCkSpxju(o3t(&|!Y<*#aqVjP>&RSHwY_L-r>yVY0GzfN>- zuJ{HSJST|p&HDHnm-~4Z9P#7oB_wxiOPsr>=GDyC5k2L1zB` zNn2|WlHKqQg=Mr}jVe9c?i2GDTCNCg8}+D?b^h&@9>HM{B>EXkbXO3PP4t3+L=Py@ zIqfqGg3_LiP!TNTj(}{K_lbofL9xz8_}vq3O|GbC!=6-FCi|H+6$a%u8{u2QLat0_ z!@lu}g^Gf*nvIYM7INh`8@A+_g$(Mpe26+l_{4^u;{uP_kWnu1n2d&8;4v9_{qYR` zknABOblrt1_a9T&XLq5sS1Lj3#}o%`)8Fb+pSm~-4h_EeZrA_S2C89DtD@K4N4keU z^1RL(4(ic+zxew`qJy{!ItvpOQj z4R%Y+t#@xuKQ^_FSqi`Yy0+J=ldo>Sf0ftsL%S&Z&Of%j9@CFLW8W)IzWUBT`b+-G zHa_N$`i70GbrB=eG0Xh^&#ob#q+y7Lp4;{A9}N*Dc8Z3JG$@$A|D6J%>|cTXWxouJ zi;4&TP0syg!WX;0y5sx>5w^I$*5mxyd{sREseiNdUJ83}l)W0t-u^UO-!IS`gRa!L zUW2`C$=;{5P}4VQSgc{#F*%+x&FiVrFhj%T8m`tbPs8;ZZq~3=!|fUp8t&0>%;Mg? z3cF9k*ERf|hJVt~t>Fh6ys=edPt||!LkkY8@p{HYwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* Gqk#Z>qSK!M diff --git a/SysCore/drivers/BSOD.c b/SysCore/drivers/BSOD.c deleted file mode 100644 index 14b5de4..0000000 --- a/SysCore/drivers/BSOD.c +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include - -char *exception_messages[] = { - "Division By Zero Exception", - "Debug Exception", - "Non Maskable Interrupt Exception", - "Breakpoint Exception", - "Into Detected Overflow Exception", - "Out of Bounds Exception", - "Invalid Opcode Exception", - "No Coprocessor", - "Double Fault Exception", - "Coprocessor Segment Overrun Exception", - "Bad TSS Exception", - "Segment Not Present Exception", - "Stack Fault Exception", - "General Protection Fault Exception", - "Page Fault Exception", - "Unknown Interrupt Exception", - "Coprocessor Fault Exception", - "Alignment Check Exception", - "Machine Check Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception", - "Reserved Exception" -}; - - -//void _STOP_ERROR_SCREEN (ISR_stack_regs *r) -//{ - //set_default_colors (0x01, 0x0F); clrscr(); - /*puts_pos (0, 0, " Blue Screen Of Death\n"); - int i; for (i = 79; i>=0; i--) putc('='); - puts_pos_font (15, 2, "A fatal error has occured, CTA OS has been halted.", 0x01, 0x0C); - puts_pos_font (10, 4, "gs", 0x01, 0x0B); put_hex_pos(15, 4, r->gs); - puts_pos_font (10, 5, "fs", 0x01, 0x0B); put_hex_pos(15, 5, r->fs); - puts_pos_font (10, 6, "es", 0x01, 0x0B); put_hex_pos(15, 6, r->es); - puts_pos_font (10, 7, "ds", 0x01, 0x0B); put_hex_pos(15, 7, r->ds); - - puts_pos_font (40, 4, "edi", 0x01, 0x0B); put_hex_pos(45, 4, r->edi); - puts_pos_font (40, 5, "esi", 0x01, 0x0B); put_hex_pos(45, 5, r->esi); - puts_pos_font (40, 6, "ebp", 0x01, 0x0B); put_hex_pos(45, 6, r->ebp); - puts_pos_font (40, 7, "esp", 0x01, 0x0B); put_hex_pos(45, 7, r->esp); - - puts_pos_font (10, 9, "eax", 0x01, 0x0B); put_hex_pos(15, 9, r->eax); - puts_pos_font (10, 10, "ebx", 0x01, 0x0B); put_hex_pos(15, 10, r->ebx); - puts_pos_font (40, 9, "ecx", 0x01, 0x0B); put_hex_pos(45, 9, r->ecx); - puts_pos_font (40, 10, "edx", 0x01, 0x0B); put_hex_pos(45, 10, r->edx); - - puts_pos_font (10, 12, "int_no", 0x01, 0x0B); put_hex_pos(17, 12, r->int_no); - puts_pos_font (10, 14, "Error code:", 0x01, 0x0B); put_hex_pos(24, 14, r->err_code); - puts_pos_font (10, 15, "Error msg: ", 0x01, 0x0B); puts_pos(24, 15, exception_messages[r->int_no]); - - puts_pos_font (10, 17, "eip", 0x01, 0x0B); put_hex_pos(17, 17, r->eip); - puts_pos_font (10, 18, "cs", 0x01, 0x0B); put_hex_pos(17, 18, r->cs); - puts_pos_font (10, 19, "eflags", 0x01, 0x0B); put_hex_pos(17, 19, r->eflags); - puts_pos_font (10, 20, "useresp", 0x01, 0x0B); put_hex_pos(17, 20, r->useresp); - puts_pos_font (10, 21, "ss", 0x01, 0x0B); put_hex_pos(17, 21, r->ss); - - puts_pos_font (29, 24, "!!! System Halted !!!", 0x01, 0x0C);*/ -//} - -/*void _STOP_ERROR_SCREEN (ISR_stack_regs *r) -{ - puts_pos_font (30, 24, "Stop error 0x", 0x01, 0x0B); put_hex_pos(37, 24, r->int_no); - puts_pos(50, 24, exception_messages[r->int_no]); - - puts_pos_font (5, 24, "!!! System Halted !!!", 0x01, 0x0C); -}*/ - -void _STOP_ERROR_SCREEN (ISR_stack_regs *r) -{ - cprintf ("%#0C** Fatal Error: "); cprintf("%#0E %s \n\r", exception_messages[r->int_no]); - for (;;); -} \ No newline at end of file diff --git a/SysCore/drivers/clock/clock.h b/SysCore/drivers/clock/clock.h deleted file mode 100644 index 1f18cc9..0000000 --- a/SysCore/drivers/clock/clock.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __PIT_H -#define __PIT_H - -#include -#include - -extern void i86_PitHandler(ISR_stack_regs *r); -extern void i86_PitInitialize(int freq); -extern unsigned char PitIsInitialized(); -extern void PitSetFrequency(int frequency); -extern unsigned int PitGetFrequency(); - -extern TIME ClockGetTime(); -extern unsigned int ClockSetTickCount(unsigned int i); -extern unsigned int ClockGetTickCount(); - -extern void i86_SetRTC (const TIME* time); -extern void i86_GetRTC(TIME* tim); - -#endif \ No newline at end of file diff --git a/SysCore/drivers/clock/pit.c b/SysCore/drivers/clock/pit.c deleted file mode 100644 index 98d96a0..0000000 --- a/SysCore/drivers/clock/pit.c +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include -#include "clock.h" - -volatile unsigned int ClockTicks = 0; -volatile unsigned int ClockFrequency = 0; -unsigned char PitInitialized = 0; -volatile TIME _InternalClock; - - -void PitSetFrequency(int frequency) -{ - int divisor = 1193180/frequency; // Calculate the divisor - outportb(0x43, 0x36); // Set our command byte 0x36 - outportb(0x40, divisor&0xFF); // Set low byte - outportb(0x40, divisor>>8); // Set high byte - ClockFrequency = frequency; -} - -void i86_PitHandler(ISR_stack_regs *r) -{ - ClockTicks++; // count tick - if (ClockTicks % ClockFrequency == 0) - _CLOCK_INC((TIME*)&_InternalClock); // update internal clock -} - -unsigned int ClockSetTickCount(unsigned int i) -{ - unsigned int r = ClockTicks; - ClockTicks = i; - return r; -} - -unsigned int ClockGetTickCount() -{ - return ClockTicks; -} -unsigned int PitGetFrequency() -{ - return ClockFrequency; -} - -void i86_PitInitialize(int freq) -{ - PitSetFrequency(freq); - ClockTicks = 0; - - i86_GetRTC((TIME*) &_InternalClock); - - PitInitialized = 1; -} - -TIME ClockGetTime() -{ - return _InternalClock; -} - -unsigned char PitIsInitialized() -{ - return PitInitialized; -} - - -inline unsigned char CmosRead (unsigned char address) -{ - outportb(0x70, address); iowait(); - return inportb(0x71); -} - -inline void CmosWrite (unsigned char address, unsigned char val) -{ - outportb(0x70, address); iowait(); - outportb(0x71, val); -} - -void i86_SetRTC (const TIME* time) -{ - unsigned char BCD = ((CmosRead(0x0b)&4)==0) ? 1 : 0; - unsigned char ampm = ((CmosRead(0x0b)&2)==0) ? 1 : 0; - - CmosWrite (0, (BCD) ? (time->second%10) | (time->second/10*16) : time->second); // Seconds - CmosWrite (2, (BCD) ? (time->minute%10) | (time->minute/10*16) : time->minute); // Minutes - - if (ampm && time->hour > 12) // Hours - CmosWrite (4, (BCD) ? (((time->hour - 12) % 10) | ((time->hour - 12)/10*16) | 0x80) : (time->hour | 0x80) ); - - else if (ampm && time->hour == 0) // Midnight convention: 12 PM = 00:00 - CmosWrite (4, (BCD) ? 0x92 : 0x8C); - - else CmosWrite (4, (BCD) ? (time->hour%10) | (time->hour/10*16) : time->hour); // 24h / AM - - CmosWrite (6, (BCD) ? (time->weekday%10) | (time->weekday/10*16) : time->weekday); // Weekday - CmosWrite (7, (BCD) ? (time->day%10) | (time->day/10*16) : time->day); // Day - CmosWrite (8, (BCD) ? (time->month%10) | (time->month/10*16) : time->month); // Month - CmosWrite (9, (BCD) ? (time->year%10) | (time->year/10*16) : time->year); // Year - CmosWrite (0x32, (BCD) ? (time->century%10) | (time->century/10*16) : time->century); // Century -} - -void i86_GetRTC(TIME* tim) -{ - unsigned char BCD = ((CmosRead(0x0b)&4)==0) ? 1 : 0; - unsigned char am_pm = ((CmosRead(0x0b)&2)==0) ? 1 : 0; - - tim->second = (BCD) ? (CmosRead(0x00)%16) + 10*(CmosRead(0x00)/16): CmosRead(0x00); - tim->minute = (BCD) ? (CmosRead(0x02)%16) + 10*(CmosRead(0x02)/16): CmosRead(0x02); - - // Time is PM - if (am_pm && CmosRead(0x04)&80) { - tim->hour = (BCD) ? ((CmosRead(0x04)-0x80)%16) + 10*((CmosRead(0x04)-0x80)/16): CmosRead(0x04)-0x80; - tim->hour += 12; - } - // 24Hour format, or AM - else tim->hour = (BCD) ? (CmosRead(0x04)%16) + 10*(CmosRead(0x04)/16): CmosRead(0x04); - - tim->weekday = (BCD) ? (CmosRead(0x06)%16) + 10*(CmosRead(0x06)/16): CmosRead(0x06); - tim->day = (BCD) ? (CmosRead(0x07)%16) + 10*(CmosRead(0x07)/16): CmosRead(0x07); - tim->month = (BCD) ? (CmosRead(0x08)%16) + 10*(CmosRead(0x08)/16): CmosRead(0x08); - tim->year = (BCD) ? (CmosRead(0x09)%16) + 10*(CmosRead(0x09)/16): CmosRead(0x09); - tim->century = (BCD) ? (CmosRead(0x32)%16) + 10*(CmosRead(0x32)/16): CmosRead(0x32); -} \ No newline at end of file diff --git a/SysCore/drivers/compile.bat b/SysCore/drivers/compile.bat deleted file mode 100644 index 9f96b12..0000000 --- a/SysCore/drivers/compile.bat +++ /dev/null @@ -1,43 +0,0 @@ -@echo off - -set loader_name=loader -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin - - -@echo ***************** CTA KERNEL ***************** - -:KernelEntry - @echo. - @echo Building Kernel entry... - @echo * Compiling kernel loader... - %nasm_path%\nasm.exe -f aout -o ./objects/%loader_name%.o %loader_name%.asm - - @echo * Compiling kernel main... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I./include -c -o ./objects/main.o main.c - - -:KernelSTDLIB - cd lib - call compile.bat - cd.. - -:KernelMemoryManager - cd memory - call compile.bat - cd.. - - -rem here go other sources: - -rem here go other sources ^ - -:Finish - cd objects - @echo Linking... - %djgpp_path%\ld -T link.ld - @echo. - - echo Copying to floppy drive... - copy KERNEL.BIN A:\KERNEL.CTA - cd.. \ No newline at end of file diff --git a/SysCore/drivers/cpu/compile.bat b/SysCore/drivers/cpu/compile.bat deleted file mode 100644 index 008276d..0000000 --- a/SysCore/drivers/cpu/compile.bat +++ /dev/null @@ -1,18 +0,0 @@ -@echo off -rem The name of the loader assembly file (without extension, must be .asm): -set loader_name=loader - -rem NASM and DJGPP executable paths: -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin -set objpath=../../objects -set incpath=../../include - -@echo on -%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/cpu.o cpu.c - -@echo off -@echo . -@echo Done! - -@pause diff --git a/SysCore/drivers/cpu/cpu.c b/SysCore/drivers/cpu/cpu.c deleted file mode 100644 index 6ed094f..0000000 --- a/SysCore/drivers/cpu/cpu.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "cpu.h" -#include "gdt/gdt.h" -#include "idt/idt.h" -#include "irq/irq.h" -#include "isrs/isrs.h" - -#define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in)); - -// initializes cpu resources -void i86_CpuInitialize() -{ - i86_GdtInstall(); - i86_IdtInstall(); - i86_IsrsInstall(); - i86_IrqInstall(); -} - -void i86_CpuShutdown() -{ - -} - -char* i86_CpuGetVendor() -{ - unsigned unused; - unsigned static arr[3]; - - cpuid(0, unused, arr[0], arr[2], arr[1]); - - return (char*) arr; -} - -_R32BIT i86_CpuID(unsigned function) -{ - _R32BIT ret = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - cpuid(function, ret.eax, ret.ebx, ret.ecx, ret.edx); - return ret; -} \ No newline at end of file diff --git a/SysCore/drivers/cpu/cpu.h b/SysCore/drivers/cpu/cpu.h deleted file mode 100644 index 3953c57..0000000 --- a/SysCore/drivers/cpu/cpu.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _CPU_H_INCLUDED -#define _CPU_H_INCLUDED - -#include -#include -#include "gdt/gdt.h" -#include "idt/idt.h" -#include "irq/irq.h" -#include "irq/pic.h" -#include "isrs/isrs.h" - - -extern void i86_CpuInitialize (); -extern void i86_CpuShutdown (); -extern char* i86_CpuGetVendor (); - -#endif diff --git a/SysCore/drivers/cpu/irq/irq.c b/SysCore/drivers/cpu/irq/irq.c deleted file mode 100644 index ad502e3..0000000 --- a/SysCore/drivers/cpu/irq/irq.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include "pic.h" -#include "irq.h" -#include "../idt/idt.h" - -/* These are own ISRs that point to our special IRQ handler -* instead of the regular 'fault_handler' function */ -extern void i86_irq0(); -extern void i86_irq1(); -extern void i86_irq2(); -extern void i86_irq3(); -extern void i86_irq4(); -extern void i86_irq5(); -extern void i86_irq6(); -extern void i86_irq7(); -extern void i86_irq8(); -extern void i86_irq9(); -extern void i86_irq10(); -extern void i86_irq11(); -extern void i86_irq12(); -extern void i86_irq13(); -extern void i86_irq14(); -extern void i86_irq15(); - -/* This array is actually an array of function pointers. We use -* this to handle custom IRQ handlers for a given IRQ */ -void *IrqRoutines[16] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* This installs a custom IRQ handler for the given IRQ */ -void i86_IrqInstallHandler (int irq, void (*handler)(ISR_stack_regs *r)) -{ - IrqRoutines[irq] = handler; -} - -void i86_IrqUninstallHandler (int irq) -{ - IrqRoutines[irq] = 0; -} - - - -/* We first remap the interrupt controllers, and then we install -* the appropriate ISRs to the correct entries in the IDT. This -* is just like installing the exception handlers */ -void i86_IrqInstall() -{ - i86_PicRemap(32,40); - - i86_IdtSetGate(32, (unsigned)i86_irq0, 0x08, 0x8E); - i86_IdtSetGate(33, (unsigned)i86_irq1, 0x08, 0x8E); - i86_IdtSetGate(34, (unsigned)i86_irq2, 0x08, 0x8E); - i86_IdtSetGate(35, (unsigned)i86_irq3, 0x08, 0x8E); - i86_IdtSetGate(36, (unsigned)i86_irq4, 0x08, 0x8E); - i86_IdtSetGate(37, (unsigned)i86_irq5, 0x08, 0x8E); - i86_IdtSetGate(38, (unsigned)i86_irq6, 0x08, 0x8E); - i86_IdtSetGate(39, (unsigned)i86_irq7, 0x08, 0x8E); - i86_IdtSetGate(40, (unsigned)i86_irq8, 0x08, 0x8E); - i86_IdtSetGate(41, (unsigned)i86_irq9, 0x08, 0x8E); - i86_IdtSetGate(42, (unsigned)i86_irq10, 0x08, 0x8E); - i86_IdtSetGate(43, (unsigned)i86_irq11, 0x08, 0x8E); - i86_IdtSetGate(44, (unsigned)i86_irq12, 0x08, 0x8E); - i86_IdtSetGate(45, (unsigned)i86_irq13, 0x08, 0x8E); - i86_IdtSetGate(46, (unsigned)i86_irq14, 0x08, 0x8E); - i86_IdtSetGate(47, (unsigned)i86_irq15, 0x08, 0x8E); -} - -/* Each of the IRQ ISRs point to this function, rather than -* the 'fault_handler' in 'isrs.c'. The IRQ Controllers need -* to be told when you are done servicing them, so you need -* to send them an "End of Interrupt" command (0x20). There -* are two 8259 chips: The first exists at 0x20, the second -* exists at 0xA0. If the second controller (an IRQ from 8 to -* 15) gets an interrupt, you need to acknowledge the -* interrupt at BOTH controllers, otherwise, you only send -* an EOI command to the first controller. If you don't send -* an EOI, you won't raise any more IRQs */ -void i86_IrqHandler (ISR_stack_regs *r) -{ - /* This is a blank function pointer */ - void (*handler)(ISR_stack_regs *r); - - /* Find out if we have a custom handler to run for this - * IRQ, and then finally, run it */ - handler = IrqRoutines[r->int_no - 32]; - if (handler) handler(r); - - /* If the IDT entry that was invoked was greater than 40 - * (meaning IRQ8 - 15), then we need to send an EOI to - * the slave controller */ - if (r->int_no >=40) outportb(0x0A, 0x20); - - /* In either case, we need to send an EOI to the master - * interrupt controller too */ - outportb(0x20, 0x20); -} diff --git a/SysCore/drivers/cpu/irq/irq.h b/SysCore/drivers/cpu/irq/irq.h deleted file mode 100644 index 77d3c33..0000000 --- a/SysCore/drivers/cpu/irq/irq.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __IRQ_H -#define __IRQ_H - -#include - -extern void i86_IrqInstallHandler (int irq, void (*handler)(ISR_stack_regs *r)); -extern void i86_IrqUninstallHandler (int irq); -extern void i86_IrqInstall(); - -#endif \ No newline at end of file diff --git a/SysCore/drivers/cpu/irq/pic.h b/SysCore/drivers/cpu/irq/pic.h deleted file mode 100644 index f6d9075..0000000 --- a/SysCore/drivers/cpu/irq/pic.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _PIC_H -#define _PIC_H - -extern void i86_PicRemap(int pic1, int pic2); - -#endif \ No newline at end of file diff --git a/SysCore/drivers/cpu/isrs/isrs.c b/SysCore/drivers/cpu/isrs/isrs.c deleted file mode 100644 index 5ce59d6..0000000 --- a/SysCore/drivers/cpu/isrs/isrs.c +++ /dev/null @@ -1,115 +0,0 @@ -#include -#include -#include "isrs.h" -#include "../idt/idt.h" - -// Assembly coded -extern void i86_isr0(); -extern void i86_isr1(); -extern void i86_isr2(); -extern void i86_isr3(); -extern void i86_isr4(); -extern void i86_isr5(); -extern void i86_isr6(); -extern void i86_isr7(); -extern void i86_isr8(); -extern void i86_isr9(); -extern void i86_isr10(); -extern void i86_isr11(); -extern void i86_isr12(); -extern void i86_isr13(); -extern void i86_isr14(); -extern void i86_isr15(); -extern void i86_isr16(); -extern void i86_isr17(); -extern void i86_isr18(); -extern void i86_isr19(); -extern void i86_isr20(); -extern void i86_isr21(); -extern void i86_isr22(); -extern void i86_isr23(); -extern void i86_isr24(); -extern void i86_isr25(); -extern void i86_isr26(); -extern void i86_isr27(); -extern void i86_isr28(); -extern void i86_isr29(); -extern void i86_isr30(); -extern void i86_isr31(); - - -void* IdtFaultHandlers[32] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - }; - -void i86_IsrsInstall() -{ - i86_IdtSetGate(0, (unsigned)i86_isr0, 0x08, 0x8E); - i86_IdtSetGate(1, (unsigned)i86_isr1, 0x08, 0x8E); - i86_IdtSetGate(2, (unsigned)i86_isr2, 0x08, 0x8E); - i86_IdtSetGate(3, (unsigned)i86_isr3, 0x08, 0x8E); - i86_IdtSetGate(4, (unsigned)i86_isr4, 0x08, 0x8E); - i86_IdtSetGate(5, (unsigned)i86_isr5, 0x08, 0x8E); - i86_IdtSetGate(6, (unsigned)i86_isr6, 0x08, 0x8E); - i86_IdtSetGate(7, (unsigned)i86_isr7, 0x08, 0x8E); - i86_IdtSetGate(8, (unsigned)i86_isr8, 0x08, 0x8E); - i86_IdtSetGate(9, (unsigned)i86_isr9, 0x08, 0x8E); - i86_IdtSetGate(10, (unsigned)i86_isr10, 0x08, 0x8E); - i86_IdtSetGate(11, (unsigned)i86_isr11, 0x08, 0x8E); - i86_IdtSetGate(12, (unsigned)i86_isr12, 0x08, 0x8E); - i86_IdtSetGate(13, (unsigned)i86_isr13, 0x08, 0x8E); - i86_IdtSetGate(14, (unsigned)i86_isr14, 0x08, 0x8E); - i86_IdtSetGate(15, (unsigned)i86_isr15, 0x08, 0x8E); - i86_IdtSetGate(16, (unsigned)i86_isr16, 0x08, 0x8E); - i86_IdtSetGate(17, (unsigned)i86_isr17, 0x08, 0x8E); - i86_IdtSetGate(18, (unsigned)i86_isr18, 0x08, 0x8E); - i86_IdtSetGate(19, (unsigned)i86_isr19, 0x08, 0x8E); - i86_IdtSetGate(20, (unsigned)i86_isr20, 0x08, 0x8E); - i86_IdtSetGate(21, (unsigned)i86_isr21, 0x08, 0x8E); - i86_IdtSetGate(22, (unsigned)i86_isr22, 0x08, 0x8E); - i86_IdtSetGate(23, (unsigned)i86_isr23, 0x08, 0x8E); - i86_IdtSetGate(24, (unsigned)i86_isr24, 0x08, 0x8E); - i86_IdtSetGate(25, (unsigned)i86_isr25, 0x08, 0x8E); - i86_IdtSetGate(26, (unsigned)i86_isr26, 0x08, 0x8E); - i86_IdtSetGate(27, (unsigned)i86_isr27, 0x08, 0x8E); - i86_IdtSetGate(28, (unsigned)i86_isr28, 0x08, 0x8E); - i86_IdtSetGate(29, (unsigned)i86_isr29, 0x08, 0x8E); - i86_IdtSetGate(30, (unsigned)i86_isr30, 0x08, 0x8E); - i86_IdtSetGate(31, (unsigned)i86_isr31, 0x08, 0x8E); -} - - -void i86_IsrsInstallHandler(int interr, void (*function)(ISR_stack_regs *r)) -{ - if (interr < 32) IdtFaultHandlers[interr] = function; -} - -void i86_IsrsUninstallHandler(int interr) -{ - if (interr < 32) IdtFaultHandlers[interr] = 0; -} - -/* All of our Exception handling Interrupt Service Routines will -* point to this function. This will tell us what exception has -* happened! Right now, we simply halt the system by hitting an -* endless loop. All ISRs disable interrupts while they are being -* serviced as a 'locking' mechanism to prevent an IRQ from -* happening and messing up kernel data structures */ -void i86_FaultHandler(ISR_stack_regs *r) -{ - /* Is this a fault whose number is from 0 to 31? */ - if (r->int_no < 32) - { - void (*func)(ISR_stack_regs *r); - func = IdtFaultHandlers[r->int_no]; - - // Halt system if unhandled - if (!func) { - cprintf("%#0C*** %#0EFatal error: Unhandled interrupt (INT%u)", r->int_no); - for(;;); - } - - else (*func)(r); - } -} diff --git a/SysCore/drivers/cpu/isrs/isrs.h b/SysCore/drivers/cpu/isrs/isrs.h deleted file mode 100644 index 4dd2425..0000000 --- a/SysCore/drivers/cpu/isrs/isrs.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ISRS_H_ -#define __ISRS_H_ - -extern void i86_IsrsInstall(); -extern void i86_IsrsInstallHandler(int interr, void (*function)(ISR_stack_regs *r)); -extern void i86_IsrsUninstallHandler(int interr); - -#endif \ No newline at end of file diff --git a/SysCore/drivers/drivers.c b/SysCore/drivers/drivers.c deleted file mode 100644 index 8a93d14..0000000 --- a/SysCore/drivers/drivers.c +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include "cpu/cpu.h" -#include "clock/clock.h" -#include "floppy/floppy.h" -#include -//BSOD - -extern void _STOP_ERROR_SCREEN(ISR_stack_regs *); - -void DriversInstall() -{ - // Initialize CPU stuff (GDT, IDT etc) - i86_CpuInitialize(); - - // Install default fault handler - int i; - for (i=0; i<32; i++) - i86_IsrsInstallHandler(i, _STOP_ERROR_SCREEN); - - - // Start installing keyboard - i86_IrqInstallHandler(1, i86_KeyboardHandler); - KeyboardInstallA(); - - // Install PIT - i86_PitInitialize(100); - i86_IrqInstallHandler(0, i86_PitHandler); - - // Finish installing keyboard - KeyboardInstallB(); - - // Install floppy driver - asm volatile ("sti"); - i86_IrqInstallHandler(6, i86_FloppyHandler); - FloppyInstall(); - -} - -void SystemShutDown() -{ - i86_CpuShutdown(); - // TODO: real shutdown -} - -void SystemReboot() -{ - unsigned char good = 0x02; - while ((good & 0x02) != 0) - good = inportb(0x64); - outportb(0x64, 0xFE); - - asm volatile ("cli"); - asm volatile ("hlt"); -} - diff --git a/SysCore/drivers/drivers.h b/SysCore/drivers/drivers.h deleted file mode 100644 index 57840e0..0000000 --- a/SysCore/drivers/drivers.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __DRIVERS__H__ -#define __DRIVERS__H__ - - -extern void DriversInstall(); -extern void SystemShutDown(); -extern void SystemReboot(); - -#endif \ No newline at end of file diff --git a/SysCore/drivers/filesys/fat.c b/SysCore/drivers/filesys/fat.c deleted file mode 100644 index fe82398..0000000 --- a/SysCore/drivers/filesys/fat.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "../floppy/floppy.h" -//#include "vfs.h" -#include "fat.h" - -#include - -// Detect what FAT is used -unsigned FATDetect(unsigned TotalClusters) -{ - if (TotalClusters == 0) return 0; - if (TotalClusters < 4085) return 12; - if (TotalClusters < 65525) return 16; - return 32; -} - - - -/*FatMountInfo FloppyMount(int drive) -{ - FatMountInfo a; - FATBootSectorPointer fat = (FATBootSectorPointer)0x7e00; - FloppyReadSector((unsigned*)fat, drive, 0); - - // Write mount info - a.FATEntrySize = 8; - a.FATOffset = 1; - a.FATSize = (unsigned)fat->SectorsPerFAT; - a.NumberOfRootEntries = (unsigned)fat->NumberOfDirectoryEntries; - a.NumberOfSectors = (unsigned)(fat->NumberOfSectors == 0) ? (fat->NumberOfSectorsLong) : (fat->NumberOfSectors); - a.RootOffset = (unsigned)(fat->NumberOfFATs)*a.FATSize + 1; - a.RootSize = (a.NumberOfRootEntries * 32) / (unsigned)fat->BytesPerSector; - - return a; -}*/ \ No newline at end of file diff --git a/SysCore/drivers/filesys/fat.h b/SysCore/drivers/filesys/fat.h deleted file mode 100644 index d84e318..0000000 --- a/SysCore/drivers/filesys/fat.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef __FAT_H__ -#define __FAT_H__ - -typedef struct { - unsigned char Drive; //useless - unsigned char FlagsNT; - unsigned char Signature; // 0x28 or 0x29 - unsigned SerialNumber; - char VolumeLabel[11]; - char SysIDString[8]; // unreliable -} __attribute__((packed)) BPB_EXT_16; - - -typedef struct { - unsigned SectorsPerFAT; - unsigned short Flags; - unsigned short Version; - unsigned ClusterOfRootDirectory; - unsigned short ClusterOfFSInfo; - unsigned short ClusterOfBackupBootSector; - unsigned char Reserved[12]; // Should be 0 at format - unsigned char Drive; - unsigned char FlagsNT; - unsigned char Signature; // 0x28 or 0x29 - unsigned SerialNumber; - char VolumeLabel[11]; - char SysIDString[8]; // always FAT12 - -} __attribute__((packed)) BPB_EXT_32; - - -typedef struct { - unsigned char _ignore[3]; - - // Bios Parameter Block - char OEMIdentify[8]; - unsigned short BytesPerSector; - unsigned char SectorsPerCluster; - unsigned short ReservedSectors; - unsigned char NumberOfFATs; - unsigned short NumberOfDirectoryEntries; - unsigned short NumberOfSectors; - unsigned char MediaDescriptorType; - unsigned short SectorsPerFAT; - unsigned short SectorsPerTrack; - unsigned short HeadsPerCylinder; - unsigned HiddenSectors; - unsigned NumberOfSectorsLong; - - union { - BPB_EXT_16 Ext16; - BPB_EXT_32 Ext32; - } Extended; - -} __attribute__((packed)) FATBootSector, *FATBootSectorPointer; - - -typedef struct { - unsigned NumberOfSectors; - unsigned SizeOfSector; - unsigned FatOffset; - unsigned NumberOfRootEntries; - unsigned RootOffset; - unsigned SizeOfRoot; - unsigned SizeOfFat; - unsigned SizeOfFatEntry; - unsigned SizeOfCluster; - void (*ReadSector) (void* buffer, int lba); -} FatMountInfo, *FatMountInfoPointer; - - -typedef struct { - char FileName[8]; - char Extension[3]; - unsigned char Atributes; - unsigned char Reserved; - unsigned char CreateTimeFine; - unsigned short CreateTime; - unsigned short CreateDate; - unsigned short LastAccessedDate; - unsigned short EAIndex; - unsigned short LastModifiedTime; - unsigned short LastModifiedDate; - unsigned short FirstCluster; - unsigned FileSize; -} __attribute__((packed)) FatDirectoryEntry, *FatDirectoryEntryPointer; - - -extern FatMountInfo FloppyMount(int drive); - -#endif \ No newline at end of file diff --git a/SysCore/drivers/filesys/vfs.c b/SysCore/drivers/filesys/vfs.c deleted file mode 100644 index 9009d38..0000000 --- a/SysCore/drivers/filesys/vfs.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "vfs.h" -#define MaxDevices 256 - -#define ReturnInvalid() { File ret; ret.Type = FileTypeInvalid; return ret;} - -unsigned CurrentDevice = 0; -unsigned DeviceCount = 0; - -FileSystemPointer _FileSystems[MaxDevices]; - -File VFSOpenFile (const char* FileName) -{ - unsigned Device = CurrentDevice; - - // No filename specified. - if (!FileName) ReturnInvalid(); - - // File length - int len = strlen(FileName); - // File name without drive - char* Name = 0; - - // Check if relative or absolute path - int i; - for (i=0; i < len; i++) - if (FileName[i] == ':') { - Name = &FileName[i+1]; - FileName[i] = 0; - len = i; - } - - // If absolute path, find device - if (Name != 0) { - for (i=0; i < MaxDevices; i++) - if (_FileSystems[i]) { - if (strcmp(_FileSystems[i]->Name, FileName) == 0) Device = i; - } - } - // Drive is nonexistant or current drive not mounted - if (i==MaxDevices || !_FileSystems[Device]) ReturnInvalid(); - - // Open file - return _FileSystems[Device]->Open((Name) ? Name : FileName); -} - - -int VFSInstallFileSystem(FileSystemPointer fs) -{ - // Sanity check - if (!fs) return 0; - - // Verify device does not exist - int i; - for (i=0; i < DeviceCount; i++) - if (_FileSystems[i]) - if (strcmp (fs->Name, _FileSystems[i]->Name) == 0) return 0; - - _FileSystems[DeviceCount] = fs; DeviceCount++; -} - -void VFSUninstallFileSystem(FileSystemPointer fs) -{ - if (!fs) return; - - int i; - for (i=0; iName, fs) == 0){ - _FileSystems[i] = 0; - return; - } -} - -void VFSReadFile (FilePointer f, unsigned char* buffer, unsigned len) -{ - if (!f || !_FileSystems[f->Device]) return; - _FileSystems[f->Device]->Read (f, buffer, len); -} - -void VFSCloseFile (FilePointer f) -{ - if (!f || !_FileSystems[f->Device]) return; - _FileSystems[f->Device]->Close(f); -} - diff --git a/SysCore/drivers/filesys/vfs.h b/SysCore/drivers/filesys/vfs.h deleted file mode 100644 index 1a83b9f..0000000 --- a/SysCore/drivers/filesys/vfs.h +++ /dev/null @@ -1,57 +0,0 @@ -/***** vfs.h ********************************************************* - * (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * - * * - * Virtual File System (VFS) Implementation * - * ======================================== * - * * - ************************************************************ cta os */ -#ifndef __VFS__H___ -#define __VFS__H___ - -#include - -typedef enum { - FileTypeInvalid, - FileTypeFile, - FileTypeDirectory, - FileTypeSymbolicLink -} FileType; - -enum FileFlags { - FileFlagReadOnly = 0x1, - FileFlagHidden = 0x2, - FileFlagSystem = 0x4, - FileFlagVolumeID = 0x8, - FileFlagDirectory = 0x10, - FileFlagArchive = 0x20 -}; - - -typedef struct { - char Name[256]; - FileType Type; - unsigned Flags; - unsigned Length; - unsigned EndOfFile; - unsigned ID; - unsigned Position, CurrentCluster; - unsigned Device; - TIME Created; - DATE LastAccessed; - TIME LastModified; -} File, *FilePointer; - - -typedef struct { - char Name[256]; - - File (*Directory) (const char* DirectoryName); - void (*Mount) (); - void (*Read) (FilePointer, unsigned char*, unsigned); - void (*Close) (FilePointer); - FILE (*Open) (const char*); - -} FileSystem, *FileSystemPointer; - - -#endif diff --git a/SysCore/drivers/floppy/dma.c b/SysCore/drivers/floppy/dma.c deleted file mode 100644 index 1afe8cd..0000000 --- a/SysCore/drivers/floppy/dma.c +++ /dev/null @@ -1,137 +0,0 @@ -/***** dma.c ********************************************************* - * (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * - * * - * Direct Memory Access (DMA) Routines * - * =================================== * - * * - ************************************************************ cta os */ - -#include "dma.h" -#include - -enum DMA0InputOutput { - DMA0StatusRegister = 0x08, - DMA0CommandRegister = 0x08, - DMA0RequestRegister = 0x09, - DMA0ChannelMaskRegister = 0x0a, - DMA0ModeRegister = 0x0b, - DMA0ClearByteFlipFlopRegister = 0x0c, - DMA0TempRegister = 0x0d, - DMA0MasterClearRegister = 0x0d, - DMA0ClearMaskRegister = 0x0e, - DMA0MaskRegister = 0x0f -}; - -enum DMA1InputOutput { - DMA1StatusRegister = 0xd0, - DMA1CommandRegister = 0xd0, - DMA1RequestRegister = 0xd2, - DMA1ChannelMaskRegister = 0xd4, - DMA1ModeRegister = 0xd6, - DMA1ClearByteFlipFlopRegister = 0xd8, - DMA1InterRegister = 0xda, - DMA1UnmaskAllRegister = 0xdc, - DMA1MaskRegister = 0xde -}; - -void DMASetAddress(unsigned short channel, unsigned char low, unsigned char high) -{ - if (channel > 7) return; // Ignore if channel > 7 - - // Calculate port - unsigned short port = (channel >= 4) ? 4*(channel - 4) + 0xc0 : 2*channel; - - // Set address - outportb (port, low); - outportb (port, high); -} - - -void DMASetCount (unsigned short channel, unsigned char low, unsigned char high) -{ - if (channel > 7) return; // Ignore if channel > 7 - - // Calculate port - unsigned short port = (channel >= 4) ? 4*(channel - 4) + 0xc2 - : (2*channel) + 1; - - // Set count - outportb (port, low); - outportb (port, high); -} - - -void DMASetExternalPageRegisters (unsigned char channel, unsigned char val) -{ - unsigned short port = 0; - - switch (channel) { - case 1: port = 0x83; break; - case 2: port = 0x81; break; - case 3: port = 0x82; break; - // <- nothing should ever write to chan 4 - case 5: port = 0x89; break; - case 6: port = 0x87; break; - case 7: port = 0x88; break; - default: if (channel == 4 || channel > 14) return; - } - - outportb(port, val); -} - - -void DMAMaskChannel (unsigned char channel) -{ - if (channel <= 4) outportb (DMA0ChannelMaskRegister, (1<< (channel -1))); - else outportb (DMA1ChannelMaskRegister, (1<< (channel -5))); -} - - -void DMAUnmaskChannel (unsigned char channel) -{ - if (channel <= 4) outportb (DMA0ChannelMaskRegister, channel); - else outportb (DMA1ChannelMaskRegister, channel); -} - - -void DMAUnmaskAll() -{ - outportb (DMA1UnmaskAllRegister, 0xff); -} - - -void DMAResetFlipFlop (unsigned char dma) -{ - switch (dma) { - case 0: outportb (DMA0ClearByteFlipFlopRegister, 0xff); - case 1: outportb (DMA1ClearByteFlipFlopRegister, 0xff); - } -} - -void DMAReset () -{ - outportb (DMA0TempRegister, 0xff); -} - - -void DMASetMode(unsigned char channel, unsigned char mode) -{ - unsigned char dma = (channel < 4) ? 0:1; - unsigned char chan = (dma == 0) ? channel : channel-4; - - DMAMaskChannel (channel); - outportb ((channel < 4) ? DMA0ModeRegister : DMA1ModeRegister, chan | mode); - DMAUnmaskAll (); -} - - -void DMASetRead (unsigned char channel) -{ - DMASetMode (channel, DMAModeReadTransfer | DMAModeTransferSingle); -} - - -void DMASetWrite (unsigned char channel) -{ - DMASetMode (channel, DMAModeWriteTransfer | DMAModeTransferSingle); -} diff --git a/SysCore/drivers/floppy/dma.h b/SysCore/drivers/floppy/dma.h deleted file mode 100644 index a687e16..0000000 --- a/SysCore/drivers/floppy/dma.h +++ /dev/null @@ -1,42 +0,0 @@ -/***** dma.h ********************************************************* - * (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * - * * - * Direct Memory Access (DMA) Routines * - * =================================== * - * * - ************************************************************ cta os */ - -#ifndef __DMA__H__ -#define __DMA__H__ - -enum DMA_MODE_REG_MASK { - DMAModeMaskSelect = 3, - - DMAModeMaskTra = 0xc, - DMAModeSelfTest = 0, - DMAModeReadTransfer = 4, - DMAModeWriteTransfer = 8, - - DMAModeMaskAuto = 0x10, - DMAModeMaskIdec = 0x20, - - DMAModeMask = 0xc0, - DMAModeTransferOnDemand = 0, - DMAModeTransferSingle = 0x40, - DMAModeTransferBlock = 0x80, - DMAModeTransferCascade = 0xC0 -}; - -extern void DMASetAddress(unsigned short channel, unsigned char low, unsigned char high); -extern void DMASetCount (unsigned short channel, unsigned char low, unsigned char high); -extern void DMASetExternalPageRegisters (unsigned char channel, unsigned char val); -extern void DMAMaskChannel (unsigned char channel); -extern void DMAUnmaskChannel (unsigned char channel); -extern void DMAUnmaskAll(); -extern void DMAResetFlipFlop (unsigned char dma); -extern void DMAReset (); -extern void DMASetMode(unsigned char channel, unsigned char mode); -extern void DMASetRead (unsigned char channel); -extern void DMASetWrite (unsigned char channel); - -#endif \ No newline at end of file diff --git a/SysCore/drivers/floppy/floppy.c b/SysCore/drivers/floppy/floppy.c deleted file mode 100644 index ff3b499..0000000 --- a/SysCore/drivers/floppy/floppy.c +++ /dev/null @@ -1,494 +0,0 @@ -/***** floppy.c ****************************************************** - * (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * - * * - * Floppy Drive I/O Routines * - * ========================= * - * * - ************************************************************ cta os */ -#include -#include -#include -#include "dma.h" -#include "storage.h" - -unsigned char CmosReadFloppyData () -{ - outportb (0x70, 0x10); - return inportb(0x71); -} - -unsigned char FloppyDrivesInstalled; -volatile unsigned char FloppyNewInterrupt; - - -typedef struct { - unsigned char Type; - unsigned Size; - unsigned char SectorsPerTrack; - unsigned char Heads; - unsigned char Tracks; - unsigned char DataRate; - unsigned char StepRateTime; - unsigned char HeadLoadTime; - unsigned char HeadUnloadTime; - unsigned char Gap3; - unsigned char Gap3Format; -} FloppyType; - -FloppyType fd[2]; - -void FloppyReset(); -enum FloppyRegisters { - FloppyRegDOR = 0x3f2, - FloppyRegMSR = 0x3f4, - FloppyRegFIFO = 0x3f5, - FloppyRegCTRL = 0x3f7 -}; - -enum FloppyCommands { - FloppyCommandReadTrack = 2, - FloppyCommandSpecify = 3, - FloppyCommandCheckStatus = 4, - FloppyCommandWriteSector = 5, - FloppyCommandReadSector = 6, - FloppyCommandCalibrate = 7, - FloppyCommandCheckInt = 8, - FloppyCommandFormatTrack = 0xd, - FloppyCommandSeek = 0xf, - - FloppyCommandExtSkip = 0x20, - FloppyCommandExtDensity = 0x40, - FloppyCommandExtMultiTrack = 0x80 -}; - -// Initialize DMA -unsigned char FloppyInitializeDMA(unsigned char* buffer, unsigned length) -{ - union { unsigned char byt[4]; // Low[0], Mid[1], Hi[2] - unsigned long l; - } a, c; - - a.l = (unsigned) buffer; - c.l = (unsigned) length-1; - - // Check for buffer issues - if ((a.l >> 24) || (c.l >> 16) || (((a.l & 0xffff)+c.l) >> 16)) return 0; - - DMAReset(); - DMAMaskChannel(2); // Mask channel 2 - DMAResetFlipFlop(1); // FlipFlop reset on DMA1 - - DMASetAddress(2, a.byt[0], a.byt[1]); // Buffer address - DMAResetFlipFlop(1); // FlipFlop reset on DMA2 - - DMASetCount(2, c.byt[0], c.byt[1]); // Set count - DMASetRead(2); - DMAUnmaskAll(); - - return 1; -} - - - - -inline void FloppyDisableController() { - outportb (FloppyRegDOR, 0); -} - -inline void FloppyEnableController() { - outportb (FloppyRegDOR, 4 | 8); -} - - -inline unsigned char FloppySendCommand (unsigned char command) -{ - int i; - for (i = 0; i < 750; i++) - if (inportb(FloppyRegMSR) & 128) { - outportb(FloppyRegFIFO, command); return 1; - } - return 0; -} - - -inline unsigned char FloppyReadData () -{ - int i; - for (i = 0; i < 750; i++) - if (inportb(FloppyRegMSR) & 0x80) - return inportb(FloppyRegFIFO); - return 0; -} - - -inline void FloppyCheckInt(unsigned* st0, unsigned* cyl) -{ - int t; - for (t=3; t>=0; t--) { - if (!FloppySendCommand(0x8)) FloppyReset(); - else break; - } - for (t=50; !(inportb(FloppyRegMSR) & 0x80) && t>0; --t); - - *st0 = FloppyReadData(); - *cyl = FloppyReadData(); -} - - -inline unsigned char FloppyWaitIRQ() -{ - unsigned tick = ClockGetTickCount(); - unsigned freq = PitGetFrequency(); - tick = tick + (freq * 3); // Wait 3 seconds - - while (FloppyNewInterrupt==0) - if (tick <= ClockGetTickCount()) return 0; // timeout - - FloppyNewInterrupt = 0; - return 1; -} - - -void FloppyMotor (unsigned char drive, unsigned char on) -{ - if (drive >= FloppyDrivesInstalled) return; - - // Read DOR register - unsigned char dor = inportb(FloppyRegDOR); - - // Un/set selected drive motor - if (on) dor |= 1 << (4+drive); - else dor &= ~(1 << (4+drive)); - - // Write DOR - outportb (FloppyRegDOR, dor); - - // Wait a fifth of a second for motor to turn on - unsigned temp = ClockGetTickCount(); - unsigned freq = PitGetFrequency(); - while (temp + (freq/5) > ClockGetTickCount()); -} - - -void i86_FloppyHandler(ISR_stack_regs *r) -{ - FloppyNewInterrupt = 1; -} - - -void FloppyDriveData (unsigned char drv, unsigned char dma) -{ - unsigned data = 0; - if (drv >= FloppyDrivesInstalled) return; - - outportb(FloppyRegCTRL, fd[drv].DataRate); - - FloppySendCommand (0x3); - - data = ((fd[drv].StepRateTime & 0xf) << 4) | (fd[drv].HeadUnloadTime & 0xf); - FloppySendCommand (data); - - data = (fd[drv].HeadLoadTime <<1 ) | (dma) ? 1 : 0; - FloppySendCommand (data); -} - - -inline void FloppySelect(unsigned char drive) -{ - if (drive >= FloppyDrivesInstalled) return; - - unsigned char dor = inportb(FloppyRegDOR) & 0xf0; - - // Send mechanical drive data - FloppyDriveData(drive, 1); - - // Select drive in DOR register - outportb (FloppyRegDOR, dor | 4 | 8 | drive); - -} - - -unsigned char FloppyCalibrate(unsigned drive) -{ - unsigned st0, cyl; - - if (drive >= FloppyDrivesInstalled) return 0; - - FloppyMotor (drive, 1); - - int i; - for (i = 0; i < 15; i++) { - FloppyNewInterrupt = 0; - FloppySendCommand(FloppyCommandCalibrate); - FloppySendCommand(drive); - FloppyWaitIRQ(); - FloppyCheckInt(&st0, &cyl); - - if (!cyl) { - FloppyMotor(drive, 0); - return 1; - } - } - FloppyMotor(drive, 0); - return 0; -} - - -void FloppyReset() -{ - unsigned st0, cyl; - - FloppyNewInterrupt = 0; - FloppyDisableController(); - FloppyEnableController(); - FloppyWaitIRQ(); - - int i; - for (i = 0; i < 4; i++) - FloppyCheckInt(&st0, &cyl); - - unsigned char drive; - for (drive = 0; drive < FloppyDrivesInstalled; drive++) { - FloppyDriveData(drive, 1); - FloppyCalibrate(drive); - } -} - - -unsigned FloppyReadSectorImp (unsigned* where, unsigned char drive, unsigned char head, unsigned char track, unsigned char sector) -{ - int t, fail; - for (t=3; t>=0; t--) { - fail = 0; - FloppySelect (drive); - FloppyInitializeDMA((unsigned char*) where, 512); - DMASetRead(2); - - FloppyNewInterrupt = 0; - - fail += 1-FloppySendCommand(0x06 | 0x80 | 0x40 ); - fail += 1-FloppySendCommand(head<<2 | drive); - fail += 1-FloppySendCommand(track); - fail += 1-FloppySendCommand(head); - fail += 1-FloppySendCommand(sector); - fail += 1-FloppySendCommand(2); - fail += 1-FloppySendCommand( ((sector+1) >= fd[drive].SectorsPerTrack) ? fd[drive].SectorsPerTrack : sector+1); - fail += 1-FloppySendCommand(fd[drive].Gap3); - fail += 1-FloppySendCommand(0xff); - - if (fail) { - FloppyReset(); continue; - } - - FloppyWaitIRQ(); - while (!(inportb(FloppyRegMSR) & 0x80)); - - int i; unsigned ccc=0; - - for (i = 0; i < 7; i++) { - if (i<3) ccc |= FloppyReadData() << (i*4); - else FloppyReadData(); - } - - return ccc; - } - return 0xFFFFFFFF; -} - - -unsigned FloppyWriteSectorImp (unsigned* where, unsigned char drive, unsigned char head, unsigned char track, unsigned char sector) -{ - int t, fail; - for (t=3; t>=0; t--) { - fail = 0; - FloppySelect (drive); - FloppyInitializeDMA((unsigned char*) where, 512); - DMASetWrite(2); - - FloppyNewInterrupt = 0; - - fail += 1-FloppySendCommand(0x05 | 0x80 | 0x40 ); - fail += 1-FloppySendCommand(head<<2 | drive); - fail += 1-FloppySendCommand(track); - fail += 1-FloppySendCommand(head); - fail += 1-FloppySendCommand(sector); - fail += 1-FloppySendCommand(2); - fail += 1-FloppySendCommand( ((sector+1) >= fd[drive].SectorsPerTrack) ? fd[drive].SectorsPerTrack : sector+1); - fail += 1-FloppySendCommand(fd[drive].Gap3); - fail += 1-FloppySendCommand(0xff); - - if (fail) { - FloppyReset(); continue; - } - - FloppyWaitIRQ(); - - int i; unsigned ccc=0; - for (i = 0; i < 7; i++) - if (i<3) ccc |= FloppyReadData() << (i*4); - else FloppyReadData(); - - return ccc; - } - return 0xFFFFFFFF; -} - -unsigned char FloppySeek (unsigned drive, unsigned cyl, unsigned head) -{ - unsigned st0, cyl0; - - if (drive >= FloppyDrivesInstalled) return 0; - - FloppySelect (drive); - - int i; - for (i = 0; i < 20; i++) { - FloppyNewInterrupt = 0; - FloppySendCommand (0xF); - FloppySendCommand ( (head) << 2 | drive); - FloppySendCommand (cyl); - - FloppyWaitIRQ(); - FloppyCheckInt(&st0, &cyl0); - - if (cyl0 == cyl) return 1; - } - return 0; -} - - -inline void FloppyLBAtoCHS (int lba, unsigned char drive, unsigned char *head, unsigned char *track, unsigned char *sectors) -{ - *head = (lba % (fd[drive].SectorsPerTrack * 2)) / fd[drive].SectorsPerTrack; - *track = lba / (fd[drive].SectorsPerTrack * 2); - *sectors = lba % fd[drive].SectorsPerTrack + 1; -} - - -/*const char* types[] = { - "Nonexistant", "5.25\", unsupported.", "5.25\", unsupported.", - "3.5\", 720kb", "3.5\", 1.44mb", "3.5\", 2.88 mb"};*/ - -void FloppyInstall() -{ - unsigned char temp = CmosReadFloppyData(); - int i; - - // Set fd0 and fd1 types - fd[1].Type = temp & 0xf; - fd[0].Type = temp >> 4; - - // SRT = 16 - (ms * datarate / 500000); - // HLT = ms * datarate / 1000000 - // HUT = ms * datarate / 8000000 - - // Set up - for (i = 0; i < 2; i++) { - if (fd[i].Type >= 3) FloppyDrivesInstalled++; // 5.25" drives unsupported - if (fd[i].Type == 3) { // 720 kb, DD - fd[i].DataRate = 2; // speed = 250 kbps - fd[i].StepRateTime = 12; // 16 - (ms * 250000 / 500000), ms = 8 - fd[i].HeadLoadTime = 7; - fd[i].HeadUnloadTime = 7; - fd[i].SectorsPerTrack = 9; - fd[i].Size = 1440; - fd[i].Gap3 = 0x2A; - fd[i].Gap3Format = 0x50; - fd[i].Heads = 2; - fd[i].Tracks = 80; - } - else if (fd[i].Type == 4) { // 1.44 MB, HD - fd[i].DataRate = 0; // speed = 500 kbps - fd[i].StepRateTime = 8; - fd[i].HeadLoadTime = 15; - fd[i].HeadUnloadTime = 15; - fd[i].SectorsPerTrack = 18; - fd[i].Size = 2880; - fd[i].Gap3 = 0x1B; - fd[i].Gap3Format = 0x6C; - fd[i].Heads = 2; - fd[i].Tracks = 80; - } - else if (fd[i].Type == 5) { // 2.88 MB, ED - fd[i].DataRate = 3; // speed = 1000 kbps; - fd[i].StepRateTime = 0; - fd[i].HeadLoadTime = 30; - fd[i].HeadUnloadTime = 30; - fd[i].SectorsPerTrack = 36; - fd[i].Size = 5760; - fd[i].Gap3 = 0x1B; - fd[i].Gap3Format = 0x54; - fd[i].Heads = 2; - fd[i].Tracks = 80; - } - } - if (FloppyDrivesInstalled == 0) return; // No drives to set - - - FloppyReset(); -} - - -unsigned char FloppyIsDriverEnabled() -{ - return FloppyDrivesInstalled; -} - -unsigned* FloppyReadSectors (unsigned* where, unsigned char drive, int sectorLBA, unsigned count) -{ - if (drive >= FloppyDrivesInstalled || !where) return 0; - - unsigned head=0, track=0, sector=1, i, addr = (unsigned)where; - - // start motor, seek to track - FloppyMotor(drive, 1); - - // read count sectors - for (i=0; i= FloppyDrivesInstalled || !where) return 0; - - unsigned head=0, track=0, sector=1, i, addr = (unsigned)where; - - // start motor, seek to track - FloppyMotor(drive, 1); - - // read count sectors - for (i=0; i - -extern unsigned char FloppyInitializeDMA(unsigned char* buffer, unsigned length); -extern void FloppyMotor (unsigned char drive, unsigned char on); -extern void i86_FloppyHandler(ISR_stack_regs *r); -extern void FloppyDriveData (unsigned char drv, unsigned char dma); -extern unsigned char FloppyCalibrate(unsigned drive); -extern void FloppyReset(); - -extern unsigned char FloppySeek (unsigned drive, unsigned cyl, unsigned head); -extern void FloppyInstall(); -extern unsigned char FloppyIsDriverEnabled(); - -// Read/Write routines -extern unsigned* FloppyReadSectors (unsigned* where, unsigned char drive, int sectorLBA, unsigned count); -extern unsigned* FloppyWriteSectors (unsigned* where, unsigned char drive, int sectorLBA, unsigned count); - -extern void FloppyReadSectorImp (unsigned* where, unsigned char drive, unsigned char head, unsigned char track, unsigned char sector); -extern void FloppyWritedSectorImp (unsigned* where, unsigned char drive, unsigned char head, unsigned char track, unsigned char sector); \ No newline at end of file diff --git a/SysCore/drivers/floppy/storage.h b/SysCore/drivers/floppy/storage.h deleted file mode 100644 index f6d4ec7..0000000 --- a/SysCore/drivers/floppy/storage.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __STORAGE__H__ -#define __STORAGE__H__ - -/**Structure used by the file system drivers.\n - \Warning: the driver that provides the Read/Write routines must - include conversions for partitions on hard drives.*/ -typedef struct { - unsigned NumberOfSectors; - unsigned SizeOfSector; - void (*ReadSectors) (void* buffer, int startlba, int endlba); - void (*WriteSectors) (void* buffer, int startlba, int endlba); -} StorageDeviceInterface, *StorageDeviceInterfacePointer; - -#endif \ No newline at end of file diff --git a/SysCore/drivers/keyboard/compile.bat b/SysCore/drivers/keyboard/compile.bat deleted file mode 100644 index b100048..0000000 --- a/SysCore/drivers/keyboard/compile.bat +++ /dev/null @@ -1,16 +0,0 @@ -@echo off - -rem NASM and DJGPP executable paths: -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin -set objpath=../../objects -set incpath=../../include - -@echo on -%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/drivers/keyboard.o keyboard.c - -@echo off -@echo . -@echo Done! - -@pause diff --git a/SysCore/drivers/keyboard/key_list.txt b/SysCore/drivers/keyboard/key_list.txt deleted file mode 100644 index 5ff143e..0000000 --- a/SysCore/drivers/keyboard/key_list.txt +++ /dev/null @@ -1,135 +0,0 @@ -*0x00 Pause/Break -0x01 F9 -0x02 F7 -0x03 F5 -0x04 F3 -0x05 F1 -0x06 F2 -0x07 F12 -0x08 Print Screen -0x09 F10 -0x0A F8 -0x0B F6 -0x0C F4 -0x0D Tab -0x0E `~ -0x0F - -0x10 -0x11 -0x12 -0x13 -0x14 -0x15 Q -0x16 1! -0x17 -0x18 -0x19 -0x1A Z -0x1B S -0x1C A -0x1D W -0x1E 2@ -0x1F LeftWin - -0x20 -0x21 C -0x22 X -0x23 D -0x24 E -0x25 4$ -0x26 3# -0x27 RightWin -0x28 -0x29 Space -0x2A V -0x2B F -0x2C T -0x2D R -0x2E 5% -0x2F Menu - -0x30 -0x31 N -0x32 B -0x33 H -0x34 G -0x35 Y -0x36 6^ -0x37 -0x38 -0x39 -0x3A M -0x3B J -0x3C U -0x3D 7& -0x3E 8* -0x3F - -0x40 -0x41 ,< -0x42 K -0x43 I -0x44 O -0x45 0) -0x46 9( -0x47 -0x48 -0x49 .> -0x4A /? -0x4B L -0x4C ;: -0x4D P -0x4E -_ -0x4F - -0x50 -0x51 -0x52 '" -0x53 -0x54 [{ -0x55 =+ -0x56 -0x57 -0x58 -0x59 Numpad Enter -0x5A Enter -0x5B ]} -0x5C -0x5D \| -0x5E End -0x5F Left - -0x60 Home -0x61 Insert -0x62 Delete -0x63 Down -0x64 Right -0x65 Up -0x66 Backspace -0x67 PageDown -0x68 PageUp -0x69 Numpad 1 (end) -0x6A Numpad / -0x6B Numpad 4 (left) -0x6C Numpad 7 (Home) -0x6D -0x6E -0x6F - -0x70 Numpad 0 (insert) -0x71 Numpad . (del) -0x72 Numpad 2 (down) -0x73 Numpad 5 -0x74 Numpad 6 (right) -0x75 Numpad 8 (up) -0x76 Esc -0x77 -0x78 F11 -0x79 Numpad + -0x7A Numpad 3 (pgdwn) -0x7B Numpad - -0x7C Numpad * -0x7D Numpad 9 (pgup) -0x7E -0x7F \ No newline at end of file diff --git a/SysCore/drivers/keyboard/keyboard.c b/SysCore/drivers/keyboard/keyboard.c deleted file mode 100644 index e753f9e..0000000 --- a/SysCore/drivers/keyboard/keyboard.c +++ /dev/null @@ -1,306 +0,0 @@ -#include -#include - -const char KeyMap[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t', '`', 0, - 0, 0, 0, 0, 0, 'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2', 0, - 0, 'c', 'x', 'd', 'e', '4', '3', 0, 0, ' ', 'v', 'f', 't', 'r', '5', 0, - 0, 'n', 'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j', 'u', '7', '8', 0, - 0, ',', 'k', 'i', 'o', '0', '9', 0, 0, '.', '/', 'l', ';', 'p', '-', 0, - 0, 0, '\'', 0, '[', '=', 0, 0, 0, '\n', '\n', ']', 0, '\\', 0, 0, - 0, 0, 0x7F, 0, 0, 0, '\b', 0, 0, '1', '/', '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', 0, 0, 0, '+', '3', '-', '*', '9', 0, 0 - }; - -const char KeyMapShift[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t', '~', 0, - 0, 0, 0, 0, 0, 'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@', 0, - 0, 'C', 'X', 'D', 'E', '$', '#', 0, 0, ' ', 'V', 'F', 'T', 'R', '%', 0, - 0, 'N', 'B', 'H', 'G', 'Y', '^', 0, 0, 0, 'M', 'J', 'U', '&', '*', 0, - 0, '<', 'K', 'I', 'O', ')', '(', 0, 0, '>', '?', 'L', ':', 'P', '_', 0, - 0, 0, '\"', 0, '{', '+', 0, 0, 0, '\n', '\n', '}', 0, '|', 0, 0, - 0, 0, 0x7F, 0, 0, 0, '\b', 0, 0, '1', '/', '4', '7', 0, 0, 0, - '0', '.', '2', '5', '6', '8', 0, 0, 0, '+', '3', '-', '*', '9', 0, 0 - }; - -volatile unsigned char KeyArray[16]; -volatile unsigned char KeyboardNewData; -volatile unsigned char KeyModifierStatus; -volatile unsigned char KeyScancodePrefix; -volatile unsigned char KeyLightsStatus; -unsigned char KeyboardScancodeSet; - - -void KeyboardSetKey(unsigned char scancode, unsigned char val) -{ - unsigned char pos = scancode/8; - unsigned char offset = scancode%8; - - if (val) { - KeyArray[pos] |= 1<3 || delay>31) return; - - unsigned char out = rate<<5 | delay; - while ((inportb(0x64)&2) != 0); - outportb(0x60, 0xF3); - while ((inportb(0x64)&2) != 0); - outportb(0x60, out); -} - - -/*************************************** - * Set keyboard LEDs * - *************************************** - +-----------+-------+-------+--------+ - | Bits 7-3 | Bit 2 | Bit 1 | Bit 0 | - | 0 | Caps | Num | Scroll | - |(reserved) | lock | lock | lock | - +-----------+-------+-------+--------+ - ***************************************/ -void KeyboardSetLEDs(unsigned char status) -{ - while ((inportb (0x64)&2)!=0); - outportb (0x60, 0xED); - - while ((inportb (0x64)&2)!=0); - outportb (0x60, status); -} - -/*************************************** - * Set scancode set * - *************************************** - 0 Get current scancode set - 1 Set to scancode set 1 - 2 Set to scancode set 2 - 3 Set to scancode set 3 - ***************************************/ -void KeyboardSetScancodeSet(unsigned char set) -{ - if (set>3) return; - - while ((inportb (0x64)&2)!=0); - outportb (0x60, 0xF0); - - while ((inportb (0x64)&2)!=0); - outportb (0x60, set); - - KeyboardScancodeSet = set; -} - -/*unsigned char i86_kb_get_scancodeset() { - return KeyboardScancodeSet; -}*/ - -void KeyboardWaitInput() -{ - int fail_safe=200000; - while ((inportb(0x64)&2)!=0 && fail_safe>0) fail_safe--; -} - -void KeyboardWaitOutput() -{ - int fail_safe=200000; - while ((inportb(0x64)&1)==0 && fail_safe>0) fail_safe--; -} - - -void KeyboardInstallA() -{ - KeyboardWaitInput(); outportb(0x60, 0xFF); // Reset kb - - // Initialize variables - KeyboardNewData = 0; - KeyModifierStatus = 0; - KeyScancodePrefix = 0; - KeyLightsStatus = 0; - KeyboardScancodeSet = 0; - - memset((void*)KeyArray, 0, 16); -} - - -void KeyboardInstallB() -{ - // Wait for BAT test results - unsigned char temp; - do temp = inportb(0x60); - while (temp!=0xAA && temp!=0xFC); - - // Error - if (temp == 0xFC) return; - - // Set new repeat rate - KeyboardSetRepeatRate(1, 11); - - // Set scancode set 2 - KeyboardSetScancodeSet(2); // Set new scancode set - - KeyboardWaitInput(); - outportb(0x64, 0x20); // Get "Command unsigned char" - - do { temp = inportb(0x60); - } while (temp==0xFA || temp==0xAA); - - temp &= 0xFF - (1<<6); // Set bit6 to 0: disable conversion - KeyboardWaitInput(); outportb(0x64, 0x60); // Function to write cmd unsigned char - KeyboardWaitInput(); outportb(0x60, temp); // Send it -} diff --git a/SysCore/drivers/keyboard/keyboard.deprecated.h b/SysCore/drivers/keyboard/keyboard.deprecated.h deleted file mode 100644 index 261e9fb..0000000 --- a/SysCore/drivers/keyboard/keyboard.deprecated.h +++ /dev/null @@ -1,135 +0,0 @@ - -#define KB_KEY_LSHIFT 0x81 // 1000 0001 -#define KB_KEY_RSHIFT 0X82 // 1000 0010 -#define KB_KEY_LALT 0X84 // 1000 0100 -#define KB_KEY_RALT 0x88 // 1000 1000 -#define KB_KEY_LCTRL 0x90 // 1001 0000 -#define KB_KEY_RCTRL 0xA0 // 1010 0000 -#define KB_KEY_FSHIFT 0xC0 // 1100 0000 -extern volatile unsigned char KeyModifierStatus; - -#define KB_PREFIX_GRAY 0x01 // Gray -#define KB_PREFIX_BREAK 0x02 // Break code -#define KB_PREFIX_PAUSE 0x04 // Pause/break key -#define KB_PREFIX_PAUSE1 0x08 // Recieved first unsigned char from pause/break -extern volatile unsigned char KeyScancodePrefix; - -#define KB_KEY_SCROLL 0xF1 // 1111 0001 -#define KB_KEY_NUM 0xF2 // 1111 0010 -#define KB_KEY_CAPS 0xF4 // 1111 0100 -extern volatile unsigned char KeyLightsStatus; - -extern unsigned char KeyboardScancodeSet; - -enum KeyboardKeys { - KeyboardKeyPAUSE = 0x00, - KeyboardKeyF9 = 0x01, - KeyboardKeyF7 = 0x02, - KeyboardKeyF5 = 0X03, - KeyboardKeyF3 = 0x04, - KeyboardKeyF1 = 0x05, - KeyboardKeyF2 = 0x06, - KeyboardKeyF12 = 0x07, - KeyboardKeyPRINTSCRN = 0x08, - KeyboardKeyF10 = 0x09, - KeyboardKeyF8 = 0x0A, - KeyboardKeyF6 = 0x0B, - KeyboardKeyF4 = 0x0C, - KeyboardKeyTAB = 0x0D, - KeyboardKeyTILDA = 0x0E, - KeyboardKeyQ = 0x15, - KeyboardKey1 = 0x16, - KeyboardKeyZ = 0x1A, - KeyboardKeyS = 0x1B, - KeyboardKeyA = 0x1C, - KeyboardKeyW = 0x1D, - KeyboardKey2 = 0x1E, - KeyboardKeyLWIN = 0x1F, - KeyboardKeyC = 0x21, - KeyboardKeyX = 0x22, - KeyboardKeyD = 0x23, - KeyboardKeyE = 0x24, - KeyboardKey4 = 0x25, - KeyboardKey3 = 0x26, - KeyboardKeyRWIN = 0x27, - KeyboardKeySPACE = 0x29, - KeyboardKeyV = 0x2A, - KeyboardKeyF = 0x2B, - KeyboardKeyT = 0x2C, - KeyboardKeyR = 0x2D, - KeyboardKey5 = 0x2E, - KeyboardKeyMENU = 0x2F, - KeyboardKeyN = 0x31, - KeyboardKeyB = 0x32, - KeyboardKeyH = 0x33, - KeyboardKeyG = 0x34, - KeyboardKeyY = 0x35, - KeyboardKey6 = 0x36, - KeyboardKeyM = 0x3A, - KeyboardKeyJ = 0x3B, - KeyboardKeyU = 0x3C, - KeyboardKey7 = 0x3D, - KeyboardKey8 = 0x3E, - KeyboardKeyCOMMA = 0x41, - KeyboardKeyK = 0x42, - KeyboardKeyI = 0x43, - KeyboardKeyO = 0x44, - KeyboardKey0 = 0x45, - KeyboardKey9 = 0x46, - KeyboardKeyPERIOD = 0x49, - KeyboardKeySLASH = 0x4A, - KeyboardKeyL = 0x4B, - KeyboardKeySEMICOLON = 0x4C, - KeyboardKeyP = 0x4D, - KeyboardKeyDASH = 0x4E, - KeyboardKeyAPOSTROPHE = 0x52, - KeyboardKeyLBRACKET = 0x54, - KeyboardKeyEQUAL = 0x55, - KeyboardKeyNUMPAD_ENTER = 0x59, - KeyboardKeyENTER = 0x5A, - KeyboardKeyRBRACKET = 0x5B, - KeyboardKeyBACKSLASH = 0x5D, - KeyboardKeyEND = 0x5E, - KeyboardKeyLEFT = 0x5F, - KeyboardKeyHOME = 0x60, - KeyboardKeyINSERT = 0x61, - KeyboardKeyDELETE = 0x62, - KeyboardKeyDOWN = 0x63, - KeyboardKeyRIGHT = 0x64, - KeyboardKeyUP = 0x65, - KeyboardKeyBACKSPACE = 0x66, - KeyboardKeyPGDOWN = 0x67, - KeyboardKeyPGUP = 0x68, - KeyboardKeyNUMPAD_1 = 0x69, - KeyboardKeyNUMPAD_SLASH = 0x6A, - KeyboardKeyNUMPAD_4 = 0x6B, - KeyboardKeyNUMPAD_7 = 0x6C, - KeyboardKeyNUMPAD_0 = 0x70, - KeyboardKeyNUMPAD_COLON = 0x71, - KeyboardKeyNUMPAD_2 = 0x72, - KeyboardKeyNUMPAD_5 = 0x73, - KeyboardKeyNUMPAD_6 = 0x74, - KeyboardKeyNUMPAD_8 = 0x75, - KeyboardKeyESC = 0x76, - KeyboardKeyF11 = 0x78, - KeyboardKeyNUMPAD_PLUS = 0x79, - KeyboardKeyNUMPAD_3 = 0x7A, - KeyboardKeyNUMPAD_MINUS = 0x7B, - KeyboardKeyNUMPAD_ASTERISK = 0x7C, - KeyboardKeyNUMPAD_9 = 0x7D -}; - -typedef struct { - unsigned char status; - unsigned char lights; - unsigned char scancode; - unsigned char character; -} kb_key; - - -extern char getch(); -extern kb_key get_key(); -extern char scancode_to_ascii(unsigned char scancode); -extern unsigned char get_key_status(unsigned char scancode); -extern void kb_set_repeat(float rate, int delay); -extern void kb_set_LEDs(unsigned char status); \ No newline at end of file diff --git a/SysCore/drivers/keyboard/keyboard.h.deprecated b/SysCore/drivers/keyboard/keyboard.h.deprecated deleted file mode 100644 index b7979f4..0000000 --- a/SysCore/drivers/keyboard/keyboard.h.deprecated +++ /dev/null @@ -1,135 +0,0 @@ - -#define KB_KEY_LSHIFT 0x81 // 1000 0001 -#define KB_KEY_RSHIFT 0X82 // 1000 0010 -#define KB_KEY_LALT 0X84 // 1000 0100 -#define KB_KEY_RALT 0x88 // 1000 1000 -#define KB_KEY_LCTRL 0x90 // 1001 0000 -#define KB_KEY_RCTRL 0xA0 // 1010 0000 -#define KB_KEY_FSHIFT 0xC0 // 1100 0000 -extern volatile unsigned char KeyModifierStatus; - -#define KB_PREFIX_GRAY 0x01 // Gray -#define KB_PREFIX_BREAK 0x02 // Break code -#define KB_PREFIX_PAUSE 0x04 // Pause/break key -#define KB_PREFIX_PAUSE1 0x08 // Recieved first unsigned char from pause/break -extern volatile unsigned char KeyScancodePrefix; - -#define KB_KEY_SCROLL 0xF1 // 1111 0001 -#define KB_KEY_NUM 0xF2 // 1111 0010 -#define KB_KEY_CAPS 0xF4 // 1111 0100 -extern volatile unsigned char KeyLightsStatus; - -extern unsigned char KeyboardScancodeSet; - -enum KB_KEYS { - KB_KEY_PAUSE = 0x00, - KB_KEY_F9 = 0x01, - KB_KEY_F7 = 0x02, - KB_KEY_F5 = 0X03, - KB_KEY_F3 = 0x04, - KB_KEY_F1 = 0x05, - KB_KEY_F2 = 0x06, - KB_KEY_F12 = 0x07, - KB_KEY_PRINTSCRN = 0x08, - KB_KEY_F10 = 0x09, - KB_KEY_F8 = 0x0A, - KB_KEY_F6 = 0x0B, - KB_KEY_F4 = 0x0C, - KB_KEY_TAB = 0x0D, - KB_KEY_TILDA = 0x0E, - KB_KEY_Q = 0x15, - KB_KEY_1 = 0x16, - KB_KEY_Z = 0x1A, - KB_KEY_S = 0x1B, - KB_KEY_A = 0x1C, - KB_KEY_W = 0x1D, - KB_KEY_2 = 0x1E, - KB_KEY_LWIN = 0x1F, - KB_KEY_C = 0x21, - KB_KEY_X = 0x22, - KB_KEY_D = 0x23, - KB_KEY_E = 0x24, - KB_KEY_4 = 0x25, - KB_KEY_3 = 0x26, - KB_KEY_RWIN = 0x27, - KB_KEY_SPACE = 0x29, - KB_KEY_V = 0x2A, - KB_KEY_F = 0x2B, - KB_KEY_T = 0x2C, - KB_KEY_R = 0x2D, - KB_KEY_5 = 0x2E, - KB_KEY_MENU = 0x2F, - KB_KEY_N = 0x31, - KB_KEY_B = 0x32, - KB_KEY_H = 0x33, - KB_KEY_G = 0x34, - KB_KEY_Y = 0x35, - KB_KEY_6 = 0x36, - KB_KEY_M = 0x3A, - KB_KEY_J = 0x3B, - KB_KEY_U = 0x3C, - KB_KEY_7 = 0x3D, - KB_KEY_8 = 0x3E, - KB_KEY_COMMA = 0x41, - KB_KEY_K = 0x42, - KB_KEY_I = 0x43, - KB_KEY_O = 0x44, - KB_KEY_0 = 0x45, - KB_KEY_9 = 0x46, - KB_KEY_PERIOD = 0x49, - KB_KEY_SLASH = 0x4A, - KB_KEY_L = 0x4B, - KB_KEY_SEMICOLON = 0x4C, - KB_KEY_P = 0x4D, - KB_KEY_DASH = 0x4E, - KB_KEY_APOSTROPHE = 0x52, - KB_KEY_LBRACKET = 0x54, - KB_KEY_EQUAL = 0x55, - KB_KEY_NUMPAD_ENTER = 0x59, - KB_KEY_ENTER = 0x5A, - KB_KEY_RBRACKET = 0x5B, - KB_KEY_BACKSLASH = 0x5D, - KB_KEY_END = 0x5E, - KB_KEY_LEFT = 0x5F, - KB_KEY_HOME = 0x60, - KB_KEY_INSERT = 0x61, - KB_KEY_DELETE = 0x62, - KB_KEY_DOWN = 0x63, - KB_KEY_RIGHT = 0x64, - KB_KEY_UP = 0x65, - KB_KEY_BACKSPACE = 0x66, - KB_KEY_PGDOWN = 0x67, - KB_KEY_PGUP = 0x68, - KB_KEY_NUMPAD_1 = 0x69, - KB_KEY_NUMPAD_SLASH = 0x6A, - KB_KEY_NUMPAD_4 = 0x6B, - KB_KEY_NUMPAD_7 = 0x6C, - KB_KEY_NUMPAD_0 = 0x70, - KB_KEY_NUMPAD_COLON = 0x71, - KB_KEY_NUMPAD_2 = 0x72, - KB_KEY_NUMPAD_5 = 0x73, - KB_KEY_NUMPAD_6 = 0x74, - KB_KEY_NUMPAD_8 = 0x75, - KB_KEY_ESC = 0x76, - KB_KEY_F11 = 0x78, - KB_KEY_NUMPAD_PLUS = 0x79, - KB_KEY_NUMPAD_3 = 0x7A, - KB_KEY_NUMPAD_MINUS = 0x7B, - KB_KEY_NUMPAD_ASTERISK = 0x7C, - KB_KEY_NUMPAD_9 = 0x7D -}; - -typedef struct { - unsigned char status; - unsigned char lights; - unsigned char scancode; - unsigned char character; -} kb_key; - - -extern char getch(); -extern kb_key get_key(); -extern char scancode_to_ascii(unsigned char scancode); -extern unsigned char get_key_status(unsigned char scancode); -extern void kb_set_repeat(float rate, int delay); -extern void kb_set_LEDs(unsigned char status); \ No newline at end of file diff --git a/SysCore/drivers/makeall.bat b/SysCore/drivers/makeall.bat deleted file mode 100644 index 569ffc3..0000000 --- a/SysCore/drivers/makeall.bat +++ /dev/null @@ -1,158 +0,0 @@ -@echo off -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin - -goto this - -:error - @echo. - @echo There have been build errors. Building halted. - @pause - exit - -:this - @echo Building Drivers... - set objpath=..\objects\drivers - set incpath=../include - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o drivers.o drivers.c - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o BSOD.o BSOD.c - - if not exist drivers.o goto error - if not exist BSOD.o goto error - - xcopy /Y *.o %objpath% >nul - del *.o - -:clock - set objpath=..\..\objects\drivers - set incpath=../../include - - cd clock - @echo * Compiling internal clock... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o pit.o pit.c - if not exist pit.o goto error - - xcopy /Y *.o %objpath% >nul - del *.o - - cd.. - - -:floppy - cd floppy - @echo * Compiling floppy driver... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o dma.o dma.c - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o floppy.o floppy.c - if not exist dma.o goto error - if not exist floppy.o goto error - xcopy /Y *.o %objpath% >nul - del *.o - - cd.. - -:filesys - cd filesys - @echo * Compiling file systems... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o fat.o fat.c - rem %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o floppy.o floppy.c - if not exist fat.o goto error - rem if not exist floppy.o goto error - xcopy /Y *.o %objpath% >nul - del *.o - - cd.. - -:keyboard - cd keyboard - @echo * Compiling keyboard driver... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o keyboard.o keyboard.c - if not exist keyboard.o goto error - xcopy /Y *.o %objpath% >nul - del *.o - - cd.. - - -:cpu - cd cpu - @echo * Compiling Central Processing Unit (CPU) modules... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o cpu.o cpu.c - if not exist cpu.o goto error - - xcopy /Y *.o %objpath% >nul - del *.o - - set objpath=..\..\..\objects\drivers - set incpath=../../../include - - :gdt - @echo + Global Descriptor Table - cd gdt - - rem Assembly File: - %nasm_path%\nasm.exe -f aout -o gdt_asm.o gdt.asm - if not exist gdt_asm.o goto error - - rem C File: - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o gdt.o gdt.c - if not exist gdt.o goto error - - xcopy /Y *.o %objpath% >nul - del *.o - cd.. - - :idt - @echo + Interrupt Descriptor Table - cd idt - - rem Assembly File: - %nasm_path%\nasm.exe -f aout -o idt_asm.o idt.asm - if not exist idt_asm.o goto error - - rem C File: - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o idt.o idt.c - if not exist idt.o goto error - - xcopy /Y *.o %objpath% >nul - del *.o - cd.. - - :irq - @echo + Interrupt Requests - cd irq - - rem IRQ Assembly File: - %nasm_path%\nasm.exe -f aout -o irq_asm.o irq.asm - if not exist irq_asm.o goto error - - rem IRQ C File: - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o irq.o irq.c - if not exist irq.o goto error - - @echo + Programmable Interrupt Controller - rem PIC C File: - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o pic.o pic.c - if not exist pic.o goto error - - xcopy /Y *.o %objpath% >nul - del *.o - cd.. - - :isrs - @echo + Interrupt Service Routines - cd isrs - - rem Assembly File: - %nasm_path%\nasm.exe -f aout -o isrs_asm.o isrs.asm - if not exist isrs_asm.o goto error - - rem C File: - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o isrs.o isrs.c - if not exist isrs.o goto error - - xcopy /Y *.o %objpath% >nul - del *.o - cd.. - - - cd.. \ No newline at end of file diff --git a/SysCore/filelist.txt b/SysCore/filelist.txt deleted file mode 100644 index 9188990..0000000 --- a/SysCore/filelist.txt +++ /dev/null @@ -1,82 +0,0 @@ -.: -compile.bat drivers include loader.asm makeall.bat memory shell -debug filelist.txt lib main.c makeallh.bat objects video - -./debug: -BIOS-bochs-latest bochs_config.bxrc ctaos.img OSDev.log VGABIOS-lgpl-latest - -./drivers: -BSOD.c compile.bat drivers.c filesys keyboard makeall.bat.bak -clock cpu drivers.h floppy makeall.bat - -./drivers/clock: -clock.h pit.c - -./drivers/cpu: -compile.bat cpu.c cpu.h gdt idt irq isrs - -./drivers/cpu/gdt: -gdt.asm gdt.c gdt.h - -./drivers/cpu/idt: -idt.asm idt.c idt.h - -./drivers/cpu/irq: -irq.asm irq.c irq.h pic.c pic.h - -./drivers/cpu/isrs: -isrs.asm isrs.c isrs.h - -./drivers/filesys: -fat.c fat.h vfs.c vfs.h - -./drivers/floppy: -dma.c dma.h floppy.c floppy.h storage.h - -./drivers/keyboard: -compile.bat keyboard.deprecated.h key_list.txt -keyboard.c keyboard.h.deprecated - -./include: -bootinfo.h crtdefs.h cstring hal.h size_t.h stdlib.h system.h -cctype cstdarg ctype.h _null.h stdarg.h string.h time.h -conio.h cstdint drivers regs.h stdint.h sys va_list.h - -./include/drivers: -floppy.h keyboard.h - -./include/sys: -declarat.h - -./lib: -compile.bat conio.c ctype.c stdlib.c string.c system.c time.c - -./memory: -compile.bat lib mmngr.asm mmngr_ph.c mmngr_ph.h mmngr_vi.c mmngr_vi.h - -./memory/lib: -pde.c pde.h pte.c pte.h - -./objects: -compile.bat drivers main.o mmngr_ph.o release string.o video -conio.o link.ld mmngr_de.o mmngr_te.o shell.o system.o -ctype.o loader.o mmngr.o mmngr_vi.o stdlib.o time.o - -./objects/drivers: -BSOD.o drivers.o floppy.o idt_asm.o irq.o keyboard.o -cpu.o fat12.o gdt_asm.o idt.o isrs_asm.o pic.o -dma.o fat.o gdt.o irq_asm.o isrs.o pit.o - -./objects/release: - -./objects/video: -vga03h.o - -./shell: -apps.h compile.bat shell.c - -./video: -color compile.bat vga03h.c vga03h.h vga.h - -./video/color: -color.c color.h diff --git a/SysCore/include/_null.h b/SysCore/include/_null.h deleted file mode 100644 index 8d731bf..0000000 --- a/SysCore/include/_null.h +++ /dev/null @@ -1,30 +0,0 @@ - -#ifndef __NULL_H -#define __NULL_H - -/****************************** - * _null.h * - * - NULL declaration * - ******************************/ - -#if defined (_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#ifdef NULL -#undef NULL -#endif - -#ifdef __cplusplus -extern "C" -{ -/* standard NULL declaration */ -#define NULL 0 -} -#else -/* standard NULL declaration */ -#define NULL (void*)0 -#endif - - -#endif diff --git a/SysCore/include/bootinfo.h b/SysCore/include/bootinfo.h deleted file mode 100644 index 3215d82..0000000 --- a/SysCore/include/bootinfo.h +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef _BOOTINFO_H -#define _BOOTINFO_H -//**************************************************************************** -//** bootinfo.h -//**************************************************************************** - -#include - -/**The structure used by the VESA Controller Info table.*/ -struct _VESA_CONTROLLER_INFO { - /** Vesa signature, should be "VESA". */ - unsigned char Signature[4]; - /** Version number, example: 0x0300 for VBE 3.0. */ - uint16_t Version; - /** FAR pointer to OEM string. (seg:offset). */ - uint16_t OEMString[2]; - /** Capabilities, taken as 4 bytes. */ - uint32_t Capabilities; - /** Video modes. FAR pointer (seg:offset). */ - uint16_t VideoModes[2]; - /** Total memory as number of 64k blocks. */ - uint16_t TotalMemory; -} __attribute__((packed)); - - -enum _VESA_MODE_ATTRIBUTES { - /** The mode is supported by the present hardware configuration. */ - IsSupported = 0x01, - /** Optional information is available (must be = 1 for VBE v1.2+) */ - OptionalInformation = 0x02, - /** BIOS output is supported. */ - BiosOutput = 0x04, - /** Set if color, clear if monochrome. */ - IsColor = 0x08, - /** Set if graphic mode, clear if text mode. */ - IsGraphic = 0x10, - /** (VBE v2.0+) mode is not VGA compatible. */ - VGACompatible = 0x20, - /** (VBE v2.0+) Bank switched mode not supported. */ - BankSwitchedNotSupported = 0x40, - /** (VBE v2.0+) Linear framebuffer mode supported. */ - LinearFramebufferSupported = 0x80, - /** (VBE v3.0) Interlaced mode available. */ - InterlacedAvailable = 0x100, - /** (VBE/AF v1.0P) Application must call EnableDirrectAccess before calling bank-switching functions. */ - EnableDirectAccess = 0x100, - /** (VBE v3.0) Hardware supports triple buffering. */ - TripleBufferingSupported = 0x200, - /** (VBE v3.0) Hardware supports stereoscopic display. */ - StereoscopicSupported = 0x400, - /** (VBE v3.0) Dual display start address support. */ - DualDisplayStartAddress = 0x800 -} VESAModeAttributeMasks; - -enum _VESA_MODE_WINDOW_ATTRIBUTES { - /** Window exists. */ - Exists = 0x1, - /** Window is readable. */ - Readable = 0x2, - /** Window is writable. */ - Writable = 0x4 -} VESAModeWindowAttributeMasks; - -enum _VESA_MODE_MEMORY_MODELS { - /** Text */ - Text = 0x00, - /** CGA graphics*/ - CGA = 0x01, - /** HGC graphics*/ - HGC = 0x02, - /** 16-color EGA grahpics*/ - EGA = 0x03, - /** packed pixel graphics*/ - PackedPixel = 0x04, - /** "sequ 256 (non chain 4) grahpics*/ - Sequ256 = 0x05, - /** Direct color (HiColor, 24bit TrueColor)*/ - DirectColor = 0x06, - /** YUV (luminance-chrominance, also called YIQ)*/ - YUV = 0x07 -} VESAModeMemoryModels; - -struct _VESA_MODE_INFO { - /** Mode attributes, defined in VESAModeAttributeMasks. */ - uint16_t Attributes; - /** Window attributes (window A or B), defined in VESAModeWindowAttributeMasks. */ - uint8_t WindowAttributesA, WindowAttributesB; - /** Window granularity in KB. */ - uint16_t WindowGranularity; - /** Start segment of window A (0x0000 if not supported).*/ - uint16_t WindowStartSegmentA; - /** Start segment of window B (0x0000 if not supported).*/ - uint16_t WindowStartSegmentB; - /** FAR window positioning function (equivalent to AX = 0x4F05. */ - uint32_t WindowPositioningFunction; - /** Bytes per scanline.*/ - uint16_t BytesPerScanline; - /** Width in pixels (graphics) or characters (text).*/ - uint16_t Width; - /** Height in pixels (graphics) or characters (text).*/ - uint16_t Height; - /** Width of character cell in pixels. */ - uint8_t CharacterWidth; - /** Height of character cell in pixels. */ - uint8_t CharacterHeight; - /** Number of memory planes. */ - uint8_t MemoryPlanes; - /** Number of bits per pixel. */ - uint8_t Bpp; - /** Number of banks.*/ - uint8_t Banks; - /** Memory model type, defined in VESAModeMemoryModels.*/ - uint8_t MemoryModelType; - /** Size of bank in KB. */ - uint8_t BankSize; - /** Number of image pages minus one, that will fit in video RAM.*/ - uint8_t ImagePages; - /** Reserved, 0x00 for VBE 1.0 to 2.0, 0x01 for VBE 3.0.*/ - uint8_t Reserved_0; - - /** (VESA v1.2+) Self explanatory.*/ - uint8_t RedMaskSize, RedFieldPosition; - uint8_t GreenMaskSize, GreenFieldPosition; - uint8_t BlueMaskSize, BlueFieldPosition; - uint8_t ReservedMaskSize, ReservedFieldPosition; - /** (VESA v1.2+) Direct Color Mode info\n - Bit 0: color ramp is programmable\n - Bit 1: bytes in reserved field may be used by application.*/ - uint8_t DirectColorModeInfo; - /** (VESA v2.0+) Physical address of linear video buffer.*/ - void* LinearVideoBuffer; - /** (VESA v2.0+) Pointer to start of offscreen memory.*/ - void* OffscreenMemory; - /** (VESA v2.0+) KB of offscreen memory.*/ - uint16_t OffscreenMemorySize; - - /** (VESA v3.0) Bytes per scanline in linear modes.*/ - uint16_t BytesPerScanlineLinear; - /** (VESA v3.0) Number of images minus one for banked video modes.*/ - uint8_t ImagesBankedMode; - /** (VESA v3.0) Number of images minus one for linear video modes.*/ - uint8_t ImagesLinearMode; - /** (VESA v3.0) LINEAR MODES ONLY\n - * \DirectColorMaskSize: size of direct color mask (in bits).\n - * \BitPosition: bit position of mask LSB (e.g. shift count)*/ - uint8_t RedDirectColorMaskSize, RedBitPosition; - uint8_t GreenDirectColorMaskSize, GreenBitPosition; - uint8_t BlueDirectColorMaskSize, BlueBitPosition; - uint8_t ReservedDirectColorMaskSize, ReservedBitPosition; - /** (VESA v3.0) Maximum pixel clock for graphics video mode, in Hz*/ - uint32_t MaxPixelClock; -} __attribute__ ((packed)); - -/**The structure passed by the bootloader. */ -typedef struct { - /** How much memory is installed on the system (in KB). */ - uint64_t Memory; - /** Boot device. */ - uint32_t BootDevice; - /** Pointer to a char[] string containing kernel parameters. */ - unsigned char* CommandLine; - /** Number of other modules loaded by the bootloader. */ - uint32_t ModulesCount; - /** Pointer to where other modules were loaded. */ - void* ModulesAddress; - /** Size of memory map. */ - uint32_t MemoryMapLength; - /** Pointer to memory map. */ - void* MemoryMapAddress; - /** Drives info length. */ - uint32_t DrivesLength; - /** Pointer to drives info. */ - void* DrivesAddress; - /** BIOS ROM configuration table. */ - uint32_t ConfigurationTable; - /** Name of bootloader, should be "CTA" (0 ended string). */ - unsigned char BootloaderName[4]; - /** APM Table. */ - uint32_t APMTable; - /** VGA current video mode information. */ - uint8_t VGACurrentVideoMode; - uint8_t VGACurrentVideoModeColumns; - uint8_t VGACurrentVideoPage; - /** VESA video mode(s) information. */ - struct _VESA_CONTROLLER_INFO* VESAControllerInformation; - - -} multiboot_info ; - - -#endif - diff --git a/SysCore/include/cctype b/SysCore/include/cctype deleted file mode 100644 index 7ce3762..0000000 --- a/SysCore/include/cctype +++ /dev/null @@ -1,9 +0,0 @@ -// cerrno standard header - -#ifndef _CSTDCTYPE_ -#define _CSTDCTYPE_ -#include - -#endif /* _CSTDCTYPE_ */ - - diff --git a/SysCore/include/conio.h b/SysCore/include/conio.h deleted file mode 100644 index a80343d..0000000 --- a/SysCore/include/conio.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef __CONIO_H -#define __CONIO_H - -#include -//#define _ATTRIB 0x0F - -typedef struct { - /** Console window width. */ - unsigned width; - /** Console window height. */ - unsigned height; - /** Default colors (can be changed later with ConsoleSetDefaultColors() routine)*/ - unsigned char defcolors; - /** Pointer to a routine to set the blinking cursor position.\n - Parameters are as following: (int x, int y), where x, y is a 2D position on the screen. */ - void (*cursor)(int, int); - /** Pointer to a routine to put a character in a specified position.\n - Parameters are as following: (int x, int y, unsigned char c),\n - * where: x, y = 2D position on the screen\n - * c = ascii character*/ - void (*putc)(int, int, unsigned char); - /** Pointer to a routine to return a character in a specified position.\n - Parameters are as following: (int x, int y), where x, y is a 2D position on the screen. */ - unsigned char (*getc)(int, int); - /** Pointer to a routine to set the colors for the character in the specified position\n - Parameters are as following: (int x, int y, unsigned char color),\n - * where: x, y = 2D position on the screen\n - * color = index in 16 color palette for background (high nibble) and foreground (low nibble)*/ - void (*putcolor)(int, int, unsigned char); - /** Pointer to a routine to return the colors for the character in the specified position\n - Parameters are as following: (int x, int y, unsigned char c),\n - * where: x, y = 2D position on the screen*/ - unsigned char (*getcolor)(int, int); -} ConsoleScreen; - - -typedef struct { - /**Integer coordonates*/ - int X, Y; -} Point; - -typedef struct { - /**Unsigned integer coordonates.*/ - unsigned X, Y; -} UPoint; - -enum COLORS { - BLACK = 0x0, - BLUE = 0x1, - GREEN = 0x2, - CYAN = 0x3, - RED = 0x4, - MAGENTA = 0x5, - BROWN = 0x6, - LIGHTGRAY = 0x7, - DARKGRAY = 0x8, - LIGHTBLUE = 0x9, - LIGHTGREEN = 0xA, - LIGHTCYAN = 0xB, - LIGHTRED = 0xC, - LIGHTMAGENTA = 0xD, - YELLOW = 0xE, - WHITE = 0xF, - BLINK = 0x80 -}; - -enum CURSORSHAPE { - _NOCURSOR = 0x0, - _SOLIDCURSOR = 0x1, - _NORMALCURSOR = 0x2 -}; - -/***/ -//extern char* cgets(char* string); - - -extern void ConsoleInstall(ConsoleScreen screen); -extern void ConsoleUpdateCursor(UPoint position, unsigned char type); -extern void ConsoleScroll(unsigned lines); - - -/** Clears to end of line in text window\n\n - Declaration: void clreol(void);\n\n - Remarks:\n -clreol clears all characters from the cursor position to the end of the line - within the current text window, without moving the cursor.\n\n - Return Value: None*/ -extern void clreol(); -extern void clrscr(); -extern int gettext (int left, int top, int right, int bottom, unsigned char* dest); -extern void gotoxy (int x, int y); -extern int cprintf(const char* str, ...); -extern int cputs(const char* str); -extern int cgets(char* string, int maxlen); -extern int getch(); -extern int getche(); -extern void movetext(int left, int top, int right, int bottom, int destleft, int desttop); -extern int putch(const char c); -extern int puttext(int left, int top, int right, int bottom, unsigned char* src); -extern void _setcursortype (int cursor); -extern int wherex(); -extern int wherey(); - -#endif \ No newline at end of file diff --git a/SysCore/include/crtdefs.h b/SysCore/include/crtdefs.h deleted file mode 100644 index 42c63aa..0000000 --- a/SysCore/include/crtdefs.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _CRTDEFS_H -#define _CRTDEFS_H - -/****************************** - * crtdefs.h * - * - basic definitions * - ******************************/ - -#if !defined (CRT_EXPORTS) && !defined (CRT_IMPORTS) -#define CRT_EXPORTS -#endif - -#undef far -#undef near -#undef pascal - -#define far -#define near - -#ifdef _WIN32 -#if (!defined(_MAC)) && ((_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)) -#define pascal __stdcall -#else -#define pascal -#endif -#endif - -#ifdef _MAC -#ifndef _CRTLIB -#define _CRTLIB __cdecl -#endif -#ifdef _68K_ -#ifndef __pascal -#define __pascal -#endif -#endif -#elif defined( _WIN32) -#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) -#ifndef _CRTLIB -#define _CRTLIB __stdcall -#endif -#else -#ifndef _CRTLIB -#define _CRTLIB -#endif -#endif -#endif - - -#endif diff --git a/SysCore/include/cstdarg b/SysCore/include/cstdarg deleted file mode 100644 index 37ccae7..0000000 --- a/SysCore/include/cstdarg +++ /dev/null @@ -1,7 +0,0 @@ -// cerrno standard header - -#ifndef _CSTDARG_ -#define _CSTDARG_ -#include - -#endif /* _CSTDARG_ */ diff --git a/SysCore/include/cstdint b/SysCore/include/cstdint deleted file mode 100644 index 7629317..0000000 --- a/SysCore/include/cstdint +++ /dev/null @@ -1,9 +0,0 @@ -// cerrno standard header - -#ifndef _CSTDINT_ -#define _CSTDINT_ -#include - -#endif /* _CSTDINT_ */ - - diff --git a/SysCore/include/cstring b/SysCore/include/cstring deleted file mode 100644 index beb9135..0000000 --- a/SysCore/include/cstring +++ /dev/null @@ -1,9 +0,0 @@ -// cstring standard header - -#ifndef _CSTDSTRING_ -#define _CSTDSTRING_ -#include - -#endif /* _CSTDINT_ */ - - diff --git a/SysCore/include/drivers/floppy.h b/SysCore/include/drivers/floppy.h deleted file mode 100644 index 13ad970..0000000 --- a/SysCore/include/drivers/floppy.h +++ /dev/null @@ -1,26 +0,0 @@ -/***** floppy.h ****************************************************** - * (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * - * * - * Floppy Drive I/O Routines * - * ========================= * - * * - ************************************************************ cta os */ -#include - -extern unsigned char FloppyInitializeDMA(unsigned char* buffer, unsigned length); -extern void FloppyMotor (unsigned char drive, unsigned char on); -extern void i86_FloppyHandler(ISR_stack_regs *r); -extern void FloppyDriveData (unsigned char drv, unsigned char dma); -extern unsigned char FloppyCalibrate(unsigned drive); -extern void FloppyReset(); - -extern unsigned char FloppySeek (unsigned drive, unsigned cyl, unsigned head); -extern void FloppyInstall(); -extern unsigned char FloppyIsDriverEnabled(); - -// Read/Write routines -extern unsigned* FloppyReadSectors (unsigned* where, unsigned char drive, int sectorLBA, unsigned count); -extern unsigned* FloppyWriteSectors (unsigned* where, unsigned char drive, int sectorLBA, unsigned count); - -extern void FloppyReadSectorImp (unsigned* where, unsigned char drive, unsigned char head, unsigned char track, unsigned char sector); -extern void FloppyWritedSectorImp (unsigned* where, unsigned char drive, unsigned char head, unsigned char track, unsigned char sector); \ No newline at end of file diff --git a/SysCore/include/drivers/keyboard.h b/SysCore/include/drivers/keyboard.h deleted file mode 100644 index 671f3a8..0000000 --- a/SysCore/include/drivers/keyboard.h +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef __KEYBOARD_H -#define __KEYBOARD_H - -#include - -#define KeyboardKeyModifierLeftShift 0x81 // 1000 0001 -#define KeyboardKeyModifierRightShift 0x82 // 1000 0010 -#define KeyboardKeyModifierLeftAlt 0x84 // 1000 0100 -#define KeyboardKeyModifierRightAlt 0x88 // 1000 1000 -#define KeyboardKeyModifierLeftCtrl 0x90 // 1001 0000 -#define KeyboardKeyModifierRightCtrl 0xA0 // 1010 0000 -#define KeyboardKeyFakeShift 0xC0 // 1100 0000 - -#define KeyboardLightScroll 0xF1 // 1111 0001 -#define KeyboardLightNum 0xF2 // 1111 0010 -#define KeyboardLightCaps 0xF4 // 1111 0100 - - -enum KeyboardKeys { - KeyboardKeyPause = 0x00, - KeyboardKeyF9 = 0x01, - KeyboardKeyF7 = 0x02, - KeyboardKeyF5 = 0X03, - KeyboardKeyF3 = 0x04, - KeyboardKeyF1 = 0x05, - KeyboardKeyF2 = 0x06, - KeyboardKeyF12 = 0x07, - KeyboardKeyPrintScreen = 0x08, - KeyboardKeyF10 = 0x09, - KeyboardKeyF8 = 0x0A, - KeyboardKeyF6 = 0x0B, - KeyboardKeyF4 = 0x0C, - KeyboardKeyTab = 0x0D, - KeyboardKeyTilda = 0x0E, - KeyboardKeyQ = 0x15, - KeyboardKey1 = 0x16, - KeyboardKeyZ = 0x1A, - KeyboardKeyS = 0x1B, - KeyboardKeyA = 0x1C, - KeyboardKeyW = 0x1D, - KeyboardKey2 = 0x1E, - KeyboardKeyLeftWin = 0x1F, - KeyboardKeyC = 0x21, - KeyboardKeyX = 0x22, - KeyboardKeyD = 0x23, - KeyboardKeyE = 0x24, - KeyboardKey4 = 0x25, - KeyboardKey3 = 0x26, - KeyboardKeyRightWin = 0x27, - KeyboardKeySpace = 0x29, - KeyboardKeyV = 0x2A, - KeyboardKeyF = 0x2B, - KeyboardKeyT = 0x2C, - KeyboardKeyR = 0x2D, - KeyboardKey5 = 0x2E, - KeyboardKeyMenu = 0x2F, - KeyboardKeyN = 0x31, - KeyboardKeyB = 0x32, - KeyboardKeyH = 0x33, - KeyboardKeyG = 0x34, - KeyboardKeyY = 0x35, - KeyboardKey6 = 0x36, - KeyboardKeyM = 0x3A, - KeyboardKeyJ = 0x3B, - KeyboardKeyU = 0x3C, - KeyboardKey7 = 0x3D, - KeyboardKey8 = 0x3E, - KeyboardKeyComma = 0x41, - KeyboardKeyK = 0x42, - KeyboardKeyI = 0x43, - KeyboardKeyO = 0x44, - KeyboardKey0 = 0x45, - KeyboardKey9 = 0x46, - KeyboardKeyPeriod = 0x49, - KeyboardKeySlash = 0x4A, - KeyboardKeyL = 0x4B, - KeyboardKeySemicolon = 0x4C, - KeyboardKeyP = 0x4D, - KeyboardKeyDash = 0x4E, - KeyboardKeyApostrophe = 0x52, - KeyboardKeyLeftBracket = 0x54, - KeyboardKeyEqual = 0x55, - KeyboardKeyNumpadEnter = 0x59, - KeyboardKeyReturn = 0x5A, - KeyboardKeyRightBracket = 0x5B, - KeyboardKeyBackSlash = 0x5D, - KeyboardKeyEnd = 0x5E, - KeyboardKeyLeft = 0x5F, - KeyboardKeyHome = 0x60, - KeyboardKeyInsert = 0x61, - KeyboardKeyDelete = 0x62, - KeyboardKeyDown = 0x63, - KeyboardKeyRight = 0x64, - KeyboardKeyUp = 0x65, - KeyboardKeyBackspace = 0x66, - KeyboardKeyPageDown = 0x67, - KeyboardKeyPageUp = 0x68, - KeyboardKeyNumpad1 = 0x69, - KeyboardKeyNumpadSlash = 0x6A, - KeyboardKeyNumpad4 = 0x6B, - KeyboardKeyNumpad7 = 0x6C, - KeyboardKeyNumpad0 = 0x70, - KeyboardKeyNumpadColon = 0x71, - KeyboardKeyNumpad2 = 0x72, - KeyboardKeyNumpad5 = 0x73, - KeyboardKeyNumpad6 = 0x74, - KeyboardKeyNumpad8 = 0x75, - KeyboardKeyEscape = 0x76, - KeyboardKeyF11 = 0x78, - KeyboardKeyNumpadPlus = 0x79, - KeyboardKeyNumpad3 = 0x7A, - KeyboardKeyNumpadMinus = 0x7B, - KeyboardKeyNumpadAsterisk = 0x7C, - KeyboardKeyNumpad9 = 0x7D -}; - -typedef struct { - unsigned char ModifierStatus; - unsigned char Lights; - unsigned char Scancode; - unsigned char Character; -} KeyboardKey; - -extern void KeyboardSetKey(unsigned char scancode, unsigned char val); -extern unsigned char KeyIsPressed(unsigned char scancode); -extern void i86_KeyboardHandler(ISR_stack_regs *r); -extern KeyboardKey GetKey(); - -/**\n - Sets the repeat rate/delay\n - \n\Delay: - Values for inter-character delay (bits 4-0)\n - (characters per second; default is 10.9)\n - | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 \n - ----+----+----+----+----+----+----+----+----\n - 0 |30.0|26.7|24.0|21.8|20.0|18.5|17.1|16.0\n - 8 |15.0|13.3|12.0|10.9|10.0|9.2 |8.6 |8.0\n - 16 |7.5 |6.7 |6.0 |5.5 |5.0 |4.6 |4.3 |4.0\n - 24 |3.7 |3.3 |3.0 |2.7 |2.5 |2.3 |2.1 |2.0\n - \n - Values for delay:\n - (miliseconds; default is 500)\n - 0 | 1 | 2 | 3\n - -----+-----+-----+-----\n - 250 | 500 | 750 | 1000\n \n*/ -extern void KeyboardSetRepeatRate(unsigned char rate, unsigned char delay); - -/*************************************** - * Set keyboard LEDs * - *************************************** - +-----------+-------+-------+--------+ - | Bits 7-3 | Bit 2 | Bit 1 | Bit 0 | - | 0 | Caps | Num | Scroll | - |(reserved) | lock | lock | lock | - +-----------+-------+-------+--------+ - ***************************************/ -extern void KeyboardSetLEDs(unsigned char status); - -/*************************************** - * Set scancode set * - *************************************** - 0 Get current scancode set - 1 Set to scancode set 1 - 2 Set to scancode set 2 - 3 Set to scancode set 3 - ***************************************/ -extern void KeyboardSetScancodeSet(unsigned char set); -extern void KeyboardWaitInput(); -extern void KeyboardWaitOutput(); -extern void KeyboardInstallA(); -extern void KeyboardInstallB(); - -#endif \ No newline at end of file diff --git a/SysCore/include/hal.h b/SysCore/include/hal.h deleted file mode 100644 index cf49b24..0000000 --- a/SysCore/include/hal.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef _HAL_H -#define _HAL_H - -#include -#include -//#include <..\hal\floppy\floppy.h> -#define far -#define near - -#define i86_start_interrupts() __asm__ __volatile__ ("sti"); -#define i86_clear_interrupts() __asm__ __volatile__ ("cli"); - -extern TIME ClockGetTime() ; -extern unsigned* i86_read_sector (unsigned* where, unsigned char drive, int sectorLBA); -// initialize hardware abstraction layer -extern void i86_hal_initialize (); - -// shutdown hardware abstraction layer -extern int i86_hal_shutdown (); - -//! notifies hal interrupt is done -//extern void interruptdone (unsigned int intno); - -//! output sound to speaker -extern void sound (unsigned frequency); - -//! read unsigned char from device using port mapped io -//extern unsigned char inportb (unsigned short _port); - -//! write unsigned char to device through port mapped io -//extern void outportb (unsigned short _port, unsigned char _data); - -//! sets new interrupt vector -//extern void setvect (int intno, void ( far &vect) ( ) ); - -//! returns current interrupt vector -//extern void ( far * getvect (int intno)) ( ); - -//! returns cpu vender -extern const char* get_cpu_vender (); - -extern void SystemReboot(); - - -/********************************************************************** - * KEYBOARD STUFF * - **********************************************************************/ - -#define KeyboardKeyModifierLeftShift 0x81 // 1000 0001 -#define KeyboardKeyModifierRightShift 0x82 // 1000 0010 -#define KeyboardKeyModifierLeftAlt 0x84 // 1000 0100 -#define KeyboardKeyModifierRightAlt 0x88 // 1000 1000 -#define KeyboardKeyModifierLeftCtrl 0x90 // 1001 0000 -#define KeyboardKeyModifierRightCtrl 0xA0 // 1010 0000 -#define KeyboardKeyFakeShift 0xC0 // 1100 0000 - -#define KeyboardLightScroll 0xF1 // 1111 0001 -#define KeyboardLightNum 0xF2 // 1111 0010 -#define KeyboardLightCaps 0xF4 // 1111 0100 - -enum KeyboardKeys { - KeyboardKeyPause = 0x00, - KeyboardKeyF9 = 0x01, - KeyboardKeyF7 = 0x02, - KeyboardKeyF5 = 0X03, - KeyboardKeyF3 = 0x04, - KeyboardKeyF1 = 0x05, - KeyboardKeyF2 = 0x06, - KeyboardKeyF12 = 0x07, - KeyboardKeyPrintScreen = 0x08, - KeyboardKeyF10 = 0x09, - KeyboardKeyF8 = 0x0A, - KeyboardKeyF6 = 0x0B, - KeyboardKeyF4 = 0x0C, - KeyboardKeyTab = 0x0D, - KeyboardKeyTilda = 0x0E, - KeyboardKeyQ = 0x15, - KeyboardKey1 = 0x16, - KeyboardKeyZ = 0x1A, - KeyboardKeyS = 0x1B, - KeyboardKeyA = 0x1C, - KeyboardKeyW = 0x1D, - KeyboardKey2 = 0x1E, - KeyboardKeyLeftWin = 0x1F, - KeyboardKeyC = 0x21, - KeyboardKeyX = 0x22, - KeyboardKeyD = 0x23, - KeyboardKeyE = 0x24, - KeyboardKey4 = 0x25, - KeyboardKey3 = 0x26, - KeyboardKeyRightWin = 0x27, - KeyboardKeySpace = 0x29, - KeyboardKeyV = 0x2A, - KeyboardKeyF = 0x2B, - KeyboardKeyT = 0x2C, - KeyboardKeyR = 0x2D, - KeyboardKey5 = 0x2E, - KeyboardKeyMenu = 0x2F, - KeyboardKeyN = 0x31, - KeyboardKeyB = 0x32, - KeyboardKeyH = 0x33, - KeyboardKeyG = 0x34, - KeyboardKeyY = 0x35, - KeyboardKey6 = 0x36, - KeyboardKeyM = 0x3A, - KeyboardKeyJ = 0x3B, - KeyboardKeyU = 0x3C, - KeyboardKey7 = 0x3D, - KeyboardKey8 = 0x3E, - KeyboardKeyComma = 0x41, - KeyboardKeyK = 0x42, - KeyboardKeyI = 0x43, - KeyboardKeyO = 0x44, - KeyboardKey0 = 0x45, - KeyboardKey9 = 0x46, - KeyboardKeyPeriod = 0x49, - KeyboardKeySlash = 0x4A, - KeyboardKeyL = 0x4B, - KeyboardKeySemicolon = 0x4C, - KeyboardKeyP = 0x4D, - KeyboardKeyDash = 0x4E, - KeyboardKeyApostrophe = 0x52, - KeyboardKeyLeftBracket = 0x54, - KeyboardKeyEqual = 0x55, - KeyboardKeyNumpadEnter = 0x59, - KeyboardKeyReturn = 0x5A, - KeyboardKeyRightBracket = 0x5B, - KeyboardKeyBackSlash = 0x5D, - KeyboardKeyEnd = 0x5E, - KeyboardKeyLeft = 0x5F, - KeyboardKeyHome = 0x60, - KeyboardKeyInsert = 0x61, - KeyboardKeyDelete = 0x62, - KeyboardKeyDown = 0x63, - KeyboardKeyRight = 0x64, - KeyboardKeyUp = 0x65, - KeyboardKeyBackspace = 0x66, - KeyboardKeyPageDown = 0x67, - KeyboardKeyPageUp = 0x68, - KeyboardKeyNumpad1 = 0x69, - KeyboardKeyNumpadSlash = 0x6A, - KeyboardKeyNumpad4 = 0x6B, - KeyboardKeyNumpad7 = 0x6C, - KeyboardKeyNumpad0 = 0x70, - KeyboardKeyNumpadColon = 0x71, - KeyboardKeyNumpad2 = 0x72, - KeyboardKeyNumpad5 = 0x73, - KeyboardKeyNumpad6 = 0x74, - KeyboardKeyNumpad8 = 0x75, - KeyboardKeyEscape = 0x76, - KeyboardKeyF11 = 0x78, - KeyboardKeyNumpadPlus = 0x79, - KeyboardKeyNumpad3 = 0x7A, - KeyboardKeyNumpadMinus = 0x7B, - KeyboardKeyNumpadAsterisk = 0x7C, - KeyboardKeyNumpad9 = 0x7D -}; - -typedef struct { - unsigned char ModifierStatus; - unsigned char Lights; - unsigned char Scancode; - unsigned char Character; -} KeyboardKey; - - -#endif \ No newline at end of file diff --git a/SysCore/include/regs.h b/SysCore/include/regs.h deleted file mode 100644 index 492ee1f..0000000 --- a/SysCore/include/regs.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef _REGS_H_INCLUDED -#define _REGS_H_INCLUDED -//**************************************************************************** -//** -//** regs.h -//** -//** processor register structures and declarations. This interface abstracts -//** register names behind a common, portable interface -//** -//**************************************************************************** - -//============================================================================ -// INTERFACE REQUIRED HEADERS -//============================================================================ - -#include - -//============================================================================ -// INTERFACE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS -//============================================================================ -//============================================================================ -// INTERFACE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES -//============================================================================ -//============================================================================ -// INTERFACE STRUCTURES / UTILITY CLASSES -//============================================================================ - -//! 32 bit registers -typedef struct { - uint32_t eax, ebx, ecx, edx, esi, edi, ebp, esp, eflags; - uint8_t cflag; -} _R32BIT; - -//! 16 bit registers -typedef struct { - uint16_t ax, bx, cx, dx, si, di, bp, sp, es, cs, ss, ds, flags; - uint8_t cflag; -} _R16BIT ; - -//! 16 bit registers expressed in 32 bit registers -typedef struct { - uint16_t ax, axh, bx, bxh, cx, cxh, dx, dxh; - uint16_t si, di, bp, sp, es, cs, ss, ds, flags; - uint8_t cflags; -} _R16BIT32 ; - -//! 8 bit registers -typedef struct { - uint8_t al, ah, bl, bh, cl, ch, dl, dh; -} _R8BIT; - -//! 8 bit registers expressed in 32 bit registers -typedef struct { - uint8_t al, ah; uint16_t axh; - uint8_t bl, bh; uint16_t bxh; - uint8_t cl, ch; uint16_t cxh; - uint8_t dl, dh; uint16_t dxh; -} _R8BIT32; - -//! 8 and 16 bit registers union -typedef union { - _R16BIT x; - _R8BIT h; -}_INTR16; - -//! 32 bit, 16 bit and 8 bit registers union -typedef union { - _R32BIT x; - _R16BIT32 l; - _R8BIT32 h; -} _INTR32; - -/* This defines what the stack looks like after an ISR was running */ -typedef struct -{ - unsigned int gs, fs, es, ds; /* pushed the segs last */ - unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */ - unsigned int int_no, err_code; /* our 'push byte #' and ecodes do this */ - unsigned int eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */ -} ISR_stack_regs; - - -//============================================================================ -// INTERFACE DATA DECLARATIONS -//============================================================================ -//============================================================================ -// INTERFACE FUNCTION PROTOTYPES -//============================================================================ -//============================================================================ -// INTERFACE OBJECT CLASS DEFINITIONS -//============================================================================ -//============================================================================ -// INTERFACE TRAILING HEADERS -//============================================================================ -//**************************************************************************** -//** -//** END regs.h -//** -//**************************************************************************** -#endif diff --git a/SysCore/include/size_t.h b/SysCore/include/size_t.h deleted file mode 100644 index 7e4b1cc..0000000 --- a/SysCore/include/size_t.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __SIZE_T_H -#define __SIZE_T_H - -/************************************ - * size_t.h * - * - Standard C/C++ size_t type * - ************************************/ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* standard size_t type */ -typedef unsigned size_t; - -#ifdef __cplusplus -} -#endif - - - -#endif diff --git a/SysCore/include/stdint.h b/SysCore/include/stdint.h deleted file mode 100644 index 3338763..0000000 --- a/SysCore/include/stdint.h +++ /dev/null @@ -1,163 +0,0 @@ - -#ifndef _STDINT_H -#define _STDINT_H - -#define __need_wint_t -#define __need_wchar_t - - -/*************************************** - * stdint.h * - * - Standard C++ integral types * - ***************************************/ - -/* 7.18.1.1 Exact-width integer types */ -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef int int32_t; -typedef unsigned uint32_t; -typedef long long int64_t; -typedef unsigned long long uint64_t; - -/* 7.18.1.2 Minimum-width integer types */ -typedef signed char int_least8_t; -typedef unsigned char uint_least8_t; -typedef short int_least16_t; -typedef unsigned short uint_least16_t; -typedef int int_least32_t; -typedef unsigned uint_least32_t; -typedef long long int_least64_t; -typedef unsigned long long uint_least64_t; - -/* 7.18.1.3 Fastest minimum-width integer types - * Not actually guaranteed to be fastest for all purposes - * Here we use the exact-width types for 8 and 16-bit ints. - */ -typedef char int_fast8_t; -typedef unsigned char uint_fast8_t; -typedef short int_fast16_t; -typedef unsigned short uint_fast16_t; -typedef int int_fast32_t; -typedef unsigned int uint_fast32_t; -typedef long long int_fast64_t; -typedef unsigned long long uint_fast64_t; - -/* 7.18.1.4 Integer types capable of holding object pointers */ -typedef int intptr_t; -typedef unsigned uintptr_t; - -/* 7.18.1.5 Greatest-width integer types */ -typedef long long intmax_t; -typedef unsigned long long uintmax_t; - -/* 7.18.2 Limits of specified-width integer types */ -#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS) - -/* 7.18.2.1 Limits of exact-width integer types */ -#define INT8_MIN (-128) -#define INT16_MIN (-32768) -#define INT32_MIN (-2147483647 - 1) -#define INT64_MIN (-9223372036854775807LL - 1) - -#define INT8_MAX 127 -#define INT16_MAX 32767 -#define INT32_MAX 2147483647 -#define INT64_MAX 9223372036854775807LL - -#define UINT8_MAX 0xff /* 255U */ -#define UINT16_MAX 0xffff /* 65535U */ -#define UINT32_MAX 0xffffffff /* 4294967295U */ -#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ - -/* 7.18.2.2 Limits of minimum-width integer types */ -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST64_MIN INT64_MIN - -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MAX INT64_MAX - -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -/* 7.18.2.3 Limits of fastest minimum-width integer types */ -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST64_MIN INT64_MIN - -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MAX INT64_MAX - -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -/* 7.18.2.4 Limits of integer types capable of holding - object pointers */ -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX - -/* 7.18.2.5 Limits of greatest-width integer types */ -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -/* 7.18.3 Limits of other integer types */ -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX - -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -#define SIZE_MAX UINT32_MAX - -#ifndef WCHAR_MIN /* also in wchar.h */ -#define WCHAR_MIN 0 -#define WCHAR_MAX ((wchar_t)-1) /* UINT16_MAX */ -#endif - -/* - * wint_t is unsigned short for compatibility with MS runtime - */ -#define WINT_MIN 0 -#define WINT_MAX ((wint_t)-1) /* UINT16_MAX */ - -#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */ - - -/* 7.18.4 Macros for integer constants */ -#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS) - -/* 7.18.4.1 Macros for minimum-width integer constants */ - -#define INT8_C(val) ((int8_t) + (val)) -#define UINT8_C(val) ((uint8_t) + (val##U)) -#define INT16_C(val) ((int16_t) + (val)) -#define UINT16_C(val) ((uint16_t) + (val##U)) - -#define INT32_C(val) val##L -#define UINT32_C(val) val##UL -#define INT64_C(val) val##LL -#define UINT64_C(val) val##ULL - -/* 7.18.4.2 Macros for greatest-width integer constants */ -#define INTMAX_C(val) INT64_C(val) -#define UINTMAX_C(val) UINT64_C(val) - -#endif /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */ - - - -#endif diff --git a/SysCore/include/stdlib.h b/SysCore/include/stdlib.h deleted file mode 100644 index 9558dd0..0000000 --- a/SysCore/include/stdlib.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef __STDLIB_H__ -#define __STDLIB_H__ - -/** Returns the absolute value of an integer.*/ -#define abs(x) (x>0) ? (x) : (x*-1) -/** Returns the absolute value of a long variable.*/ -#define labs(x) (x>0) ? (x) : (x*-1) -/** Returns the maximum of two numbers.*/ -#define max(a, b) (a > b) ? a : b -/** Returns the minimum of two numbers.*/ -#define min(a, b) (a < b) ? a : b -#define NULL 0 - -/** div_t is a structure of integers used by div()\n - Notes:\n - - quot = quotient;\n - - rem = remainder;\n */ -typedef struct { - /** Quotient */ - long quot; - /** Remainder */ - long rem; -} div_t; - -/** ldiv_t is a structure of integers used by ldiv()\n - Notes:\n - - quot = quotient;\n - - rem = remainder;\n */ -typedef struct { - /** Quotient*/ - long quot; - /** Remainder*/ - long rem; -} ldiv_t; - - -// TODO: extern long double _atold (const char* string); -// TODO: extern double atof (const char* string); // TODO: initialize FPU - -/** Convert ASCII string to INT */ -extern int atoi (const char* string); - -/** Convert ASCII string to LONG */ -extern long atol (const char* string); - -/** Convert ASCII string in hexadecimal to unsigned integer.*/ -extern unsigned int atox (const char* string); - -/** Peform a binary search\n - Notes:\n - - const void* key = A pointer to the element to look for\n - - const void* base = A pointer to the first element of the table\n - - unsigned nelem = The number of elements in the table\n - - unsigned width = The size of one element of the table\n - - int *fcmp = A user defined comparison routine\n */ -extern void* bsearch (const void* key, const void* base, unsigned nelem, unsigned width, int (*fcmp)(const void*, const void*)); - -/**Divides two integers and returns both the quotient and the remainder as a div_t structure.*/ -extern div_t div (int numerator, int denominator); - -/** Convert SIGNED INT to ASCII string */ -extern void itoa (signed int value, char *string, int radix); - -/**Divides two longs and returns both the quotient and the remainder as a ldiv_t structure.*/ -extern ldiv_t ldiv (long numerator, long denominator); - -/**Does a linear search for *key in a table\n - Notes:\n - - const void* key = A pointer to the element to look for\n - - const void* base = A pointer to the first element of the table\n - - unsigned nelem = The number of elements in the table\n - - unsigned width = The size of one element of the table\n - - int *fcmp = A user defined comparison routine\n */ -void* lfind (const void* key, const void* base, unsigned nelem, unsigned width, int (*fcmp)(const void*, const void*)); - -/** Convert SIGNED LONG to ASCII string */ -extern void ltoa (signed long value, char *string, int radix); - -/** Sorts an array using an optimized quick sort algorithm.\n - Notes:\n - - void base = A pointer to the first element of the table\n - - unsigned *nelem = The number of elements in the table\n - - unsigned width = The size of one element of the table\n - - int *fcmp = A user defined comparison routine\n */ -void qsort (void* base, unsigned nelem, unsigned width, int (*fcmp)(const void*, const void*)); - -/** Convert UNSIGNED INT to ASCII string */ -extern void uitoa (unsigned int value, char *string, int radix); - -/** Convert UNSIGNED LONG to ASCII string */ -extern void ultoa (unsigned long value, char *string, int radix); - -#endif \ No newline at end of file diff --git a/SysCore/include/string.h b/SysCore/include/string.h deleted file mode 100644 index 54a553f..0000000 --- a/SysCore/include/string.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _STRING_H -#define _STRING_H -//**************************************************************************** -//** -//** [string.h] -//** - Standard C String routines -//** -//**************************************************************************** -//============================================================================ -// INTERFACE REQUIRED HEADERS -//============================================================================ - -#include - -//============================================================================ -// INTERFACE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS -//============================================================================ -//============================================================================ -// INTERFACE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES -//============================================================================ -//============================================================================ -// INTERFACE STRUCTURES / UTILITY CLASSES -//============================================================================ -//============================================================================ -// INTERFACE DATA DECLARATIONS -//============================================================================ -//============================================================================ -// INTERFACE FUNCTION PROTOTYPES -//============================================================================ - -extern size_t strlen (const char *str); -extern int strcmp(const char *pStr1, const char *pStr2); - -//============================================================================ -// INTERFACE OBJECT CLASS DEFINITIONS -//============================================================================ -//============================================================================ -// INTERFACE TRAILING HEADERS -//============================================================================ -//**************************************************************************** -//** -//** END [string.h] -//** -//**************************************************************************** - -#endif diff --git a/SysCore/include/sys/declarat.h b/SysCore/include/sys/declarat.h deleted file mode 100644 index 8b9c97f..0000000 --- a/SysCore/include/sys/declarat.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __DECLARAT_H -#define __DECLARAT_H - -// Data type declarations -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned int dword; - -// Functions -void system_init(); - -void isrs_install(); - -void irq_install_handler(int irq, void (*handler)(ISR_stack_regs *r)); -void irq_uninstall_handler(int irq); -void irq_install(); -void kb_handler(ISR_stack_regs *r); -void reboot(); -void kb_waitin(); - -#endif \ No newline at end of file diff --git a/SysCore/include/system.h b/SysCore/include/system.h deleted file mode 100644 index 106fdf6..0000000 --- a/SysCore/include/system.h +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************* - * system.c - Basic system functions and variables declaration * - *******************************************************************/ -#ifndef __SYSTEM_H -#define __SYSTEM_H -#include - -#define true 1 -#define false 0 - -// Data type declarations -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned int dword; - -extern byte *TextVideoRam; -extern volatile int cursor_x, cursor_y; -extern int current_mode_width; -extern int current_mode_height; - -extern void *memcpy(void *dest, const void *src, int count); -extern void *memset(void *dest, char val, int count); -extern unsigned short *memsetw(unsigned short *dest, unsigned short val, int count); - -extern byte inportb (word _port); -extern byte inb (word _port); - -static inline void outportb (word _port, byte _data) { - __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); -} -static inline void outb (word _port, byte _data) { - __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); -} - -static inline void iowait() { - asm volatile ("outb %al, $0x80"); -} - - -#endif \ No newline at end of file diff --git a/SysCore/include/time.h b/SysCore/include/time.h deleted file mode 100644 index 46df665..0000000 --- a/SysCore/include/time.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __TIME_C -#define __TIME_C - -extern const char* clock_month[13]; -extern const char* clock_weekday[8]; -extern unsigned char clock_month_len[13]; - -typedef struct { - unsigned char second; - unsigned char minute; - unsigned char hour; - unsigned char weekday; - unsigned char day; - unsigned char month; - unsigned char year; - unsigned char century; -} TIME; - -extern void _CLOCK_INC(TIME *tim); - -#include "../drivers/clock/clock.h" - -//extern char* asctime (TIME time); - -#endif \ No newline at end of file diff --git a/SysCore/include/va_list.h b/SysCore/include/va_list.h deleted file mode 100644 index 2eaabc8..0000000 --- a/SysCore/include/va_list.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __VA_LIST_H -#define __VA_LIST_H -//**************************************************************************** -//** -//** va_list.h -//** - varable length parameter definition -//** -//**************************************************************************** -//============================================================================ -// INTERFACE REQUIRED HEADERS -//============================================================================ -//============================================================================ -// INTERFACE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS -//============================================================================ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* va list parameter list */ -typedef unsigned char *va_list; - -#ifdef __cplusplus -} -#endif - -//============================================================================ -// INTERFACE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES -//============================================================================ -//============================================================================ -// INTERFACE STRUCTURES / UTILITY CLASSES -//============================================================================ -//============================================================================ -// INTERFACE DATA DECLARATIONS -//============================================================================ -//============================================================================ -// INTERFACE FUNCTION PROTOTYPES -//============================================================================ -//============================================================================ -// INTERFACE OBJECT CLASS DEFINITIONS -//============================================================================ -//============================================================================ -// INTERFACE TRAILING HEADERS -//============================================================================ -//**************************************************************************** -//** -//** END va_list.h -//** -//**************************************************************************** - -#endif diff --git a/SysCore/lib/compile.bat b/SysCore/lib/compile.bat deleted file mode 100644 index 229f2fb..0000000 --- a/SysCore/lib/compile.bat +++ /dev/null @@ -1,51 +0,0 @@ -@echo off - -rem NASM and DJGPP executable paths: -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin -set objpath=..\objects -set incpath=../include - -@echo Building Kernel Standard Libraries... - -del %objpath%\system.o -del %objpath%\string.o -del %objpath%\conio.o -del %objpath%\stdlib.o -del %objpath%\time.o -del %objpath%\ctype.o - -goto build -:error - @echo. - @echo There have been build errors. Building halted. - @pause - exit - -:build - @echo * Compiling SYSTEM.C ... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/system.o system.c - - @echo * Compiling STRING.C ... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/string.o string.c - - @echo * Compiling CONIO.C ... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/conio.o conio.c - - @echo * Compiling CTYPE.C ... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/ctype.o ctype.c - - - @echo * Compiling STDLIB.C ... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/stdlib.o stdlib.c - - @echo * Compiling TIME.C ... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/time.o time.c - -:check - if not exist %objpath%\system.o goto error - if not exist %objpath%\string.o goto error - if not exist %objpath%\conio.o goto error - if not exist %objpath%\ctype.o goto error - if not exist %objpath%\stdlib.o goto error - if not exist %objpath%\time.o goto error diff --git a/SysCore/lib/conio.c b/SysCore/lib/conio.c deleted file mode 100644 index ff8e91a..0000000 --- a/SysCore/lib/conio.c +++ /dev/null @@ -1,695 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "../memory/mmngr_ph.h" - -unsigned char ColorDefault; -unsigned char ConsoleScreenInstalled = 0; -/*char hex[] = "0123456789ABCDEF"; */ - -/* External routines the user must specify */ -void (*_console_cursor)(int x, int y); -void (*_console_putc)(int x, int y, unsigned char c); -unsigned char (*_console_getc) (int x, int y); -void (*_console_putcolor)(int x, int y, unsigned char color); -unsigned char (*_console_getcolor)(int x, int y); - -/* Other external routines */ -extern void *memset(void *dest, char val, int count); - -/* Important variables */ -UPoint ScreenSize, Cursor; - -void ConsoleInstall(ConsoleScreen screen) -{ - - _console_cursor = screen.cursor; - _console_putc = screen.putc; - _console_getc = screen.getc; - - _console_putcolor = screen.putcolor; - _console_getcolor = screen.getcolor; - - ScreenSize.X = screen.width; - ScreenSize.Y = screen.height; - - ColorDefault = screen.defcolors; - - Cursor.X = 0; Cursor.Y = 0; - ConsoleUpdateCursor (Cursor, _NORMALCURSOR); - - ConsoleScreenInstalled = 1; - -} - -unsigned char _cuc_ex_type; -UPoint _cuc_ex_pos; -void ConsoleUpdateCursor(UPoint position, unsigned char type) -{ - if (_cuc_ex_type == _SOLIDCURSOR) - (*_console_putcolor) ( - _cuc_ex_pos.X, - _cuc_ex_pos.Y, - 0xFF - (*_console_getcolor)(_cuc_ex_pos.X, _cuc_ex_pos.Y) - ); - if (_cuc_ex_type == _NORMALCURSOR && type != _NORMALCURSOR) - (*_console_cursor)(ScreenSize.X, ScreenSize.Y); - - switch (type) { - case _NORMALCURSOR: - (*_console_cursor)(position.X, position.Y); - break; - case _SOLIDCURSOR: - (*_console_putcolor) ( - position.X, position.Y, - 0xFF - (*_console_getcolor)(position.X, position.Y) - ); break; - case _NOCURSOR: - (*_console_cursor)(ScreenSize.X, ScreenSize.Y); break; - } - - _cuc_ex_type = type; - _cuc_ex_pos.X = position.X; - _cuc_ex_pos.Y = position.Y; -} - - -void ConsoleScroll(unsigned lines) -{ - movetext(0, (int)lines, ScreenSize.X, ScreenSize.Y, 0, 0); -} - - -void ConsoleSetDefaultColors (unsigned char background, unsigned char foreground) -{ - ColorDefault = (foreground & 0xF) | (background<<4); -} - - -void ConsoleSetCursorPosition (Point rel, unsigned char display) -{ - Point abs = { (int)(Cursor.X) + rel.X, - (int)(Cursor.Y) + rel.Y }; - - while (abs.X < 0) { abs.X += (int)ScreenSize.X; abs.Y--; } - while (abs.X >= (int)ScreenSize.X) { abs.X -= (int)ScreenSize.X; abs.Y++; } - if (abs.Y < 0) abs.Y = 0; - - if (abs.Y >= (int)ScreenSize.Y) { - ConsoleScroll((unsigned)abs.Y - ScreenSize.Y + 1); - abs.Y = (int)ScreenSize.Y - 1; - } - - Cursor.X = (unsigned)abs.X; - Cursor.Y = (unsigned)abs.Y; - if (display) ConsoleUpdateCursor(Cursor, _cuc_ex_type); - -} - -/**Inline function to return the index of next word\n - Parameters:\n - - const char* string = string to check for words\n - - int len = length of string\n - - int current = current cursor position\n - - int plus = direction (0:back, 1:foward)\n*/ -inline int __cgets__skip_word(const char* string, int len, int current, int plus) -{ - int tmp = current; - - if (!plus) { - --tmp; - while ((isspace((unsigned char)string[tmp]) || ispunct((unsigned char)string[tmp])) && tmp > 0) --tmp; - while (isalnum((unsigned char)string[tmp]) && tmp > 0) --tmp; - } - - else { - ++tmp; - while (isalnum((unsigned char)string[tmp]) && tmp < len) ++tmp; - while ((isspace((unsigned char)string[tmp]) || ispunct((unsigned char)string[tmp])) && tmp < len) ++tmp; - } - - if (tmp != 0 && plus==0) tmp++; - return tmp; -} - -/**Macro which defines the INSERT key behaviour (overwrite/insert mode)*/ -#define __cgets__key_insert() OverWrite = 1 - OverWrite -/**Macro which defines the ENTER key behaviour*/ -#define __cgets__key_enter() { ConsoleSetCursorPosition((Point){Len, 0}, 1); return Len; } - -/**Move the cursor to the left/right\n - Parameters:\n - - const char* string = the character string to work with\n - - int direction = direction to go (0: backward, 1:foward)\n - - int len = length of string\n - - int* cursor = pointer to cursor integer\n - - int word = move one word (1) or just one character(0)\n */ -inline void __cgets__move_cursor(const char* string, int direction, int len, int* cursor, int word) -{ - int dtmp = (direction) ? 1 : -1; - if ((*cursor <= 0 && direction == 0) || (*cursor >= len && direction == 1)) return; - - // Skip one word (e.g. CTRL is pressed) - if (word) { - int tmp = __cgets__skip_word(string, len, *cursor+dtmp, direction); - *cursor = tmp; - } - else { - *cursor += dtmp; - } -} - -/**Deletes the substring between index_start and index_end-1, also updates string length\n - Parameters:\n - - char* string = the character string to work with\n - - int index_start = where to start\n - - int index_end = where to stop\n - - int* len = pointer to length of string\n*/ -inline void __cgets__delete (char* string, int index_start, int index_end, int* len) -{ - for (; index_end <= *len+1; index_start++, index_end++) - string[index_start] = string[index_end]; - - *len = strlen(string); -} - -/**Inserts a char in position of index, also updates string length\n - Parameters:\n - - char* string = the character string to work with\n - - int index = where to insert\n - - char c = characer to insert\n - - int* len = pointer to length of string\n*/ -inline void __cgets__insert (char* string, int index, char c, int* len) -{ - *len = *len+1; - int i; - - for (i = *len-1; i > index; i--) - string[i] = string[i-1]; - string[index] = c; - - string[*len] = 0; -} - -int cgets(char* string, int maxlen) -{ - unsigned char OverWrite = 0; - memset ((void*)string, 0, maxlen); - - int Len = 0, CurPos = 0; - KeyboardKey Key; - UPoint CursorSave; - - while (Len < maxlen) - { - // Display string on the screen - CursorSave = Cursor; - ConsoleUpdateCursor(Cursor, _NOCURSOR); - cputs(string); clreol(); - // Display cursor in right position - Cursor = CursorSave; - ConsoleSetCursorPosition((Point){CurPos, 0}, 0); - ConsoleUpdateCursor(Cursor, (OverWrite) ? _SOLIDCURSOR : _NORMALCURSOR); - // Restore cursor - Cursor = CursorSave; - - // Get key and process - Key = GetKey(); - - switch (Key.Scancode) { - // Switch overwrite/insert - case KeyboardKeyInsert: __cgets__key_insert(); break; - - // Finish writing (return) - case KeyboardKeyReturn: __cgets__key_enter(); break; - case KeyboardKeyNumpadEnter: __cgets__key_enter(); break; - - // Left - case KeyboardKeyLeft: - __cgets__move_cursor(string, 0, Len, &CurPos, ((Key.ModifierStatus & KeyboardKeyModifierLeftCtrl) || (Key.ModifierStatus & KeyboardKeyModifierRightCtrl))); - break; - - // Right - case KeyboardKeyRight: - __cgets__move_cursor(string, 1, Len, &CurPos, ((Key.ModifierStatus & KeyboardKeyModifierLeftCtrl) || (Key.ModifierStatus & KeyboardKeyModifierRightCtrl))); - break; - - case KeyboardKeyHome: - CurPos = 0; - break; - - case KeyboardKeyEnd: - CurPos = Len; - break; - - case KeyboardKeyBackspace: - if (CurPos > 0) { - int tmp; - if ((Key.ModifierStatus & KeyboardKeyModifierLeftCtrl) || (Key.ModifierStatus & KeyboardKeyModifierRightCtrl)) - tmp = __cgets__skip_word(string, Len, CurPos, 0); - else tmp = CurPos-1; - - __cgets__delete(string, tmp, CurPos, &Len); - CurPos = tmp; - - }; - break; - - // Delete - case KeyboardKeyDelete: - if (CurPos < Len) { - int tmp; - // If CTRL is pressed, foward one word - if ((Key.ModifierStatus & KeyboardKeyModifierLeftCtrl) || (Key.ModifierStatus & KeyboardKeyModifierRightCtrl)) - tmp = __cgets__skip_word(string, Len, CurPos, 1); - else tmp = CurPos+1; - - __cgets__delete(string, CurPos, tmp, &Len); - - - } - break; - - // Text character - default: - if (isprint(Key.Character)) { - // fix CAPS bug - if ((Key.Lights & KeyboardLightCaps) && islower((unsigned char)Key.Character)) - Key.Character = toupper(Key.Character); - - // Cursor is at the end of the string - if (CurPos == Len) { - Len++; string[Len-1] = Key.Character; - string[Len] = 0; - } - - // Cursor is not at the end in OverWrite mode - else if (OverWrite) string[CurPos] = Key.Character; - - // Cursor is not at the end in Insert mode - else __cgets__insert(string, CurPos, Key.Character, &Len); - - // Increase cursor position - CurPos++; - } - break; - } - - } - - __cgets__key_enter(); -} - - -void clreol() -{ - int counter = Cursor.X; - while (counter < ScreenSize.X) { - (*_console_putc)(counter, Cursor.Y, 0); - ++counter; - } -} - - -void clrscr() -{ - for (Cursor.Y = 0; Cursor.Y < ScreenSize.Y; Cursor.Y++) - for (Cursor.X = 0; Cursor.X < ScreenSize.X; Cursor.X++) { - _console_putc(Cursor.X, Cursor.Y, 0); - _console_putcolor(Cursor.X, Cursor.Y, ColorDefault); - } - Cursor.X = 0; Cursor.Y = 0; -} - - -void getpass (char* string) -{} - - -int gettext (int left, int top, int right, int bottom, unsigned char* dest) -{ - if (left < 0 || top < 0 || (unsigned)right > ScreenSize.X || (unsigned)bottom > ScreenSize.Y) - return 0; - - int i, j; - - for (i = top; i < bottom; i++) - for (j = left; j < right; j++) { - *dest++ = (*_console_getc)(j, i); - *dest++ = (*_console_getcolor)(j, i); - } - return 1; -} - - -void gotoxy (int x, int y) -{ - Cursor.X = x; Cursor.Y = y; - ConsoleUpdateCursor(Cursor, _cuc_ex_type); -} - -int cputs(const char* str) -{ - while (*str != 0) { - putch(*str); str++; - } - return (int)*str; -} - - -int getch() -{ - KeyboardKey k; - k = GetKey(); - - if ((k.Lights & KeyboardLightCaps) && k.Character >= 'a' && k.Character <= 'z') - return (int)(k.Character - 'a' + 'A'); - - return k.Character; -} - - -int getche() -{ - int ret = getch(); - putch((char)ret); - return ret; -} - - -/*TODO: kbhit()*/ -void movetext(int left, int top, int right, int bottom, int destleft, int desttop) -{ - int destright = destleft + right - left; - int destbottom = desttop + bottom - top; - // Sanity check - if (left < 0 || top < 0 || (unsigned)right > ScreenSize.X || - (unsigned)bottom > ScreenSize.Y || destleft < 0 || desttop < 0) - return; - - // Allocate memory - int needed_mem = ((right-left) * (bottom - top) * 2) / pmmngr_get_block_size(); - unsigned char* map = (unsigned char*) pmmngr_alloc_blocks(needed_mem); - - // Save box in a buffer - gettext(left, top, right, bottom, map); - - // Empty box - int i, j; - for (i = top; i < bottom; i++) - for (j = left; j < right; j++) { - (*_console_putc)(j, i, 0); - (*_console_putcolor)(j, i, ColorDefault); - } - // Put new text - puttext(destleft, desttop, destright, destbottom, map); - - // Free used memory - pmmngr_free_blocks((unsigned)map, needed_mem * pmmngr_get_block_size()); -} - -int putch(const char c) -{ - switch(c) - { - case '\n': ConsoleSetCursorPosition((Point){0, 1}, 0); - break; - - case '\r': Cursor.X = 0; - break; - - case '\t': ConsoleSetCursorPosition((Point){6 - (Cursor.X % 6), 0}, 0); - break; - - case '\b': ConsoleSetCursorPosition((Point){-1, 0}, 0); - (*_console_putc)(Cursor.X, Cursor.Y, 0); - break; - - default: - (*_console_putc)(Cursor.X, Cursor.Y, c); - (*_console_putcolor)(Cursor.X, Cursor.Y, ColorDefault); - ConsoleSetCursorPosition((Point){1,0}, 0); - break; - } - - return c; -} - -int puttext(int left, int top, int right, int bottom, unsigned char* src) -{ - if (left < 0 || top < 0 || (unsigned)right > ScreenSize.X || (unsigned)bottom > ScreenSize.Y) - return 0; - int i,j; - for (i = top; i < bottom; i++) - for (j = left; j < right; j++) { - (*_console_putc)(j, i, *src++); - (*_console_putcolor)(j, i, *src++); - } - return 1; -} - -void _setcursortype (int cursor) -{ - ConsoleUpdateCursor(Cursor, cursor); -} - -int wherex() { return (int)Cursor.X; }; -int wherey() { return (int)Cursor.Y; }; - - -int cprintf(const char* str, ...) -{ - if (!ConsoleScreenInstalled) return -1; - if (!str || !*str) return 0; - - va_list args; - va_start (args, str); - unsigned i, len = strlen(str); - unsigned char temp_col = ColorDefault; - - for (i = 0; i < len; i++) - switch (str[i]) { - case '%': - switch (str[i+1]) { - // Character - case 'c': {char c = va_arg (args, char); - putch(c); i++; break;} - // String - case 's': {int* c = (int*) va_arg (args, char*); - cputs((const char*)c); i++; break;} - // Integers - case 'd': - case 'i': {int c = va_arg(args, int); - char temp[32]; - itoa(c, temp, 10); - cputs(temp); - i++; break;} - // Integers - hex - case 'X': - case 'x': {int c = va_arg(args, int); - char temp[32]; - uitoa(c, temp, 16); - cputs(temp); - i++; break;} - - // Integers - unsigned - case 'u': { int c = va_arg(args, unsigned int); - char temp[32]; - uitoa(c, temp, 10); - cputs(temp); - i++; break; - } - - case '#': { char temp[] = {str[i+2], str[i+3], 0}; - ColorDefault = (unsigned char) atox(temp); - i+=3; - break; } - - - default: va_end(args); return 1; - }; - break; - default: putch(str[i]); break; - } - - va_end(args); - ColorDefault = temp_col; - return i; -} - -/* -void graphics_init() -{ - -} - -// Change cursor position -void text_mode_cursor(int x, int y) -{ - unsigned temp = y*current_mode_width + x; - - outportb (0x3D4, 14); - outportb (0x3D5, temp >> 8); - outportb (0x3D4, 15); - outportb (0x3D5, temp); -} - -// Set the default colors; max is 0x0F -void set_default_colors(unsigned char back, unsigned char fore) -{ - if (back < 0x10) ColorDefaultBack = back; - if (fore < 0x10) ColorDefaultFore = fore; -} - - -// Clear screen, and set font to default font -void clrscr() -{ - unsigned char font = ColorDefaultFore | (ColorDefaultBack<<4); - int i = 0; - for (i = 0; i < current_mode_width*current_mode_height; i++) - { TextVideoRam[2*i] = 0; - TextVideoRam[2*i+1] = font; - } - cursor_x = 0; cursor_y = 0; -} - -void scroll(int n) -{ - memcpy(TextVideoRam, - TextVideoRam+(current_mode_width*n*2), - 2*current_mode_width*(current_mode_height - n)); - - unsigned char blank = ColorDefaultFore | (ColorDefaultBack<<4); - - int i; - for (i = current_mode_width*(current_mode_height-n); - i < current_mode_width*current_mode_height; i++){ - TextVideoRam[2*i] = 0; - TextVideoRam[2*i+1] = blank; - } -} - - -void prev_line() -{ - cursor_x = 79; - if (--cursor_y < 0) { - cursor_y = 0; cursor_x=0; - } -} - -void next_line() -{ - cursor_x = 0; - if (++cursor_y >=25) { - cursor_y = 24; scroll(1); - } -} - - -// Put character on screen in specified position; can use different font colors -void putc_pos_font(int x, int y, char c, unsigned char back, unsigned char fore) -{ - TextVideoRam[2*(y*current_mode_width+x)] = c; - TextVideoRam[2*(y*current_mode_width+x)+1] = fore|(back<<4); -} -// Put character on screen in specified position; use default font colors -void putc_pos(int x, int y, char c) -{ - TextVideoRam[2*(y*current_mode_width+x)] = c; -} -// Put character on screen in the current cursor position; different font colors -void putc_font(char c, unsigned char back, unsigned char fore) -{ - if (cursor_x >= current_mode_width) next_line(); - - if (c == '\n') {next_line(); return;}; - TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)] = c; - TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)+1] = fore|(back<<4); - cursor_x++; -} -// Put character on screen in the current cursor position; default font colors -void putc(char c) -{ - if (cursor_x >= current_mode_width) next_line(); - - if (c == '\n') {next_line(); return;}; - if (c == '\r') {cursor_x = 0; return; }; - TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)] = c; - cursor_x++; -} - - - - -// Put string on screen in specified position; can use different font colors -void puts_pos_font(int x, int y, const char *str, unsigned char back, unsigned char fore) -{ - int i; - for (i = 0; str[i] != 0; i++) - putc_pos_font(x+i, y, str[i], back, fore); - -} - -// Put string on screen in specified position; use default font colors -void puts_pos(int x, int y, const char *str) -{ - int i; - for (i = 0; str[i] != 0; i++) - putc_pos(x+i, y, str[i]); -} -void puts(const char *str) -{ - int i; - for (i = 0; str[i] != 0; i++) - putc(str[i]); -} - -void puts_font(const char *str, unsigned char back, unsigned char fore) -{ - int i; - for (i = 0; str[i] != 0; i++) - putc_font(str[i], back, fore); -} - -void put_hex(unsigned int alpha) -{ - char nr[9]; - int i; - for (i = 7; i >= 0; i--) { - nr[i] = hex[alpha%16]; - alpha /= 16; - } - nr[8] = 0; - puts(nr); -} -void put_hex_pos(int x, int y, unsigned int alpha) -{ - char nr[9]; - int i; - for (i = 7; i >= 0; i--) { - nr[i] = hex[alpha%16]; - alpha /= 16; - } - nr[8] = 0; - puts_pos(x,y,nr); -} - -void put_bin (int x, int y, unsigned char xz) -{ - int i; - char arr[9] = {0,0,0,0,0,0,0,0,0}; - for(i=7; i>=0; i--) { - arr[i] = (xz%2) + '0'; xz/=2; - } - puts_pos (x, y, arr); -} - - - - -*/ \ No newline at end of file diff --git a/SysCore/lib/stdlib.c b/SysCore/lib/stdlib.c deleted file mode 100644 index f4ea5db..0000000 --- a/SysCore/lib/stdlib.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include - -const char base_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -void uitoa (unsigned int value, char *string, int radix) -{ - if (radix == 1 || radix>36) return; - - // Variables - int len; *string = '0'; - unsigned int temp = value; - - // Calculate string length needed - for (len = 0; temp > 0; len++) temp /= radix; - if (len == 0) len = 2; - - // Last character is NULL - string[len] = 0; - - // Write characters - for (len--; len >=0; len-- ) { - string[len] = base_chars[value%radix]; - value/=radix; - } -} - -void ultoa (unsigned long value, char *string, int radix) -{ - if (radix == 1 || radix>36) return; - - // Variables - int len; *string = '0'; - unsigned long temp = value; - - // Calculate string length needed - for (len = 0; temp > 0; len++) temp /= radix; - if (len == 0) len = 2; - - // Last character is NULL - string[len] = 0; - - // Write characters - for (len--; len >=0; len-- ) { - string[len] = base_chars[value%radix]; - value/=radix; - } -} - -void itoa (signed int value, char *string, int radix) -{ - if (radix == 1 || radix>36) return; - - // Variables - int len = 0; *string = '0'; - unsigned int copy = value; - - // If number is < 0 - if (value < 0) { - if (radix == 10) { - len++; copy = abs(value); - } - else copy = (unsigned) value; // If base is not 10, set high bit - } - - // Calculate string length needed - unsigned int temp = copy; - for (; temp > 0; len++) temp /= radix; - if (len == 0) len = 2; - - // Last character is NULL - string[len] = 0; - - // Write characters - for (len--; len >= 0; len-- ) { - string[len] = base_chars[copy%radix]; - copy/=radix; - } - - // Add minus sign - if (value < 0 && radix == 10) string[0] = '-'; -} - -void ltoa (signed long value, char *string, int radix) -{ - if (radix == 1 || radix>36) return; - - // Variables - int len = 0; *string = '0'; - unsigned long copy = value; - - // If number is < 0 - if (value < 0) { - if (radix == 10) { - len++; copy = abs(value); - } - else copy = (unsigned) value; // If base is not 10, set high bit - } - - // Calculate string length needed - unsigned long temp = copy; - for (; temp > 0; len++) temp /= radix; - if (len == 0) len = 2; - - // Last character is NULL - string[len] = 0; - - // Write characters - for (len--; len >= 0; len-- ) { - string[len] = base_chars[copy%radix]; - copy/=radix; - } - - // Add minus sign - if (value < 0 && radix == 10) string[0] = '-'; -} - -int atoi (const char* string) -{ - int ret = 0; - unsigned char sign = 0; - - for (;!isdigit((unsigned char)*string); string++) { - if (*string == NULL) return 0; - else if (*string == '-' && isdigit(*(string+1))) - sign = 1; - } - - for (;isdigit(*string); string++) - ret = ret*10 + (*string - '0'); - - if (sign) ret*=-1; - - return ret; -} - -long atol (const char* string) -{ - long int ret = 0; - unsigned char sign = 0; - - for (;!isdigit(*string); string++) { - if (*string == NULL) return 0; - else if (*string == '-' && *(string+1) > '0' && *(string+1) < '9') - sign = 1; - } - - for (;isdigit(*string); string++) - ret = ret*10 + (*string - '0'); - - if (sign) ret*=-1; - - return ret; -} - -unsigned int atox (const char* string) -{ - unsigned ret = 0; - unsigned temp; - - for (;!isxdigit(*string); string++) - if (*string == 0) return 0; - - for (;isxdigit(*string); string++) { - if (isdigit(*string)) temp = (unsigned)*string - '0'; - else if (isupper(*string)) temp = 10 + (unsigned)(*string) - 'A'; - else temp = 10 + (unsigned)(*string) - 'a'; - ret = ret*0x10 + temp; - } - return ret; -} - -void* bsearch (const void* key, const void* base, unsigned nelem, unsigned width, int (*fcmp)(const void*, const void*)) -{ - int beg = 0, end = nelem, mid, result; - unsigned addr; - - while (beg != end && beg != end-1) { - mid = (beg + end) / 2; - addr = (unsigned)base + (mid * width); - result = (*fcmp)(key, (void*) addr); - - if (result == 0) return (void*) addr; - else if (result > 0) beg = mid; - else end = mid; - } - return 0; -} - -void* lfind (const void* key, const void* base, unsigned nelem, unsigned width, int (*fcmp)(const void*, const void*)) -{ - int result = 1, i = 0; - - while (result != 0 && i != nelem) { - base = (void*)((unsigned)base + width); - result = (*fcmp)(key, base); - i++; - } - - if (result == 0) return (void*) base; - return 0; -} - -div_t div (int numerator, int denominator) -{ - div_t ret; - ret.quot = numerator / denominator; - ret.rem = numerator % denominator; - return ret; -} - -ldiv_t ldiv (long numerator, long denominator) -{ - ldiv_t ret; - ret.quot = numerator / denominator; - ret.rem = numerator % denominator; - return ret; -} - -inline void __qassign (void *dest, void *source, unsigned width) -{ - unsigned char* dst = (unsigned char*)dest; - unsigned char* src = (unsigned char*)source; - int i; - - for (i = 0; i < width; i++, dst++, src++) - *dst = *src; - -} - -void __qsort(void* base, unsigned width, int (*fcmp)(const void*, const void*), int beg, int end) -{ - unsigned char piv_str[width]; - unsigned char tmp_str[width]; - void* piv = (void*) piv_str; void* tmp = (void*) tmp_str; - - int l,r,p; - - while (beg 0 ) ) r--; - - if (l>r) break; - - __qassign (tmp, (void*) ((unsigned)base + (width * l)), width); - __qassign ((void*) ((unsigned)base + (width * l)), (void*) ((unsigned)base + (width * r)), width); - __qassign ((void*) ((unsigned)base + (width * r)), tmp, width); - //tmp=base[l]; base[l]=base[r]; base[r]=tmp; - - if (p==r) p=l; - - l++; r--; - } - - __qassign((void*) ((unsigned)base + (width * p)), (void*) ((unsigned)base + (width * r)), width); - __qassign((void*) ((unsigned)base + (width * r)), piv, width); - //base[p]=base[r]; base[r]=piv; - r--; - - // Recursion on the shorter side & loop (with new indexes) on the longer - if ((r-beg)<(end-l)) - { - __qsort(base, width, *fcmp, beg, r); - beg=l; - } - else - { - __qsort(base, width, *fcmp, l, end); - end=r; - } - } -} - -void qsort (void* base, unsigned nelem, unsigned width, int (*fcmp)(const void*, const void*)) -{ - __qsort(base, width, *fcmp, 0, nelem-1); -} - diff --git a/SysCore/lib/string.c b/SysCore/lib/string.c deleted file mode 100644 index 35e2e29..0000000 --- a/SysCore/lib/string.c +++ /dev/null @@ -1,23 +0,0 @@ -#include - -unsigned strlen (const char *str) -{ - unsigned i; - for (i = 0; *str!=0; str++) i++; - return i; -} - -int strcmp(const char *pStr1, const char *pStr2) -{ - char c1, c2; - int v; - - do { - c1 = *pStr1++; - c2 = *pStr2++; - /* the casts are necessary when pStr1 is shorter & char is signed */ - v = (unsigned int)c1 - (unsigned int)c2; - } while ((v == 0) && (c1 != '\0')); - - return v; -} diff --git a/SysCore/lib/system.c b/SysCore/lib/system.c deleted file mode 100644 index fbaee98..0000000 --- a/SysCore/lib/system.c +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************** - * system.c - Basic system functions * - ******************************************************************/ - -#include - -extern unsigned char *TextVideoRam; -volatile int cursor_x, cursor_y; -int current_mode_width; -int current_mode_height; - -void *memcpy(void *dest, const void *src, int count) -{ - const char *sp = (const char *)src; - char *dp = (char *)dest; - for(; count != 0; count--) *dp++ = *sp++; - return dest; -} - -void *memset(void *dest, char val, int count) -{ - char *temp = (char *)dest; - for( ; count != 0; count--) *temp++ = val; - return dest; -} - -unsigned short *memsetw(unsigned short *dest, unsigned short val, int count) -{ - unsigned short *temp = (unsigned short *)dest; - for( ; count != 0; count--) *temp++ = val; - return dest; -} - - -unsigned char inportb (word _port) { - unsigned char rv; - __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); - return rv; -} -unsigned char inb (word _port) { - unsigned char rv; - __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); - return rv; -} \ No newline at end of file diff --git a/SysCore/lib/time.c b/SysCore/lib/time.c deleted file mode 100644 index 50baf6f..0000000 --- a/SysCore/lib/time.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -const char* clock_month[] = {0, - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December"}; -const char* clock_weekday[] = {0, - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; - -unsigned char clock_months_len[] = { - 0, - 31, // January - 28, // February - 31, // March - 30, // April - 31, // May - 30, // June - 31, // July - 31, // August - 30, // September - 31, // October - 30, // November - 31 // December -}; - -void _CLOCK_INC(TIME *tim) -{ - // New minute - if (++tim->second > 59) { - tim->second = 0; - // New hour - if (++tim->minute > 59) { - tim->minute = 0; - tim->hour++; - if (tim->hour == 24) { // Midnight - tim->hour = 0; - // New day - tim->weekday = 1+(tim->weekday%7); - // Leap years - if ((tim->day==28) && (tim->month==2)) { tim->day++; return; } - // New month - if (++tim->day > clock_months_len[tim->month]) { - tim->day = 1; - // New year - if (++tim->month>12) { - tim->month = 1; - // New century - if (++tim->year > 99) { tim->year = 0; tim->century++;} - } - } - } - } - } -} - - -/* ASCTIME Formats: **************************************************************** -* 1 W = weekday, M = month, D = day, H = Hour, M = Minute, S = Second, Y = year) * -* A = AM/PM * -* 2 Use capital letter for one letter/digit; else, use lower * -* * -* Example: asctime (time, "Today is: %W3 %D2 %m") * -* Result: Today is: Mon 22 June * -************************************************************************************/ - -/*char* asctime (TIME time, char* format) -{ - char str[100]; - int l = strlen(format), i; - unsigned char special = 0; - - for (i=0; i -#include -#include -//#include -//#include "hal/floppy/floppy.h" -#include "drivers/drivers.h" -#include -#include -#include "memory/mmngr_ph.h" -#include "memory/mmngr_vi.h" -#include "video/vga03h.h" - -#include - -// format of a memory region -typedef struct { - unsigned startLo; - unsigned startHi; - unsigned sizeLo; - unsigned sizeHi; - unsigned type; - unsigned acpi_3_0; -} memory_region ; - -// different memory regions (in memory_region.type) -/*char* strMemoryTypes[] = { - "", - "Available", //memory_region.type==0 - "Reserved", //memory_region.type==1 - "ACPI Reclaim", //memory_region.type==2 - "ACPI NVS Memory" //memory_region.type==3 -};*/ - -extern void _code, _data, _bss, _end; - -void k_init(multiboot_info* bootinfo) -{ - memset(&_bss, 0, &_end - &_bss); // zero the bss - unsigned int i; - - // Start phyiscal memory manager - unsigned memSize = bootinfo->Memory; - - memory_region* memMap = bootinfo->MemoryMapAddress; - pmmngr_init (memSize, (unsigned)&_end); - - // Initialize graphics & HAL - //graphics_init(); - DriversInstall(); - - // Initialize memory - for (i=0; (memMap[i].sizeHi != 0 || memMap[i].sizeLo != 0) && i<15; ++i) - if (memMap[i].type==1) - pmmngr_init_region (memMap[i].startLo, memMap[i].sizeLo); - - // Protect kernel, bios data area etc - pmmngr_deinit_region (0x100000, 4096+(unsigned)((&_end) + (memSize / 4)*3) - 0xC0000000); - pmmngr_deinit_region (0x0, 0x500); // IVT, Bios Data Area - - // Initialize virtual mem manager - vmmngr_initialize(); -} - - -extern void shell(); -void k_main(unsigned kernel_size, multiboot_info* bootinfo) -{ - k_init(bootinfo); - vga03h_install(); - - shell(); - for(;;); -} diff --git a/SysCore/makeall.bat b/SysCore/makeall.bat deleted file mode 100644 index 1f603a1..0000000 --- a/SysCore/makeall.bat +++ /dev/null @@ -1,76 +0,0 @@ -@echo off - -set loader_name=loader -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin - - -@echo ***************** CTA KERNEL ***************** - -goto KernelEntry - -:error - @echo. - @echo There have been build errors. Building halted. - @pause - exit - -:KernelEntry - del objects\%loader_name%.o - del objects\main.o - - @echo. - @echo Building Kernel entry... - @echo * Compiling kernel loader... - %nasm_path%\nasm.exe -f aout -o ./objects/%loader_name%.o %loader_name%.asm - - @echo * Compiling kernel main... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I./include -c -o ./objects/main.o main.c - if not exist objects\%loader_name%.o goto error - if not exist objects\main.o goto error - - @echo. - -:KernelSTDLIB - cd lib - rem call compile.bat - @echo. - cd.. - -:KernelMemoryManager - cd memory - rem call compile.bat - @echo. - cd.. - -:KernelDrivers - cd drivers - rem call makeall.bat - cd.. - -:KernelVIDEO - cd video - call compile.bat - cd.. - -:KernelSHELL - cd shell - call compile.bat - cd.. - -rem here go other sources: - -rem here go other sources ^ - -:Finish - cd objects - @echo Linking... - del kernel.bin - %djgpp_path%\ld -T link.ld - if not exist kernel.bin goto error - - @echo. - - echo Copying to floppy drive... - copy KERNEL.BIN A:\KERNEL.CTA >nul - cd.. \ No newline at end of file diff --git a/SysCore/makeallh.bat b/SysCore/makeallh.bat deleted file mode 100644 index 01132bb..0000000 --- a/SysCore/makeallh.bat +++ /dev/null @@ -1,76 +0,0 @@ -@echo off - -set loader_name=loader -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin - - -@echo ***************** CTA KERNEL ***************** - -goto KernelEntry - -:error - @echo. - @echo There have been build errors. Building halted. - @pause - exit - -:KernelEntry - del objects\%loader_name%.o - del objects\main.o - - @echo. - @echo Building Kernel entry... - @echo * Compiling kernel loader... - %nasm_path%\nasm.exe -f aout -o ./objects/%loader_name%.o %loader_name%.asm - - @echo * Compiling kernel main... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I./include -c -o ./objects/main.o main.c - if not exist objects\%loader_name%.o goto error - if not exist objects\main.o goto error - - @echo. - -:KernelSTDLIB - cd lib - call compile.bat - @echo. - cd.. - -:KernelMemoryManager - cd memory - call compile.bat - @echo. - cd.. - -:KernelDrivers - cd drivers - call makeall.bat - cd.. - -:KernelVIDEO - cd video - call compile.bat - cd.. - -:KernelSHELL - cd shell - call compile.bat - cd.. - -rem here go other sources: - -rem here go other sources ^ - -:Finish - cd objects - @echo Linking... - del kernel.bin - %djgpp_path%\ld -T link.ld - if not exist kernel.bin goto error - - @echo. - - echo Copying to floppy drive... - copy KERNEL.BIN A:\KERNEL.CTA >nul - cd.. \ No newline at end of file diff --git a/SysCore/memory/compile.bat b/SysCore/memory/compile.bat deleted file mode 100644 index aead81c..0000000 --- a/SysCore/memory/compile.bat +++ /dev/null @@ -1,35 +0,0 @@ -@echo off - -rem NASM and DJGPP executable paths: -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin -set objpath=..\objects -set incpath=../include -goto build - -:error - @echo. - @echo There have been build errors. Building halted. - @pause - exit - -:build - @echo Building Memory Manager... - - del %objpath%\mmngr.o - del %objpath%\mmngr_ph.o - - @echo * Compiling Physical Memory Manager... - %nasm_path%\nasm.exe -f aout -o %objpath%/mmngr.o mmngr.asm - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/mmngr_ph.o mmngr_ph.c - - @echo * Compiling Virtual Memory Manager... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/mmngr_vi.o mmngr_vi.c - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/mmngr_de.o lib/pde.c - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/mmngr_te.o lib/pte.c -:check - if not exist %objpath%\mmngr_vi.o goto error - if not exist %objpath%\mmngr_de.o goto error - if not exist %objpath%\mmngr_te.o goto error - if not exist %objpath%\mmngr.o goto error - if not exist %objpath%\mmngr_ph.o goto error diff --git a/SysCore/memory/lib/pde.c b/SysCore/memory/lib/pde.c deleted file mode 100644 index 0e07272..0000000 --- a/SysCore/memory/lib/pde.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "pde.h" - -void pd_entry_add_attrib (pd_entry* entry, unsigned mask) { - *entry |= mask; -} - -void pd_entry_del_attrib (pd_entry* entry, unsigned mask) { - *entry &= ~mask; -} - -void pd_entry_set_frame (pd_entry* entry, unsigned address) { - *entry = (*entry & ~_I86_PDE_FRAME) | address; -} - -unsigned pd_entry_get_frame (pd_entry entry) { - return entry&_I86_PDE_FRAME; -} - -unsigned char pd_entry_is_present (pd_entry entry) { - return (entry & _I86_PDE_PRESENT); -} - -unsigned char pd_entry_is_user (pd_entry entry) { - return (entry & _I86_PDE_USER); -} - -unsigned char pd_entry_is_4mb (pd_entry entry) { - return (entry & _I86_PDE_4MB); -} - -unsigned char pd_entry_is_writable (pd_entry entry) { - return (entry & _I86_PDE_WRITABLE); -} - -void pd_entry_enable_global (pd_entry entry) { -} \ No newline at end of file diff --git a/SysCore/memory/lib/pde.h b/SysCore/memory/lib/pde.h deleted file mode 100644 index fe77351..0000000 --- a/SysCore/memory/lib/pde.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __PAGE_DIRECTORY_ENTRY_ -#define __PAGE_DIRECTORY_ENTRY_ - -enum __PAGE_PDE_FLAGS { - _I86_PDE_PRESENT = 1, - _I86_PDE_WRITABLE = 2, - _I86_PDE_USER = 4, - _I86_PDE_PWT = 8, - _I86_PDE_PCD = 0x10, - _I86_PDE_ACCESSED = 0x20, - _I86_PDE_DIRTY = 0x40, - _I86_PDE_4MB = 0x80, - _I86_PDE_CPU_GLOBAL = 0x100, - _I86_PDE_LV4_GLOBAL = 0x200, - _I86_PDE_FRAME = 0x7FFFF000 - }; - -typedef unsigned pd_entry; - -extern void pd_entry_add_attrib (pd_entry* entry, unsigned mask); -extern void pd_entry_del_attrib (pd_entry* entry, unsigned mask); -extern void pd_entry_set_frame (pd_entry* entry, unsigned address); -extern unsigned pd_entry_get_frame (pd_entry entry); - -extern unsigned char pd_entry_is_present (pd_entry entry); -extern unsigned char pd_entry_is_user (pd_entry entry); -extern unsigned char pd_entry_is_4mb (pd_entry entry); -extern unsigned char pd_entry_is_writable (pd_entry entry); -extern void pd_entry_enable_global (pd_entry entry); -#endif \ No newline at end of file diff --git a/SysCore/memory/lib/pte.c b/SysCore/memory/lib/pte.c deleted file mode 100644 index 5f8bb35..0000000 --- a/SysCore/memory/lib/pte.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "pte.h" - -void pt_entry_add_attrib (pt_entry* entry, unsigned mask) { - *entry |= mask; -} - - void pt_entry_del_attrib (pt_entry* entry, unsigned mask) { - *entry &= ~mask; -} - - void pt_entry_set_frame (pt_entry* entry, unsigned address) { - *entry = (*entry & ~_I86_PTE_FRAME) | address; - } - - unsigned pt_entry_get_frame (pt_entry entry) { - return (entry & _I86_PTE_FRAME); -} - - unsigned char pt_entry_is_present (pt_entry entry) { - return (entry & _I86_PTE_PRESENT); - } - - unsigned char pt_entry_is_writable (pt_entry entry) { - return (entry & _I86_PTE_WRITABLE); -} - - -/*#include - -void pt_entry_print(pt_entry entry) -{ - cprintf ("page "); -}*/ \ No newline at end of file diff --git a/SysCore/memory/lib/pte.h b/SysCore/memory/lib/pte.h deleted file mode 100644 index 246f007..0000000 --- a/SysCore/memory/lib/pte.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __PAGE_TABLE_ENTRY_ -#define __PAGE_TABLE_ENTRY_ - -enum __PAGE_FLAGS { - _I86_PTE_PRESENT = 1, - _I86_PTE_WRITABLE = 2, - _I86_PTE_USER = 4, - _I86_PTE_WRITETHROUGH = 8, - _I86_PTE_NOT_CACHEABLE = 0x10, - _I86_PTE_ACCESSED = 0x20, - _I86_PTE_DIRTY = 0x40, - _I86_PTE_PAT = 0x80, - _I86_PTE_CPU_GLOBAL = 0x100, - _I86_PTE_LV4_GLOBAL = 0x200, - _I86_PTE_FRAME = 0x7FFFF000 - }; - -typedef unsigned pt_entry; - -extern void pt_entry_add_attrib (pt_entry* entry, unsigned mask); -extern void pt_entry_del_attrib (pt_entry* entry, unsigned mask); -extern void pt_entry_set_frame (pt_entry* entry, unsigned address); -extern unsigned pt_entry_get_frame (pt_entry entry); - -extern unsigned char pt_entry_is_present (pt_entry entry); -extern unsigned char pt_entry_is_writable (pt_entry entry); - -extern void pt_entry_print(pt_entry entry); -#endif \ No newline at end of file diff --git a/SysCore/memory/mmngr.asm b/SysCore/memory/mmngr.asm deleted file mode 100644 index 8c4421d..0000000 --- a/SysCore/memory/mmngr.asm +++ /dev/null @@ -1,38 +0,0 @@ -bits 32 - -global _read_cr0 -_read_cr0: - mov eax, cr0 - retn - -global _write_cr0 -_write_cr0: - push ebp - mov ebp, esp - mov eax, [ebp+8] - mov cr0, eax - pop ebp - retn - -global _read_cr3 -_read_cr3: - mov eax, cr3 - retn - -global _write_cr3 -_write_cr3: - ;xchg bx, bx ; bochs magic breakpoint - push ebp - mov ebp, esp - mov eax, [ebp+8] - mov cr3, eax - pop ebp - retn - -global _vmmngr_flush_tbl_entry -_vmmngr_flush_tbl_entry: - mov eax, [ebp+8] - cli - invlpg [eax] - sti - retn \ No newline at end of file diff --git a/SysCore/memory/mmngr_ph.c b/SysCore/memory/mmngr_ph.c deleted file mode 100644 index a3374e8..0000000 --- a/SysCore/memory/mmngr_ph.c +++ /dev/null @@ -1,352 +0,0 @@ -/********************************************************************* - * (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * - * * - * Physical Memory Manager * - * ======================= * - ************************************************************ cta os */ - -// +==============================================+ -// | HEADERS | -// +===================================== cta os =+ -#include "mmngr_ph.h" - - -// +==============================================+ -// | DEFINITIONS | -// +===================================== cta os =+ -#define PMMNGR_BLOCK_SIZE 4096 // block size (4k) -#define PMMNGR_BLOCK_ALIGN PMMNGR_BLOCK_SIZE // block alignment - - -// +==============================================+ -// | DATA DECLARATIONS | -// +===================================== cta os =+ -static unsigned _mmngr_memory_size=0; // size of physical memory -static unsigned _mmngr_used_blocks=0; // number of blocks currently in use -static unsigned _mmngr_max_blocks=0; // maximum number of available memory blocks -static unsigned _mmngr_index = 0; - -static mstack* _mmngr_memory_stack= 0; // memory stack - - -// +==============================================+ -// | LOCAL FUNCTIONS | -// +===================================== cta os =+ -inline mstack mstack_pop () -{ - mstack temp; - temp.low = _mmngr_memory_stack[--_mmngr_index].low; - temp.high = _mmngr_memory_stack[_mmngr_index].high; - _mmngr_used_blocks++; - - _mmngr_memory_stack[_mmngr_index].low = 0xFFFF; - _mmngr_memory_stack[_mmngr_index].high = 0xFF; - - return temp; -} - -inline void mstack_push (const mstack *block) -{ - if (block->low == 0 && block-> high == 0) return; - - _mmngr_memory_stack[_mmngr_index].low = block->low; - _mmngr_memory_stack[_mmngr_index].high = block->high; - - _mmngr_index++; - _mmngr_used_blocks--; -} - -inline int mstack_test (const mstack *block) -{ - unsigned i; - for (i = 0; i < _mmngr_index; i++) - if (_mmngr_memory_stack[i].low == block->low && _mmngr_memory_stack[i].high == block->high) - return (int) i; - - return -1; -} - -inline int mstack_qsort_cmp (mstack a, mstack b) -{ - return (a.high == b.high) ? (int)a.low - (int)b.low : (int)a.high - (int)b.high; -} - -void mstack_qsort(int beg, int end) -{ - - mstack piv; mstack tmp; - - int l,r,p; - - while (beg 0)) r--; - - if (l>r) break; - - tmp.low = _mmngr_memory_stack[l].low; - tmp.high = _mmngr_memory_stack[l].high; - - _mmngr_memory_stack[l].low = _mmngr_memory_stack[r].low; - _mmngr_memory_stack[l].high = _mmngr_memory_stack[r].high; - - _mmngr_memory_stack[r].low = tmp.low; - _mmngr_memory_stack[r].high = tmp.high; - - if (p==r) p=l; - - l++; r--; - } - - _mmngr_memory_stack[p].low = _mmngr_memory_stack[r].low; - _mmngr_memory_stack[p].high = _mmngr_memory_stack[r].high; - - _mmngr_memory_stack[r].low = piv.low; - _mmngr_memory_stack[r].high = piv.high; - r--; - - // Recursion on the shorter side & loop (with new indexes) on the longer - if ((r-beg)<(end-l)) { - mstack_qsort(beg, r); - beg=l; - } - else { - mstack_qsort(l, end); - end=r; - } - } -} - - -// +==============================================+ -// | DEBUGGING FUNCTIONS | -// +===================================== cta os =+ -/*void print_stack() -{ - int i; - for (i = 0; i < _mmngr_index; i++) \n\r (" %u", _mmngr_memory_stack[i].low); -} -extern char getch();*/ - -// +==============================================+ -// | INITIALISATION FUNCTIONS | -// +===================================== cta os =+ -void pmmngr_init (unsigned memSize, unsigned stack) { - - _mmngr_memory_size = memSize; - _mmngr_memory_stack = (mstack*) stack; - _mmngr_max_blocks = (_mmngr_memory_size*1024) / PMMNGR_BLOCK_SIZE; - _mmngr_used_blocks = _mmngr_max_blocks; - _mmngr_index = 0; - - // By default, all of memory is in use -} - -void pmmngr_init_region (unsigned base, unsigned size) { - - mstack block; - - - unsigned int count = size / PMMNGR_BLOCK_SIZE; - unsigned int start = base / PMMNGR_BLOCK_SIZE; - - for (; count!=0; count--) { - block.low = (start + count) & 0xFFFF; - block.high = ((start + count) << 16) & 0xFF; - mstack_push(&block); - - } - -} - -void pmmngr_deinit_region (unsigned base, unsigned size) { - unsigned int start = base / PMMNGR_BLOCK_SIZE; - unsigned int count = size / PMMNGR_BLOCK_SIZE; - int temp; - - unsigned int i; - unsigned int j; - - // Find free blocks in the area and zero them - for (i = 0; i < _mmngr_index; i++) { - temp = (_mmngr_memory_stack[i].high << 16) | _mmngr_memory_stack[i].low; - if (temp >=start && temp < start+count) - { _mmngr_memory_stack[i].high = 0; - _mmngr_memory_stack[i].low = 0; - } - } - - // Eliminate zero blocks - for (i = 0; i<_mmngr_index; i++) - if (_mmngr_memory_stack[i].high == 0 && _mmngr_memory_stack[i].low == 0) - { - // Find next non-zero - for (j = i; _mmngr_memory_stack[j].high == 0 && _mmngr_memory_stack[j].low == 0; j++) - if (j == _mmngr_index-1) { - j = 0; break; } - - if (j == 0) { - _mmngr_index = i; - break; - } - - _mmngr_memory_stack[i].high = _mmngr_memory_stack[j].high; - _mmngr_memory_stack[i].low = _mmngr_memory_stack[j].low; - _mmngr_memory_stack[j].high = 0; - _mmngr_memory_stack[j].low = 0; - - } -} - - -// +==============================================+ -// | MEMORY MANAGING FUNCTIONS | -// +===================================== cta os =+ -unsigned char pmmngr_test_block (unsigned block) -{ - mstack temp; - temp.low = block & 0xFFFF; - temp.high = (block>>16) & 0xFF; - - return (mstack_test(&temp) == -1)? 0 : 1; -} - -void pmmngr_free_block(void* address) -{ - // Calculate block - mstack block; - unsigned temp = (unsigned)address / PMMNGR_BLOCK_SIZE; - block.low = temp & 0xFFFF; - block.high = (temp>>16) & 0xFF; - - // Push it - mstack_push (&block); -} - -void pmmngr_free_blocks (unsigned base, unsigned size) -{ - mstack start, end, i; - - // 4k align - base /= PMMNGR_BLOCK_SIZE; - size /= PMMNGR_BLOCK_SIZE; - - // Calculate blocks - start.low = base & 0xFFFF; - start.high = (base >> 16) & 0xFF; - end.low = (base + size) & 0xFFFF; - end.high = ((base + size)>>16) & 0xFF; - - for (i.low = start.low, i.high = start.high; // i = start - i.low < end.low || i.high < end.high;) // i != end - { - // only push if block is used - if (mstack_test(&i) == -1) mstack_push(&i); - - // increment i.high - if (i.low == 0xFFFF) { - i.low = 0; i.high++; - } - else i.low++; - } -} - -void* pmmngr_alloc_block() -{ - if (_mmngr_index == 0) return 0;// Out of memory - // pop a block - mstack block = mstack_pop(); - - // Calculate and return address; - void* address; - unsigned temp = block.low | (block.high<<16); - address = (void *)(temp * PMMNGR_BLOCK_SIZE); - - return address; -} - -void* pmmngr_alloc_blocks (unsigned blocks) -{ - // Less than 2 blocks requested - if (blocks == 0) return 0; - if (blocks == 1) return pmmngr_alloc_block(); - - // Sort the stack for the next step - mstack_qsort(0, (int)_mmngr_index); - - int i = (int) _mmngr_index-1; // i = counter - int l = 1; // l = number of consecutive blocks - unsigned temp; // temp = temporary storage - unsigned prev = _mmngr_memory_stack[i].low | (_mmngr_memory_stack[i].high<<16); --i; - - // Search consecutive blocks - for (i = 0; i < _mmngr_index; i++) { - temp = _mmngr_memory_stack[i].low | (_mmngr_memory_stack[i].high<<16); - - if (temp == prev+1) l++; - else l = 1; - - if (l == blocks) { - pmmngr_deinit_region (temp * PMMNGR_BLOCK_SIZE, blocks * PMMNGR_BLOCK_SIZE); - return (void*) ((temp-l+1) * PMMNGR_BLOCK_SIZE); - } - - prev = temp; - } - - return 0; // Could not find so many free blocks -} - - - - -// +==============================================+ -// | GET DATA FUNCTIONS | -// +===================================== cta os =+ -unsigned pmmngr_get_memory_size () { - return _mmngr_memory_size; -} - -unsigned pmmngr_get_block_count () { - return _mmngr_max_blocks; -} - -unsigned pmmngr_get_use_block_count () { - return _mmngr_used_blocks; -} - -unsigned pmmngr_get_free_block_count () { - return _mmngr_index; -} - -unsigned pmmngr_get_block_size () { - return PMMNGR_BLOCK_SIZE; -} - - -// +==============================================+ -// | PAGING RELATED FUNCTIONS | -// +===================================== cta os =+ -void pmmngr_paging_enable (unsigned char b) { - unsigned temp; - - temp = read_cr0(); - // Enable - if (b) temp |= 0x80000000; - else temp &= ~0x80000000; - - write_cr0(temp); -} - -unsigned char pmmngr_is_paging () { - unsigned temp = read_cr0(); - return ((temp&0x80000000)>0); -} \ No newline at end of file diff --git a/SysCore/memory/mmngr_ph.h b/SysCore/memory/mmngr_ph.h deleted file mode 100644 index d80425c..0000000 --- a/SysCore/memory/mmngr_ph.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _MMNGR_PHYS_H -#define _MMNGR_PHYS_H - -#define pmmngr_load_PDBR(addr) write_cr3(addr) -#define pmmngr_get_PDBR() read_cr3() - -// physical address -typedef unsigned physical_addr; - -struct memory_stack_entry{ - unsigned short low; - unsigned char high; -} __attribute__ ((__packed__)); -typedef struct memory_stack_entry mstack; - -// CR registers r/w operations -extern unsigned read_cr0(); -extern unsigned read_cr3(); -extern void write_cr0(unsigned data); -extern void write_cr3(unsigned data); - -// Free/Alloc memory block(s) -extern void pmmngr_free_block(void* address); -extern void pmmngr_free_blocks(unsigned base, unsigned size); -extern void* pmmngr_alloc_block (); -extern void* pmmngr_alloc_blocks (unsigned blocks); - -// De/Initialisation routines -extern void pmmngr_init (unsigned memSize, unsigned stack); -extern void pmmngr_init_region (unsigned base, unsigned size); -extern void pmmngr_deinit_region (unsigned base, unsigned size); - -// Useful information -extern unsigned pmmngr_get_memory_size (); // returns amount of physical memory the manager is set to use -extern unsigned pmmngr_get_use_block_count (); // returns number of blocks currently in use -extern unsigned pmmngr_get_free_block_count (); // returns number of blocks not in use -extern unsigned pmmngr_get_block_count (); // returns number of memory blocks -extern unsigned pmmngr_get_block_size (); // returns default memory block size in unsigned chars -extern unsigned char pmmngr_test_block (unsigned block); - -// Paging -extern void pmmngr_paging_enable (unsigned char b); // enable or disable paging -extern unsigned char pmmngr_is_paging (); // test if paging is enabled - -extern void print_stack(); - -#endif diff --git a/SysCore/memory/mmngr_vi.c b/SysCore/memory/mmngr_vi.c deleted file mode 100644 index 21c2363..0000000 --- a/SysCore/memory/mmngr_vi.c +++ /dev/null @@ -1,193 +0,0 @@ -// +==============================================+ -// | HEADERS | -// +===================================== cta os =+ -#include "mmngr_vi.h" -#include "mmngr_ph.h" - -// +==============================================+ -// | DEFINITIONS & MACROS | -// +===================================== cta os =+ -#define PAGE_SIZE 4096 -#define PTABLE_ADDR_SPACE_SIZE 0x400000 -#define DTABLE_ADDR_SPACE_SIZE 0xffffffff -#define PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3ff) -#define PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3ff) -#define PAGE_GET_PHYSICAL_ADDRESS(x) (*x & ~0xfff) - -pdirectory* _current_directory; -unsigned _current_page_directory_base_register; -extern unsigned char *memset (unsigned char *dest, unsigned char val, int count); - -// +==============================================+ -// | PAGE FUNCTIONS | -// +===================================== cta os =+ -unsigned char vmmngr_alloc_page (pt_entry* entry) -{ - void* p = pmmngr_alloc_block (); - if (!p) return 0; - - pt_entry_set_frame(entry, (unsigned)p); - pt_entry_add_attrib (entry, _I86_PTE_PRESENT); - - return 1; -} - -void vmmngr_free_page (pt_entry* entry) -{ - void* p = (void*) pt_entry_get_frame(*entry); - - if (p) pmmngr_free_block (p); - - pt_entry_del_attrib (entry, _I86_PTE_PRESENT); -} - - -// +==============================================+ -// | PAGE TABLE FUNCTIONS | -// +===================================== cta os =+ -inline void vmmngr_ptable_clear(ptable* p) -{ - if(p) memset ((unsigned char*)p, 0, sizeof(ptable)); -} - -inline unsigned vmmngr_ptable_virt_to_index (unsigned addr) -{ - return (addr >= PTABLE_ADDR_SPACE_SIZE) ? 0 : addr/PAGE_SIZE; -} - -inline pt_entry* vmmngr_ptable_lookup_entry (ptable* p, unsigned addr) -{ - if (p) return &p->m_entries[vmmngr_ptable_virt_to_index(addr)]; - return 0; -} - - -// +==============================================+ -// | PAGE DIRECTORY FUNCTIONS | -// +===================================== cta os =+ -inline void vmmngr_pdirectory_clear(pdirectory* dir) -{ - if(dir) memset ((unsigned char*)dir, 0, sizeof(pdirectory)); -} - -inline unsigned vmmngr_pdirectory_virt_to_index (unsigned addr) -{ - return (addr > DTABLE_ADDR_SPACE_SIZE) ? 0 : addr/PAGE_SIZE; -} - -inline pd_entry* vmmngr_pdirectory_lookup_entry (pdirectory* dir, unsigned addr) -{ - if (dir) return &dir->m_entries[vmmngr_ptable_virt_to_index(addr)]; - return 0; -} - -// +==============================================+ -// | VIRTUAL MEMORY MANAGER | -// +===================================== cta os =+ -inline unsigned char vmmngr_switch_pdirectory (pdirectory* dir) -{ - if (!dir) return 0; - _current_directory = dir; - - write_cr3 (_current_page_directory_base_register); - return 1; -} - -pdirectory* vmmngr_get_directory() { - return _current_directory; -} - - -unsigned char vmmngr_map_page (unsigned phys, unsigned virt) -{ - pdirectory* dir = _current_directory; // get page directory - pd_entry* e = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt)]; // get page table - - if ((*e & _I86_PTE_PRESENT) != _I86_PTE_PRESENT) { - - // Page table not present, allocate it - ptable* table = (ptable *)pmmngr_alloc_block(); - if (!table) return 0; - - // Clear it - vmmngr_ptable_clear(table); - - // Create new entry - pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt)]; - - // Map in the table - pd_entry_add_attrib (entry, _I86_PDE_PRESENT); - pd_entry_add_attrib (entry, _I86_PDE_WRITABLE); - pd_entry_set_frame (entry, (unsigned) table); - } - - // get table - ptable* table = (ptable*) PAGE_GET_PHYSICAL_ADDRESS(e); - - // get page - pt_entry* page = &table->m_entries [PAGE_TABLE_INDEX (virt)]; - - pt_entry_set_frame (page, phys); - pt_entry_add_attrib (page, _I86_PTE_PRESENT); - - return 1; -} - -unsigned char vmmngr_initialize() -{ - unsigned int i, virt, frame; - - // Allocate default page & directory table(s) - ptable* table = (ptable*) pmmngr_alloc_block(); - ptable* table2 = (ptable*) pmmngr_alloc_block(); - pdirectory* dir = (pdirectory*) pmmngr_alloc_blocks(3); - - if (!table || !table2 || !dir) return 0; - - // Clear page & directory tables - vmmngr_ptable_clear(table); - vmmngr_ptable_clear(table2); - vmmngr_pdirectory_clear(dir); - - // Identity map the first page table - virt = 0; frame = 0; - for (i = 0; i < 1024; i++, virt+=4096, frame += 4096) - { - pt_entry* page = &table2->m_entries[PAGE_TABLE_INDEX(virt)]; - *page = 0; - pt_entry_add_attrib (page, _I86_PTE_PRESENT); - pt_entry_set_frame (page, frame); - } - - // Map 0x100000 to 0xC0000000 - virt = 0xC0000000; frame = 0x100000; - for (i = 0; i < 1024; i++, virt+=4096, frame += 4096) - { - pt_entry* page = &table->m_entries[PAGE_TABLE_INDEX(virt)]; - *page = 0; - pt_entry_add_attrib (page, _I86_PTE_PRESENT); - pt_entry_set_frame (page, frame); - } - - // Get tables in dir table and point them to our tables - pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (0xC0000000)]; - pd_entry_add_attrib (entry, _I86_PDE_PRESENT); - pd_entry_add_attrib (entry, _I86_PDE_WRITABLE); - pd_entry_set_frame (entry, (unsigned) table); - - entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (0x00000000)]; - pd_entry_add_attrib (entry, _I86_PDE_PRESENT); - pd_entry_add_attrib (entry, _I86_PDE_WRITABLE); - pd_entry_set_frame (entry, (unsigned) table2); - - // Store current PDBR - _current_page_directory_base_register = (unsigned) &dir->m_entries; - - // Switch to our page directory - vmmngr_switch_pdirectory (dir); - - // Enable paging - pmmngr_paging_enable (1); - - return 1; -} \ No newline at end of file diff --git a/SysCore/memory/mmngr_vi.h b/SysCore/memory/mmngr_vi.h deleted file mode 100644 index 765a336..0000000 --- a/SysCore/memory/mmngr_vi.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __MEMORY_MANAGER_VIRTUAL__ -#define __MEMORY_MANAGER_VIRTUAL__ - -#include "lib/pde.h" -#include "lib/pte.h" - -#define PAGES_PER_TABLE 1024 -#define PAGES_PER_DIR 1024 - -typedef unsigned virtual_address; - -typedef struct { - pt_entry m_entries[PAGES_PER_TABLE]; -} ptable ; - -typedef struct { - pd_entry m_entries[PAGES_PER_DIR]; -} pdirectory ; - -//extern pdirectory* _current_directory; - -extern void vmmngr_flush_tbl_entry (unsigned addr); -extern unsigned char vmmngr_initialize(); -extern unsigned char vmmngr_map_page(unsigned phys, unsigned virt); - -#endif \ No newline at end of file diff --git a/SysCore/objects/CONIO.O b/SysCore/objects/CONIO.O deleted file mode 100644 index 589edf52c9a34f0240de94c07af59273f69eefac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8431 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 diff --git a/SysCore/objects/CTYPE.O b/SysCore/objects/CTYPE.O deleted file mode 100644 index d29f25ad12ea7bf719ac498a9bc5c195c26e0553..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 672 zcmeZaWM%+?Ba93TJYW_Jqh3jBMG2S7NYG13EJ*~5KnbAy z24p^v?ZA+5KrgAd7)=<1+rVIOpxZ@-rC|ryl1k?07Yc_#0^b@y0uCk2%?A_?Pnf{K z2m{O@0OKHNHV#x^00&U<1Tb*G0w4+&fI$Nm0Fnp04#V~I6JP^c#SX-54B~K>URq{O zD%1)8{xdM7GbWc*7NqJWL&ZQ;d`W(3K|yK}h|S2Lz`%sXBS1Ad`Q@oaf-p4<$SDD& tftgVWNP^-Y0gzJxNQRjaXaO2PP643w22_Iq;^V=t28)BtVPaqbk^pf=Mg{-? diff --git a/SysCore/objects/LOADER.O b/SysCore/objects/LOADER.O deleted file mode 100644 index 14e7e1c0b5c306e708cd7a6b68151cc44049a46a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148 zcmZQ)Okt2=fC2>u1_LOQ14_SUu&p|C??9j*Z4RMEn`#e5df1DoOCaFEgQU13f&rn}9{e%gx??hQcO$!-_yZ5Z zdRbQg1N{>OFM{YnONAcAizokpKs|cy`rb^o$(rWDeEadu_uiYyyxh{tK=D@tSe8uJ z%!ogYBvrejC8RAxg98sE(AFr4jBJ1^09XLDmc{!>lw8LOX2 zy+n{$MrGeJbmIHEL7yQ(dLa#0@{Q!8Aw>yaY5NPo!MXTFv!?YIQ>$6QLVBt<6J1$v z#CyxQTZR5Seku^n#o5B(M>5}{Y0dWb@+u?lgxZ1T#k(5Fazjlo-KUyp;8pG9VUFCra;5jE{)#)KMy6s zE{f6vlaoUUWsPQs&N+_BsVSjcKBn^I#L#>m=b?%;6?7*Gss*rutEgNlD2#F6A>$}Y zz*uoSQ3<=;b#n*aUDDgR0J*X?rHscs_asxEcT>vyg2FuRg*^ZNQJv4Y&o-{FueEy) zUyGtZZ1*GHw!@uptZxe6={=dX+vZ*`ct-gy<_tP^quIp=4kH^c$_Ae2cLMp~!gj@T h4(zd#98Ocf0^Sil|41!pRv-pE2yf=aMwxPY{sD(ivts}N diff --git a/SysCore/objects/MMNGR.O b/SysCore/objects/MMNGR.O deleted file mode 100644 index bc7bef7aa7857eac4da0054e62eeba592b22bd5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 202 zcmZQ)OkvPqKmZ#A6U^dQIB+<$^J%v$2fxyR*u(q^H{jeGv4?@ezxWv~ejlE|0#wZk z)yoHEgTy4EYXWg?Ov9l$rdnvuKHv z+0R+F1{&q1B5$67{V|4+CMcDrArL}>CLO;P$06yM5b36gO8hDyHm4q-RhpKHQS&|T z*~fO({xR_++n@Wr=iYPfJ@=lM^g5h^o+-BwnnkjsMGsBu7TaI*E+L) z^-C?o1Nwk1-SpchT9;b}W3f_$qos{J&kEmipYe7>!moJ~x3)sHn*MJ_NO20OX!;W zC9vq&P93opJJz3(q%6rz;f~7qEy|+5Nowzs;<9-@Tf5&_aoX0=Kb_0r>3=v43$3!< zuhqbKDWJ*9l3#P}Udg&C^h)Zj*}YX6&s{9tC=4>CMPUISVk{4^K*G?e*iB0tTxpOZgEyaRTQuml8N zOM&l&Ni7B5p4>47u|90dwYC*{>d{jxB?8*s(>_EIHa$*q*>1HK0#2z-*E~qrjOICT zWb=2|=zNhOw%(K6;lna)KXN@!NzUqN%I?CH4w|wjKcz!DVqUp3piNWuc5k(GtVVu`oOa04jzMjgu^~2^{N%?kckGAI5BoRKf zTzV%Idx7P5;{Kc5i9_+T#;S_otfLA)9&vy5kFsw5Gg z3LBkOB0gchlemrC9x_*w@>JWa`tAFTW#{aS3Y#j}s6xMd>Xo=+TES)Sx9)WIpZ3ym zev!FDVcBnztzLo z$|=t-D~rp^c$ zIHgjXDoXOMq(=>#0ZmO^R&jmnXsuMK!>Cv4<2CKQTAgB?M<&cS&9_R|-h6|~S%W>d zDyKeKQZ@f-RZXlre!%<>a;G7MvokojrKk1-EsZA0#Z|mV@cz4ov}E0=)Xyhm%}4R$ zH{5~nmAOO6C1TPf)ap8At`kjTwUv&$@pk7qI(x=GI%YzTSnrSSGt|mgVS2%MT$B@( z1($@~DZam4xm@9eV;`?IKVCN0>kE5nxuohzJL?7PQkGsr%5hh!QEF3{+{S8W{^j7d z!?Ka=AE++2G-B|nGQtEH2nXZ04 z+2v@v7_ZD>rmTzS!)d}{aVhhCh}it|e!5GR%jnDY+E(3G^*ascB7NFxeIsHp?RNSc zg-;j3r7RxTRH`##{ttT9cKps}D?Wx1ux)+~HQOopU zrcW^KW9nj>Vwz)0Fnx>ZdrU7fQ6==^Qz_C+n@pd_UfaE6OdCv{QlWQ{NoSg4dYl`|O!uJB+TQjtbu%4i>SKC}>6=X7VfrD{BGWIJ{=syWsZlOOu$$@AOkGUJndX?D zVS0h-CrrO&`YqE{CPziV@5h-!Oph@=$@EpGXPBO2dY9?HOgk$JK735QOb;*(GL11s znbJ(JGF@Q$J<~f(?=w|Y6(aZs(+f;znJzFjx(XxiV!DT^jp;t70O+GQzaB9L+GWub zthIzk$3oEPxt0@R#4$b|8HolbA88q~Rr?!>u^t=@K_4L+@S*EoRQ90dEmQ78i;6+f z<}g~mGG!1gdK?%l;U?Yai9j62$Fi{uPT>1TWy%6t@0BUvMr$W#ERK2+N(+K1Drcb_ zFH>HD@|!Z{FHru74JeMf0%bqWQBkRYpYN6_jZj`fri(UrLBXFvCCcZZ>_IMyHV;Ah zWSJ6$vbRk68kEnLDL;VXFH=^a^pq(Vp~P7!{m&8|!s(#@EsueUPw9V^C`qs>_7$k~ zKT0dhj-!RHvfs-*7Fo7>-YrvdXa$4z*&7dyPeh*x#zvnEu@;YohJ%A+6GM;2SQ{Uh zzFr!Q42PzR2KkBffuTo5a6Cr8!O4lqBFAHoa6=EpbZ$Hrn~3Vcq4A=vrHJ699ph+Z z6vicuU^Fx`IuT)QI7BAbtK`FunGM6yQ0S%-7Mu4mFowlnXIG*X4M#$HuxtnO6Oe9g zU~p(69w`P-I(GM_eZ}~0FwmaR&Q#vdO6v7{k1?>(Id^|d;hk`@V LR)O6a7`Ett>;cd) diff --git a/SysCore/objects/SHELL.O b/SysCore/objects/SHELL.O deleted file mode 100644 index 8a47567be8ee35c01596803d840e249b5a44d685..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8752 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 diff --git a/SysCore/objects/STDLIB.O b/SysCore/objects/STDLIB.O deleted file mode 100644 index eb82997a1794f050f5f62241fff72f13d09c38ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2845 zcmdT`Z)_7~7=N!lXn`YFw8V;yG~tL4#;kvk9pl3`S_ZOBU^@`EQo5~-CJoc}PQh$Y zxisO;d65s0NHo!p`iaCCP>D1rm8#R@p%blMS}2RvklgPZW?^g9CheG-QGQ|N)zW$`Z%W|axS?@v8PjVkz+r| zEXsXENex3bFCM-~mL)HX%ohYqO>Rl1qx;w)Kje1NSt9VTW)SdC-yl-vrt!7igu8WAvT!aaP2h zw@fC;COIT;ViS^VpOK>;+m+a~UV4NbXrRhkalsJKsfG$)%&`L&oHq1Mm3~j{sLwU9 z1B)l$(k&Jeec(d0OkKw#@*v%wox}ft>Hp~&{&y1p%Mx!=-eXJPS##WQZ_>r958)n~ z!>;Ad4wMt~NRKCYGi{;1q7ZKb#u+_7k643q>h7GeSIa@C?!2r|>!gL+^kY1d9;H>c z1FS5YJVExrBMsw`_N)LMBNv!2$=*Wotl|F@TcCc$?W%7B!kP5ll~fLAuijUDTorpR z3rEDMn;lT~G)O#{=1Ogx7rKCgABB1z;LH@ za2%BB8Yolm=Omf|;-4>ytF0Ye74E25{|2YGCR6O06klY|WZ3hmWKM!JgQi(9%dlLq zmpc;TV$M$W!M8?l2YJvAZSWv1e40e)-X`ecHqN1)0zVOFprB4tTk0G5iP*jN{aFG3 zqV3gY93EHvjGTHBr{y2V@o=8RuC{Tjf;>8o{dq-j@q&|8??a+WGlQE) zm3}9lw)$P={k=Mk{kIg!1ynnZ!alACgE{4421+;AQ#+FrQ9}R z;u82G1q6aBnA_pK2Hr+{<&$7Z9&~3_e;Jx@SXPIT8q)dwTdFv!R#mJsTp;$n9+(plZ5 z%g8e*Ma15aKBtfeSs>4Uj-V9PI6a`yI4D?N^i@ToQ_vf*zRU@Uy%ErRAk&H@3X%_J zNsfSICFD`&bjHJ>Sl6L-!((;ayo7NG+bNmLgdGbKb16ZF0*2?m3& z#d~97rXtbi2rY#hnQnRJJ&|mLm8u6FxgA!<%sV0^0-TD@Kr`=$kjUJe8Fxbxsg+u7 zET8pe%QM2UpkS~|Jo>6}s=6c;jrMkhj71i$4oJ44cs$Z`7zH~+@o=!~P$(8he*=tk B61M;V diff --git a/SysCore/objects/STRING.O b/SysCore/objects/STRING.O deleted file mode 100644 index 86b2567379286e7c1ef44794117f0027c288d5c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 414 zcmeZaWM%+?D?rQ*X0bBrm84dbfY}hj14#8C@j*-l27?5>l*E!mG;wsU1B1ZnK`LY3;z9QU`S^yE-A{)OV>+A*cuNM z%1O-w3ortG!^DV?gRwwrl5-0f#DD@|H4Mlh1Jc0E2nriifE+4JKq+P{CL@OkDEzUh IVF8K*067#ovj6}9 diff --git a/SysCore/objects/SYSTEM.O b/SysCore/objects/SYSTEM.O deleted file mode 100644 index ef974d6bffe62b67751f3f15a658e99dc9824eff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 649 zcmeZaWM%*X7DfgJAux-TQLiMmq6Ex_5EVeG2Z;}2Dlix%=%plaeF?p7L2Pxp+9-_kXhJV`uB-VrpdTE(C zsZa;~`_I6T&RASoT#}lrmyB>_d~RxPazQ0nfD!0>CSZ7>1CW~H)Di||pafVA15~8k z5h0S9SCC&+l9Yrj0^%^_z(tV5A7l+PV;M*R3P28fCZG&67WW{BJ1Ca1sR0?v0>lC! z1`vSEVqo9{VpI_c3=tg^5s(k#lS_+=^NZpu;H*k8t0*U0O)Mid JGd-h(0RVysaLxb# diff --git a/SysCore/objects/TIME.O b/SysCore/objects/TIME.O deleted file mode 100644 index 91fd98d3d24ccd0ed5f1b7b18a568dd7f05f735b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1160 zcmaKr&ubG=5Xa~3ZqguuC>HD?wJ8({C?R<8V2h+|DB2{gkf4HA|~*hob*ObY|DQY;x#?@4U~> z%;axOhh6s>hc75oa$|-=1mcBQQ8P6+<#-!?5sN4P=iS6O0fl~SztM0eT;Xhp_hZKF zf?b^diyr2&1jG~Bv%R&zShm;KL#H3HHk4tkGP}(%KBHJ=n2_wYv}BzORS819lzb5C zUA$Mm(^717{zF1{8R&eA4o1IW)W4KEgZ@uBI*4A3&pRpEZYyCcXt#ZmsCj#aiC3s1s)A~w-l9%Xuo7OmjX%dxJZIZl&C-k(Z1H`= zfsAJ8CD=SR$`#0HE!ehd99^Xao7SP#Fd@s2Oalq-d>~jl35i!b=cIreTMCfbEdTkd3%iZC9@Bc(#%L_Pe#vj+nH`` wVkSc;TM(H?Ncp^)-c?iiCp#+S^-5ho%2(?(vor}_bACiuz*}qNE4&8(0QkbQK>z>% diff --git a/SysCore/objects/compile.bat b/SysCore/objects/compile.bat deleted file mode 100644 index bd60274..0000000 --- a/SysCore/objects/compile.bat +++ /dev/null @@ -1,16 +0,0 @@ -@echo off -rem The name of the loader assembly file (without extension, must be .asm): -set loader_name=loader - -rem NASM and DJGPP executable paths: -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin - -@echo on -ld -T link.ld -@echo off -@echo. -@echo Done! - -@pause -copy KERNEL.BIN A:\KERNEL.CTA \ No newline at end of file diff --git a/SysCore/objects/drivers/BSOD.o b/SysCore/objects/drivers/BSOD.o deleted file mode 100644 index 67d5d9be129477bf19fc8aae1554e9b4c26055d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1556 zcmb7^L2DC16vtVJ0I*=Z_*1OJ)dy!U42%_j4fj53jJAH%tf%0@L| zTS>-wSHtiDdR5BjlNczetyVoJadK1EZ=?SP?HyUUe;wf&XmVq_$TT$2X)C zgm}jBWpz@kzucexT(10r=eu<7n3b8GdTpotTF%~>l`_2Nu{QJmJa{Y3m!O-_GUP!r z_C2%%uSd_J0m9g0pHZtb<%|L zK5g(c^kU7v7>=C4$CAk99@89cPMbUu++}gh1u=OlQ+nv6fqt?ULM=AfV8~0JF49oj ztKoQb#j-TZQEZzhv@2LF*A<_|N*s51;;ct3WWos$&*eSk7adQh>kLlj_&6Mfd^7y( z=hX8b-|Ru)55nw5&2@%+iu{%xcij&e9k=&z5i!CKP=wB1t2O86k!XUaA?D`J*3l$rWMU7npJc`(Pc$cQE}RJ zWs~nF&p=j!obD*PtLVO>x*}82f}$lwT}3O3o+x^zXjPG?XkAgDC{mOt+EP^Q`vJpD zwu9e<42*`=F{^HFDSG)$WitrPYC=9Mdc8iP9FUT63;kpf0MctCN)cjSpqCY~XnI|g zC9@DgAZ*J`zi P&5ml3y@7|0=M$4Z=SdqN diff --git a/SysCore/objects/drivers/cpu.o b/SysCore/objects/drivers/cpu.o deleted file mode 100644 index e4c4489c54d0f854e78a41ac2a9256b144f315c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 854 zcmZ`%-zx-B6h31&p~YfES+x(7JZRdqA+6f7(w4knUI@burnbe*T_g``OP$7F;nj;r zJjwb4{1-fUP+o;|X4c(VKTe(ReCIo-bMMT#b4mo*&J}=epG6g2SVzL=0bFsNJVQNf zE#yf^t?LC-n7;BqWFd8@Z@6x_BOXp_{1mcxm6zBvr$3d|zXn)YaVK}Zx)7=Gi7yQ^%Dlte<&5CdIev4fW=a&eOa7eb8=3O2P*TUuAy9a}rKHb^V6 zAdz&7>Qo&>BG%>-;u?u~kdpA=A%esxJexw>_s{H(Go}6TzxVy$_rL$Wee?cp7bHfu zUB%d83rRvq=Oem>?O{n^>kW7*(R47oEy<5&v)gs@72Ff_dm+o`IQi7-Pt0vJ#$=LO?N2@3P$>JyEX;b8;OQHxgL(iQXKym<*;>d zIH^~H3nMyDCAGw5t)F-B{&*Upof*~Aw_0y%$s|u$$ybsCdotmKt#|M=*V_{Dp|-@} ZkhQ{MDjP)yW4wYpxE8D6tEsro*&iz%CN=;7 diff --git a/SysCore/objects/drivers/drivers.o b/SysCore/objects/drivers/drivers.o deleted file mode 100644 index 9485c04885782c47c754934f024ff65787d93cbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1191 zcmZ`&&x_Mg5PoTE*+cyuT@^tOJ$MR>h^#lYtyuiAOX5WYV`{Q%ASN|=b+;Zw2_k~R z9>u>v#DjM)iVJ)5>|Y=vJ$Ufs!s<8knlx*=1M_9(n{Otslh>vsd1%P?!cU61JBI5>hnbz>yqNoB^pa#}g{nM(&Pqo!KPdf3u+eVT==tJ! zlgU=PdE)WUjNPa;=`>tn0O4jtK|~WKqRm33zO9n3&)oWwjvA~@*BcZUN4~8Letp>b z?*92r#kI9v=sp71#R1@9cwHO=&N6q3k+?I64smu4c#xwGkh*kn4Y(g(7dL@QcN@_@ zxGt7~wClQ{^{MJAqCIe3JOl3L=rypxk+I|l9wM@>zd|f)ZtOqw;>5VC$T9L_5o`F4 z724wz)4@H3vxe(U;H#V|-Vz#7)!qT=yb~+lkP7JPly?Gh&W3frGQYq$CXD!W|16h!_0Fz=?iqAok38+fs>uXw{= z%j|Tn QtNv~hC;w~5zo_u?e=0$}6951J diff --git a/SysCore/objects/drivers/fat.o b/SysCore/objects/drivers/fat.o deleted file mode 100644 index 93f3741b86d42d93b197ce50363c954c1ee813b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 379 zcmeZaWM%+?9YD+lX0bBrm84dbfY}g22T1iG@j*-l27?5>l*E!mG;wsU1B1ZVJu|7f~1)lHDOY48rh#rU^Q?lI0M;_ Ypb%xoVi(XW4DoJ`Aug#UsmUb_0M!#KV*mgE diff --git a/SysCore/objects/drivers/fat12.o b/SysCore/objects/drivers/fat12.o deleted file mode 100644 index 17658c20023911910b5e447bc1bbef8990d3cee1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2324 zcma);U1%d!6vuCx*loH^w`J>6Ws!j0vCm+m5 zN$|4{i?l)Li$1O3n=hjK;KQ=}u+av5Rsz^$6&_$#r=cuA;G__DwZP9q1Pu+w`!V) z3cQKeQI{u)Lz>OJ##g7bVb5$EuS1H|WkSO)t!; z;D?s0b>>Z&*b2*2HH(`mZlrnEDjS{2suYjer$O=78muhlP?gYa)8f6du)NGoZmeTE&+g zFF^FG8y|Sqg*X^f=9- zRH{%#{tj?&k%+)o5x*wn!#;TfdA=(j5%M1qr-b~tPaX;Ye@yUEACDuKy35=xmdPLv z3;7A3{AJ|3cU^c+O;kxL{&LhyEJy(_*eT)qK8u+4O2 z<8#;gb9W;YZM_5vr#Z5*eWhW?Z(!Q%Qxeo@b2+m9J!FxQI@Mb0Xq}ybbm0tca6usF z&d9Mh9Z>rV7jQQndg6XT-b3;w5T`j%cmQjC z3(2P*IgjLPB-dO56&rYVd&?WMiNvH7pIv90@Wu1fOGU7%ccE>u1No zin#1iVi$QLscD z_Ys>QcAnVd#4ZzCAodKg6=FAuHHiH{tVL{(Sew`=bY0=!39y8J6U5@g9w9bKY?jzO zF*&E{9IA!mA2_7>Ku)n9J}YMhaez3;Z z?ICE;jP6@S+~OP#+y?h!47xqr1+z;|x?EiP*h;nnZ%`}OfqhH{a|K@aN%!>+ru(~K Q0e=>BZkC}XiB`h?1t^jtw*UYD diff --git a/SysCore/objects/drivers/floppy.o b/SysCore/objects/drivers/floppy.o deleted file mode 100644 index 022f87797f78d5d445dcb52f0fb7b15258ec8090..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9373 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 diff --git a/SysCore/objects/drivers/gdt.o b/SysCore/objects/drivers/gdt.o deleted file mode 100644 index 0b0ac12ee7936756afafcbd4af3d36380613ba2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 920 zcmZ`%ze_?<6h6=Qv=>>vLCC?u;m!|f2#25sNhG&c!7P7dNJQSCK*)FzK5UR^i2jaf zXsQ$hA!=-lrZ+f9Q#EMkT)ex&WFXsd0n7=cNIK6Ra)AfasRVG2 zP(uybG>#C2H}p)Jrv)>4T7mGrzF8_wRtz!~)EOPkOftpfOf}2QTT3v1Ey)74G7Hu? z3;AxNj8&sdHolbO_#LgwnaQ@xe0{LAs`8{DK{$YTN+g%s<|pMIEAKv9Ewirrf>{qK zy9nF}@CXIBSMeCH(bO77Czxwd0_LIR9zGdbQKk`x-aGW_(9^llQW!Za((m_4`%D~a zuLoX5n)qKWRunAnnD)Y1OINVodjI$RcGl8oS~p|b4`(gi#j2v#LI6fH*r?a*I>H$o z9$2=~nvDuJ+P4vP29?AEmo~bxvq$*SS&aOk=L*FvBC=i|ATQ-JT;CcHBeN(G#uE0J zi|XWHe&o(@2n~$(D=mU2yR8ZMr=g~f;LON+ucxl=-OcR<5Qu#fBM0*H^ oLeUL^$5+4tqEsQWn2KfidX~r1JZs1C-4ah1i*~$PJSc6$4>*3WI{*Lx diff --git a/SysCore/objects/drivers/gdt_asm.o b/SysCore/objects/drivers/gdt_asm.o deleted file mode 100644 index 2a3f089b3cdada04a41e6d1066dccbb5ff31b7c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145 zcmZQ)Okq%9KmZjeQvgcyGm3&(X*&cM`fl_c=zGxjqVK{h8K4jc!{G@NCNM+P@rVIw x79av*21bY&Pz3`6E0hhDX8`Gx1>*Sh0*3fZ3$u9lloGd`(&7w;G!SXT002;}6XtG24G3XG)DxNLh>}-;&6vyVGUssV+Bfw zj_(OiD)ZA8l%AZUD4Ji9I@efN?>D$%J~X*y4r{#lNKP2r;jpIVZ#;XWyzed)eevmzNP>tTFV#CaVli8{7;-~ z*lqo%_ZeGK8}sIGja2AZ6{TeFlD5ccH<;-L|B$^$YFBQ?x3YIgFJ@Mai^q_=Vw(v% zkV3skUlu6@>Sqc(7r33E69wr)dRIDZqv^Ib*4?Tv>Vc?uB2e?nzj^gE5?;Hl{Mwo4 F!#AWySoQz_ diff --git a/SysCore/objects/drivers/idt_asm.o b/SysCore/objects/drivers/idt_asm.o deleted file mode 100644 index c03174e5351bc7bf78af587b16b00a39afd847c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95 zcmZQ)Okv<)KmZ9S6DG#bC<_uf%nT9dVFA*N5HoQQ=6<-$fX!^ z2=ON%g5W{Hlb|4Y@Mt839K3iD4<0-S{y=XYMdLfO+1U*f=nU-aGtc+#&g`-~XO#e< z?U_o5#z<8R+q!KtcDk2sgxm#2oG8)38VS!C3DY)xxmFk@;fir3oAuYC{y~FR$Xul~ zqpPJ!Jy=v9QCkJ8HMQWTtNFE14Qddgrs^6_KWPna(|zY03_52#jCAGzqU+t~phTum zB17NYdUN$lWDZGW1|%|r5}CsinIjUJA&JaUiOeyHj3JR3b~E|aP&J-k3zjbHU8RX| zNiD3@>-9p#-cStb^^f^nc;J@$TKm2chn8OrUaFSMl*RXghQ7xcdy+#@sjV{(!bJ*MYsldEQ=77jr}0O@OvAcaFOS z&}Qbc+!aC2+cmBxQx>YU{lg^1)`h$1px%_aX1NH@`d5_L;W=b6TcX6U^LFbk;UgsncdUk+L#eUq~lg7aDmU?3ImfS^)x#CVl&ww+|{?tW%8a!eK9AXx#gaH*| z4obv46o~~W5Q|_D8IZ&hn1l%iu?#6<1(L)nB#1T8h;&|?h+q)B1;gO` zW?1giHNRg6`m_F^P1U;Z@y}kbcOBk1K7z)=7L({GcbZ#6Gu#O@%bi4bxl?G7+d#|Q zCVI#%QJ337eeME!#ZBMna+lD6yMo?wSJ6jq2Yuo8&{rJ#pEH~f9NV+<_I{_mSM%M* zNhf^wI_(WrQdL&frm8JfIaPU8+o~*8JF4WrCD9fct&!0l87-1Ifd|^ht!A_3+vgXT Gj`#!XZIGt` diff --git a/SysCore/objects/drivers/isrs.o b/SysCore/objects/drivers/isrs.o deleted file mode 100644 index 797e8edf6ae723742894c28712a504aaa0935d74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3547 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 Se5Qq2d_ZP$P-<>s0RsTM&MguE diff --git a/SysCore/objects/drivers/pit.o b/SysCore/objects/drivers/pit.o deleted file mode 100644 index 51514da504ba67e783a44a25f58a25302336fac9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3386 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 C>O{Z* diff --git a/SysCore/objects/video/VGA03H.O b/SysCore/objects/video/VGA03H.O deleted file mode 100644 index 9b66a1f8cc0892f967469400bc00c8fca32f7e9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1057 zcmZ`&&ui2`6n@zZwX%y{Z3RUSIYj8ehJZbIC?Ying@7XBH5=2oE~JfYQt?t)C`gx8 z*pp}f1Wz7H4_#Wc2aomU!DA1y|A3%=Z!($0AAKE$oXk!OX|9lVj;05d$MkG5^6l2>BCoO2TK&5w^|=q?pF(Bw zSB+C#9xB`4{ZF24J;39U?aRm?J$vyC$aP*5*-z88r7VH*p;gK)Fh0IYxexYEEA`vX3!BE0+C7Mh`c21=f}V1} zWd~9HmgBynr>fOapa?&wK|z%Cv#75$yt_o}iW9NI-!mwVEr>SzS=!h1`DPwz(v53` oD``?| -#include -#include -#include "../drivers/drivers.h" -#include "../drivers/cpu/cpu.h" -#include -#include -#include -#include -#include "../memory/mmngr_ph.h" -#include "../drivers/filesys/fat.h" -#include "apps.h" - - -void shell() -{ - apps_osver(); - char str[256]; - char* param[16]; - int i, len, params=0; - - for (;;) { - cprintf("%#0A\n] "); - cgets(str, 256); - cprintf("\n\r"); - - len = strlen(str); - - // Ignore spaces in front of command - i=0; params = 0; - while (str[i] == ' ') i++; - param[params] = str+i; params++; i++; // Parameter 0 = app itself - - - for (; i < len && params<16; i++) { - if (str[i] == ' ') str[i]=0; - - if (str[i] != 0 && str[i-1]==0) { - param[params] = str+i; params++; - } - } - - for (i = 0; strcmp(apps_lst[i], param[0])!=0 && i -#include - -RGBColor RGBColors_4bpp[] = {{0, 0, 0}, // 00 Black - {0, 0, 127}, // 01 Dark Blue - {0, 127, 0}, // 02 Dark Green - {0, 127, 127}, // 03 Dark Cyan - {127, 0, 0}, // 04 Dark Red - {127, 0, 127}, // 05 Dark Magenta - {127, 127, 0}, // 06 Dark Yellow - {192, 192, 192},// 07 Light Gray - {127, 127, 127},// 08 Dark Gray - {0, 0, 255}, // 09 Blue - {0, 255, 0}, // 10 Green - {0, 255, 255}, // 11 Cyan - {255, 0, 0}, // 12 Red - {255, 0, 255}, // 13 Magenta - {255, 255, 0}, // 14 Yellow - {255, 255, 255} // 15 White -}; - - -RGBColor Convert_1bpp_to_RGB(Color_1Bpp c) -{ - unsigned char t = (c) ? 0xFF : 0x00; - RGBColor temp = {t, t, t}; - return temp; -} - -RGBColor Convert_4bpp_to_RGB(Color_4Bpp c) -{ - return RGBColors_4bpp[c]; -} - -RGBColor Convert_6bpp_to_RGB(Color_6Bpp c) -{ - unsigned char R, G, B; - R = (unsigned char) ((unsigned)((c & 0x30)>>4) * 255 / 3 ); - G = (unsigned char) ((unsigned)((c & 0x0C)>>2) * 255 / 3 ); - B = (unsigned char) ((unsigned) (c & 0x03) * 255 / 3 ); - RGBColor ret = {R, G, B}; - return ret; -} - -RGBColor Convert_8bpp_to_RGB(Color_8Bpp c) -{ - unsigned char R, G, B; - R = (unsigned char) ((unsigned)((c & 0xE0)>>5) * 255 / 7 ); - G = (unsigned char) ((unsigned)((c & 0x1C)>>2) * 255 / 7 ); - B = (unsigned char) ((unsigned) (c & 0x03) * 255 / 3 ); - RGBColor ret = {R, G, B}; - return ret; -} - -RGBColor Convert_15bpp_to_RGB(Color_15Bpp c) -{ - unsigned char R, G, B; - R = (unsigned char) ((unsigned)((c & 0x7C00)>>10) * 255 / 31 ); - G = (unsigned char) ((unsigned)((c & 0x03E0)>>5) * 255 / 31 ); - B = (unsigned char) ((unsigned) (c & 0x001F) * 255 / 31 ); - RGBColor ret = {R, G, B}; - return ret; -} - -RGBColor Convert_16bpp_to_RGB(Color_16Bpp c) -{ - unsigned char R, G, B; - R = (unsigned char) ((unsigned)((c & 0xF800)>>11) * 255 / 31 ); - G = (unsigned char) ((unsigned)((c & 0x07E0)>>5) * 255 / 63 ); - B = (unsigned char) ((unsigned) (c & 0x001F) * 255 / 31 ); - RGBColor ret = {R, G, B}; - return ret; -} - -RGBColor Convert_18bpp_to_RGB(Color_18Bpp c) -{ - unsigned char R, G, B; - R = (unsigned char) ((unsigned)(c.R) * 255 / 0x3F ); - G = (unsigned char) ((unsigned)(c.G) * 255 / 0x3F); - B = (unsigned char) ((unsigned)(c.B) * 255 / 0x3F); - RGBColor ret = {R, G, B}; - return ret; -} - -RGBColor Convert_24bpp_to_RGB(Color_24Bpp c) -{ - return c; -} - - -Color_1Bpp Convert_RGB_to_1bpp(RGBColor c) -{ - if (((unsigned)c.R + (unsigned)c.G + (unsigned)c.B) / 3 >= 128) return 1; - return 0; -} - -Color_4Bpp Convert_RGB_to_4bpp(RGBColor c) -{ - int i; int minim = 0xFFFF; int index = 0; - int R, G, B; - - for (i = 0; i < 16; i++) - { - R = (int)(c.R) - (int)(RGBColors_4bpp[i].R); - G = (int)(c.G) - (int)(RGBColors_4bpp[i].G); - B = (int)(c.B) - (int)(RGBColors_4bpp[i].B); - - R = abs(R) + abs(G) + abs(B); - if (R <= minim) { - minim = R; index = i; - } - } - - return index; -} - -Color_6Bpp Convert_RGB_to_6bpp(RGBColor c) -{ - Color_6Bpp temp = 0; unsigned tmp; - tmp = (unsigned)(c.R) * 3 / 255; temp |= (tmp & 0x03) << 4; - tmp = (unsigned)(c.G) * 3 / 255; temp |= (tmp & 0x03) << 2; - tmp = (unsigned)(c.B) * 3 / 255; temp |= (tmp & 0x03); - return temp; -} - -Color_8Bpp Convert_RGB_to_8bpp(RGBColor c) -{ - Color_8Bpp temp = 0; unsigned tmp; - tmp = (unsigned)(c.R) * 7 / 255; temp |= (tmp & 0x07) << 5; - tmp = (unsigned)(c.G) * 7 / 255; temp |= (tmp & 0x07) << 2; - tmp = (unsigned)(c.B) * 3 / 255; temp |= (tmp & 0x03); - return temp; -} - -Color_15Bpp Convert_RGB_to_15bpp(RGBColor c) -{ - Color_15Bpp temp = 0; unsigned tmp; - tmp = (unsigned)(c.R) * 0x1F / 255; temp |= (tmp & 0x1F) << 10; - tmp = (unsigned)(c.G) * 0x1F / 255; temp |= (tmp & 0x1F) << 5; - tmp = (unsigned)(c.B) * 0x1F / 255; temp |= (tmp & 0x1F); - return temp; -} - -Color_16Bpp Convert_RGB_to_16bpp(RGBColor c) -{ - Color_16Bpp temp = 0; unsigned tmp; - tmp = (unsigned)(c.R) * 0x1F / 255; temp |= (tmp & 0x1F) << 11; - tmp = (unsigned)(c.G) * 0x3F / 255; temp |= (tmp & 0x3F) << 5; - tmp = (unsigned)(c.B) * 0x1F / 255; temp |= (tmp & 0x1F); - return temp; -} - -Color_18Bpp Convert_RGB_to_18bpp(RGBColor c) -{ - Color_18Bpp temp; unsigned tmp; - tmp = (unsigned)(c.R) * 0x3F / 255; temp.R = (unsigned char)tmp; - tmp = (unsigned)(c.G) * 0x3F / 255; temp.G = (unsigned char)tmp; - tmp = (unsigned)(c.B) * 0x3F / 255; temp.B = (unsigned char)tmp; - return temp; -} - -Color_24Bpp Convert_RGB_to_24bpp(RGBColor c) -{ - return c; -} diff --git a/SysCore/video/color/color.h b/SysCore/video/color/color.h deleted file mode 100644 index f879fe3..0000000 --- a/SysCore/video/color/color.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __COLOR__H__ -#define __COLOR__H__ - -/**RGB color structure.*/ -typedef struct { - unsigned char R,G,B; -} RGBColor; - -/**\Monochrome (black and white)*/ -typedef bool Color_1Bpp; - -/**CGA 2 bits per pixel indexed color.\n\n\Notes: Cannot be converted to/from RGB.*/ -typedef unsigned char Color_2Bpp; - -/**16 color VGA. - * \n\n\Format: Uses 1-1-1 bit format, highest bit is intensity. - * \n\n\Notes: Unused bits are ignored (should be 0).*/ -typedef unsigned char Color_4Bpp; - -/**64 color EGA. - * \n\n\Format: Uses 2-2-2 bit format. - * \n\n\Notes: High 2 bits are ignored (should be 0).*/ -typedef unsigned char Color_6Bpp; - -/**256 color VGA. - * \n\n\Format: Uses 3-3-2 bit format - * \n\n\Notes: The palette must be changed before usable.*/ -typedef unsigned char Color_8Bpp; - -/**SVGA Highcolor palette. - * \n\n\Format: Uses 5-5-5 bit format. - * \n\n\Notes: Unused high bit is ignored (should be 0).*/ -typedef unsigned short Color_15Bpp; - -/**SVGA Highcolor palette. - * \n\n\Format: Uses 5-6-5 bit format.*/ -typedef unsigned short Color_16Bpp; - -/**VGA 18-bit RGB - * \n\n\Format: Uses the RGBColor structure, with the R, G and B components. - * \n\n\Notes: High 2 bits of each component are ignored, should be 0.*/ -typedef RGBColor Color_18Bpp; - -/**24-bit Truecolor - * \n\n\Format: Uses the RGBColor structure, with the R, G and B components.*/ -typedef RGBColor Color_24Bpp; - -/**Few functions to convert values from one format to another.*/ -extern RGBColor Convert_1bpp_to_RGB(Color_1Bpp c); -extern RGBColor Convert_4bpp_to_RGB(Color_4Bpp c); -extern RGBColor Convert_6bpp_to_RGB(Color_6Bpp c); -extern RGBColor Convert_8bpp_to_RGB(Color_8Bpp c); -extern RGBColor Convert_15bpp_to_RGB(Color_15Bpp c); -extern RGBColor Convert_16bpp_to_RGB(Color_16Bpp c); -extern RGBColor Convert_18bpp_to_RGB(Color_18Bpp c); -extern RGBColor Convert_24bpp_to_RGB(Color_24Bpp c); -extern Color_1Bpp Convert_RGB_to_1bpp(RGBColor c); -extern Color_4Bpp Convert_RGB_to_4bpp(RGBColor c); -extern Color_6Bpp Convert_RGB_to_6bpp(RGBColor c); -extern Color_8Bpp Convert_RGB_to_8bpp(RGBColor c); -extern Color_15Bpp Convert_RGB_to_15bpp(RGBColor c); -extern Color_16Bpp Convert_RGB_to_16bpp(RGBColor c); -extern Color_18Bpp Convert_RGB_to_18bpp(RGBColor c); -extern Color_24Bpp Convert_RGB_to_24bpp(RGBColor c); - -#endif \ No newline at end of file diff --git a/SysCore/video/compile.bat b/SysCore/video/compile.bat deleted file mode 100644 index 3197f6e..0000000 --- a/SysCore/video/compile.bat +++ /dev/null @@ -1,24 +0,0 @@ -@echo off - -rem NASM and DJGPP executable paths: -set nasm_path=C:\nasm -set djgpp_path=C:\mingw\bin -set objpath=..\objects\video -set incpath=../include - -@echo Building Video Drivers... - -goto build -:error - @echo. - @echo There have been build errors. Building halted. - @pause - exit - -:build - @echo * Compiling Text Mode 0x03 video driver ... - %djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o vga03h.o vga03h.c - if not exist vga03h.o goto error - xcopy /Y *.o %objpath% >nul - del *.o - \ No newline at end of file diff --git a/SysCore/video/vga.h b/SysCore/video/vga.h deleted file mode 100644 index 451a85a..0000000 --- a/SysCore/video/vga.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __VGA__H__ -#define __VGA__H__ - -typedef struct { - enum MODE_TYPES { - TextMode = 0, - GraphicsMode = 1 - }; - /**Defines the mode returned by BIOS int 0x10, ah = 0xF*/ - unsigned char Mode; - /**Text mode or Graphic mode (defined in MODE_TYPES enumeration)*/ - unsigned char ModeType; - - /**Screen size (characters in text modes, pixels in graphic modes)*/ - unsigned Width, Height; - - /**Bits per pixel*/ - unsigned bpp; - - /**Pointer to a function that sets the cursor position*/ - void (*SetCursor) (int wherex, int wherey); - /**Pointer to a function that prints an ascii character in a specified position*/ - void (*PutChar) (int wherex, int wherey, unsigned char character); - /**Pointer to a function that returns the ascii character in the specified position*/ - unsigned char (*GetChar) (int wherex, int wherey); - - /**Pointer to a function which plots a pixel on the screen. Should be set NULL in text modes. - \nColor is a void pointer, to ensure compatibility with different colors.*/ - void (*PutPixel) (int wherex, int wherey, void* color); - - /**Pointer to a function which returns the color of a pixel on the screen. Should be set NULL in text modes. - \nReturn is a void pointer, to ensure compatibility with different colors.*/ - void* (*GetPixel) (int wherex, int wherey); - -} VideoMode; - -#endif \ No newline at end of file diff --git a/SysCore/video/vga03h.c b/SysCore/video/vga03h.c deleted file mode 100644 index f7917cf..0000000 --- a/SysCore/video/vga03h.c +++ /dev/null @@ -1,30 +0,0 @@ -//#include "vga.h" -#include -#include - -unsigned char* TextVideoRam = (unsigned char*)0xB8000; - -void vga03h_cursor(int x, int y) -{ - unsigned temp = y*80 + x; - - outportb (0x3D4, 14); - outportb (0x3D5, temp >> 8); - outportb (0x3D4, 15); - outportb (0x3D5, temp); -} - -void vga03h_putc (int x, int y, unsigned char c) { TextVideoRam[2*(y*80+x)] = c; } -unsigned char vga03h_getc (int x, int y) { return TextVideoRam[2*(y*80+x)]; } -void vga03h_putcolor (int x, int y, unsigned char c) { TextVideoRam[2*(y*80+x)+1] = c; } -unsigned char vga03h_getcolor (int x, int y) { return TextVideoRam[2*(y*80+x)+1]; } - -void vga03h_install() -{ - ConsoleScreen screen = { - 80, 25, 0x07, vga03h_cursor, vga03h_putc, vga03h_getc, - vga03h_putcolor, vga03h_getcolor}; - - ConsoleInstall (screen); - clrscr(); -} \ No newline at end of file diff --git a/SysCore/video/vga03h.h b/SysCore/video/vga03h.h deleted file mode 100644 index c9a91b0..0000000 --- a/SysCore/video/vga03h.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __DEFAULT__TEXT__MODE__H__ -#define __DEFAULT__TEXT__MODE__H__ - -void vga03h_install(); - - -#endif \ No newline at end of file diff --git a/VIDEO.CPP b/VIDEO.CPP deleted file mode 100644 index ecfb604..0000000 --- a/VIDEO.CPP +++ /dev/null @@ -1,476 +0,0 @@ -/***************************************************************** - * INCLUDE DIRECTIVES * - *****************************************************************/ -#include -#include -#include -#include -#include - -/***************************************************************** - * UNIVERSAL DATA TYPES, CONSTANTS * - *****************************************************************/ -typedef unsigned char byte; - -typedef struct { - int X, Y; -} Point; - - -#define DEBUG 1 -#define LOG(x) printf(x); - - -/***************************************************************** - * VIDEO DRIVER * - *****************************************************************/ - -// Used variables -byte far* VGAMem = (byte far *)0xA0000000L; -byte* Buffer; - -// Used by cursor. Need to be initialized here -int SaveX, SaveY; - -// Change video mode routine -void VideoMode(byte mode) -{ - asm { - mov ah, 0 - mov al, mode - int 0x10 - } -} - -// Initialize graphic mode 0x13, use duble buffering if possible -void InitGraph() -{ - Buffer = (byte*)malloc(320 * 200); - - if (Buffer) memset(Buffer, 0, 320*200); - - #if DEBUG == 1 - if (!Buffer) LOG("Error: Not enough memory. Double buffering disabled."); - #endif - - VideoMode(0x13); - - SaveX = SaveY = 400; -} - -// Go back to normal text mode 0x03 -void ExitGraph() -{ - free(Buffer); - VideoMode(0x03); -} - -// Put a pixel in specified position. Does not put it on the screen if double buffering. -void PutPixel(int x, int y, int c) -{ - if (y >= 200 || x >= 320) return; - - if (Buffer) Buffer[y*320 + x] = c; - else VGAMem[y*320 + x] = c; -} - -// Get a pixel from screen/double buffer -byte GetPixel(int x, int y) -{ - return (Buffer) ? Buffer[320*y + x] : VGAMem[320*y+x]; -} - -// Put double buffer on the screen. Should be called after e.g. displaying something new. -void Update() -{ - if (Buffer) memcpy(VGAMem, Buffer, 320*200); -} - - - - -/***************************************************************** - * MOUSE DRIVER * - *****************************************************************/ - -// Defines cursor size and array -#define cX 7 -#define cY 7 -byte Cursor[cY][cX] = { {1, 0, 0, 1, 1, 1, 1}, - {1, 0, 0, 1, 0, 0, 0}, - {1, 0, 0, 1, 0, 0, 0}, - {1, 1, 1, 1, 1, 1, 1}, - {0, 0, 0, 1, 0, 0, 1}, - {0, 0, 0, 1, 0, 0, 1}, - {1, 1, 1, 1, 0, 0, 1}}; - -// Save what is under the cursor -byte Save[cY][cX]; -void SaveUnder(int x, int y) -{ - for (int i = 0; i < cX; i++) - for (int j = 0; j < cY; j++) - Save[i][j] = GetPixel(i+x, j+y); - - SaveX = x; SaveY = y; -} - -// Restore what was under the cursor -void RestoreUnder () -{ - for (int i = 0; i < cX; i++) - for (int j = 0; j < cY; j++) - PutPixel(i+SaveX, j+SaveY, Save[j][i]); -} - -// Display the cursor -void PutCursor(int x, int y, byte c) -{ - // restore old - RestoreUnder(); - SaveUnder(x, y); - for (int i = 0; i < cX; i++) - for (int j = 0; j < cY; j++) - { - Save[j][i] = GetPixel(i+x, j+y); - if (Cursor[j][i] == 1) PutPixel(i+x, j+y, Cursor[j][i] * c); - if (Cursor[j][i] == 2) PutPixel(i+x, j+y, 256-(Cursor[j][i] * c)); - - } - -} - -// Check if mouse cursor is in specified area -unsigned char MouseIsInArea (int MouseX, int MouseY, int left, int top, int right, int bottom) -{ - if (MouseX >= left && MouseX <= right - && MouseY >= top && MouseY <= bottom) return 1; - return 0; -} - -// Bit masks for mouse buttons -const byte MouseLeftB = 1, MouseRightB = 2, MouseMiddleB = 4; - -// Initialize mouse driver -int MouseInit(int *NumberOfButtons) -{ - int r; - int tmp; - asm { - mov ax, 0 - int 0x33 - mov tmp, ax - mov r, bx - } - - *NumberOfButtons = tmp; - return r; -} - -// Get the status of the mouse (buttons, etc) -byte MouseGetStatus() -{ - byte re; - asm { - mov ax, 3 - int 0x33 - mov re, bl - } - return re; -} - -// Get movement -void MouseGetDirection (int *x, int *y) -{ - int tx, ty; - asm { - mov ax, 0x0B - int 0x33 - mov tx, cx - mov ty, dx - } - *x = tx; *y = ty; -} - - - -/***************************************************************** - * FONT MANAGER * - *****************************************************************/ - -class Font { - char Path[256]; - ifstream file; - - public: - byte Error; - Font(char* c); - Font(); - - ~Font() { - file.close(); - } - - Point PutChar(int x, int y, char c); - - void PutString(int x, int y, char* str); - - void OpenNew(char* c); -}; - -Font::Font(char* c) { - int len = strlen(c); - - for (int i = 0; i < len && i<256; i++) - Path[i] = c[i]; - - file.open(c); - - if (!file) Error = 1; - else Error = 0; -} - -Font::Font() { - Path[0] = 0; -} - -void Font::OpenNew(char* c) -{ - int len = strlen(c); - for (int i = 0; i < len && i<256; i++) - Path[i] = c[i]; - file.open(c); - if (!file) Error = 1; - else Error = 0; -} - - -Point Font::PutChar(int x, int y, char c) -{ - Point ret; - int cSizeX, cSizeY; - if (Error) return ret; - - int tmp = 0; - file.seekg(0, ios::beg); - - for (int i = 0; i < c; i++) { - file>>cSizeX>>cSizeY; - for (int j = 0; j < cSizeX * cSizeY; j++) file>>tmp; - } - - file>>cSizeX>>cSizeY; - for (int yy=0; yy>tmp; - if (tmp) PutPixel(xx+x, yy+y, c); - } - - ret.X = cSizeX; - ret.Y = cSizeY; - return ret; -} - -void Font::PutString(int x, int y, char* str) -{ - if (Error) return; - - Point temp; int sum = 0; - - // Use a default kerning value of 1 pixels. - int len = strlen(str); - for (int i=0; i < len; i++) { - - temp = PutChar(x+sum, y, str[i]); - sum += temp.X+1; - } -} - - - - - -/***************************************************************** - * WINDOW MANAGER * - *****************************************************************/ - -class Window -{ - byte Visible; - - char Title[256]; - Font Fnt; - -public: - Point Pos, Size; - - Window(char* s); - Window(); - Window(Point pos, Point siz, char* s); - - void Show(); - void Hide(); - - void DrawPixel(int x, int y, int c) - { - if (x < this->Size.X && y < this->Size.Y) - PutPixel (x+this->Pos.X, y+this->Pos.Y, c); - } - - void Update(); - - void MouseAction(int X, int Y, byte Buttons) - { - if (Buttons & MouseLeftB) DrawPixel(5,5, 150); - else DrawPixel(5, 5, 0); - - } - - -}; - -Window::Window(char* s) -{ - memcpy(Title, s, 256); - Visible = 0; - Size.X = 0; Size.Y = 0; Pos.X = 0; Pos.Y = 0; - - Fnt.OpenNew("font.txt"); -} - -Window::Window() -{ - Visible = 0; - Size.X = 0; Size.Y = 0; Pos.X = 0; Pos.Y = 0; - Title[0] = 0; - - Fnt.OpenNew("font.txt"); -} - -Window::Window(Point pos, Point siz, char* s) -{ - Visible = 0; - Size = siz; Pos = pos; - memcpy(Title, s, 256); -} - - -void Window::Show() -{ - Visible = 1; - for (int i = Pos.X; i < Size.X + Pos.X; i++) { - for (int j = Pos.Y+10; j < Size.Y + Pos.Y; j++) - PutPixel(i, j, 7); - - for (j = Pos.Y; j < Pos.Y+10; j++) - PutPixel(i, j, 12); - } - Fnt.PutString(Pos.X+3, Pos.Y+2, Title); -} - -void Window::Hide() -{ - Visible = 0; - - for (int i = Pos.X; i < Size.X + Pos.X; i++) - for (int j = Pos.Y; j < Size.Y + Pos.Y; j++) - PutPixel(i, j, 0); -} - - - -/***************************************************************** - * MAIN FUNCTION * - *****************************************************************/ - -int main() -{ - int a; - InitGraph(); - MouseInit(&a); - - Window alpha("AaBbCcXyZhSgGZz@,HEL"); - alpha.Pos.X = 320/2; - alpha.Pos.Y = 200/2; - alpha.Size.X = 140; - alpha.Size.Y = 80; - - - int MouseX = 320/2, MouseY = 200/2; - int dx, dy, oldX, oldY; - int Col = 15; - - for (;;) - { - if (oldX != MouseX || oldY != MouseY) { - memset (Buffer, 0, 320*200); - alpha.Show(); - PutCursor(MouseX, MouseY, Col); - - - Update(); - - } - - oldX = MouseX; oldY = MouseY; - - MouseGetDirection(&dx, &dy); - MouseX+=dx; - MouseY+=dy; - - if (MouseX > 320) MouseX = 320; - if (MouseY > 200) MouseY = 200; - if (MouseX < 0) MouseX = 0; - if (MouseY < 0) MouseY = 0; - - int ok=0; - - if (MouseGetStatus() & MouseLeftB) { - alpha.MouseAction(MouseX, MouseY, MouseGetStatus()); - - // Check if bottom right corner => ok=2 - if (MouseIsInArea (oldX, oldY, alpha.Pos.X+alpha.Size.X-5, alpha.Pos.Y + alpha.Size.Y-5, - alpha.Pos.X+alpha.Size.X, alpha.Pos.Y + alpha.Size.Y)) - ok = 2; - - else if (MouseIsInArea (oldX, oldY, alpha.Pos.X, alpha.Pos.Y, - alpha.Pos.X+alpha.Size.X, alpha.Pos.Y + alpha.Size.Y)) - ok = 1; - - if (ok==1) - { - alpha.Pos.X += dx; - alpha.Pos.Y += dy; - - if (alpha.Pos.X < 0) alpha.Pos.X = 0; - if (alpha.Pos.Y < 0) alpha.Pos.Y = 0; - if (alpha.Pos.X > 320 - alpha.Size.X) alpha.Pos.X = 320-alpha.Size.X; - if (alpha.Pos.Y > 200 - alpha.Size.Y) alpha.Pos.Y = 200-alpha.Size.Y; - - } - - else if (ok==2) - { - alpha.Size.X += dx; - alpha.Size.Y += dy; - - if (alpha.Size.X > 300) alpha.Size.X = 300; - if (alpha.Size.X < 40) alpha.Size.X = 40; - if (alpha.Size.Y > 150) alpha.Size.Y = 150; - if (alpha.Size.Y < 30) alpha.Size.Y = 30; - } - } - - if (!(MouseGetStatus() & MouseLeftB)) ok=0; - - - if(kbhit()) break; - - - } - - - ExitGraph(); - return 0; -} diff --git a/Video.exe b/Video.exe deleted file mode 100644 index fdbfea56d06ef816ea3700ad00bd0de8c9e6892b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46776 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

Vx-?iC;5~)GCjpm@q5Fh4* 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 a{5Sti)27G6wP_^S3Af|IIzEKd_> pCHc)pkB=NJH^C}qNx{XjsM*w%-z;I#=;eYcRWB6&miuyiT5p*5Sh)ZI diff --git a/_play/fat16.img.gz b/_play/fat16.img.gz deleted file mode 100644 index 63e6fd8f3b07faa459e847d854ac754b87abc2f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1673 zcmb2|=HSRqWO8F*PD?B?G}Ft>O=oy}W22W-q6FK6_~{P8ixe|nEnn-pV&Te#V$a#K zIh&N_y!$GT6pJnFeqps}qi#puf$EHm;*VTL=9zjc9#;N%Q2j7=-_P0eZSJJ*-Sa|R zF+_W6KrR3BuSe5v@Lknul \ No newline at end of file diff --git a/_play/stage2/STAGE2.CTA b/_play/stage2/STAGE2.CTA deleted file mode 100644 index a496df97541a767ce49c80cd33c1d786c2debb95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1213 zcmeH`PiPZC6vhY4rklmo;GriE11dyN$Xc};XrXEkB9cH$%`w~Tyk#NDmf4NA$9QSi z!-5y@xeFfZA)qWtgZ~aIB8Y!-%V~1Tp`}7H7-u517r}!^`)=QR@Avo^=G*G_U!TB# zsicN7`sLXxSFg=ozhSJEOajGcYRj8?F&(A)`(vY1%)itS3y|L~Sa0fzf)LU_{n)GT zW{|c0Bqnrk5Go3LD|aE!77+MtINSw)7wWxJf`T@SK_2v$_4rX*VAghB(opDiCBG$j zv4x7DcftP#{&$#{+DlBp#r|Ln{`8JwKx0Sg6!rIF>Z#JoVt;QunaF`ej_ZGafuwe) z3J$Fpp6ygIB_(1%ASQNer4n&nsFll`S*#_|r3JifTUEoWQIf?dsforap{}5^IJ5D) zkz2aA>`}XF;k03zR2;Z)G`wZ38*6si_H5!FbysbZIJn}N#QhVr;&?_GS4hR7n>c;< zrnrZeD0S#XT&t3ebyD(#TS|m2;R6lzR`4}wH4zFvz8a55&C@7KMG2v!8IdROJ2G-2 zXw3r|s63pPc@w%IqZ73JFHMw-Qu8_FoeZC=> Signature: ", 0x00 -printInfo2 db 0x0D, 0x0A, "-> Version: 0x", 0x00 -printInfo3 db 0x0D, 0x0A, "-> OEMString (address): 0x", 0x00 -printInfo4 db 0x0D, 0x0A, "-> Capabilities: 0x", 0x00 -printInfo5 db 0x0D, 0x0A, "-> Video modes (address): 0x", 0x00 -printInfo6 db 0x0D, 0x0A, "-> Total memory (KB): ", 0x00 -printFailure db "Error, unexpected return: ", 0x00 - -;******************************************************* -; Code Section -;******************************************************* -main: - - ;-------------------------------; - ; Setup segments and stack ; - ;-------------------------------; - - cli ; clear interrupts - xor ax, ax ; null segments - mov ds, ax - mov es, ax - mov ax, 0x0000 ; stack begins at 0x9000-0xffff - mov ss, ax - mov sp, 0xFFFF - sti ; enable interrupts - -; Switch to graphic mode - mov ax, 0012h - int 10h - int 09h - - mov ax, 0 - int 16h -; ************************************** -; * Start by getting some VESA info * -; ************************************** - xor eax, eax - mov ebx, eax - mov ecx, eax - mov edx, eax - - mov eax, vbeControllerInfo - push eax - and eax, 0fh - mov dx, ax - pop eax - - shr eax, 4 - - mov es, ax - mov di, dx - mov ax, 4F00h - int 10h - - ; See if interrupt returned ok. - cmp ax, 004Fh - je .yes - - ; no: - mov si, printFailure ; print error message - call Puts16 - call PrintHEX ; print error code - jmp .done - -.yes: - mov si, printSuccess ; print success message - call Puts16 - -; Print Info1 - mov si, printInfo1 - call Puts16 - - mov si, vbeControllerInfo_signature - call Puts16 - - -; Print Info2 - mov si, printInfo2 - call Puts16 - xor eax, eax - mov ax, [vbeControllerInfo_version] - call PrintHEX - -; Print Info3 - mov si, printInfo3 - call Puts16 - mov eax, [vbeControllerInfo_oemString] - call PrintHEX - -; Print Info4 - mov si, printInfo4 - call Puts16 - mov eax, [vbeControllerInfo_capabilities] - call PrintHEX - -; Print Info5 - mov si, printInfo5 - call Puts16 - mov eax, [vbeControllerInfo_videomodes] - call PrintHEX - -; Print Info6 - mov si, printInfo6 - call Puts16 - xor eax, eax - mov ax, [vbeControllerInfo_totalMemory] - call PrintINT - -.done: - cli - hlt - - -vbeModeInfo: - vbeModeInfo_attributes dw 0 - vbeModeInfo_winA db 0 - vbeModeInfo_winB db 0 - vbeModeInfo_granularity dw 0 - vbeModeInfo_winsize dw 0 - vbeModeInfo_segmentA dw 0 - vbeModeInfo_segmentB dw 0 - vbeModeInfo_realFctPtr dd 0 - vbeModeInfo_pitc dw 0 ; // bytes per scanline - vbeModeInfo_Xres dw 0 - vbeModeInfo_Yres dw 0 - vbeModeInfo_Wchar db 0 - vbeModeInfo_Ychar db 0 - vbeModeInfo_planes db 0 - vbeModeInfo_bpp db 0 - vbeModeInfo_banks db 0 - vbeModeInfo_memory_model db 0 - vbeModeInfo_bank_size db 0 - vbeModeInfo_image_pages db 0 - vbeModeInfo_reserved0 db 0 - - ; VBE v1.2+ - vbeModeInfo_red_mask db 0 - vbeModeInfo_red_position db 0 - vbeModeInfo_green_mask db 0 - vbeModeInfo_green_position db 0 - vbeModeInfo_blue_mask db 0 - vbeModeInfo_blue_position db 0 - vbeModeInfo_rsv_mask db 0 - vbeModeInfo_rsv_position db 0 - vbeModeInfo_directcolor_attrib db 0 - - ; VBE v2.0+ - vbeModeInfo_physbase dd 0 - vbeModeInfo_start_offscreen_mem dd 0 - vbeModeInfo_size_offscreen_mem dw 0 - - ; VBE v3.0+ - vbeModeInfo_bytes_per_scanline dw 0 - vbeModeInfo_number_images_banked db 0 - vbeModeInfo_number_images_linear db 0 - vbeModeInfo_linear_red_mask db 0 - vbeModeInfo_linear_red_pos db 0 - vbeModeInfo_linear_green_mask db 0 - vbeModeInfo_linear_green_pos db 0 - vbeModeInfo_linear_blue_mask db 0 - vbeModeInfo_linear_blue_pos db 0 - vbeModeInfo_linear_res_mask db 0 - vbeModeInfo_linear_res_pos db 0 - vbeModeInfo_max_pixel_clock dd 0 \ No newline at end of file diff --git a/_play/stage2/stdio.inc b/_play/stage2/stdio.inc deleted file mode 100644 index 479ad79..0000000 --- a/_play/stage2/stdio.inc +++ /dev/null @@ -1,386 +0,0 @@ -;***** stdio.inc ***************************************************** -;* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God * -;* * -;* Standard Input/Output routines * -;* ============================== * -;* * -;************************************************************ cta os */ - - -%ifndef __STDIO_INC_CTA008__ -%define __STDIO_INC_CTA008__ - - -;========================================================== -; -; 16 Bit Real Mode Routines -;========================================================== - - -;************************************************; -; Puts16 () -; -Prints a null terminated string -; DS=>SI: 0 terminated string -;************************************************; -tmpStr db " ", 0x0D, 0x0A, 0x00 -hex db "0123456789abcdef" - -bits 16 - -Puts16: - pusha ; save registers -.Loop1: - lodsb ; load next byte from string from SI to AL - or al, al ; Does AL=0? - jz Puts16Done ; Yep, null terminator found-bail out - mov ah, 0eh ; Nope-Print the character - int 10h ; invoke BIOS - jmp .Loop1 ; Repeat until null terminator found -Puts16Done: - popa ; restore registers - ret ; we are done, so return - - -;************************************************; -; PrintINT (uint16_t number) -; -Prints an integer on the screen -; -; Parameters: ax = number -;************************************************; -PrintINT: - pusha - - push ax ; save ax - mov bx, 10 ; base 10 in bx - call DigitsINT ; get number of digits - - mov cx, ax ; move in cx number of digits - pop ax ; restore ax = number - - mov byte[tmpStr+ecx], 0x00 ; Mark end of string - - .loop: - xor dx, dx - div bx ; divide by base - add dx, '0' - - mov byte[tmpStr+ecx-1], dl ; write in position - loop .loop ; loop while cx > 0 - - mov si, tmpStr - call Puts16 - - .done: - popa - ret - -;************************************************; -; PrintHEX (uint32_t number) -; -Prints an integer in hex on the screen -; -; Parameters: push on the stack number -;************************************************; -PrintHEX: - pusha - - push eax ; save ax - call DigitsHEX ; get number of digits - - mov ecx, eax ; move in cx number of digits - pop eax ; restore ax = number - - mov byte[tmpStr+ecx], 0x00 ; Mark end of string - - .loop: - mov edx, eax ; Put number in edx - and edx, 0x0f ; Remove all digits but the last - - shr eax, 4 ; Remove digit from end - - push eax ; save eax - xor eax, eax ; make it 0 - mov al, [hex+edx] - - mov byte[tmpStr+ecx-1], al ; write in position - - pop eax - - loop .loop ; loop while cx > 0 - - mov si, tmpStr - call Puts16 - - .done: - popa - ret - - -;************************************************; -; DigitsHEX (uint32_t number) -; -Calculate number of digits of a number in hex -; -; Parameters: number in eax -; Returns: value in eax -;************************************************; -_Number dd 0 -DigitsHEX: - pusha ; Save all registers - - xor ebx, ebx ; Empty registers - mov ecx, ebx - mov edx, ebx - - .loop: - cmp eax, 0 - je .done - shr eax, 4 - inc ecx - jmp .loop - - .done: - mov dword[_Number], ecx - popa - mov eax, [_Number] - ret - -;************************************************; -; DigitsINT (uint16_t number, uint16_t base) -; -Calculate number of digits of a number in the specified base -; -; Parameters: number in ax, base in bx -; Returns: value in ax -;************************************************; -DigitsINT: - pusha ; Save all registers - - xor cx, cx ; Empty registers - - .loop: - cmp ax, 0 - je .done - xor dx, dx - div bx - inc cx - jmp .loop - - .done: - mov word[_Number], cx - popa - mov ax, [_Number] - ret -;========================================================== -; -; 32 Bit Protected Mode Routines -;========================================================== - - ;bits 32 - -;%define VIDMEM 0xB8000 ; video memory -;%define COLS 80 ; width and height of screen -;%define LINES 25 -;%define CHAR_ATTRIB 14 ; character attribute (White text on black background) - -;_CurX db 0 ; current x/y location -;_CurY db 0 - -;**************************************************; -; Putch32 () -; - Prints a character to screen -; BL => Character to print -;**************************************************; - -;Putch32: -; -; pusha -; mov edi, VIDMEM -; -; xor eax, eax ; clear eax -; -; ; y * screen width -; -; mov ecx, COLS*2 ; Mode 7 has 2 bytes per char, so its COLS*2 bytes per line -; mov al, byte [_CurY] ; get y pos -; mul ecx ; multiply y*COLS -; push eax ; save eax--the multiplication - - ; now add _CurX * 2 - -; mov al, byte [_CurX] ; multiply _CurX by 2 because it is 2 bytes per char -; mov cl, 2 -; mul cl -; pop ecx ; pop y*COLS result -; add eax, ecx - - ; add the position to draw to the base of vid memory - -; xor ecx, ecx -; add edi, eax ; add it to the base address -; - ; watch for new line - -; cmp bl, 0x0A ; is it a newline character? -; je .Row ; yep--go to next row -; - ; print the character - -; mov dl, bl ; Get character -; mov dh, CHAR_ATTRIB ; the character attribute -; mov word [edi], dx ; write to video display -; -; ; go to next location - -; inc byte [_CurX] ; go to next character -; jmp .done ; nope, bail out - -;.Row: -; mov byte [_CurX], 0 ; go back to col 0 -; inc byte [_CurY] ; go to next row - -;.done: -; popa -; ret - -;**************************************************; -; Puts32 () -; - Prints a null terminated string -; parm\ EBX = address of string to print -;**************************************************; - -;Puts32: - -; pusha -; push ebx ; copy the string address -; pop edi - -;.loop: - - ;-------------------------------; - ; Get character ; - ;-------------------------------; - -; mov bl, byte [edi] ; get next character -; cmp bl, 0 ; is it 0 (Null terminator)? -; je .done ; yep-bail out - - ;-------------------------------; - ; Print the character ; - ;-------------------------------; - -; call Putch32 ; Nope-print it out - - ;-------------------------------; - ; Go to next character ; - ;-------------------------------; - -; inc edi ; go to next character -; jmp .loop - -;.done: - - ;-------------------------------; - ; Update hardware cursor ; - ;-------------------------------; - -; mov bh, byte [_CurY] ; get current position -; mov bl, byte [_CurX] -; call MovCur ; update cursor - -; popa ; restore registers, and return -; ret - -;**************************************************; -; MoveCur () -; - Update hardware cursor -; parm/ bh = Y pos -; parm/ bl = x pos -;**************************************************; - - - -;bits 32 - -;MovCur: - -; pusha -; - ;-------------------------------; - ; Get current position ; - ;-------------------------------; - - ; location = _CurX + _CurY * COLS - -; xor eax, eax -; mov ecx, COLS -; mov al, bh ; get y pos -; mul ecx ; multiply y*COLS -; add al, bl ; Now add x -; mov ebx, eax -; - ;--------------------------------------; - ; Set low byte index to VGA register ; - ;--------------------------------------; - -; mov al, 0x0f -; mov dx, 0x03D4 -; out dx, al -; -; mov al, bl -; mov dx, 0x03D5 -; out dx, al ; low byte - - ;---------------------------------------; - ; Set high byte index to VGA register ; - ;---------------------------------------; - -; xor eax, eax - -; mov al, 0x0e -; mov dx, 0x03D4 -; out dx, al - -; mov al, bh -; mov dx, 0x03D5 -; out dx, al ; high byte - -; popa -; ret - -;**************************************************; -; ClrScr32 () -; - Clears screen -;**************************************************; -; -;bits 32 -; -;ClrScr32: -; -; pusha -; cld -; mov edi, VIDMEM -; mov cx, 2000 -; mov ah, CHAR_ATTRIB -; mov al, ' ' -; rep stosw -; mov byte [_CurX], 0 -; mov byte [_CurY], 0 -; popa -; ret - -;**************************************************; -; GotoXY () -; - Set current X/Y location -; parm\ AL=X position -; parm\ AH=Y position -;**************************************************; - -;bits 32 - -;GotoXY: -; pusha -; mov [_CurX], al -; mov [_CurY], ah -; popa -; ret - - -%endif ;__STDIO_INC_67343546FDCC56AAB872_INCLUDED__ diff --git a/bochs/.bochsrc b/bochs/.bochsrc new file mode 100644 index 0000000..a7be8a6 --- /dev/null +++ b/bochs/.bochsrc @@ -0,0 +1,9 @@ +megs: 32 + + +floppya: 1_44=../luxos.img, status=inserted +boot: a +log: bochs_run.log +mouse: enabled=0 +magic_break: enabled=1 +display_library: x, options="gui_debug" \ No newline at end of file diff --git a/bochs/.bochsrc~ b/bochs/.bochsrc~ new file mode 100644 index 0000000..490468d --- /dev/null +++ b/bochs/.bochsrc~ @@ -0,0 +1,10 @@ +megs: 32 +romimage: file="/usr/share/bochs/BIOS-bochs-latest" +vgaromimage: file="C:\Program Files\Bochs-2.4.6\VGABIOS-lgpl-latest" + +floppya: 1_44=../luxos.img, status=inserted +boot: a +log: bochs_run.log +mouse: enabled=0 +magic_break: enabled=1 +display_library: x, options="gui_debug" \ No newline at end of file diff --git a/bochs/bochs_run.log b/bochs/bochs_run.log new file mode 100644 index 0000000..16cd2dd --- /dev/null +++ b/bochs/bochs_run.log @@ -0,0 +1,206 @@ +00000000000i[ ] Bochs x86 Emulator 2.4.6 +00000000000i[ ] Build from CVS snapshot, on February 22, 2011 +00000000000i[ ] Compiled at Aug 28 2011, 16:32:50 +00000000000i[ ] System configuration +00000000000i[ ] processors: 1 (cores=1, HT threads=1) +00000000000i[ ] A20 line support: yes +00000000000i[ ] CPU configuration +00000000000i[ ] level: 6 +00000000000i[ ] SMP support: yes, quantum=5 +00000000000i[ ] APIC support: yes +00000000000i[ ] FPU support: yes +00000000000i[ ] MMX support: yes +00000000000i[ ] 3dnow! support: yes +00000000000i[ ] SEP support: yes +00000000000i[ ] SSE support: sse2 +00000000000i[ ] XSAVE support: no +00000000000i[ ] AES support: no +00000000000i[ ] MOVBE support: no +00000000000i[ ] x86-64 support: yes +00000000000i[ ] 1G paging support: no +00000000000i[ ] VMX support: 1 +00000000000i[ ] Optimization configuration +00000000000i[ ] RepeatSpeedups support: yes +00000000000i[ ] Trace cache support: yes +00000000000i[ ] Fast function calls: yes +00000000000i[ ] Devices configuration +00000000000i[ ] ACPI support: yes +00000000000i[ ] NE2000 support: no +00000000000i[ ] PCI support: yes, enabled=yes +00000000000i[ ] SB16 support: yes +00000000000i[ ] USB support: no +00000000000i[ ] VGA extension support: vbe +00000000000i[MEM0 ] allocated memory at 0xb4116008. after alignment, vector=0xb4117000 +00000000000i[MEM0 ] 32.00MB +00000000000i[MEM0 ] mem block size = 0x00100000, blocks=32 +00000000000i[MEM0 ] rom at 0xfffe0000/131072 ('/usr/local/share/bochs/BIOS-bochs-latest') +00000000000i[MEM0 ] rom at 0xc0000/40448 ('/usr/local/share/bochs/VGABIOS-lgpl-latest') +00000000000i[CMOS ] Using local time for initial clock +00000000000i[CMOS ] Setting initial clock to: Mon Aug 29 10:21:59 2011 (time0=1314602519) +00000000000i[DMA ] channel 4 used by cascade +00000000000i[DMA ] channel 2 used by Floppy Drive +00000000000i[FDD ] fd0: '../luxos.img' ro=0, h=2,t=80,spt=18 +00000000000i[PCI ] 440FX Host bridge present at device 0, function 0 +00000000000i[PCI ] PIIX3 PCI-to-ISA bridge present at device 1, function 0 +00000000000i[VGA ] interval=50000 +00000000000i[MEM0 ] Register memory access handlers: 0x00000000000a0000 - 0x00000000000bffff +00000000000i[XGUI ] test_alloc_colors: 16 colors available out of 16 colors tried +00000000000i[XGUI ] font 8 wide x 16 high, display depth = 24 +00000000000i[MEM0 ] Register memory access handlers: 0x00000000e0000000 - 0x00000000e0ffffff +00000000000i[VGA ] VBE Bochs Display Extension Enabled +00000000000i[ ] init_dev of 'unmapped' plugin device by virtual method +00000000000i[ ] init_dev of 'biosdev' plugin device by virtual method +00000000000i[ ] init_dev of 'speaker' plugin device by virtual method +00000000000i[SPEAK] Failed to open /dev/console: Resource temporarily unavailable +00000000000i[SPEAK] Deactivating beep on console +00000000000i[ ] init_dev of 'extfpuirq' plugin device by virtual method +00000000000i[ ] init_dev of 'gameport' plugin device by virtual method +00000000000i[ ] init_dev of 'iodebug' plugin device by virtual method +00000000000i[ ] init_dev of 'pci_ide' plugin device by virtual method +00000000000i[PCI ] PIIX3 PCI IDE controller present at device 1, function 1 +00000000000i[ ] init_dev of 'acpi' plugin device by virtual method +00000000000i[PCI ] ACPI Controller present at device 1, function 3 +00000000000i[ ] init_dev of 'ioapic' plugin device by virtual method +00000000000i[IOAP ] initializing I/O APIC +00000000000i[MEM0 ] Register memory access handlers: 0x00000000fec00000 - 0x00000000fec00fff +00000000000i[ ] init_dev of 'keyboard' plugin device by virtual method +00000000000i[KBD ] will paste characters every 1000 keyboard ticks +00000000000i[ ] init_dev of 'harddrv' plugin device by virtual method +00000000000i[HD ] Using boot sequence floppy, none, none +00000000000i[HD ] Floppy boot signature check is enabled +00000000000i[ ] init_dev of 'serial' plugin device by virtual method +00000000000i[SER ] com1 at 0x03f8 irq 4 +00000000000i[ ] init_dev of 'parallel' plugin device by virtual method +00000000000i[PAR ] parallel port 1 at 0x0378 irq 7 +00000000000i[ ] register state of 'unmapped' plugin device by virtual method +00000000000i[ ] register state of 'biosdev' plugin device by virtual method +00000000000i[ ] register state of 'speaker' plugin device by virtual method +00000000000i[ ] register state of 'extfpuirq' plugin device by virtual method +00000000000i[ ] register state of 'gameport' plugin device by virtual method +00000000000i[ ] register state of 'iodebug' plugin device by virtual method +00000000000i[ ] register state of 'pci_ide' plugin device by virtual method +00000000000i[ ] register state of 'acpi' plugin device by virtual method +00000000000i[ ] register state of 'ioapic' plugin device by virtual method +00000000000i[ ] register state of 'keyboard' plugin device by virtual method +00000000000i[ ] register state of 'harddrv' plugin device by virtual method +00000000000i[ ] register state of 'serial' plugin device by virtual method +00000000000i[ ] register state of 'parallel' plugin device by virtual method +00000000000i[SYS ] bx_pc_system_c::Reset(HARDWARE) called +00000000000i[CPU0 ] cpu hardware reset +00000000000i[APIC0] allocate APIC id=0 (MMIO enabled) to 0x00000000fee00000 +00000000000i[CPU0 ] CPU[0] is the bootstrap processor +00000000000i[CPU0 ] CPUID[0x00000000]: 00000003 68747541 444d4163 69746e65 +00000000000i[CPU0 ] CPUID[0x00000001]: 00000f23 00000800 00002020 07cbfbff +00000000000i[CPU0 ] CPUID[0x00000002]: 00000000 00000000 00000000 00000000 +00000000000i[CPU0 ] CPUID[0x00000003]: 00000000 00000000 00000000 00000000 +00000000000i[CPU0 ] CPUID[0x00000004]: 00000000 00000000 00000000 00000000 +00000000000i[CPU0 ] CPUID[0x00000007]: 00000000 00000000 00000000 00000000 +00000000000i[CPU0 ] CPUID[0x80000000]: 80000008 68747541 444d4163 69746e65 +00000000000i[CPU0 ] CPUID[0x80000001]: 00000f23 00000000 00000001 ebd3fbff +00000000000i[CPU0 ] CPUID[0x80000002]: 20444d41 6c687441 74286e6f 7020296d +00000000000i[CPU0 ] CPUID[0x80000003]: 65636f72 726f7373 00000000 00000000 +00000000000i[CPU0 ] CPUID[0x80000004]: 00000000 00000000 00000000 00000000 +00000000000i[CPU0 ] CPUID[0x80000005]: 01ff01ff 01ff01ff 40020140 40020140 +00000000000i[CPU0 ] CPUID[0x80000006]: 00000000 42004200 02008140 00000000 +00000000000i[CPU0 ] CPUID[0x80000007]: 00000000 00000000 00000000 00000000 +00000000000i[CPU0 ] CPUID[0x80000008]: 00003028 00000000 00000000 00000000 +00000000000i[ ] reset of 'unmapped' plugin device by virtual method +00000000000i[ ] reset of 'biosdev' plugin device by virtual method +00000000000i[ ] reset of 'speaker' plugin device by virtual method +00000000000i[ ] reset of 'extfpuirq' plugin device by virtual method +00000000000i[ ] reset of 'gameport' plugin device by virtual method +00000000000i[ ] reset of 'iodebug' plugin device by virtual method +00000000000i[ ] reset of 'pci_ide' plugin device by virtual method +00000000000i[ ] reset of 'acpi' plugin device by virtual method +00000000000i[ ] reset of 'ioapic' plugin device by virtual method +00000000000i[ ] reset of 'keyboard' plugin device by virtual method +00000000000i[ ] reset of 'harddrv' plugin device by virtual method +00000000000i[ ] reset of 'serial' plugin device by virtual method +00000000000i[ ] reset of 'parallel' plugin device by virtual method +00000000000i[XGUI ] [x] Mouse off +00000003305i[BIOS ] $Revision: 1.257 $ $Date: 2011/01/26 09:52:02 $ +00000318072i[KBD ] reset-disable command received +00000444792i[VBIOS] VGABios $Id: vgabios.c,v 1.69 2009/04/07 18:18:20 vruppert Exp $ +00000444863i[VGA ] VBE known Display Interface b0c0 +00000444895i[VGA ] VBE known Display Interface b0c5 +00000447820i[VBIOS] VBE Bios $Id: vbe.c,v 1.62 2009/01/25 15:46:25 vruppert Exp $ +00000600000i[XGUI ] charmap update. Font Height is 16 +00000760509i[BIOS ] Starting rombios32 +00000761006i[BIOS ] Shutdown flag 0 +00000761687i[BIOS ] ram_size=0x02000000 +00000762165i[BIOS ] ram_end=32MB +00000802749i[BIOS ] Found 1 cpu(s) +00000821736i[BIOS ] bios_table_addr: 0x000fb928 end=0x000fcc00 +00000821839i[PCI ] 440FX PMC write to PAM register 59 (TLB Flush) +00001149536i[PCI ] 440FX PMC write to PAM register 59 (TLB Flush) +00001477464i[P2I ] PCI IRQ routing: PIRQA# set to 0x0b +00001477485i[P2I ] PCI IRQ routing: PIRQB# set to 0x09 +00001477506i[P2I ] PCI IRQ routing: PIRQC# set to 0x0b +00001477527i[P2I ] PCI IRQ routing: PIRQD# set to 0x09 +00001477537i[P2I ] write: ELCR2 = 0x0a +00001478422i[BIOS ] PIIX3/PIIX4 init: elcr=00 0a +00001486380i[BIOS ] PCI: bus=0 devfn=0x00: vendor_id=0x8086 device_id=0x1237 class=0x0600 +00001488942i[BIOS ] PCI: bus=0 devfn=0x08: vendor_id=0x8086 device_id=0x7000 class=0x0601 +00001491343i[BIOS ] PCI: bus=0 devfn=0x09: vendor_id=0x8086 device_id=0x7010 class=0x0101 +00001491573i[PIDE ] new BM-DMA address: 0xc000 +00001492277i[BIOS ] region 4: 0x0000c000 +00001494587i[BIOS ] PCI: bus=0 devfn=0x0b: vendor_id=0x8086 device_id=0x7113 class=0x0680 +00001494825i[ACPI ] new irq line = 11 +00001494839i[ACPI ] new irq line = 9 +00001494869i[ACPI ] new PM base address: 0xb000 +00001494883i[ACPI ] new SM base address: 0xb100 +00001494911i[PCI ] setting SMRAM control register to 0x4a +00001659005i[CPU0 ] Enter to System Management Mode +00001659005i[CPU0 ] enter_system_management_mode: temporary disable VMX while in SMM mode +00001659015i[CPU0 ] RSM: Resuming from System Management Mode +00001823035i[PCI ] setting SMRAM control register to 0x0a +00001832206i[BIOS ] MP table addr=0x000fba00 MPC table addr=0x000fb930 size=0xd0 +00001834265i[BIOS ] SMBIOS table addr=0x000fba10 +00001836653i[BIOS ] ACPI tables: RSDP addr=0x000fbb30 ACPI DATA addr=0x01ff0000 size=0x988 +00001839891i[BIOS ] Firmware waking vector 0x1ff00cc +00001851004i[PCI ] 440FX PMC write to PAM register 59 (TLB Flush) +00001851848i[BIOS ] bios_table_cur_addr: 0x000fbb54 +00014041552i[BIOS ] Booting from 0000:7c00 +00023137422i[BIOS ] int13_harddisk: function 41, unmapped device for ELDL=80 +00023142203i[BIOS ] int13_harddisk: function 08, unmapped device for ELDL=80 +00023146854i[BIOS ] *** int 15h function AX=00c0, BX=0000 not yet supported! +00037427421i[CPU0 ] [37427421] Stopped on MAGIC BREAKPOINT +00037475097i[KBD ] setting typematic info +00037475122i[KBD ] setting delay to 500 mS (unused) +00037475122i[KBD ] setting repeat rate to 10.9 cps (unused) +00037475183i[KBD ] Switched to scancode set 2 +00037475271i[KBD ] keyboard: scan convert turned off +00037475895i[KBD ] keyboard: scan convert turned off +00037491918i[FDD ] controller reset in software +00039078683i[FDD ] io_write: config control register: 0x00 +00055400059i[CPU0 ] [55400059] Stopped on MAGIC BREAKPOINT +00165600000i[ ] dbg: Quit +00165600000i[CPU0 ] CPU is in protected mode (active) +00165600000i[CPU0 ] CS.d_b = 32 bit +00165600000i[CPU0 ] SS.d_b = 32 bit +00165600000i[CPU0 ] EFER = 0x00000000 +00165600000i[CPU0 ] | RAX=00000000000000ff RBX=000000000010d78c +00165600000i[CPU0 ] | RCX=00000000000003d4 RDX=000000000010d6ca +00165600000i[CPU0 ] | RSP=000000000010d68c RBP=000000000010d6a4 +00165600000i[CPU0 ] | RSI=000000000010d6ca RDI=0000000000000002 +00165600000i[CPU0 ] | R8=0000000000000000 R9=0000000000000000 +00165600000i[CPU0 ] | R10=0000000000000000 R11=0000000000000000 +00165600000i[CPU0 ] | R12=0000000000000000 R13=0000000000000000 +00165600000i[CPU0 ] | R14=0000000000000000 R15=0000000000000000 +00165600000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df IF tf sf ZF af PF cf +00165600000i[CPU0 ] | SEG selector base limit G D +00165600000i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D +00165600000i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1 +00165600000i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00165600000i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00165600000i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00165600000i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00165600000i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00165600000i[CPU0 ] | MSR_FS_BASE:0000000000000000 +00165600000i[CPU0 ] | MSR_GS_BASE:0000000000000000 +00165600000i[CPU0 ] | RIP=0000000000105eb4 (0000000000105eb4) +00165600000i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000000000 +00165600000i[CPU0 ] | CR3=0x00110000 CR4=0x00000000 +00165600000i[CMOS ] Last time is 1314602560 (Mon Aug 29 10:22:40 2011) +00165600000i[XGUI ] Exit +00165600000i[CTRL ] quit_sim called with exit code 0 diff --git a/bochs/bochsrc.bxrc b/bochs/bochsrc.bxrc new file mode 100644 index 0000000..db458f5 --- /dev/null +++ b/bochs/bochsrc.bxrc @@ -0,0 +1,9 @@ +megs: 32 +romimage: file="C:\Program Files\Bochs-2.4.6\BIOS-bochs-latest" +vgaromimage: file="C:\Program Files\Bochs-2.4.6\VGABIOS-lgpl-latest" + +floppya: 1_44=a:, status=inserted +boot: a +log: bochs_run.log +mouse: enabled=0 +magic_break: enabled=1 \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..84d6b2d --- /dev/null +++ b/build.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +# ----------------- lux Operating System ----------------- +OBJ=build +COMPILER=gcc +LINKER=ld + +BuildC() +{ + Percent=10 + + while read descript + do + read line + read empty + echo "[ $Percent%] KERNEL :: $descript" + File=${line##*/} + File=${File%%.*} + $COMPILER -Wall -Wextra -O -nostdinc -fno-builtin -I./Kernel/include -c -o $OBJ/$File.o $line -nostdlib -nostartfiles -nodefaultlibs + Percent=$(($Percent + 2)) #Increase PERCENT + done < $1 + + return 0 +} + +BuildAsm() +{ + Percent=85 + + while read descript + do + read line + read empty + echo "[ $Percent%] KERNEL :: $descript" + File=${line##*/} + File=${File%%.*} + nasm -f elf -o $OBJ/$File.o $line + Percent=$(($Percent + 1)) #Increase PERCENT + done < $1 + + return 0 +} + + +echo "lux operating system v0.1" + +# Clean up +echo "[ 1%] CLEANUP" +rm $OBJ/* 2>/dev/null + +# Calculate version number +read buildno < ./scripts/version.txt +buildno=$(($buildno + 1)) +echo $buildno > ./scripts/version.txt +echo "#define OS_BUILD \"0.1.0.$buildno\"" > ./Kernel/include/version.h + +# Build kernel +BuildC "filelistC.txt" +BuildAsm "filelistAsm.txt" + +# Link +echo "[ 95%] LINKING..." +$LINKER -T link.ld $OBJ/*.o + +# Make floppy image +echo "[ 97%] WRITING FLOPPY IMAGE..." +cp floppy/original.img luxos.img +mkdir /media/floppy1 +mount -o loop luxos.img /media/floppy1 +cp kernel.bin /media/floppy1/ +sleep 1 +umount /media/floppy1 +rm -r /media/floppy1 + +# DONE +echo "[100%] DONE!\n" + + +exit 0 diff --git a/build.sh~ b/build.sh~ new file mode 100644 index 0000000..400ef01 --- /dev/null +++ b/build.sh~ @@ -0,0 +1,78 @@ +#!/bin/sh + +# ----------------- lux Operating System ----------------- +OBJ=build +COMPILER=gcc +LINKER=ld + +BuildC() +{ + Percent=10 + + while read descript + do + read line + read empty + echo "[ $Percent%] KERNEL :: $descript" + File=${line##*/} + File=${File%%.*} + $COMPILER -Wall -Wextra -O -nostdinc -fno-builtin -I./Kernel/include -c -o $OBJ/$File.o $line -nostdlib -nostartfiles -nodefaultlibs + Percent=$(($Percent + 2)) #Increase PERCENT + done < $1 + + return 0 +} + +BuildAsm() +{ + Percent=85 + + while read descript + do + read line + read empty + echo "[ $Percent%] KERNEL :: $descript" + File=${line##*/} + File=${File%%.*} + nasm -f elf -o $OBJ/$File.o $line + Percent=$(($Percent + 1)) #Increase PERCENT + done < $1 + + return 0 +} + + +echo "lux operating system v0.1" + +# Clean up +echo "[ 1%] CLEANUP" +rm $OBJ/* 2>/dev/null + +# Calculate version number +read buildno < ./scripts/version.txt +buildno=$(($buildno + 1)) +echo $buildno > ./scripts/version.txt +echo "#define OS_BUILD \"0.1.0.$buildno\"" > ./Kernel/include/version.h + +# Build kernel +BuildC "filelistC.txt" +BuildAsm "filelistAsm.txt" + +# Link +echo "[ 95%] LINKING..." +$LINKER -T link.ld $OBJ/*.o + +# Make floppy image +echo "[ 97%] WRITING FLOPPY IMAGE..." +cp floppy/original.img luxos.img +mkdir /media/floppy1 +mount -o loop luxos.img /media/floppy1 +cp kernel.bin /media/floppy1/ +umount /media/floppy1 +rm -r /media/floppy1 + +# DONE +echo "[100%] DONE!\n" + + +exit 0 diff --git a/build/clock.o b/build/clock.o new file mode 100644 index 0000000000000000000000000000000000000000..a85951d02bc9de751f483205b255d58faf3f663f GIT binary patch literal 936 zcma)4O-my|5UnxBWMu_i@TALnQT$4~NECH(SqOfCdeNLz!eneoFqz<_Bf6J8h@iOp z9~6Ir7x5(cGdwTs)%D;-i1lW=G@i7e=GA-sx@M-jf6Xk;I*vmU4#nt&5k1<4bcp@b zN(ssy|6Mux4B_zBWKPx=JppJDCb+BpY?3n^Of zi=V@?wsAvqnaosAe>Pw9O>Jbc=(|CsC#}ZRXlkMsis^xf6RGNc*|>Q|6GT{$D$pfm z^qwKL=^B?*zFH;aRmx@Uv*uTfR&&eQRMoiNHa_HC@r7NONsD!37OS=f;1>{GoFBp} zdK7phKe$YCVn2MSdoAbXFpew=NWUQ#;D5{al|ASWM4%t`N?;8+X;JhGDJ;T+=-`xh zg2T6f!iM;OO(HV>W^&4i86-IIAMKVm_8VsMjdcm>CtR>mZ>GDt=)l*v6uj{b;4;N% zSM2%pgvX!H3TOF=C)CM^UC0jlUms?~H{cAw$tzX7ZROEwv8?A^f3u_m$`yU11K%y> qwgSCV)4sQ#EBtJb4V$C8<8UL)!{GsicYtxw@^OpbEoLk(S$qO?KVd8Y literal 0 HcmV?d00001 diff --git a/build/cmos.o b/build/cmos.o new file mode 100644 index 0000000000000000000000000000000000000000..ff52882982af758ae0c6c693460b34188658baf2 GIT binary patch literal 2616 zcmb7FZ)jUp6n|-7n#2a4|8;EA4JRaQdy}mW75in+w$pV|*JT51m9$N}TAOz1i*u+L zeHr93gIN6FM?pUf_C1se?!72WQYLmq*w-v*Q~QRr73x-mc+SnauP`?dELIFG zC^?h8yjO+@m_5%BjQsaE3fxd~B^yf90{1dxJ=|H7aAtf|mXa61r7v|i_}+0gZ_KBZ z+#*{|oBBTRWc(hS8yy)L!8)wXrg|0mtUTi}!LAHT;G&sfm%EGUGHeE{YVe6?) z&koZlZ+d6oh7#H$X>2WB(!&^j4%@(r8x@uxu~z)%N;6xq%5wJ68P8(qMxY3duw|&q zx7`VLQb}J0_e!p><$LaCb)zEsX<4_ZpLyOIYJg893Pv)!58qXoU+{q&s|x4NV=1{4 z)sW>55O56cu(f+UFT2YhIL~f=Qmp~kJ_^OPP;sv8G?~tv3@{c|;RLDsU?1{FI3z+F zKkn~;>+SzFzE^QF_7wR0_q(Sq(^++^<}!9w$wjJ0MajxXGg<(yow2I39d$d~-s$$W z-B$BotR>F_!x@yzz4|Cm=~eeBE4VcnkZkYghM7{1fu9}zgXJFx zMHYYk-Be4aD&IoX#qcsxoTj9(FCpsDsu}gBwfavXA>@ZNBVc}&u z+7^{pI&Kczy})*=*p_)lYsfF7HDsaWRvTkM7U0oyjU5&v3cZrLHSNXSp~zq|t|t%n zjK!mg$=&VhbLyc3&nNj|d$_Jkk~)21LXQpt>WMm@6}v?2T~&|0uS@E1RF6vP;PkYl z4oyx>#Nu!kpVVV&_iK>@(|UAh9HagxX#*Dir_f)Cg#RU9c(+V(Qc-ro!gdQO!Xr(A zA-)ybBMzK*8xp}o#9z6P>oC10DA)rWWUS*s(%t?(gQ74OA;O=~1-j2=X$?P=jx_$uW4`VP zsEaPvO`4t86S|l87PVcl9)=EK-9j+$9kB535mx2r-Ci;Jhu!FFNu%GZ9!Vd`l0hrMb!vFvP literal 0 HcmV?d00001 diff --git a/build/console-base.o b/build/console-base.o new file mode 100644 index 0000000000000000000000000000000000000000..c552d928a9ff2d023587e8862cab82311053810f GIT binary patch literal 2520 zcma)7ZD?Cn7(O?-U1OK-uEmW_qZ_Qky3zR6g0cETVoV3?C}!yxqt-ON#bTOUlA9%y z*$JW8%O&Cue>o867zjmze`?*YCUs48*sW!VR2T&-6kBRKkP1`k`<#1jlgS1ixOvX= zydUR1?>YD8QsCqpk|Z&ENX*HqjIkA`WohSdlr^w=7B+r6(;LdJyUc*gY?R63D=Wc* z5m;|6=>55NRti+$zSe2nSMoobjUdv3lAlwiWNAV^m@P_Ipyk}mw~$`S1}c)3=Xm#e zcFxh+T{(Y%I~YZ2QC~L0mE0@M*AcPym5(o&?piyecN}iLP=YTTR z0oi;Nzs9|Z)BRF*Ml$z-`ikir*@9%{Ip1W7)3A&$rY6@`Oxi{rHkJL(b?&YHzFFEX zHp+voGL5}Pm)uvB(FvHs?yHD5_92W1)bs}yUi;Rj#Pb@roplhcn0a6M;xUs)8aKCo zG5RX4W$KSnat10nkIQ#=Y}3kX@XheHjL%#+WQ9oO?C+8>E0ula%%8%KH{l9D7QWs^ zcS&x+nXdl5y}ezttL(a5;+3Ep9zadHioni?1b&Z3(4iZi7DI25%?>yYDS6)MAtwjr zo5m=~(|gEd{IHQbD;brc!m7(y+L%@>%~&!j8>Xklq#VXNZ&rw}t>k$v<1>2abyUlb z#JW3k@@q_);`_3M2~QK1nk_o4^HB2qiunrZTP0pOg|q6`_`c8arIe|FtFSCL1l;zy zegR)$;|17;M;>^X?!9|_F|)_Vuf*6cgX8#2rqRb&AFJa{?3+dE4|cO2f`jzbg9rWo zmk%Ee52WIH>e-XS@kl~D-0to0zR>nkii_>77H7o`%XVTRzz3s=o>~+9PH>C$WBUOeHM&msWRyho0B4H&_R<4hn{S00dBjdawwfui z>ZsLawz*xkAYZK&ymkd}yE|5tbLaGIUdL+#`-7fl%J(!OqR`_e%5aPj0~+{?gl>AU zGI)>>!}6!E9?g*p_W=2Z2phZhs=zkGM9`FKTH#HbH6?~p> znmE1~;CBd1#Bq1P*9h+rM~&bP%C$_~uBVCked1nWXHhMl)M9GeKqRSpqs(v7P&A>% zVmoa3J(cwi52{*^p0LH&)uBi#ru(&+wxjt|iDZ=pRsBIB^k2a;pNK~jDlOlmCGF&v z;gp(=4ae07#qcP-)@oNIF_?}dsk*a!x9Ktq51FQmqnyxX1FSbMn z{5+5@azOB2fjDE>FA4kzNPd?E$C*kEj7}-cs#=3LjT4S0XE^bY_%Z09B z+QGHh|=+_F>L14lzP&r)(gjh#G&--TSWBOi*8V@Av+m z=Xsxh_r8~mDqT-WlElQ2SQT4kjMd%dYIZuXg9X`ordmIB+iJk>t+SsAnfV|a?kmK~ z@?=*79v1DsalXdbIzBbB#axu+$)L|8_K#1EF0GL*{IltT;h35$l6kqj{6ZlHPdyEI zoOUA2U|aOd{1$TxqHTz9Q|ynPrwASyl8K&2G8LvZhGTlTcLo(5dam2f1?+sC-5auN zqu=BkY&BR2ZMIgBZ1qG9Hruu4v;^nB+Dfo#r4S5QwX^;W?C^{6n;zV*-}nKtIe)kZ0%zaYRIUy@w91VpTPaz4!$Dgq0s?b;!+r!Pchw@|;Qz@^Vc!^S?ws-j_=y+Q5XqPZ-MO&Ryz8nUu& zGX>sRw|1*1?Dy8)TU=Ibq@@;@_ngenGh>&0PMN=Pk}{Wa5Acl94Qd<`_imCPMfC{m5QP`1dan7 z*!foFf)T`RiQ*l-p8B&~MuZv>p`iWdToCZ%KE_U0G1iNz@p%Td(RvZOO_;1B7Tevp zL+#6@jod?BsdPfmH13SFL>_H!%{juIO)h6Fk{uo}5`92Jckzf=>DsY~p`9>Tq(5OK zSfnqTWf2nU8CQ_Z3=C*#=+hZPi*!7zHfN1Q@+cDcZ{u#5(QB#Z=Jb7Rq0aFkmRrHs z3n8!(q!k;fKeV6h0+`!5M=P9hOgP|N&{MFtA?yf64Wzn; zhVO^47Hi6j+}B}J4PJjwKzRi+F@!(C1$yOvcD*d*glm5ZiF+duUt3(2)3H?#RZfOp zzK(6+^dfL0I!5P6465TkOwv7xN&3ftAtd=Y=OjM>{v(<~`h(zN(EdI_fW%*^;G-4X zuHf%g@J}lE*A<*4GwE#RnAV(1N0Ka_#+{1~W%T}dD&4Q0VDY3eJgBia?qw?day+SL z25*v7I;-ghi@6RCXo>!A$4W?IIX#=v87ZFDh8bpGCZYFtXa<(uM#9KtS$s%O8CpDf zB%zD78)~hSed(mGC9>N7Om?k89mMBA>xA2(gsutQA#xfcpX@HwE8%dpaNNi7C5|UK zzQgfDj?)~E;$2C%AjD5%PFG8H%`|*BBzKdfIA>`wnzs+%) z%dZgP(*DlnH8`rYzl9L{4iZ9t97y$?B92S+0deH_5yv@_kNPi}%e&j+ogb*n>801K2ljLMdSkG}A$3~8S12Haao&W#< literal 0 HcmV?d00001 diff --git a/build/console-out.o b/build/console-out.o new file mode 100644 index 0000000000000000000000000000000000000000..777f3535fd045e31197d2cf7f3bc15c6bdbb3f74 GIT binary patch literal 2572 zcma)8Z)jUp9KC5@XWF%URXV7%n^QaKkY&TQ=<0J0+N`VVW?9W9$}Cy>=7MRSCNJAM zWSORM4KbojKdG>Z4C#dFmoOca>PA~Zzf1%LQ5*=XnIA;N3B!2KefPHM?3fpB&ON{L z`}gjB_mOn4Z>!Je6MFbWwU}o@v>2Y!E}>1-iQBZR#8B>+%++SI81!4U?xR+1y3z8R z*_WXeigYMFVb!_yRzvDV#p|wIFPF=+Q>-V7$H$oQr@&cZ7&+dWD)s}q9pKJG;$xUY`k2arYMRUSfrF+a=@NN1j z{afZ@%QMdo?qwu*Xd>v>4)ZA?sY*R!G&$ju31XjTP1!x6z!K)TL*a!37OUDe4}vqUrTk#NBR1(kra{3I|c( zXH>MFGP8bo?tf$UDCv-y{Tm3q)MKU0(GxTtF1Ys#H*6)%><<*Z^KQya8Ro>+>vI*~ zg$7%`!j$t&)7`E9IxH!5w;F}uj1H<;mIe__&&FGNb|}wV=Ui$Qm%NXBcp^g{mwEiF zf6C=jjdz&E;IvfbLFK+H)ttj#h|I-4eW3dF3DsAJ{HK^GzoT)izF(g9;v(Lto2WR8 zn+2N1ZicZyPghsx>bB6nRNPIi?~BI631@YCpd;|$x`$KJ*uK`|LIjc{!)|yV&`o%F zK(7*ZEa2LQT@e@xyI~R7mrRO4#2Fs8`oG5A@Ztt7QQljC zcC{h^o*c(rn6+}{{k-KD;xGaMGM@L8>otn&6d&pZ>>TQoBp$$;{#w47-v;=wKOzVH z7^??0&P@un{TrQF8R)}tJ7%Rszh0?$KiZF2Rbl@Kcl9KU+yj0^`5fFE^2&UD5PNhI zXcbGa`B7;%#P8*Kh50H~^2!S2dKbN@>bcX?yhfNR;T7N=$j9^3gMI7$q>X$t7iy62 z(F8~yxq-)S;K#sOs}qy;UI*&I__s0d#bezGq<&h9K>F9suV)P=5%#7raGr5pm*4CuXm6Qf?q31`j2o zu00qz5Kf3LPw7e}l1^f$eJB=<+Y5~gS#La&u)|5a-$`m=AbP|WyQ4$4)9=nD?6&uZ zQ!%&8i8%>f5O+Nqe@*~mc3emAVJ}_(X(jXmz618QaAN3CI5F3ebRO{1sLrK{$qw2H zw>R!S>CEdig>JBM9|mlE-#D3eNAY{Y(6;bQZB^5JsqP{=P*6+Z4G3e&VN z72;K;zozg_V!aUWDg6Uw=YJ07`&j9pDt%Jfrxboo#GipnMC9Rn!@AdqxD+PNy$W}9 zgTf9XJ__52%h0dlBSiSW0%X23P@Y1iwe|jfy{}_)f*2R{URay&x6< literal 0 HcmV?d00001 diff --git a/build/console.o b/build/console.o new file mode 100644 index 0000000000000000000000000000000000000000..1a17ea017095589681cbade8f4005905dd86dd90 GIT binary patch literal 8964 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 F{|BUnZjb-~ literal 0 HcmV?d00001 diff --git a/build/convert_ops.o b/build/convert_ops.o new file mode 100644 index 0000000000000000000000000000000000000000..40a7650f716d4e2b343f5b2661551528ce4f0f36 GIT binary patch literal 1736 zcma)6O>7fa5Ppl--~_`uz@_3Zih=|x-iBaWKp<$71uA|-n}i}F6WPv^1ngZ{zl{wC zuvi~>TJ5E(fE!$?sva$%QosZOxuA#>f=i{QYARPE;Sv&1%*^gSvT&gzjlMTC-<$c~ z+n-Cyp?!iN5N-kqk%fqmcZ3%iIXZ96wG?)- z&Q_7F`JjVUpGL`{^d?u4C4O40(%}9bF9l&B2uM|y)Mng zrC+L2Wz2~}qRBZiejC}Pw+)3a9I+&gJaam~8<#3S2v${qDintQVGm|ru<6olTObK>!N~)~%BuiIE9peT{4og?7>}mO>`FnZH{MET| zkIh1I_@?zxbe}=nmiDcQZC`)0eMc&t=~qt;3=W+>lg(-R*>gson!|*au z{v$Znj{|-ShuZ4LSwIT$bw9ogh=$6WP+vyZhE;?1>1XqDhIDw*_ZsciyQndw4G_)D zWmSz=dV(eM`6v$P>~Enie$@(g!HORsM!CJm@EW I4B+P912o!dQ2+n{ literal 0 HcmV?d00001 diff --git a/build/crash.o b/build/crash.o new file mode 100644 index 0000000000000000000000000000000000000000..766a54e426226e2e9ffbec32bd5eb6b60d926366 GIT binary patch literal 4120 zcma)9U2IfE6rQ##mI_jSGz3VPNLP!tOTl8Af)Uu=wi}^ccekMYZSL+)cW>C{@NPIve;l&q83Wlx;7eh1{(HLKd21EVM-81FZZi16czjMCx z&ADgp%$=P+m)t$j)YK$&YZ5KumM28d;(DYvfKIVgw29G~pZ8{`e``PKw_c8PEJ5U# ze`aTAVUsAZ&!=HsPIN>*CyaD7>%jE2CjTl0mem9JJ2$#Z+b0KlrvF+w8J$UVEIAoD zK^mB?p<#Du>9y7WiLB5OJe7*jr5z91^lZ&XU{hjDU^d`R4s;=91jE;aWcMzVNtSI0 z$vPLxI$1V1J7n%(DC=O^)=;(vwY9VCv5>4mZL3%|6p}Tljb0wj^ofwHL2c_;wm&3W zSlc32l|rfprA1g)4apjm*2*$3Bx_LG5|%v^k}WK4ppRv=m-NavsBJsTUJS_^)V70V zuZCm|YD=)}bV$~qwjq|?=Dqc>>^ASMmu2VlL#L1R+`a6?Cvca^FB|Q>nS;R|_)rgk zWSY5%9`OYH{^AG$~~ZX1!aA3ct~A6=na=sx;!^f%GpMZb)G z1^qgDGfuO$==Y;PfW8HN7kV1KO+TiS-7(y9SkM>MOr-UkKqo|Ei z-Dnf4WU|QBMxmyey3r=eZk-upRE(uMB8$mmidr#NHS{RoRgQ9XF6B7+qFqw;j7F)1 zm`>v;!?mq`i7BLa4kq)%Be{G!lguWEbK8jAmr3Q4`H^%ovon_(84kF3dNiLJ&W~o3 znf#uSL^2>#!`WPBG)|)YKr$B}0-G==OxLt6SvV@6R*o$as^FK)$`QjL#|`(0QK%|u zS{_RDYo6GJa*ot&5MpFPIb&6OQtYyQtK^E5HDOfElC*0y6%n^fDajI%WhrH@;ca1<$a+Tc2&WxX zmU4_LVz#G>9!;_SytGl)j~06jufp`ss#&&zhZifVcm$zh#k7>Hd)d^Ugv4A8&$PFdV}tAOY-^+Ko~vNx<)qcSs(Pvv3la|@ZI{IJT{&)+ zE0C#bO^%rs#1%#9@Y2WogBqe6Xot`y%Ir-h^1;5se#$(RAK9DC(2mL_X(x%nc)VYB zjuw2&^Ed4_EyJ;8Z)|I9OLw0iki8r0z7R3@=(uMTfSyywinbh8jd^Oy6EU(%hG&Ra z!FA!<zXU!=v5U16Z5?-_}Elqe3j=A#{KGh>lfm+FT2t zuUJ8(hJ&rOMTooL(Rk9eqHkm$p?bp&h^{xfNj9RuaK0(rb>0F;`Dm=pw+S}o)%nuM z7jC*fs+;QA!a>qmIOlYu81*=#)?L7F!*^N)q05r-93n zA;~@g#YNFE+)At{;)Hu}nBw%pk!iVhRb`czP{E-Vx2v|J>3xprDS@-ccH%gPUCqaR z2S@Rs?b$-CMCxXo1Z#jzm^OVU%~*?v+3#b2H~IK@=w?dsC)q#5evN#r%`_qMyukb^ z_D{2ahJ55X%l`Z9f5867gsA6x!lk%JP#pPw=Q#aqMEo)!@vF#3J)O)y!u&SoN0>jv ze1Z81=IKsBd1jbD#XQ|Hh(E{tCFZ|i{#)j+G5|=Wc&xIQx9dA?zokxW94HB+mT+O(SQ8IQg fb~1J`_AmzLH}cSTMftWf?qEzX4lxGb9d!Q!3^3#` literal 0 HcmV?d00001 diff --git a/build/ctype.o b/build/ctype.o new file mode 100644 index 0000000000000000000000000000000000000000..a69db89867b956abfc04930e773a550b3f4f0230 GIT binary patch literal 1108 zcmcIj!AiqG5S`fCRy|Y&K@>Cx1w~woR8UWX)>bIurAN`U1{B+-v|F?%3+h3n;3xF% zUA$`lz%LNN4-mZTyks{<$ia&bHgDdW*`4fea*@ez8-_s|21V#c5q&C=b_?cckm6Lh zdB4phI(x6}M>m_yJ@5BCGx=}_>+)@*lQXYhl9{Ldo?befxw(f3pv4cz62Fo1q5MM^ z8zJxtx-QxwKt8zF@E81NH@msHZq5~o&8loJgG9-xRO~8yRY%$)yIWXnNUL=E=M7DBCC(?NX5brG zQZXp1;z{NK6@#`oG0dFcf%&LIJgans8EE4XxBwHHvA_fMeqEpjdEGa~F;ZZl%>r{Z zki%G0to?hK0cbhGp6-b>>UKivP~R8uuXs|IHO?T;1Mi3ZLkHKJ;e^SahVHAi=Aa*? zk1y?mfB&7(!4A;+bi7#+|Ms-*_wQXRR?QYAl1{T$ Wv+H!=8Z67s8OtHAGx)-$6n_KI5N2Tj literal 0 HcmV?d00001 diff --git a/build/dma.o b/build/dma.o new file mode 100644 index 0000000000000000000000000000000000000000..595a7086ceffb68b3f2eb2981c70130b5d32dabc GIT binary patch literal 1852 zcma)+PiPcZ9LL|f8#ifJcQv*&X{#HFuu?M-O^QeaL)_>gNhQsq2N#@VCmOPUWOuen zOM@HNgVP*(YH!}W*<)GC13`>Pkm4bT=&5396qJAxOK4Ko?|0@s97{zXeE0LdzxSKp z{^re_IiDQp4+H{2kAMh@*G`DL8@!b+7YPv&O(Ny|6|JQjqqSrtS{sa2{s~X@M{A4q z_Mey}`SY|>hKPjRNVLi8M60|>G|L4dB7Y|uB>!T0sp2dwr{~{ZJB}>L)=;~FNXRhJ zCT|d}@)pr7Zxa!DhiH&N;D2hf=lx#Khmj$x%x;qxh*mjAG)sqw$RCIXISY6VR%RMQ zEsK>$UE{Mi?u*|LR}1cRX_I>w-h8vVqhw=Gc&fR_z3fX|c2`s%2CEApeaG&4>_6+? zV)a?fNv}BNRcB^BT1#WwXCjrg@YL?gTBzmk@!6&B`uOavdm>t!cS7w?*6a0p_0M3_ zAI=MBb=kFZ>6N+i>fFq_^DI4&X17CMLA#(m(0=G3)C(PhzJsnpyyHvIkI>K1W#|gD z1}#D_p$E!81Rq1okT}}ccQBqvjh6FvxpQD5Zx##jE~DGn*Kwfi2D^59UI?S~ZO%4F zLA&VjtezFEtYKTzwlFfLZ3<(wR1yY*#ex?YE97!k9_#snZ5c<0QXM7R9GheZ?=^NH ziwBBFl!Isd8Ut$Z1ao`}HMukIX9O1{F#P~xI`bMK?k7FZ9LI{U7QL?b1?J3uS04Le z3H1uP^-ja z==CmoR|VZ2dtD*ucIfwE!OsrIDQGKp>?1YTz73wQKlhRAhroZK7UhS)kI{5Q`4iwy zpU=P>@NuCR4QVrg*NefOk;Mlhd|U%$wQc z<{4|)Ix|s%b@PU;l4bX2C(iX}3+I^Z1~^IOb7pC>H=Csy#I*0Mna^9U_11g={P|!Z zV+qlUz5;l5-zf4^On(_YZ`drvFXSc!8OOok6CimONbU>CGeK@s{6z6H#kgX-VnUJM lG+xJZPP*?ActCmgJ%B%~{1L@tiUW$r6-N|LD)KqA?km(uK)L_` literal 0 HcmV?d00001 diff --git a/build/drivers.o b/build/drivers.o new file mode 100644 index 0000000000000000000000000000000000000000..01acae9451ff4f498301a4a0aecf15e80d315bf0 GIT binary patch literal 1476 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 Qf2wd);e^6!tZ(Z77oibbA^-pY literal 0 HcmV?d00001 diff --git a/build/gdt-asm.o b/build/gdt-asm.o new file mode 100644 index 0000000000000000000000000000000000000000..194b3654e97c65046d3d6b62a0cb15fd4dcc5e60 GIT binary patch literal 544 zcmb<-^>JflWMqH=Mh0dE1doBi0V-hvrZpJY7?@y6Nuoh!f-oCYmjRF?i)4ZTl+6yL znUTZ;fau&nOBc8PawLF!bH%JJ9!_??vB*S2AGP!yp;GlGKV42EF2p;*z40 z#3UfAG8aNa`9-NY5H%px7y#xTkOT|E$N$I*Kry2M6ad)<0gOm&hQb1Y&s!?R*$lS>tXf~ko3ZvV_aaY?C_I?9@#(vBKHB;cZG4D~tg&?mC!6thkm1BN zhgWfU6}!8z%1b*&=$SieGk7Qb7QM)P%dIrJ$;A!^(H`mq<;JOVR*NFX3`>S2u_fvR zG~n}Auh)b36>{u-&}WF#$SW@nXPfulU@x|?&AU0+>mTG@AMC|m+&GUh>TWW1sIQ6i+O?7}vrJL#v!HratEda>svtdY3X}9~ ztwwsTQYu+x&Xp^|($n+CL`|5v%UJclVn4fZY`9hg-qKyqBXf_IbNjfBa8vPy3pZKd zx?qP7{ex2D$Pmvxb3v>54s##=fBBBG2UCCu%!jcmP(wQ@sq#ON^n{Y5oKtI}4By-U zAN=Z-qWqEvy=LMJ@EgJRz|)2H&i9ZDQ=C(w)>T^3n-9=hPvybCf925L6`<8A_DA`D z-=5MzcaKolxsCA&jWHA4lH5jVy|^e<%OQ3 zbY5JrMA{S<5|C*rxjR?pw^%IF(iIeDi}hN;UEjwSe}bm~&q!t@P051fZOKRAE~3Yh aPh|cbbBHfwh&K!Bk{2a!Njf0^$NT~Y)!*X) literal 0 HcmV?d00001 diff --git a/build/hal.o b/build/hal.o new file mode 100644 index 0000000000000000000000000000000000000000..f0d70f9e473bcc1130d416450661b90fb4c4d922 GIT binary patch literal 2008 zcma)7&ubGw6n-($rnU7)RZtXNX)6)w)`kd05a|z1g0W(4>7f+5X~s5ov#YzCVnq=V z1O@*B!HY+|izg2rL_F%ZVSbdHUn=#^Lq9jYi|+M1Q)ALyW0Cz*IksVQeeIk?joG?F=O` z{K5D=%r+Yz8i(5E6wy$nOi_H@qDi1z7nklpqE?ZaxG@zPQ~fvNf%xm07Q?3x1ATLa z(bBvz&{uT)z_M*sG4d1BU9?%CxMkqRl)uFzQ`ei3>`-=|=NC;ID9@|k4t&G%l);00 zfvT9Mi7MKB;k>HOlCh%J%C6$b3x!9 zHiz43j?6{3R#Of?;kbb^^OG}!T+QMNO8l>Of?Zf8yR;j7pb*&{;i_TnC|{l01Ng}g ztTW!L>SZLqi+I+{0( z3*V$h|NxoSY(3kdHpAo_(wx0#50WtWN#Kb5*U^K;7p3nk|yIIG3#r*c^ zel%Z>-}5`xrAa>Ff>Aw1zZ#+g+fO_2=m_BQRhmyFX=n6tj?3zhIKEt~C8>jd&4#tp z%T*t0g~Pgx7$1!Bkrka9+gk!FgkR*8B^2FVQ#6zXK2Oy5qHiJZVPEqX&49=ooaK$4RZ9 O0`h{o0G<6~TK@-s(pH-Q literal 0 HcmV?d00001 diff --git a/build/idt-asm.o b/build/idt-asm.o new file mode 100644 index 0000000000000000000000000000000000000000..acd131dc91fc3021af372eb8fc2473f21af15d79 GIT binary patch literal 512 zcmb7B%?g4*5S~r3I%UV84&91KJM;iv3Zf3Zf~8=fCAvYKdbOYzswb%VbeFbc12f-z z^Yb~2x5Z{DgdlB#Ec!B{KsDwSj>w^g9{mfU33t@ij7iH-a8=%9w2XSda}$F@1J-3X zFUh&F<(kcoeIPV@iZfJp=ee;aj9PEVdE2NzxqU32>T=i~re=7hwUb7JezhK4 z53a4Q53O0hG}R(O_B1h38)yboe57m;_W~2|8VS0Qi6m%enFO7FlEf*zv~S{|aW7oW zOw@VIBm7sKM-@lMkuW&FJ=}FmnE`!)L&`d65^y6C%F=MGt-C literal 0 HcmV?d00001 diff --git a/build/irq-asm.o b/build/irq-asm.o new file mode 100644 index 0000000000000000000000000000000000000000..7146c0a8bc304fc13e3688cd3ecc248641ca7849 GIT binary patch literal 1024 zcmb7?zfV(96vxjK(&9qvz+gg9tO6F>^5lnQf`vu`BqbrygqZqT9-&QJ=<6eaiNQqU zV0Q--+4MhPba0oEk&)ysxVpgid+&RAaq}eie7~P_&pCa0eMd{HCC70j4oCXrFNrKh z7c*KXBq4X=*8fuOJ=hl+|%DC)DJwDudAIIKT z27Ey+j(FcF3U}io^b&moP|mW4JIQ|<(s-!qlu=csJW`vKjM|_)R%?_esze!63zTtH zq)aH6@>FFhS(Twos$t4AHAKm&K}udFDFr2OM-r*8sc+jSY3ZHye)P_J7az~dCwLOM zI(?n`o;prG@ZS9#_{9n%ANmKOrQYS5A~!o z+sfm}a?p9{wYQpnKwFv8+12^E&eJ;2=sc_QoX#(FF6un5vl|VYY1fRqX5KXm+*!eo YS8BVh)^5Af4fpk9f55Xk{FtM-2CbQu_y7O^ literal 0 HcmV?d00001 diff --git a/build/irq.o b/build/irq.o new file mode 100644 index 0000000000000000000000000000000000000000..4e1ea31306404e46166e765c4ac33317c8cc0fe2 GIT binary patch literal 2256 zcma)--AhzK7{=eDYrBn2b$$v#k)F3jYp2in>X-92lCfz=`; z3qcTc(M{Avbmv_{P=SF+H~j|%eGnu>_rdl)b7t1=u|(1`^}h3w=CoyuUtj+Y|B3A9IPT&m zIgdNISR#Q%+#1$>{A^we(}I`C&kJ$6upT~)@uh<0m8R9ATpTXs!^y+1d>EW!R?RO5 zL0060ipD;yRSk1^x}>UjQz5Y(fd{RUpW-R_`o)ahDIc`>)jefIpE-yc@YcmXcCdnr z^L^z)u5e5>l~1wK;<$%?=T#i~@2?}c_%DFfso1MZ3#X^JOuQqgN<13vv8P0hD|tQ6 z33JtQ9`!@)GH<$yE84?j)v(WV3RuBI4!+{x2?t+u@T7yM9emrt_Z)oR!T7OP4e$3z z0W0{4gP%G0rGpn7{K~;^nD26}I#^LJil(OYaq3S^^(XiS#$soT#6-+YAu^cESkZ); z#yFCQuA7%D=wfty(2N_C@Qntkf5I9vtvlR?)YKJ}mln(H|Fmhv+*+-zEAG z=izK2dv(ZO9;xf^LA@{Ur<@;+FDLFi^dxJ^R{P8~o*V^lBf5e4?L=A0sIgW- z^g{AmFc<%WjJrou6qToNg^rH5p4ufdHQ$5u8c4y=BdGf*VeZRLevtM>+$yD#r zgkc!MFGEy{KO{ttzR=}rhX{xYf9iiJ?ujFyS9JnxBR7iZeh{=$dz2x#-44S3k~-+o zB-a3vFsh*M58Sf}2HkHFF7}g!{(f6vUNsEAdLT#$0N3Ii+!J{@BQioRX=lhU+EvI8 z+EvQ;+EvLH+O3jLvq7Fb?o`X0uB(yPU0p4wU0owDxw=+eSkBa{vzQ^Q z#!(__6s1n3QR>wRly#~fr9t(fG^zy3dUXJ0gX%`vs7#b5wH;-XYDd|uno*inBT9>^ zMQK$*lr|-XS_9#k@cq+s5m8zwJuNMkzD_SD=OCI`c{>n(5WW*^OI>~*dV`&EMIC$6 z5z*pE(J45oG`Mp)Pc;|ptT(5;gc|?-V6RFntKhM2Er%7w-U~S?;v~;yhXSKejnl6;1h%&f=?2D41R#{Yw&5ppTK7b{{UYg zjGyXx!u7yYgxi6y5bgrLO1KyJ2I1qtc>Jf+EFnmnh;gPJ_4#gke*sl}68JgLQ#T0E)6 mlUh8f#gke*X`CmGdr61Kayd8>MQ0+dPnRe7{TcY@pzAmP%!}** literal 0 HcmV?d00001 diff --git a/build/isrs.o b/build/isrs.o new file mode 100644 index 0000000000000000000000000000000000000000..6c33f7880618a0621ce4e13a18acda88d5fccc1f GIT binary patch literal 3792 zcma);U1%It6vxlx!^SkWHjS~?+N^b>QOP7T`LNA{mZnV_X)7ozD%dcajCSp2R(58! z_Q8~v7VAm{-vqJXgAawOi0GS&g@!8B;)8-u^}!-4LW_tLaXtUtbK~?#-Fsj;^Sk$d z=bpKH@407j$F3>IambiMt@JMuebnCQ8Lhhk>ZBD$TKBo*KOXsY-O~1K*9m6!9UTqd zhVG@dEZk3j)oQi>(O|-6nidO9tAz$}HJc0H+)Q(Wg$7I2>^)enW||u)fSqYEi`K^G~E`OwHBHl3(YMSnqCXdtrnVf7Mj~EH0v!iw_9j7SZMCB z&}_8O^cl^$Gn|L2J35a1*|*qP&2=5`Im%u1bgFsfQd_-kxt-HiHP=zyHq3)w+)!=w z9{s$+gR}JmdG+^S+WEP5;oKPvx{ggxPEKS7a`{S>REBmHqM%&LjJjj4Ke)M4Zyde1 z!9;HS(n1pC*(c?O-)El6VbM*(0|~kFK@yOgk7IJ@N(&2N#BEV23Ek;ExxqLI=JsDF zkpDJgd5~I>s$g6Bcd4G2K}0xOF#N4ZF~&aN9FXCBi`0bi7=q`1VWe5u0Py7!=S@hW9Y+gi+Iz%U(E{*3~9j335IS44`N0KkL$$PcFxlm zxdCf{l#TDe+JMvV%W{r=Ej7@*k7d_by1k7q*V3KW-mZ9mdIqpr#m1=C<$up`dwp#| zuduY6R|qM|7~;+vU=JQr{E*^D6wfLyDPC0ky5f_H-&g#Z;tPs@P<%ykYifbPR{VtGg5raUtBT)Jd|L6RioaHTQSoKPEvY?+?_H}nt9XnVdjr=8_Qy`?Kg7I- z_t%rmC%GS22l^xCPnd^<7e&w5$PtCO9J_Ng!)_+x98@e4H_e6z=ECQbLMfUZrkVNV zu`rnql2CPdihac+iboZXDIQn+fa1-Hwgz~-9jUJ)^>w7aj?~wY`a04P9qEXd-Yh$VXucShu}7wYN-+_R>zZ6t zXl$uv74NdNj3&!Lyl;0H$HB89p-gf3a=Dv*3n%CY!JL;L7S4mY&W(hRf%!grL--V! z>(`Hk&x5&E{azTk##v4Dw{S0?MTZaFCia+b0?Zf9l<;0K*Ot!-9|m(Bc|!PIFem5_ zg}(%IefX{LZ(yzkuL^hb*>m{dZe)-7#=(40w+TN5=6dcK;g`X@D6a~?1Lh0;J>j!p zuF1X;{u#{m*B`>G`1*0U)>_XV^ZDRDURUAA!5N~w@ImmMM8|~R25%xdCHw{WE~4|o zm%w}>T@mi&Jmd5e^|Hr&E|~w!3E@Y<_YmzBegQl{bXfRJ@O?z5#eXIKJM<3{{R8AN B&u#z! literal 0 HcmV?d00001 diff --git a/build/keyboard.o b/build/keyboard.o new file mode 100644 index 0000000000000000000000000000000000000000..994a60f3bb51f98b83ffaecd9b8f95f05066b118 GIT binary patch literal 4844 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 literal 0 HcmV?d00001 diff --git a/build/mem-phys.o b/build/mem-phys.o new file mode 100644 index 0000000000000000000000000000000000000000..da17ca24882b63253be71be343d8583187f289e9 GIT binary patch literal 2396 zcma)7T}&KR6uz@RvP(yoBKF6hFcmgZg>9)AfoQbSg^&WNg>4_`Y6f;%Htg;+v$HK2 zNhKpDH)9iP)AT_fOnk9VK4?g-53;nO`18Qei@}6Y#fG|QDq_HfWIgBJxv*_w;!W;; z_dDl1=bkxt_RhI*TeBodL=1_z$rdA|+QU6{462As{6fkwLVvZxKAO$m@!AoY7F!GD zcBF*5qSv`6yWrgxmKp1`+kJF0yX3WQmA^A26Z4tug3Im2G+*PEv%k=}iW2Ld6!>sF zFghbWh93W}+_RgqYfSbtov!d%|48=3D6ppUlr7d~_LOux8%2C{8g{wL^b6VFy!KP5 zt?*priesJJkj;6o=3$KdWWLVR+0r$ZbvqX>^rl*6GlO9rXo9Gjd>bsASDe?&kA> zkzq)=v;j5H@FMJ$X}o!;(j$ZMrl%6OV?NtW4^_(G@nN;7z+)*?+*{4DNPJ>DyhuHj zJn&I^_a$lfx7IBWU5CZk+LX26vc8k-%wqPo>|gOu`zNW}j;`97b$e)oF7pmr%RZ>p zb_cOYa|iB-#fY@S75M zq=|;V(mOFV_K7~pn`B*=8s^X5!N-9kBP3YSedJ(AYg1G?96s6+Zc`X*RM63`C8G+& z1}mD?ctVRQY9gWcs%BhIDJKn0dwKsra6mb&p5iO46ttbDYM3BC-8Yzy_o@jcsU>w| zP)VvOP#TKfzo%L`sb^9#C79{&fvA?IrbeYI(vwM zp_YzFP1;m@`|&yc?CzhE2nGd^NyCf(~~B z;wTdfPMHpu&%s2!aQ~NXKWH%j0hl;Y_cUL!U-aR8#X+H~2i==Y!GEwm)O9$Bd2w6@ z9o8a-$afqJxE5nv6zUj+Z#(cp7wS%lAV8r*ENCl{q2V8Z5&t&WSF8_vjqAdE9~Tkw zJJ`e!`2-hOX!npm^TLjJ|5pNe;SR`g_pRY3?4sW^xHsPpZgR7e+jK*G5qxX-cpRV< zo>~FK^&<|)Z&DS^xWiuq#9eW2CoB2G5Ab8aFTljJ#(XirFJLAdeipDW-U40@P59FB zUj!5b`}zsYS@7=z#C)Fvy5K;l!@mJ6%=bNTF))5s5J2Q}Fl~r$0mOU+ZiyPaGD5wi zNl%^846`*A(+0ZqWp;-hV=MEH}eI9Lij$2_|b;nP$N=-NR@EppiZMaLgO`%Xe)$RU3mIplvE NIpiO9_!uJO{}<0j37`M~ literal 0 HcmV?d00001 diff --git a/build/mem_ops.o b/build/mem_ops.o new file mode 100644 index 0000000000000000000000000000000000000000..5a6a2f5641adc61c83503bc2c17d1c3d95a467cc GIT binary patch literal 876 zcma))!7l?*5XR>zrLoB_5=q0MP6(DrMY&QgjSJ<_EZNp3M7C}0+k}HSY?_e%58@AS z-iQ-=ajiIUlelmY4&uhl>w8frCYk=``}WJcx0@cOGYgC{P{kkuKMG)8ilhh(K@6gh zJ$_nUuBJPxzE-u2$^-AYpr?AM^&V+PaLs1!{rB9uRm0#KCM}UXFwQAe`Qp=h*r|uT z!7CF^s?Pggy7Vv;VS2a{Wx*vwE0(IqFM}KQ5}Wz-A4M>?z9Dvsv$KXCT3Y3nYsXhd z@!*OD&&>bGSv5Rkac*ulF_g{wMedJhwu|;|DUmd%%*nBoFU;g{Lj#!JzRT@AlJ7RS zr6%s|aWFS+ZiAWkJTMC-*L8~M6-(SP7nibQ9=8iS^j80>K1|W)jLI~9(-S!pTID=| zq+CSmJ4pqV8$_c6`>)(6W@z68HWlp~5mV!bo>5OpHe7%&HAqs1sta44Nt$wL8f2*) zu|=84GZd#tx^p`=y@!Dv!*1S}L6JaDmD;DYVzb{0Z@;el`(I4^n{Pt8`9#ufYOP=d rZ`UcEVPrRcp>8D2D^kai2iOBrgX_2(rLt!hXeyNV1>7>hb2xkhe|dMD literal 0 HcmV?d00001 diff --git a/build/memory_alloc.o b/build/memory_alloc.o new file mode 100644 index 0000000000000000000000000000000000000000..eeccbef6a87cba270c5a6dcbd8527f64bfe96682 GIT binary patch literal 2468 zcmb7FQD|FL82+=wEt{FCrH+Ezyl4U`u6Jv#Fa~0!tu3<~1Fap@EZ!t%S!{9>a&Mqj zH&4U8HgZ5e6jeb2!jmK7nLH!|2y}b^ft6m58Qm``~L6z z=RfD%d-B@E^wXhGh;$24m^K(uDdI;)B%~-tduhh|?fGYy?;4GIv~dXf<%=E@NlW7}tfy>*={n?-3y8ugy|>c!ZHkda(>qTYIZ^(HHk#zfSM zBxD(0^Yy>nS34FIA;%r`!wpJeLEg_xzhHr(AH3aLEv9k6`)B3r8yNWo))gQB#(OT& zrlE#AnmTMK#i~uDS+MS6}z+Ubuw~ zl)HxN^eoG_`sU;scaSewLoi=Z_w$imaScj7GIvUp(*|+xsZyzuvs{rkl651y=nBV3 zC7r5O5QbGM7Hp9pFf7*)cHXF*H|9mn79}HfY$3TYVD8)bcq^Z;3CA%o&`4D;EILp4 z8U9BN!5lm{O^%J7Fj6zwy6x7FP8V&fRxw7*$Iaov<8>*H4EUVLbQa65m1T5mK3>qh znkbpBSa8YATdqZB)^W(JRY2e#GKV(P5i)a?a#`3sf_GDxlc#3}9oNduvMYbol|&CR+q)rCp5Ne69>}Ygm1@v_b>%x_wWA`)H zYd{FTg7N^g4;a{1n&u6Ekwsk7*jJ?IJ6!gI`L69D`kZy$bUw{B2K5O2+15I6^S=yu za0c+riwn~|!QmX&Z-+03<;iVW!n8-$4&{A*dU@4{H^MSD*u_sM?>;UZ{;96`*)E>z z;?*vGiTTHz>m(!cz0noF%KZ00`~&94`9RJv!v6{5n*mN`QLfY$GZt}85} z(H%lC|EVmp(_h*yyV8$ZffG>-@)-zV8SMBsTBRBk`hxnr$QaB3aF+B3DUg$22i`~YJ>vW!{-pF4IKROAd5@95ml5+FQv6|slR%z#TE){! z&niBzcvay$K=xl%@z20}iEe}QhjRxQBU)E_Kc6A=VIb>MjPRdV`X!~mr}R~&-&Xp6 DS+C=M literal 0 HcmV?d00001 diff --git a/build/memory_free.o b/build/memory_free.o new file mode 100644 index 0000000000000000000000000000000000000000..11f8c7c59cbf128d6554cd4894f7c4437282b6c4 GIT binary patch literal 1260 zcma)6U279T6usL-O>O<8`kVv)u@t)00llr0;Cg+|rXYR~oX7=6Vr3KIP$c0B48Zx3?OG>F> znkH$SYQ1mI_I^ygujh8}L-w}iex;C|;B-G*fb#u!zu)h@Eaae1{-qyW`Up?2QpmX^ z+q+Uo$LxKbTC0EI-eP`jSqF6iXEFag_H|2`NW6}<7Rm_KYQ;K9#B8_N72BIS6oC$+ zct->(R2w=Lej+-dANs~uZU3!q$&*CYa`~>9t~ENL>D*lMLlsA&ByY+2nLC|SEL|UP zBAM(2Ml~2sJitwt#kwtx?i!LUWfaLql8}re5V+^$+)-L0*^Gifhdd&TjF#1v+Du|p za|?U>-?+v`9K~@v0Oz4>4#?X4GUK?-0iU_!AtP@;9S>iQTha0iBjUpV4u4&}8?3

onSUATIVI~>)s^sDc5;L(={J~{(9 zW*XY4`qGX_BmYF@pnSJg8${q8}h6-AM#MbeOpAsa}u6fDS$ zOiTB}kI$sNLyZ=v$Pd0xR4FCjCjU@Yf-3Uey+diQt=*nq==Mjc8!dN+X`E;CO>@(% zEUk{pWb>NmBBt0)T-*n`+~cN3x!pF-zHwsKV;76*7loKXmLxVsF3p@Z?I+!(!o`Cv zzV?6FWvIA{V?oV*yb3XaUrD?rPaWf{fj5A(j~>QPowtY#_5ae{ zfQIvlG|pqM8f)}h0X6?sgMie~&cgLfa_Sy22&OvXgeHNXKxUET4yNJ!j#)T)ecnFE z7v$7*o^r){eo}t^(me6VO$D!?z`AbHcQwX;Px+Lb@geTD$Q(9wDR2Vc`#PMpb8yyI zfoiPZR{|t|3cm*_{j6blOk6Fa(~R<3%nEf^T2-tL7|g* literal 0 HcmV?d00001 diff --git a/build/memory_init.o b/build/memory_init.o new file mode 100644 index 0000000000000000000000000000000000000000..1036ac1303a4cfa526c697fb35c914b49fab49ac GIT binary patch literal 2284 zcma)7-)kII6h52XCYv1I30-lR)*X2Q&D zNZJP}sg_|7AN>PF@J&Gw!IzYj#s@(`g@B-fR+Q$UrC9n9h~K$$Z+5cu!2>hj{m!pB z=g!lA<)#8PT`t*fJpD2(?oyjfb~ax1J1(55wAaG?aZnsbGI}K6`bY zGDLUY-N@wn;QjaZ&dyGF3#?zW17B_4_#=DuuN^2_@5lZdgSpIpaQNY_qAujJtZ#4B zZ$`z3QEfZiDz2l5$%%8TTisDDJ9qt;2hFE~SEA{@@V9U?J=}X@-M_qgr7N}685P2ieFq4xtMd=R*TQcE#xDieCrYHJN{NVj`XXH_JK-Vs77|dl4a4q$kPU%`%N7ND5 ze>bjQ>h|sJN$Sud_t~NPl)6l_)NQxMv8y+`r>0A?KXlg>6|-S?T(_=Y?v$Z+O4*R9 zo!=BNOLup^mzk+!E#B2N+4m=~%N8298&0jdom(iIsA=_P*Hp5GSe*(Fvz3!K<_It3 zGRU(CvwT>bfGFQHH7e|)L4&R%jEYkUDps{}x#G+lwy<4qRM&tnZ}r~%IqW!h0(Xpoiy^bg_*WQe7+}6YS`9dzUR?-+UN~kg(w?=uoqp= z@>Wzih;*!Z;q@9;wd&4V!R{0DJ$=jhWwVXwbfIw4I5Iv{bAs9nBNfN;Tw}mIZXP@O zQcWrco{c$?>95#RX)q)iQ(Y}mlzbvl2 z;%ZFL#Y8TccJn=tHTx(1C zllijP=Rcv>qVs94F{#hcJ)Wq$vUh@Wy~!sq*Sj5uq$&9(*si}0ZRa;vmo&8yk3*LC zado2Wykzl>`!XB&%i!$$J1+Jg18QM^!55mk24wq^HUioHK?DD|fq&Y-zX0bhd7lnq zwFdkLcbE}={R)Q^zN64*#7BRH5g*QVM!eLI81aAok`V{%YhbDq{})C) n?>p8b|Bs4qD*h|;$BF(`xXt(k&K3?F$8`WX?htd-X(;|5O+MAr literal 0 HcmV?d00001 diff --git a/build/mouse.o b/build/mouse.o new file mode 100644 index 0000000000000000000000000000000000000000..14f5fe2240e51b7d6f4db2d59c3410cc9b7a1d06 GIT binary patch literal 2564 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 literal 0 HcmV?d00001 diff --git a/build/storage.o b/build/storage.o new file mode 100644 index 0000000000000000000000000000000000000000..0523a7eea16e96b8ef536f1809bf97a477772a27 GIT binary patch literal 763 zcmah{F-yZh6n<%AZPB5ML%|Le3RbkIlorG_#4gpT83mIXtVk0`E=4DWB6tLUjhmyL z-24eHZXGNRy6Jn(9mc5-UcUEz_vPK)OK!~0p{8k|LW3;)F@SHm(41in3XlU!ypJY% zQLYMJ)#Ial94+6y@Ww;AAU>YR_w^~p;x#F!v9%^Lu~`%)wK^R=Yq41p#kgFJv4xnN zjG=892bG%TL>`ZJI~SfE_?0GWu||DAnu*P=gafefdcbW5kp~I(RmI&a4(!b4HZUg) zf%W{s!1Yk`eD1RLu~iSb-Mf^xnh)z}p?Tz_mFCcuHGwYc4Mg%~CBK)bK>0RN$Yaj) z?VyMH?O{?-zwKF-JZO!wB{5L}9#tWcJQORKYERCeiYrX(I!u3*PWb=NBc479@$`?&LLv79``l$c RFnn+52E60gUEk=3@CycBS^NM1 literal 0 HcmV?d00001 diff --git a/build/str_ops.o b/build/str_ops.o new file mode 100644 index 0000000000000000000000000000000000000000..5de848bfdc0c0f7950d1c3978f79668f4d0c3eb6 GIT binary patch literal 852 zcma)4y-UMD6o0X?Mhryj;@41dP*I~u3!$sjF2zMMiAWj)iZ(6H1?*&@6)ar^SO1D2 z;!t$zR>$Hjy6WVn?4pUeIIM_kzL~!dX+5(!W8hC=uK6HE{#fM8#(=${ zqXntkFD&D!mej7hTF~A5nYFLp(big^PF||xIHJ|_KX9GQ!q!$Uy=0brm-*|(W7n!x z(iuIgZ>|}BXl9lp4WN7VGP6pEtQO&sV9YsVpdVVy0=?vUpxc#l*>TZxE6mXgJLa0l zEc=9Z{8!ClijFPG({y$hoD;~L&m&SU!Sy{y0V21EhJyW9ZWS{$Zv&f(=Bzf=&N1jy;MUpO-HpL$ucKAUqQmG&d+2aGn!@rOi-?kcN)SyCO}`lNz1C6yQu zs29~DskVtC9kV1hR;%Wh)_iLH_D|Q%^Dxa4%wfby(f?Z)1IjL*VjOib;HX4Ybvdku zuEPGF9h}RV?Kl*W{pL6U{d2kxtigUu>@e*2CX4b1YVgkvp@&86c!!wi);WP#>{tSa zQk!5d--Z%&#a=`Q9D=~v36tL(^C8IkL%-wfm|bzd9VW}16O;Xf3l{Tbx*JFy`0oh@ zFTMd>rk$@U(Qt7&*I)d{NBG?5hBGk9ld2XJ=mY;(44nAbhw-jaZTgm7fc!#G!^ElS m>g^=7nl^MlFn-e6_CveXvwJ47Sc;i={7GYsLrh)+d2mm`w`!XJ literal 0 HcmV?d00001 diff --git a/build/time.o b/build/time.o new file mode 100644 index 0000000000000000000000000000000000000000..460f5d660480b264975490152aa8d40928147022 GIT binary patch literal 2240 zcma)7e@q*76#rhY{DvK6gTxz#BgCcfl*pYMC` z^WOJ;-@R+!vDH^I3`2Bb2un6KLduLuPq_*uB!^@Y2mMou=Tqk$8d#;l4cV5-MeO-p zBv2qba=A!wyE}1u=^4UBoIBiCkH-iJKWgUsfZ!995)4QxA#Xg(yAop7PA_Br4EGooCkLXIpXsdu*X@VipvxM!r6l$MW7Bj+4pEJ}k+n)pXl!Nm$7?{95(aGB!8zQk%O~x zAd@~XDNLxr2yZy9?$V@TrsQ{sYfk4Pw$V^^283S=HNy6!kjL_BlGb^)ek6C49)lI4{9#hLhw%yrGCMhxbd@`1t$L%4!M#b`0ea zSn3C_YJ`+z5^_$nVLbA{M0UeMT~BdN-+&E8&-VoEk*~Y|i&q95%x8dwg1m>5TlJ~i zD?mdY@=?wM56{pAeYjrGP`6L(1!xB3pqOB#x{!B7^&}rU4^giHJy95|!(hyYJ>C!R zn-2?nmzu94gODY#>7wV;bsbafMsf>(P5+hq{{b+6>Itap-A;zEM4kDRcqk%8SeOE= z8Rc781<HtYjLJ`vp>-r7c* z0IGc66TBcc`A})>@r%5N*nM8Hv!3@pNJv^--EDzxm&hOG`L1?Xk7}&p#X7IZ3tm?@ zW+E+aO>4o!R7&F(3i49Iss;Y70Pk(aYShNw1&%ohFn7Kp}rmF7nul - if errorlevel 5 goto floppy_yes - - @echo Insert a floppy disk, and press any key to continue. - @pause >nul - goto floppy_yes - - -:floppy_yes - @echo Formatting disk... - format A: /q nul - @echo. - -:bootloader - cd SysBoot - @echo. - call makeall.bat - cd.. - -:kernel - cd SysCore - call makeallh.bat - cd.. - -@echo ************************ Done ************************ -@echo. -@pause \ No newline at end of file diff --git a/change.log b/change.log new file mode 100644 index 0000000..bf6e22a --- /dev/null +++ b/change.log @@ -0,0 +1,28 @@ +[GOOD] BUILD 0.1.0.450 DATE 8/29/2011 AT 10:30 AM +==================================================== ++ Changed 'align 0x4' line above multiboot header in loader.asm to 'align 4' ++ Removed -e option for echo in build.sh ++ Modified build.sh for linux ++ Fixed triple fault when enabling paging ++ Fixed page faults at memory manager initialization ++ Fixed 'mem' console function ++ Added more info about page fault at crash screen ++ Added Panic() macro ++ Added verbose mode for memory manager + +[ BAD] BUILD 0.1.0.390 DATE 8/27/2011 AT 10:54 PM +==================================================== ++ Added stdlib routines, separated in different files ++ Rewritten physical memory manager ++ Added virtual mem manager ++ Added memory allocation/freeing ++ Added memory library ++ Added temporary allocation (at end of kernel), until paging is started +- Removed functionality from debug console function 'mem' +- Removed system.h, the one remaining function now in stdio.h + +TODO: +Debug initialization +Bug hunt +Implement verbose mode for memmgr +Fix function 'mem' diff --git a/change.log~ b/change.log~ new file mode 100644 index 0000000..437ddfb --- /dev/null +++ b/change.log~ @@ -0,0 +1,24 @@ +[????] BUILD 0.1.0.??? DATE 8/27/2011 AT ??:?? ?? +==================================================== ++ Changed 'align 0x4' line above multiboot header in loader.asm to 'align 4' ++ Removed -e option for echo in build.sh ++ Modified build.sh for linux ++ Fixed triple fault when enabling paging + + +[ BAD] BUILD 0.1.0.390 DATE 8/27/2011 AT 10:54 PM +==================================================== ++ Added stdlib routines, separated in different files ++ Rewritten physical memory manager ++ Added virtual mem manager ++ Added memory allocation/freeing ++ Added memory library ++ Added temporary allocation (at end of kernel), until paging is started +- Removed functionality from debug console function 'mem' +- Removed system.h, the one remaining function now in stdio.h + +TODO: +Debug initialization +Bug hunt +Implement verbose mode for memmgr +Fix function 'mem' \ No newline at end of file diff --git a/filelistAsm.txt b/filelistAsm.txt new file mode 100644 index 0000000..ab982af --- /dev/null +++ b/filelistAsm.txt @@ -0,0 +1,15 @@ +Kernel loader +Kernel/loader.asm + +HAL :: Global Descriptor Table assembly module +Kernel/hal/cpu/gdt-asm.asm + +HAL :: Interrupt Descriptor Table assembly module +Kernel/hal/cpu/idt-asm.asm + +HAL :: Interrupt Service Routines assembly module +Kernel/hal/cpu/isrs-asm.asm + +HAL :: Interrupt Requests assembly module +Kernel/hal/cpu/irq-asm.asm + diff --git a/filelistC.txt b/filelistC.txt new file mode 100644 index 0000000..17b6b65 --- /dev/null +++ b/filelistC.txt @@ -0,0 +1,111 @@ +Main file +Kernel/main.c + +Debug :: Console +Kernel/debug/console.c + +Debug :: Console base routines +Kernel/debug/console-base.c + +Debug :: Console output +Kernel/debug/console-out.c + +Debug :: Console input +Kernel/debug/console-in.c + +Drivers +Kernel/drivers/drivers.c + +Drivers :: Complementary Metal Oxide Semiconductor (CMOS) +Kernel/drivers/cmos/cmos.c + +Drivers :: Direct Memory Access Controller (DMAC) +Kernel/drivers/dma/dma.c + +Drivers :: Floppy driver +Kernel/drivers/floppy/floppy.c + +Drivers :: Programmable Interval Timer (PIT) +Kernel/drivers/pit/pit.c + +HAL (Hardware abstraction layer) +Kernel/hal/hal.c + +HAL :: Crash message +Kernel/hal/crash.c + +HAL :: Global Descriptor Table +Kernel/hal/cpu/gdt.c + +HAL :: Interrupt Descriptor Table +Kernel/hal/cpu/idt.c + +HAL :: Interrupt Service Routines +Kernel/hal/cpu/isrs.c + +HAL :: Interrupt Requests +Kernel/hal/cpu/irq.c + +HAL :: Programmable Interrupt Controller +Kernel/hal/cpu/pic.c + +HAL :: Internal clock +Kernel/hal/clock/clock.c + +HAL :: Keyboard +Kernel/hal/keyboard/keyboard.c + +HAL :: Mouse +Kernel/hal/mouse/mouse.c + +HAL :: System info and tools +Kernel/hal/sysinfo.c + +Libraries :: Character types +Kernel/library/ctype.c + +Libraries :: Memory :: Allocation +Kernel/library/memory/memory_alloc.c + +Libraries :: Memory :: Free +Kernel/library/memory/memory_free.c + +Libraries :: Memory :: Information +Kernel/library/memory/memory_info.c + +Libraries :: Memory :: Initialization +Kernel/library/memory/memory_init.c + +Libraries :: Standard input/output +Kernel/library/stdio.c + +Libraries :: Standard library :: Convert operations +Kernel/library/stdlib/convert_ops.c + +Libraries :: Standard library :: Memory operations +Kernel/library/stdlib/mem_ops.c + +Libraries :: Standard library :: Number operations +Kernel/library/stdlib/num_ops.c + +Libraries :: Standard library :: Ordered array +Kernel/library/stdlib/ord_arr.c + +Libraries :: Standard library :: String operations +Kernel/library/stdlib/str_ops.c + +Libraries :: Storage +Kernel/library/storage.c + +Libraries :: Time +Kernel/library/time.c + +Memory Manager :: Memory heap +Kernel/memory/mem-heap.c + +Memory Manager :: Physical memory manager +Kernel/memory/mem-phys.c + +Memory Manager :: Paging +Kernel/memory/mem-paging.c + diff --git a/floppy/floppy_mount.sh b/floppy/floppy_mount.sh new file mode 100644 index 0000000..6c3a21b --- /dev/null +++ b/floppy/floppy_mount.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +case $1 in +-m) + mkdir /media/floppy1 + mount -o loop $2 /media/floppy1/ + echo "Done." ;; +-u) + umount /media/floppy1/ + rm -r /media/floppy1/ + echo "Done." ;; +*) + echo "Usage: sudo floppy_mount [-m/-u] floppy_image.img\n" ;; + +esac diff --git a/_play/fat16.img/fat16.img b/floppy/grub_aux.img similarity index 93% rename from _play/fat16.img/fat16.img rename to floppy/grub_aux.img index 54b8e030c42aa21fa37123cb9fc82078e4da0baa..0b0dfbb03c0fe6e9e47c2c4e5fe2ee3098e57a7e 100644 GIT binary patch literal 1474560 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

lcfBU)Q$w<4O z7OJu423+lfkh*-&k^B;pahW4eT(Iyhf97l(r!L>KgovZSF5g-wZc|0a*RdjiuqP?E zJjSf?aaHWi6pPo2uiK+9F%Fz?TodxlvHJCsmV0h%7Pp|VVK8dOROh_%drPPQr}V0ao87^SI(ce({4TJpVcMv-0z~FZpp&gSdmlf2XpYg zv$qxT_2RTlhD3ILc-3*)583WNUTOB(O`tW8ggzCcID0xPaQ5dEEtDKExBbKEmakO^ z!?1VkaDKC=?NVydu#jc)2RX5(cHouncwkg)vn1n6vw=>(g_)r>7Za3@;;yzCq$Y@k zZm%&-8ld>?;y3W~Pj1u=ns~@7eH&*X=(zu6jl!qRs{%-X#GV%5uu3L3JnSn+2HN(J zRi?l^@GUvxP}}z)OTj)j4iR=@KvlIU`OUuxO`4n0Oc~?>aVwu|~Z)h91HCO!10s*(fl-6QuKd3}7IX>euxIKlM1 zv+eJa_Kz*L2Y{Z#*H%sXO#9X8o=+6>(@)#C=vprb2Z$WI1d9USS~-H55#$PAPw<|^ zQ7EiUjQTkeIy%E86XhejI@fk$?623G}ALnn<`0>M&q_CNCb zj*k3CexI}3yhDjZ733A;_joohETVW?E88yQ$0)o+g2Y~IALdp9R~2W2+BX!GXmR8D zq>lLyR?5CPXKndPPLnXRbgiQ2y2z?tc(h2_;*zXBJ2~yrbfN+~k+s@3hI9_16rJ4; zV-vpzS&>Pk(ts1MjEPqWONB(kd>DCB5za~Q)ZZv+&*{;cXOmK{BqgTQlFokCUH(Pe1ih)z7wO7h{~1^ zc%xkUvt$p&E%zE(PH7j>OpP4(eQw9OPM3A`o~ysrk;uu}k9l3;F32g~E;QA5kt`}< z_B)K_xyFszCGDvUhleNgq?xqm-WcBT!ElxF_#=lpcIH2F2p=f#cO(kM+$v{(e76HA zIgze=lMmK@C41uC5?r`fo(joLQs9s=qxSU8Yv2#o%|;fBy5#bLyK zt3=4v_o4oKhRM&Kq`0txIja6ncJ^+|9=$wwO6{?6-0UTZM9ETVX8%+rwT7GGS($?x z?V+|IrHX%2dsTP|jZ_)fO^2(q>D_BmMNBfH66dsK`OK<0HFAyGV~^~L^lBVpmPsvf zkbHV~;$@+i^`a3sVq)j1W1X4m^3HfKHRj0VTBl9pf8|?@KxM4kHlnGtj4;)fv#Gh^ zf6}HSQzcuO#wD(JM&Uf^mJR;6wqd>*@3+f%uIIzJa0$a7c3{raryV6AILbcdd?R4q zF*%TVegoE`aThS!1iy$mro;5cyuVXaD1*x3>s%3=_QyC|=^Vr5!dKwI%)V^h`Gk)s zndWw#2B^+;I|dnvpF>o}{C3B%)iYlfIh3EoGSpmzP?)$w5+L8qD=;eYUw_mXW8CXS z!iV`9h0;v6jH8LG&+oSv1CE*M zI)%*?|2nuJH2Jb|b+&O+uDKLsD$Sq#Co3T?*xi+1%o)Ey4WzqVj8m-pxCrL{yO;a8 z8D-gBlp~aSHh2tDK@@}3O(41zgH#*QT{fa4r_^GNy0_yYqTKzswUsi0 zW0~AoIab_=q-cHWsqGydI;z*2dWh>$a$ODi=0_lkIVOirqL0FLoZ7Sx85U|OT0n}n z=}-W@MgO?A>_vZ2>iZ@kD{p2qoL{yj_Gr!X;GVcX;M=^ML1z?-zqh)!5j-DxS7?{r zm-gZvoZBaf{Hc8*j;ZqLP-k4A4Kipqi!g9J`AMR8CsveP5i5FF*YT#A_D?~Sw%k4rJ?WNe#^+fv^Q z>b3Gb9I7ePW)7|MEjw0`-TA8D>p2cXi>pg#xqV8SYKQkWUA@&HflFjEbYWea?2Ran z5^2wh^!CT@{kwab5Khedjksj99_M72m?fEc^rq^oRApr5&y%QI93Cb-U&#VXw+MW& z*WFwIB0Ezs>`414RlrI6?4h}hvF@2BWyI$AmZ-uObCf@+2t(i3=^cI6j1W0CTh9LQ zreQEs#d&P@g&MsP>Fv`wYo8~)(7*uuZGHYaPq|`; zwMX^OwO<|Y`S?Uf5eDGLIX+ywOAqZXSKnQv^N;!OheMYFS2T1_8D6XUy)4-nF{7TQ~GXW z=E~8fJMVY49+c&ACh__N(VM3=>=@H^n}^Uu8@0W+Aw0}KSOdo~YO(!4ip?(@eR*ms zn;;!V7?E}nY}ppzmeUAzt`tZA7rmw_LnC#C6&T| zLK+bpvBWiuTOupY(#u~*@K9At${=|ardw)7_%{7uJ7y@P4AyLpV}`@532|-@^71!? zPmRDCEmqPtA4~EO{;^~eHkFyyc)kun)TyI=hM`Ads(|FhC+k;nKoV{u0 zH)hu?ar(DZZHkAkR$L%rX4_*u+fIIWzgRvfCy`6rWL!GE@8m5OUjR~A7_5yvnMh08 zH)l%~e%0Ock-c2#j*lma`5=^vkPD1WNlsBeva1f8joeM2rrtv(|BSEy6K>9JbmAt> zLB&FOECXLSmR)W8Ej1;?xb`^$0iguqQah}SQLqf>68VxatL!gW7Y{nc7>j9f;ZW1! zD)ZM!|25WBoYPHFN02!k3cdBRe$jgnI5>Wl$-0jj0*@HD@Z{L<9@vtU?@{HmnG#(= zU!@kpw(~^euDwq z;Z*}jbus?{SCg85LyNxz`{c#J_oMABf7l6tt)QQ2yAv?7w-Dr4{uDA@zF+>>{_OI- zF!nowwS=`Lu|=p3LVsnFNQv8mm24Kdj1ZqD;9pYDs7eja*kg(O}1lpP#Z> zMd3K|7$@H1q#5KdwKMosd*U@d!>c~d4h1=X{lekUJui5JJfXf>9ljHsxF4+ zH`2(+uS4yeYbZjm3q(?>8jrpI$ zo{JaqyXt4-0;nr`uk)#|evCKs-yUTgZH=f_7`jIFOPAEkmH2O(!KfW$jMLYwAfcM;A}iNC$L&L$>&{V;VBSw3zE=6WVl zZ+$FAm0WeLnuOJ)Mi^%S&%q|@DJk~l=uv(ubo+BonQFBAF`g6zjhLWza(~H*(wJ1c zD=K+ZIol*#S2WC1{`A!W^)0JDiSLRAos?bC+nqPffg(!71Ylg%q z7#>w}>1ruYUwtc2?Qt=XGh*^?sK!Fqr5Z4)%GYC3w!TKn(W5myOLs1(Yvj!?tt)yn z@6z;B)+i{dV7g(or0IEHVk`930-#hST{hcLzq6*Ol=Dh^boFgS1+Cci(dQnxfOdUH z!$cwhr1=w|l(jd4bL{SMnG9P9~wY$3`Q*bwh^;bGm9U#WU?hMoe1J z<9m)FK~WX@{DQc=8!BO>J==(dNxZ@MaO34>&JU68=?)b#m=`{h8MJQJHU+90?LRuU@dvP(a*H*GSWr zs_sq9gF&>a#xi0u;=US{KC&USbjF%vLO!|zSlV@ePNypE4y)2Qx2!t*f$>~#MYGlE zs`#<(C%ZZ0Yhz@6Rkn@ur^r@#8lBdHS(x$I@al}*S-L_JQa2pBl^$08Z_~u9T^v$HcvgS2U@e(X>=v8%Dv1$wJ_sN(d|84S2Ci+=yB<&W9%BU+wViNb*JWDCMH&_O~+oyk%1RRk`WR}JAOBpBPXdT7-34TkdaAHdwlLN zIQe0s66L(5=B4Nre6&f5QlCuK+GFnvSl?P`PyPneZ6Y{QuBJ#W`V)9GH*%966V{&+ z!zHL>U{}M*W=xX_77crj`A6i8m$Gv@^}g%g`8d++j!QP|@RsMBTZt04z&V|fo!OS9 z_eHFXNUuj%!0=rZUrAEk2Gt&V0GEwN`Xe7?^?V!|(8#{(i`nx#KF&u0$b>JL+Q}B4 zo$O?{N>ZvO{M6MQa3mL*BUZj$pp8VNTu|VygufEa)>RWc6{U-)7&Z^tKI(LQpPAbK|mo3;tm^MTLS2ctzkw4W%4qgu2V zyh~1$t(Sxk%)p@;FmFB+rctoIA`8OmkMw5E>G;GGu{?V7>Si+7+3tTWa(dMALc^<) z&7qYgj^=S$A8zL08Z9gVU)EWoO|2hoUPghckM!tDQfkp_!OBpL!9-4o9=(@mn{>1s zUULaL(I7!x(G@(UEI1Nx%#1v>NSNA|O_1~tFKO3?NaX8n8QbbjbIdstpXKpMQIpMnn( z6gf;wWpsR!5t}{CQ>H4QJ$fH_#qP(+3pYVsE3<|Ihde=s8}z5nC}V%*^vF=H-6b7( zlmF5(vgi%^WM~-gCjs9=v5nOtQ4~0xmA2 z)L1Qq5%U@W`TF8`J@{8AYs!H8%LiAYyW;;COqj0+ZZ*;Md#eVPDHG*D!EF_pMf zeM%BRC2>1X#5SqAYPiCEFH!fry*$$+;bw`JWnb?m0d3|gt@(ElpepI-pPh~MU`g7>MP9o!#*acU=FKR6Uyn+w zlueUX1J!ST0YIwS!W$;9mIgb!+6yWD49uNs7k&ZOATs~F+Nv4{KK+tv%=Ox>(ehsL zj-;As&TPcu_nmg%VfTJwGI%vTFN7c@YAE6<0*4Yb1aLrF)GOWqnN)5W$P>Om+>D z3P5XE066_>_o&s=v`umgazQP!O}Yk2>EEb{c)9M*Q|=_0o~Z9t^bI z+f<=HjSOT53mdZ{16jeKRT3E(790~9$P13ME@~5?I2)~<7ne7yI_Z<*todC&`IbNH zYGay&8HEz^y|*gco@MyD-{IoVnK}D(6_mJeEqDmN#!^!Gbq{CQ&yvn-4wNUS`GNwHyscX5l z=Hrq*E!`i6ks>y)C)L>3A|DhXwoQHv-Syi(h4H`?}=c7S^d*7x!= zr)P)z6w8Iv8uxhMl1Bey!_E@9q==b;6Q+~)pTvjcu^bFp0HWDIBK|&~r=UrJ1x!&k zGtTywtw0lCbIydeML`q6`toX=f%cW`7Xj7ZH;B+6oZD?Uo4y=Qhk^qbusYeT5CWhL zD=SsGL0D^TSTBD$tZnS6xp&8<8QB`f#ky)%|3UWI;?kDvoVxeLrD-F(#t%8hbQ3l< z`O?-sdY8L9^5?7K@)h%*8~aI-1k*j**;{M8o3(Wsh4~a_x^D>A{ z?SaD=vdc!!o&@He^@vQHFwBuDh@Q(rj`D24AUcLU!g3mCRxr9w{lnUnmph#H?8OCOLAiKz_d{=NvmH8B*i`A((+5C81oMQ*3 zvS*7sCv$Ir>UY*m2_0Nw6%U4PCsaDc@uATv^j@YQ(Obo=U2x3M=Q-k6mxel6SZF1?>hl-HRvlerR-KK@Oadq=T`5(Z-mg49IyDLcYcmXkL7+VC zNB0D|IYp|yL}FwqoQ@gpWV%YC9Ml08%5=gnCVZCp9M7f!;kJ60_V`jb7hbGl!OPts z8`>9}Ju#P6X~+|s>(e%{7dd-kCQLP_L)+k;h+F9{|6V~Sr-LzLOj}Do2_eKPu>R-{ zP9RW!J#zRe@p1bmdw1e6)Bolb-gAP5)@|&%SMQ7TUe)T&Y{{@AI}(|gfhFhfjwW@bQVX)xXO}=9vhOzqR_yqi$cXd#sc4s#wcYUcdhFhheeOlR50e@Q2~lcr0_QS9o|s_fX+|ELW79|EjtSPEq>>xq2sX}GEmX^F6s_PWxWqx(X|t+S*1 zooxSbvi-d>P*0M;cX^l#Y(%Y0VKmELS9MHH_eyK1|H(YUprO&()Xmbi7YYt~w`#ts zl6JF`NMin`a?Yz%WoX+cNGerAK;BFXhLpNUO?qIVc>RNaad|!cvM$Wk@%&;JI{tUA z9L!|0K__$Br&eAaTkBpz>eyi#jV;&1kYCe(HD}04kJCx(KGm;v9cH!-$?)d`YPi2( zxPOcQ?uy-%A-}_8H+lK3(-kRkx9*j6t9c%eiqLVSQQ*0P7jBW?k`sY3TVa)#n=RkA zjfjJfM|NHs>AV#4@X!&}D5(|_8_x1xra2KPwB`>5xq+8>2A4FR7a15E{DH`QV}jqd z?uiVX7p#g5j0?`SzTGsiOVUhj9Mv@Ns=S@wG|(=;=UD!x0dW<<=G4G`enZn-CMpUKX+|eDL+fM%#fc&TdtI!$}LOf=bA0cB`&YSKfx3b>71b*{E9Q@YXsfXNH^Wgl2fz)6MCA!L2n< zCD@)j`pidYIoY`$M;NZ=1ngYEF4i{8$+^X7@Ky$fe@58lgw?dp8NS3=>Yb6bj2o}p zD+5;(V_k#mo)y~0DlcveN&(hXRyk{arQU&d1Gua0%ZoEtwdTM)Qa0L%eEn|vEj_7RI17JkdEt9Q)ABz)#&7fDRKnO+Cc;l_fZj*rH0 zI}i4N>b0eCEm55huU!v(RqWi@-0WEBC_V-knk(2965(!ceynzHr~jC%K9~ChzGH`W z`g>i-cTWi>TW@7@+c@_ENxbONM86_1m#h6WFS2bQL>J6!%O|A69D}fHWv4#4Ae2y{ z-=9B|!x})+U?~}XEZPSd;p_yPoeP-adU=(O2 zt-0wog})?&s&>rC8k+2t!DRn#CkrN4{i}jVUCB!e8C;c3LGKO8XIoN(3U|7(w1a$y?|4)z+WW& zRit06&Y`zSv(*;`wi^hm;k_%T~HL(aIrB2`w)Pi^D05mb2HIr{4zA9_E2^*)I>bxhl^ zuj5Gex`z%b!h>((pJWWVN9LhZ!oxzNH;a26Eblaz`KAgAj<6RR<*Kw$hWM6umTT}@ zB&r^c8{soz|EfYfUBXO0=d$oD`}O0Q)}Qs=Y2#(RtL<*4V3j4ZqR17@tam3Xi|{!X z9I0ZQzzhO!S;VESYZfsz6>Sme*WAfFz0x|uxo0^tFwfQx=kpfw)}LqP$X&~Gtc?1i zS>|d|FOCdc+wk_H`fJTfS^Y3CsY`^1+HQL{sg~jach#l137$iv z^_8wNs~G6!r^GJikWECsu^*4@73$J|;%HGP0 z&~v0*-q2Ns`7jqC5~}^o;9t#07bDvRbIhMrbDz<;AlF)}%qu=LFC|r(e|PYpo%9db z_W(n@eZ>H!`*(8{L}gsU0+mw1XTf`EjrFT^sn`h-D`=<6Z~h@!&0#bJTa}Ics2bcN zRR|Vie`#=;oj==bpyia;N4fnVx88+F^btX{ULr@JrAdBqy@w0sw{udiX33U$R4yRm zpm|6F0@76GUS8?2&jKPrs!e~hLt@x17; z-UHk?l!v$S63hy0BN{&~tKO84OaI1)FVM!1SwR*Ba)OVSOU zn3#!0Y^ZyYax9e$?b@Wq{P)EGVOOqM^N+!vcStDJ-`_Q75GVazYxnoURDUbOp&gi8arm*Q4zZ z<~apxIyxS^ZmMc|ivqJwlI#ZZ-?G%qCa<=kFNNizG#e{wL8nbCQ&v(9m^=r$h=90-ZBn`A^7PV_@KBj92&c%}HRVkZ#W49H>yHr(6; zRO-)exChQ);mJ8GG%j+_uG|M_dsgjoSc%?$vb&>y;-oHXYUH#hG%MoA*sgk4Z1xp` z*~;@6kDUI;LAsp`vvBb*vkL*}i)5BX<%P0^fX|Pd9;RxX=hRq>Mxe#W>CD6;nlW>rWoG&)?Po*w$lSp^u z^f6PXK`N`xQFy3x2#L>B=ia47eWanmOAd7T zWf-C1d(#ywn9fQolv_^^zKNq`-ds(c|I4C;1~gZmpfw;0!@o6&*Z%7ER&Rbw<{Xgt z%Pd97+@7>GJR`#u`d?}`M}oBI9Ux(TpH^ago-a$Z8Q2X0INpqfunoH{o2u5k<0}cN zrvmf5GzS<3q~L`Cuk`y55$j=%^iK3LYJe7V->mSA%Uq$8;?gX4i?l#zW>M!HH>kFA z9L?k3TD)U{(5-u4rMZ>HtHQ}myZKw*rqphA%ckC##L<&N>UU_-a~Y6wxp}U6H%Q*H zH1Rqy<_4OKPELaUVpYSUA>-_xztJ2x63iF;c1zab3yMoLs`SPY5j)0TeGSDF-Cj%zzN>x0%;Vhvv&^{uTM*EfUL3HMhX{uCqSgbUPV4BMOq*2a&hH9ot0{ z`YN4agUI@!0>L2pS`7X_jKhAF<_8biI<|&_nE%ayAkpc6k8IzgOP1bd?p!6!qYO4E z0@a-0cBZUozWCtKG<1yC{Qoi#JE`F-2v;QsN{}wqn2Gt{5Ig*PoHDt>8KABHH)iAo zkIu*mc{}}Y6h)K4!vC+mI}fb0uJb+qJEbfwOQ5#T?;@-V4M1By8 zR!~ok{Yj;=+@|Eb#rHLfn$DJ?C%;?Dp4j*?KFRmrCI-)qZS$5+`+8nbDQPpsQ# z-;6Y9za4&Hv!dq{RUH4t%yn8@fA>K{^*68E{c1g7)1T@(uKl?~mLoi;r;%!`IP5!&Px|^PT z^gLaTzA4Glry}p7E87p>enI@bLf5YzJ2dm)TOZb<<8ArI4TqbxC+((n>|bZ9`*ioA zu@$z!H#(AfmcEH(>GAuNi{IXS?^!+v_{y$^2W_>7Y_6(4m4rV#N%*7s3((2-)+c5w z+Rx$dDOKoI7{!~HtF2r9;o(0M<&8IuZ&6v+I{t3`D+0YZJ9VjTa^Ugf*8cRmuEQVw zcYl`SmumT@PdxB3EwKmGYK`iB*?Z1b5%k%y$(u`a$0qgNCI6`7+;hU%;pXM%>^!Ms ze`@?onsF%gdjB`&wetS29&CAL`K+CD^-Y|QKJobXXO10SJnOUfoUs3ij)SdQaNGF) zIqRDJHwgOuW=b3PG>uKRmsamNYix3H>5b~-o?KYEW#SEElgmnj6Ga`hbc4;jxwLvB zGd9^%x^&|8W0M8-NuM${*+FWfLbJO6{GPv42kU z(%;nm;Y>yTkDEpEwAe;pbRE8XrSjC7$0_gcI_$r_P94`zZ2IH_e={BJw1YRL)IZQM zHhJZq#bc9;?ikV^@GW)kIbD(F*0ITRcK3`;o?BXG*YjF+txsNjht9uVe?)GwVImrv z+*(?07uS4y``F}`-HUC0`u3$`lW*LuKc;<0>HLX?Lo;qZ@a;p#WhSnTr-~ETXsShF z;`05o4}5!K$)OpqKiJ%?srtt!Pttsi_&o6KvBws->_2Y*=N_A!snNumr5XEYv>a@< ze|6n|&}>EX^svwc#SRoXN|TDJF(e* zo|YZ{s-LazSo6{M&Y#|=g$LEEqCZR8{wDo34@-Lb@mcP^FP`f3*MmRauF_q@Ky^8K z$Lo*n^UAYMIa$LW-tr->aIpQ!TP}L4eXnh%+DZFkeL`LTvA{`ntPL)I`gnyHq+%xkGm;UD}5V7yH;{A9`=ZKJ=qEdn!{y$yEDW zZIMb?y$4f&;H!^5s878rSGVtK<*4_ZtjIMs*|+C)W0SpiTs=0~Sh{-8tHvfTtlRfq zZMElQ#kRVA_iJ)Ov8_RmjBc^iv|()W#tD6sL9ukop5w7OOS=~5-9F1Ll^;xuj7@H++xLL2ewq?`-M)|c1?wkn&^;<$ zuS{=Zt?p21&7SkeCbM<>9=0`=Q4Eyw;~(^^4wWt)n;f2)r(0Nh%^uy=knC=PP3|t;II(l8eec8-V|VO#yHCD%>;9+O?tkobMRl8dv;Kfgs^#FS zXU1NbwR8P}wfnDJyKnc(18et9w5Ulpv107AGve4k(bRHJYf72A?(u6{?wK+1{8;VW>} z$wm6Ajf0z0W49lC(%pOd!E0ugW+~ks=sx)5#ED_zK8Em+*Z-w@$39nHaPQi^ox3hnTJAo0-`M0Cdrm(z^KT#iq#hI;IP-5G(C0Osqd$De zHql?7t=nfWcHDE~@{7t1d-tT4tK(0g@xm9&??K7zBk#b zhwj>;xZ)1HaOf_L>#?M*!7TPMXdikF&OY>`*Q1iDY3aIYDx~YBI+t@SU7w>e^VsRy zvV%BX-=)ckUQ5?q6E|DBZaHSUZr=auj)|WAuWnYl_NQg(+DDNB=cPpo* z--~VDBc7wQpoXDB6Q^2LiBq-dHk`2jSckz)oDfdbr&XJArQh7rs-3^3)i2dOsz`Z( ziq5*bzoF{w)J1nKS8MD+%k&R!&?B?$y65%dAJd`-?e^PuqwIe9st^^H`zWG%x8A_F zNV0Jv?^pWd93>B}_p0gZ=}Tc|`t{WMm~r5<8xI$*)=8)}_{cx1Gjgfl^i#jfrcZPo zzT7rF@1jA==KaYYZzrm6@w>{GDz&pt(W)t5irqB+{0XYsKiZtqH$Wd;^`)^FPO7{6 zdzz(K|D->>MiHH@=wJ7iFKBL@1l;)7tue2JG5#q{+;g4Zy5%#f$X%|gSktoySA8aI z{MhbS>g$&eoaNKW@~>O^F`V{8sJxV9UFfpHp{tzdswlhj;yMdw4+K z0Xe=%o7J90ozCLkGw(XjmYu0HjQ4(0*t;ze()cfD#<#HU(d$x{#Lqf1iTj&+aCFA_ z7qyeP^cIvI%2!R#*wMaMG5RYj^*4AlfNAeNFQ53aKW#7ePD9$dH`(d!#d{hW)yi}yph{o}&l5_tr?rXu*6jlXit4cA-_d8h z)#tUBFlrLug+M^e>muwL29HH2F}eo)7%-uG8d z&m{B>Z1I80i~LIJN_g{C+G6@@b^9*Xykyn7edp;n-$^~LuWZYSNu9YpZYglb0tQ`l^Y+G$G@Q^>Qq-h?tNp=sORFou{%De-q^=9d#e2% z<9gm6uq^&hkBueuEr!%lch?_jHI)gYslB866FB~l$nCwlzFe=bPg#C-S&x&?U4CU* zUnIGE$LfjGmuEs>*0a7Zt9+x@Nsax}lqy*h>Sd01Qd(m>IHR(IS=zzz+QG%EYgSjK zTLXs5Gd{96DZBUYw<7VtSyq&5hb2Axxmvx^esL(*-N$W>q^r}dEf1BlJ^6gebrdq0 zmaaCJ8R~cIG9{bbF;wmw$hdT4zFczAP&QZI70r7?=Wu!;GcVeaDdaLkQ7NB~da?rx zqf%isnm3%@k%@ZZRc5<*%0*GMWsPm#P+wda6*Hys$cn|g>UU{6`-Y64+&bIcHjrN7 za{0n=ddQ`VJKS()c!l4zzNqb7Lps;j(3dWy-NI-npYBWd^%dg1lrpUW?sw(F`0 zHVo(c%0rpxnkZbF{Tua+mNLb7%^;A?WlM#=W3P2vPiCZ$@5#7iLc3qz*1pwku({Fo zE$vY@*Kb0lY(Cc*b@oT4!AztBXQEtrxF=JHZ2c%(jEW znjJ*x9^KjMBHK@+E02t13bLz(nCX;zQ!nO&W%RJ(PAkx9NE3h6pK+Iog2{g zq(_Q=?Y?ZWH(lt{+OC`%%=TsCk7z^l#_rDU&h_iuCO^MAL*h~IP$pf-<_7%r&ee8( zncQ5((vl7zWlP0qBwZ+FjW8;Wj%1=nV~R%zF1UCoY+jPp@J5xkIV^xIlYtxQB6oom|N#!R};??rJbE0f-QuB6GLf!PXn zmc`6%nL>If>dW@`X9`*x?M#mfCD*6bhjsp$qU~Z>=`J7Hx%wUUXNNMesK2JDTd_k| zGorg}aUwsQ*=hHyw=g|l*>n%LLpxW>V?cmzEH~a`J-9<>d)qMD%-Ow zZd|D8AuTSh*gQ{{neH>?!E`aY(XYHY%G_E`59y=^GbU{Z?aOHMY$>DYrwc7+b-#0^ zg?@Ei;;6Ef9ky&|zObXHH424HZ%Mxw%RRSf%Ez>t4Q14?{3D!hoB(tXFHkJ^_GU7D z%3=KB)6qaa-xuYSH$*zRcTpW~B zCC!_XN;sJ+Q|`%^27RQ}d3ellCO%KA*`-+}$FsY*b1>UG==Yw@S(3HrIjR&_Q1afH z9U6*M1{D1TSpKQw=q98K1ImVlJ^eO#?MRWf_C_>@{2<)6U|zX(mYpbPm=@Q3^3{!5 z80mU4g`L@AX5kT$$fD_}trv=ea9ZXQE^|~VC%&VKi~gc2(Wt02pPN^*i?TZ&U((Ur zDhBuz9kn!ft!l9BBFboxt#}>IqM;#`ov~bOuZEfw>ceb`iTRPWj)%Z7y`-;FLK8uNqVPB1~EXEh=>2fJ=HH%&q(4%(x zHBvfhU*Jed-u*+FU6z4VAm_$AoNHy5MeCk)?~aV}Cd;4VWyNq5)O*cvFS-BXXQ~SK>cZFtv*^z4xH?@=E`fLug~c0;7Q7uTTtCMK9#u(;}qDN z&V{6=$Qde4NrdsM&-Ev15p_pSHLGg6Y3W?Ah%=Zk5A~`18nIF|TGP_(OId%aefdn$ zqP!J$cEYyMiU-xve041xEY4TAH#Agk?Yzn%W6WS#&h@FvXV)`ODEH{l8D$biZYQU! zuuQ+48_p}+@@rM=Jv)`2Lk3){C7I0D#lsb@|jE-E0 z)_3{1tlY~Yvt?piy4P=8-M%^M*tmYJO>A|ogTAh3C$ANH@~Y=q#V;fq+ay`lVt^Km zgj5r+ABFujM$JBt94;&EDkIU2OAn0AcET#dB?4%q)w`Nmb@| z^$w*~he~UuP=79F2XbmX4tazhzC zT@90k?7*O=Ra%!-0DG09>NTQ`D@P+kw!l(IaU|WV`D$M1cNMNXGOB{wj_em@^vR^= z$9we);%S{(Mkg7U&$@G&;cRbyD6b2MKW;7OOWMDxAxf7Uyy1c#i4w!a5`>`=HF;{ zFuoZJw4&l?pDwNx%E}in!z{}#h1;v!ZxsoPRaT_OAC^a!RkvKRX3YeRc`n_sGA*SF$^^&7))x^F7GR;Ve_*}XZ=VDlr&Ue|B%zlEG+h4Rv^ zu2V=zIpyGZdW5Er>x1yl6{0dTUslY@*~#h znqSm)b?cBHtR&6f2 zEj^^j>FZpEyD(aM+2X|uqbt@mDH^43%f#!|PDfkTZCV@M9&PVe5oifzo=Q!v>P?d( zL&?q>vjI9en029qzJa(sb$wtn~v|L`Tt8D-1v|pkvNzGtYTT5qi*H&F#b~vlN&LZ1(+fFyw8ijqnYL+gk zaX#W3VaF&$;wnNoss8eiuRN(>Q68LA5nyMl_K%e+an@`1BAraDuC^nj6Zj$UwZmYPoIwWzl@ArH-h^ot$!YxjcFc*^!b~uxoDbTGrmxse9@Z znJP2Z1z;_?Y_7o?!6LAj>n96EWzKf?>iUcN%%{O;2>xicmL1KOg`Pi)it+KY1=Rpb z+Q9G3qJgTBaZX>6)2#|^olNA9vZ2-TnYbG!R7cW&_iFh!RF~*Zt0YmGqkG(~lM9)M zx+6jiwtcAbp*>ris3a|`V*0vJ%?U@=4WU{GN+X}gK)YaP6>3jCq*Vu<%ix11W9arc|8AIj%!ab!sS0@^^)XfU%YzNw9FB(3ua|EhDcy{k(tjHt1( z(fTM=wU6RialEc+G>68ln0%v0w^KVQ7Oga@Ojvn7+;{0#6-!-RH?&1td>hB9q3fe> zTs(yKu-a$7_rVtdO6X-@EU2y%nt-Z~4C&MrFVtmWF*9j0#&O8wR@IS z^sNaOietMa$(bf6rmOIkFUyKWWXUHK2fq7GMS~(@W~arb{;XQ5Rzrnl;zZ9d_#6*`fs6gdQ0=hl_9}*TV%49pCbJBu$}g)HdV%|4Az@e z=}}PTZ{3d8-4S;gR=R59W5gdv9%GG?mhO|UUWG%1HLL_oN0nzUarP9}^9|Z)zSMjM zpre*59UXR?e0sDftTe2C18ZISW{^)P%J`L~OzS1`jZ5Fu_nqgqi}>M}?rG8h(sio| zUrOq_meiA)j^!nG7|TTz_2Zi3-1u^8a~$~=jJlMI zmRx)#&-XD@Y7(Jlkyraz)=D>_FjC7=z4GcPEk2mcfF=XDp=gQ73&daN*HICn*YUnGJdEYfLuNcbLYP&%GiL@q%RO_`T9J=Cd zaUQTOs;!Y&n@1<5E^jqfwc|$DqC8`VW+i*c?8@|(eG#PGST3GUKnd{rNpe?Au?sgg+C!BWWhx}sunzty>tDqvOji1NT^iCXFl zaA_CI1L~|(8DrT)lAXuL*J5?yg#BwbmSrc0%_xi2;gmAx<}#(8VxLmV+#1~@_BrHS-@|WSy0mV^rAljb+P$bPysY<3=VZxN_kE4+SMf^sE!nn` zz4;DPm(7QVxAA8bQd@X*+qr0cWbO1=!m=-m&>;!>6&qdLwU>NaJo)WizP>lODcaJv zHHzDIe$J9;i&f?nwMGeGHAS^E!mSFe$>h#8HC}3W zN5|Ixb}hAgt=(*a>G|x(p0fB$k8hGTtl67Sd`HH(V>=`#bR<|Uf}PUQ7w1p%$b%ep zJ8JvW?F?!Yu8`iT>XP*lSeD=ii}+?mwc@qLSBmuHHS|g<9Sr-l;#Uhb zBcEFxqgG@Q#rh7-QJty*|q_@3+zX&|=hS4UZH3z#!HU4hw1>2n@Ax>X?M4&cQ#)xMy(q* zC4Hzm3tf>q)OCu=m(}xUJ?$zm@*|CIm31>&UEdE2vFA3meMrCaAdoOv#M*{V4^u|` zKb8?IcT_&Qp}D)eedD@N{cVfe$hMyKejPoqrl*|MQ)TN_@DJ+ME>ka+ZsbZw zpP>5oKwQ@!$?vQwy)%9r>lLx*6}~cK`CF2++1;(4j*3eiTW2(oQD2g}LMs!Yz*A|n zSx@EL+BZh4+MC-VJx%RiztJ85>Cxo2@SFM_H~8KH+jXs5h`hC>qT-eJsO=Q?HBaUF zNkmT0BuPPG`*cD59R)?B@G!G7LMq83M^!seKcK3p{sJoxh}7Mo=KN7}L*q@ZihoCJ zP|BiG}T=mO~|3#;~oU!cJB<(Js+<225X12lnG?k|Iiv zYBjLIddKw4#u^v8*>-ZRi&ib_N=l1qg;%5NS8h`*C2h@`e8>-?QH4+Wjy+-Z|M<$N z4S`V|JY7&tKB>9bc0Sv+OvjIrQAD>ogm^3EQqWQs6F-0SRfpI=WN}H_w&s{RCH=|U zu5}99nRUUtjK;O~g@5A;%C<}6`iX0|WqzZO%c}UQt`qOBa^rlBb#2Q=E5GBqk}s=# zbn#CK<1OY|F68T>g}HIwH+_qaj;`uOHb&LB9QWVr5|g8b$3LNBrSs1B_LfI%T#wGd zk5?)dm3K5c<=@ufrVQ34`HHV1$In@_Ih90qW8)$t>6P%$+thv?NuvI6x_2-%H?3o* zR|7b$DrEPikQq=O>|3`ZgQG=z${%fPR#p*ech(^npM;WkXK@!h30sZ=XwdddT? zJM=ItQeT2UH$OKD5h#?=b|+nR(nlueOD|tk#qE!y%kxHUG^CPZ-TIAdo7Y5JR&}mi zwMLhb?3>ByvGQnI|LS>*9&fAnN=a5L6jXFszlF-;hJiwQRDH1N!j5<{ z%nmzAR?%3wWc{$iu)yy&OjdS2s!n|M+FORHgk(>QTU0()#IFp5?`m& zt08T+zmR}@^sDr~s4%xhJ_^PwA5p{A`Z?dWwjN&Fo5t_xRw*uPNob7vx>q>7#$^xa zk&cb6QXGq$ZB}pRiR=d zNP845lE%NQHZ=VeSC3I$pfd@z%A=1KhC#Y8y2DimcDOLE!^OiobPehnbb68#26eb( zOovke7KU_$DL>xA`2iiSI-bM%;T+CJbGXW24yUTDyVYIiZgAahv)kmduG6h|8(hus z4nOTjcO-Me0jgs=oEX(NY@ix>={np>y;6OxTkY1k${-J2Ol4GuKfWK-q4CQa)8UFX zq$8Y_jp)!+!QJF;bhl}rs*5_S;~9g-bhvm(hf8`g#S%tuxQ-^*vBY(}&UIYkIxck` zm${D1UB?x!W2qJ`Rw-bEINX-{zJ>n(t!|;KFV^?Hw!Sa<)PgOG8|wSE`Wdy8^?iQ! z{QBNLt*-SHdR-iM-P*1jI@hTXvcb=mW!q!VWqw?Jw57hdbzyaKcCwb@qos*>d~ki= zi>>bSHNh*_a!HPq9(9#GE1qdtR%N-OW;|^fRy?WvDxQk7D;IJr=W{AWVasJ))MjO+ zFBL5*S+BfR)B5}M_Q0_h$`RNN^>J_&M9B< ztx1h&P#)SRnfA`E=4fqrZNOJQtaVxF*Py7H{7CCH$K5y9rTtRtt?})h(0pAM)t6T< zj5gV84#}$t^Hmmv!bH`l5v#oqYUu6)zp4(iB{|MUKW441`jA}-wcx9B!^3)tsEW9T zuJ>#7mZVY$tCGm{{qR4 z(IqQeqSyLg7S0Yge2pKyV|VnZRl*A=vt4uh#SV zPHd6?f1&T6JG$CzYb=z?Y-I_d#iP4kU`q@$&EA%2l1$u3oct-TDpJZS3mabo~uCZoVnq)2k6n1B2OH zb_@;Y@*}ruXnFazox4Wg;M#NXv)SOQ8|-|aPQl*&2u~#AdmrwKo<`|JT#_=v?Y-W{ zT=~ngh?VPGuq=*WNqk$TZTyfueX7Z;;dz?yqxSUa$LHAsjU4my!w5Z>%R7xZb2i${ zMXlB?=VPKC2Gkel>cN{jq>CDY5Geyz%*f?+?2YA|-QsAjkMfE!bNvb`o{BDhPsB2s zkl{r0lO9jI`~7-#Y)G+RL#&qc7u}+a{@qrzZoZ~%muicWTcm%gbISe2C2o=ZTb-vY zS8LU7mo4U(UUu1Hw}2Bj^ou*rnj9-E zHH5uxi(BPkmhE<1{AQ4?&6>%6MceT)X5U~1knbg47P;9Qtfyb;(2weA zI%>`mo3l#YR+&Omv?7!hVT|B!`(?HZn=Sc&-E3`omz4#JcQq|e_by%*W&Jym)%U|J zKbYDNHE* zOySoG$Nebf&QLf{VUfaR3M&;>D|G)rUp=SLqmWe?QP`=lTj4GRHAU>DD)om49XET6 zz4RE~bToHstJsjBt?pFSOOE+-s`K@imFqTz*9WRMz8FRG>-$!#`DfkIi&XZnp7!eK zg4wg(>~?!YQHY^@(i_*?^bJDxcMJYOuXkG*&~%~Z_ccEY^M6n?uNbd8KmJU%wa*XM ztY^QUtq?{2eK>UuC}Xi~%8DBsy%TMT)+(FUyUI21C0XWG8EK{)TfLW&A2w*!f>6!0 zqE2<6<`yHdZc$~bc@2)KeW^xGHH|T}CnxHo7p~-O>Jj2TZOKo z(9yccTH}^sH7e^?J=F63t1M@E(QLD^(OLb@wyAUx#n0i@nUd~Nd?@=TN2Ni(j&4q+ zb?#d9Jj;$~eFl9#QP>;6R?+c`G}i`(mNihw-qf~k0IgdyNXU9%G%HzIU76O?;@?{I z{qu?@Y8Ki|JAWlhzqZdN{iCMvL`fZP8nmzGR^@PRZMLXRH2+k!I=2!N)t3;8!cZbE z@qI0pv-D`(!_KH_ZOc(PkXs#IginSl_zo0x$A^(}R>o@kB)G{tJ@?Cbd}|r^z5vZN`5n6TlP7Z&cm{Z@OH1i8SyT|s6@Nk*07&2 zygGS}vD%HU2MqRVrY^8Ielnw^=HKU4Ut@T~uBxTSdsd*hH8vJM^SK6Iuqou4ye;KZ>dHoWq5@Da2yU^+23RGDwr5N1ZMx36YFCGv!&y3WcrmLbMF zYHeG*xXD*pswpU`bgA535N*`3o{d?3*M|l@NHN-8->d7ItsaWbVte6r9mRNRNoA@s zv8F|~Y6>);-f~*&32ievj$f6!WM-FT8kTSRQE7I?*5@qqq<^BrH`Ui}h&q&C`r$fV ze)zKWIB&4WDazp0qi1zU>-rfA`J+Y~)C?@pKmzU1S1jY}Qr=kdd5FK^YQBc-Ux(=m z-!swbM`S1CV*L2Cdh2h}kCj+jF{}}F`y5ie;Gx>76t>8U3qK@8@A`&&_@bNX4Tgf! zg|F3KsH?6Xp?#OS$nCX@BM)_qU8|__@mLwFhLI;HUDM$acH8Dhyc@Rlhr|+MTid$P zKY7^D+3K#(7E1bJhUf+r#r|rWHP`BF+VL`LM*9xRxpqNo^tQ#2dg!z~ZqLLWecEn) zyPg-SXI1O#p{KG+)pf(~I$l?^wsvb<{fA#3->WTtXDWtuw-oL4u~mInu1#CCtZ8qX z?Jis_eif7|E7Xryy~*=ix;9uhlpgvhS^DjLTDMs?pzf&s>WNKJdDVHKlhaAXJ#3p)#j=W3eXl3fhu%n4@2zq)UrNQ#Ev)y?zx`hG zz|I;R{wLI|;sa@DWAX^3QuOH+DaEOI8YQOvhV|0%@omhZe^F0M!eD=YI^nx4)H|tq zO8oA-RYiZ-!!3;F>5F^pU}{9$4&$T6Wk}_fm$=g6ABoTFo#&HoW#FrCp-(^PydJ+- z+w7=A#9)f?@lmYaRz0*=NxrW_8z1v%nxFSaus*RUyjx*a?fCS=P}KSJ)`v3(2m(*|UihgMM;8NP2oksV(fysze%gYT;z=eKQNyZmd~?#=)6rMJCX*HXJpGW|JSUoxG1+PW5g@xid{%=mhT z;@@q(4{G`8@%h@i>uZkx6a9W~&APU}t&{A(to_{)A2-r^wLkCGU*@?_VXwlF!i@@T z3X2uaQ#eWC`Cq5pcNP9l;o}MqE4)?Vc7;KOZiQ69D11)gqY4iw zyh&k~LZ8A0h2;wK70y&}3P1hNl>4T_lL~*S@ZS~oE0h$rE38qtLg6BX(-nU8OZ{mI zg|8_*rtm?9cPQA;&;KIjUi*FLF3|Lprt3bOa&J`l+4sV{eVV>cVa{Ks+*6u&q1Jna zrWYs_6&}+(eZ^ztXH@eZ(mZ{EVddve&CC5$*xvz7|B1riDttoUC!f+6h{6k z<^Ji}aEwt+|C_?If355KW|;RwP2c#@l>7O|QtsVf3;X+(rn~Ts zHqHB@!pk2E+kRcsCx1cP{awoa#b?5LpVsu#3ePK?^@%X=SDMcKz4EJn)%?E++n)Gk zor}VsD|}1y>=-uvUWGFh7e1nS7S~>>>87tJJt#b&dA0FsO!NNbe}(<+*YraQbH1wM z$MeqC^lKCzQg~H7?}M8Dp2C)|r`%6I8jfqzJqmjip8cz^zkQm1o5GBLNV!hUt3B?? zns?4$hHd9)dY-~_3fn&%wzcX1R49KV{j9=A4lC_^D7d(9>Kqi_{%x)Mfw1kLYWh72|Dmw={o%N&XO%xG+^_J; zc;17We!s$niihjf_j-YxZTd@^_pu4BukVq!c~koRwC{w!kEgF%p3Cw$+xjPl_p3-!A)7kFx`uu`I zw)5p~=U=7V-)lO*{uQo8Y3xgy9@%h?`?5a&QDMs)U+I3L&*v4k-f^y*(x?5*cIUa{ zb=>gtD!1kPO0VBbxpecZ-G^oSHs!~~uJhfaT4$Hau)em)jr}0yPSx-I9T&KH|Dt?c z(*rB#y0!Xj)3$@FE_8D=eTKp<*Iwji>H5yn^p4f_?p2>wn%4Btn%B5<^!X}le9C>3ZL<>*;A(?EXxiH|rkc)-}0K&Hw&)Q*La(b@=;}+|%aoqO&lT>kW5dWTb+>DI_*v%es!U($_E)Bt zyL&6sE8Lqa(^t7as!U()?yF2+BOb!fA^C3lv%ub|}1C;UfxPRro&&^HdI9r?6MyeuWP!JgxA&!pxs3|5IpExL#pE zVVA<&72c=tq{8*_xX7lwO^=>5owCUu>?ya>2UMv%~ z=VpVEo_}4aP+vVid#*P0a@Ct&sWf`Zlid#*Qg zW6GV-opL8`3iDgEKYPBnyixIciR#e$On&V7U*CL{^9xe$D;J0Pf7(!8o~)OArj9%Q z#961E{<1UAe#LpOPG;)UwwRjH=o)M0)lT~5sTW&nYif-s*_o|DCG;?8mmUEsocEvovpxJ4a=3lWTTq zcc**YrBZjMQZrJ=rDmp1NS%~AC3Sl06{#q-ICV{GyWhbP|JZpX=aQUHa!$#4*}3US zsQz>DvF$wV9PRv0RS7vq_0^ZFOg~?BvDdoSxhq|(^08i5bYt!z_k{a_n_+PJ(f9Og zyO;V=9aDR+)4r~DdlZkSQd7rGoj6rDb^g@VQ+r;zcHx|*AgfQmEI!0Z`n2?6$FyTx z+OVrRS;5*Przjk!V7gYO3)=?{eBkeY_M7i~@*THzFFE~$ z*>z{lJo)sOA3y7~GfzBa&e>Y+MSpfZe9Jek|C^@{KRXg#^sirh*)Wy;G~as_SC=n z=hyu8HIH3))9YXJ{--`RzV-A)|Il@2+l)JZ{NOh~_n%+=$&dg3dl&q}iI+cd_o-ih z{$I|#sr~rzAG~k!p`ZQgTQl+l_pG`2V9U~9PTl$QTkoEmzJK_XD}MCrwts%~;rD&% zf3M!Y`cpq2`SfQVJ+%AJ=Kpfuga3Tj;-7u(_*deD=qax4--R%=I69 zvTg2y=l^u-;@0KJfNmJ+XO9=52p>%3JPu{%2EP-n#Fu^}FAj|L%_${^rcq z)I$%>IceP=?C$!-rT@O{kxzZ)8yEl4S1o6L>7VVoQH!<8W4eL9jH(a!NMnHg{d0d3 z?w9*sTsQu##op>q?R0hSZ<#vAMk(iqVn$P`4XvF~6e(_Kt;c?IoJAJJO8=3XO8HOa z82 z|9R@vss8h{snh&t-Bg|5aov=gY3E!wl^Try;=1kDe*9P6hRK)w_uMV@+4_;D`o1gc zN0!w0t$MMQ&)u@>+%4C>*wX6!bGKYRT>b6Er_SB-JFONH;W6&Zi|?5w2q1s}0tg_0 z00IagfB*srAbCI$r1%uZx-Q$PSW#}Gp^ zAeT>mUv$kHr2{40VO#iivoo9(hg=AzFD*#bmeu+Y&LQ;NyNn%n? zszOR;akidfaEOGF8i1T#UQjbPg-)Z$DqHWnTwpa;@f1@1R;=3fYx(r@|o6vX#92HkP}Y&0cwS`i@zLMy|2EBdk^{cUTXNT$>8? zw%U_IG$iOK1i;qy768`lJY4sF%Q0get2^(cVZc!=^ z_|0{T(tv*2Y-?p+{i2NUv84KWsTW(UAJ#vXzNFrth7z~5Igd6Oj41zx&23wf=5AUs z?rp)a<*4(FQ@e2L=i^su*UsA19IRvof;z0ZzLHH9)THJYD%m8V`A3!P20^_zr?_O6 zLzwf>laC8?SFTy*nElAwM}^{tR<05pt~G0(TqC?=5OxeZWPc-15Kp%aG)OFzJ;IhE zH1Dl+h7XM_s!tE}3!<(0lS=kGP2E=X*psVQZxlc$Xxu665IopjB!^WGsjkgFUr^9qxfoaML(;Wd*?sn6(uqnUWG(#}YbeIbZ%&ryYIRW!s z+s*fc&GWm>3kA!)4vVM2QnJEQ7O*VdZdn?(EbF%1FC?vWBt2M=^w5f=hXYBEY)^VL zob-5i5~%x*BYAB>vbZ97eIR+`_T;C+$(7y7)q=IgVU-H3!4=l;1+4ORs}i<`x~xz^g1X6yqJ>@6ilx^K9FA1p)j?~72)Ss_N{f|KEYui(Q5l;POcj}u$ z+J8FIep8UPb4A+jK-$~e)7}ZE?d?w6C#1JH(%TBs-&>I$38Wv`p03$qtV;yqtQ>j| zabSo8LmU|5zz_$9I55P4Ar1_2V2A@l92nxj5C?`hFvNlXr5qUY{|xzm{+Ej85LrVU z7~;SX2ZlH>#DO6W3~^wH14A4b;=m9GhBz?9fguk34{>1T1HzN|&kuAq;ZNG2KS7|6 zSqm2~if#O|3#-`E8>eraE(r8CaSBd6Dm)~t5uU))CVcXkaI^4$@CZKXkMf^z6)$kj zb2w(*wZI_=qa;0l>8=gaKNKcE&B2BqLmU|5zz_$9I55P4Ar1_2V2A@l92nxj5C?`h zFvNi&4h(T%hyz0$7~;SX2ZlH>#DO6W3~^wH14A4b;=m9GhB)v)z=4|wZuPJW!gp%) z^;vrB>$^7(0Q^I`Uii$lSUX-RJj~aBZ*U@#R(WV5sE>W`8Y~`LJ+a=Y!kLWD0o4NUb6n2?^;koc?*l?AphX? z>rTN9$PH}rC!DIU*D1%8BX0181hTSDBIVoVXN%N>0mQQ!^jHzK$gyySi*e$q&XWo-5 zS3UB?!;ZE7l@C93D-=mas(vHSzqp5|sNRg5c)o4>Z}ge}9a$%UjQ0eG_2g>WgoA!e z3Y-5;x;giD;d<|?NjbMX@Z^*JTONPt3GwC!y`)zE2ma3K_d;z6KkSunDtJ~9ynB1c z<0dq{Efj+2&x_7VH2p`z?~11dsFRp)A|ed$lGr4>lQMF~887 zh9UU2!9eNTw5DVau3mcEBpk|$KC6|;Cp=~Q=Ar&da^pi13IR4jyQAs52+PU!C06zX z;qP9*B}_GM-qqp%H3N_6LdgWv&F|Rzwcz;_AkYaO_#W570JI5%F^fvH(fNbE|IPlt8feQ=8 z{JhWolk>X$lSodA$Cb*hfn(KmZIh1hcBu>UcA1KHsXHcjTDznLNrvU)mn>cOyTI-9 zf-gZl_I0^guuJ$ zi}DG#QY6Sl=}J+O)MpikNqt#j3Lwz8aED#F@`PF1Z~Ye?O7Ul>L*rN*XOmVV-Q#VX zi(oz1YHR`Mc-X7mM5*T<_Sy_twFuc9VXxF-uw5PYo_rqlvO*l~0&dO=Z|UB`wsb1y z>_*a$4O0Ou@0Z_epfA~+?F_fYP{`ello*F>;sAj3HaP|%I{7uQkJiiUzR1fn)REXh zz6Xjs?QP*FuiTEL7KTgqTIx&Ey~;8xtA`?$yS99MXk^_n%I0OaBBri$>2j{l zJY}WGSodDNYjn8V=xt%fx|Vt|Q_t7w8_Pdcie^s-Mb0&myyn4a{Ig3Um#*sXzUGWnf>!|J}+KKyCi8kme*14ZMcqh9ti zo=?}Vo-)ez2gK0DfVIcPRtR169r(|WZpnS)yY_uwm zq$?}!DPhr2psma-0b7_G#l=RSHOp$w&v%Pu(&t8haeNpudA!b}&I7oDkS-5Al(puz z#(B?r<#7w1m4_8SD_^zG{dOi~Yma;8d=FcM zY+KqPjtql)mUqoqZ$8C)#Z0f%pXuF{;jQTxs5@7iylRs7Z7!9p>jEFZGi9qBlLHLT z%t|DLfo6>r4Qk%ps^U^dCmQ}WfP3XmbbJFRAIbz$Y)uf=#ts2uOIwq$@DQ)e27KCf zw=IQYAk72d^Z{UHzLjm$;SDkPxtG9u&>d>N(9Xgj5s}bjj6q!;g91`zQMQ$pQ=*U^ zJnT0V^dHJvYusU|JLYBQ&uiMU+QXuu&CRYuec$@<%T>o$WgEqFZ~ZB-DcdUejp@cO zSFkin)4p8AFjE%F+jI~-4Sw_S73!I`%^mT+`>;0x!$|)-?Nu+t!}PwOWOONlAhnoU zqQ+)HunYSH!62OaxiYpJ@ye7>@s$7kw(vY)Prcltn&mDj>}V|5EC}xk1*qfmXJA2X z2GQrX9C=rGZp+avZCk$BqVkc8`H|RUeCwAJ(e74lQMQ?tAqLequTaKbZ#D|77&+@Y zCuw=f{waA@zcVk@e^XwDKgaFaVLD_FoLjglqbUQoT)vfh$WAd!%Xg%}h&p7y*b1}X z4*5i)m%Rt8Z)KZs5127ONf72@tZ)w#ggKahE=1)$W~fiAAl#KK2=|ir!c*G(>&>L= zQ{=W^=6)icmRpxEZ7XdyhvEYO2IS>!|D6divG@N2eeH zMt_1FI}fve!^aN8q07AfG(h~vMYiW6_0&D23%u-Rq;g0Pdj!Er8a1JpjY7EYqq<(M zOzIb9r`P+l?QD(?fmZdhzx8RFu4-hIS(JQH#t(?NfzGjOol9Qu;1!nXyp=* zx8WCCpecf3aWuPt_#LK68lid}VXvIQ6Whj(S7)=>!pMrB7|smH{NnbOE-o^@FcWO=&gnX#{UBGz`uU; zsnw5vhZzad|1I|ZDa}ymTM(`j?!y57+;iLl@<=_I$}+nmW-66q&J<=E{Ey4MO3CP! zzVYp@<96BAEBAp8S?rNrEaW=whL+RBbSXT`E0=uP(rs;boejLmR!>9JbZR7 zCfH5T6~eT%wO5w$qDE_Cck#WvNTZuscsXN251n30HkMw6nw}R>Get}fR9b~d5e)@` zOph!zGm4|WAK}dtDKeu_kYKg(m!0%O zq$nLFR!9GiDBG@*-`jT0|48nXj?I`5Moh?DBPSv154Ja3Y;U&83(RtKNQ-w3W17ZqB9S4f|XWpBuJ671fMV$l)eF7DD58&iM>PFx&aAF(2uA5 zAqXYfQd<00WiLgkmnp%=2w<-dPurV)wm0{#MkrKdb%%<~?owi2Hm|rH=n8{q156#2 z=^V7mDp#ee6D|Qh%gZL<%K&J5Gs*U5krkDQRmT~QH(OlxYI^26z=FM}|BP})Yb4l> z0EiSK!A}w5ybN|F;yy}*IuoITiBLx(v_BCFCqnPWLh{}wgxCiGTp4{}351~bTeOu= z03F&+p7hewg0Ng}D@TX6Nax2_k78SD(FXa)hoebs!4`l=8}M+3bGH#ik>K$dZd(Y` zbKzB!_^AAGPK(r^R`o#5yB4Y(hN~;Z66FO;A3l^FmJ4`=%(v!WTv&Wu%s<;o<0DGz zA73@;Osknfw^Us#Z>4HRf>emk3aW(fm$;YuY-^w9zdU*^$WVCk1-V@^4@B2%K)sU+ zmG<(S{_H??a*BUkXpYsl2ASPVz|<5~U+hnnD(x0q@HD8F&QG>IqavULiN+eP$f#*62hnezKN-^yD_V5JSC1<@qW9j$O_RPGmEKp)&sdFR-3Ti1-p zZCN)g_k%U5Ijz$;Ve1Alq6P-OO{gBk#n4uwTJJ&-R6*WKWatbFqVCZ}P*Ku(hwYgM zAxz46+wKoSHT^&%^%-p6Z>{N1Lp0i#RH8V&rvD&t_-~g#k-J(>T3guYnqvaGW=d<# zxnuzP$JCs&(mS)}9A)&U*PNpqwx9)H%A8EjvREUDj}3@GfD2Zdm>t;rH_&GguN-KU zMxABUmegA6lm-%)fhL_G2)+1>w>1aHjJ)Q&6`~hD+jSM!8p^1*VR8z#-L3hYvTO5s zRjx!eV6dOGPvG_F+~WYb96~f=5c=?5wkZJ0@3$%o%}RB;yp38;4pDQ-d#P2H*5ng? z|HyZpuWwB&RXDeGoox`G(`~S_WhO$xB>IW%J0YF|KUm|D8!U=OnT`U!TM z8%A3&yreok66{4RwVJw8+sPpwVMHz)&OvH?W?&&&eX*i!wXf-<`c^|Qt`p1c$$=>ca|$a~`!dV<^Z6@Di!-QUB=bWU23Ae~LOn>U-Rutfsw_ zN+qt#0z@EP?;*EF;+aP#btu)Dht^- z`GP|b){k%(YkXSBMxcf;ztl;5NRG!|SV$b9tTzecFb!)U8M07TH~ad#lp}MX6Nzc) zdenh5!}_b6W`Kemn6N4C&>RC^70}d_+s)3E^P<4l3W43S7#*OM<6V4z=!euFRD0k~ zD7bp#tU6PnUZRHR+_p7eB^u<9;NSgdG_m-ME7Ks(ibi z+o)5?V`)|&nrn(uqTakTCdUf&r!p@Jj5Z)q+ew_%QkNy^rNQ*i4QOVL8-#S z`k)^?%7-FxwY2wBD%C&SLciBAfqvJSZI|=d6fOxU4mweMH;(1;Y$#txxt9eQG zXN)5Lc-l{g+HqPM7{ z5_ubGIO4|Gpw_enHzQgJaZ~1Ad+@NW_AW$l5V|EP{wDb4?w|4-QZuFtV+)l{8A&cmJ z)!@I)_Z?za?;LbUUc>)qS&UwV!AHspjV9uaWiqSu^lta#c@g&8CS|Z*4+2k3=f%eb6eM@8oteW zU*6gUY`J?0=ei`BzeDEfxx5~0EnJ@E^AopGx<}hduTtN7;?@2lK`7IB-AdUxE@v23 z{flBitVqOIvv^vNvWU~C=_O<-A&#j6GvQ%w=JinPrz_jI;OSEv+iuT|dJD=eXr#@D z$!LvF$4-EC(q7I_F=h;q7)O6XEahV7gbl#ErEPc7BrZz`+|1C|n>lzte7Lg@xNH^KaG( zUOvj%bG>rkq|7)ewUBVI4_q&dM|I+tmgJW5+>e)tw>-+b%Jsai^6XpF4IP}g*c5Ua z*S4`~$WQZ-rcBaXOY%h9Hg82Wxd z?2&+U$zo|Q383J2C?N{S83dq?s7PhE7NSrt`=CoGXJ^28h0nohnB${c?lL=ivHWqc z)jxJXsi`*hK4A3-vTK|N;EIqtbRUw=juRf<`fx)G=xz4$YEa}nOt#_okgX!Frk}!o zti{|%Af~V$L*DxMhL4UEFaLcUi7>YKmxQk9?+SMfFLwVZS-g zA^uH1Rg2p0M$Y=QK>tm)U?YNo{zB1O^E<%-G9M1~uf%VD{m!5+3-mugA*<>M^gqY} zP+zqu(7%eJ3)H+o|7;#D2oCj@K>x%1BLJAI1N}b!VaG>Sp#O0l4D(fMpnr{Ml78o? zH|4D*G)6TwZ=INg(yf9}Sf5sVfD37$-w`vj?nf_E4TXVeLX=i1rAn(AW*MlCxL)R+ z?{`##_9S6J%|)ugy5zw0Tf}cw3%#tNB7^LDRZWh#sD+W|4gK{Ny_`owu3C3U3Lxxe zM^3`6;HpzfYUkeFa?Cz~MjtqD4XtozZZ@=*%Zs+{C|n|)Pp&%9P>c4DxITg^5$aqY z^C_3?`jlI$?XE5q*?q>s2Ri?l2GR|(>$r)l0+WRgzF{+5#po_m~6Qfti^|HG{ zs1Vc}o#A-)%mz{*CJP}+yEZSK>)v!~8#G~H(7~5|sf@jr4JLp9J^ZnvaknMLc=Kv+VQ@Z8(z48ajU42TW zHF&_b}4d%G%Ra&SFzxUrxtdw^G`ip;roX>JO)K?`$zfn7)*s%MA3xFVibiGE$%u;= z8*!bc(j%^3dNI?Z&}LjIlA?h^t2aAy%&z9bIGeMb4@IP#CQ?P{08E8V_R1l9?##pS*U zUn0C8;gIWih1Pf)66mAp87qE_*hV5XO>y-F!&Nz0K#4V?RCzkqkcq~iMr50S2dwsu z2anj3_*fFL5Jp~M;}b+bP4DGSE@M(Y?-YIu`}I-Gx#(lA)Mv4MkM@^n*+FZR6fn)U zv?ruI?X~b{=+k+ z{^Y7-K1yOcKh?BybjD4eqaRJ_K@`^?J^{bU*hu^9kaq8%;7lQnp%3;f7bWt}qYubd z5X!6KMx!(5BLgk!pQqkxYj$aFwie9>9}9MOxU{_SSiZ@th6;r*8XYH@gQ&)e8O%Nn ztrl`=6$Ur^V+GH$Slr7Fp%vic(-~Ikah}0)y2p2xnB5G-aFi^mwtGNn4y;yhvjKDP z@+BVj3fhpy$>DDq22@Y4i24f?NPlXwWgi=fu%tW1#X?k$FdI}mmr%{^6lOTBsgREbLPUj;=E$0g0VRu|-HZQYyE5JRWHKh^q&65y&jTXrFgW zLQYLZ>Pe|X3rrVmwNC>=wWKWTQSZd)Ugm2h^ta{-LJ_$D;n#Qd1OOsMlAK4&w8`5X zu)f$_)QPX#L<*(zwyLjyOgeA(=c=i2(s!FvTs`X5rP#G{8Sva+8qYN%p6e6jN{;2S z`mw>fC!u*s>DtkXZrRm`hP@hwnhd3jhV5fx(XpwA$gT?;M~7S&+#y$=n_UU46sxzw z(pbx9LAjCcwY8ix6Gg3Z$!YakIm)^)XA6d9*J(m=8Yp_*tP9*6Kry=EG1O7okS+Mr zH1V{CeJ<|oav0xr4gYHh|tlf4+kd zC-(j)SOG?Z^-+WI0b9ziBMAR+-vKZ_V&PwaS22a8Fbz(=Qa(k1*}iML0hLS`v?U!TC3al7s9t4uyU8l zgkBUXH>;S2^*O@>ilwH<48=xm3@LmOQz#Gi?~Q+u(-3QKTkTo2PKBl`iEmc{UmNT3 zLKAU-@`Pug6JQ}l!_&J*Fv=bBksqBsUnaM+-wc1=E61rT;DVllKoyJ=ZW zQIKizG$52L@@Uo`w#ny_9txiRyQaDMP(YS#F?$oE2P~Wfp$n+&n#ymX=3}l23-U$p zKs4>W3v9Y!m*CG(X5X-9Zf>vb>61vDDYe?AepA&Kz~0ZXV_E|225kzJ&F1|>5tv_r zkh1`VIxqN~R(GG|q5)NItNo##itSK|)O(SNo#vdQ(Dw7y_3YmJ2G#S&NP5&V8)c1F zp7Y~{6a2?0hz`^;YW|#VkKtHRREC>@hHcS=w&;S)iS#0X9G=yKGbUpVvkH$uxC8U$k z``k>LqAL~uQmoH+RSs85`le+D$>jH2ut>h?+uSa3Jk*+O-bRs7iB|t8eK@;uCS=KF zh1JK0Gw~Ntm(^(z9T0M%LEmCiK$@D&hh{a!8E&Lmg)^*A$GN><(~}Lw;ylW&Ag3k= zKZ1}nY$E0aI}w!gsU0KS2~M)cjw~Tf;hzc`xarF6um%#vM#{ymTEQ#iAH|X(>%8g8 zd@G4li*7@|TQX;0l$NyQbuaA;fTfXO7s?|1dU??g5vhbeMI7E6{$O@9zi|0adwZzL+&2)zQn|EdBj?&od@{~SG& zZP%yhgVWHbTmEVfl?7_f!>Sg<;ibjC3f}%`XjshZ$WY-*oLBIzqsT{iq@CA(puVvl z2eL~VvC#hy9i}$=0YmzdUTZF=NO&_F|tPc9%!;XvlG#9 zwjvK){ABwoybXE7_|4Gxv2JYxG?$6N18P3E*)hZfQG)>sp7K!2kykLp{G2Mc**P%8 zU^|wBMi}S4P}&@2LPtG=LPEwVqpp)U;BAf$sqjb=gR zL)}8gVtwxNIJN5SP5VK>8CS0XGms7hVe??-bsSr+H1Sg%gYO{Gh~E$gS~eW2b3oiH ztiIG^`iOW=Z#D3e?-0SN+(C_wvA|e_Wf7aLVG0aAG!j|L*nxNkaby{iNh5*Q*I*sW zk@6*h8BoGMM;z=RO4=9h$Hz{A;yIWvmd8)PmIy@dRbHU0a>5P4Zn12C?GR^=V%RMnqPG4A`?&HO$tWRODt!$Z=1(_$>%Me-l#FostU+ z1}-K|6{3%$11OcpIhSW346&tAm~2`6(EW*s<=u>_5Nv4)RGm5FJ-tEdJ$LBV3OocNryL}Er*nSF-!nIzu@Dwkfa`u$nza30Wm_DGbg z(w2<)bj^*k8S?zo@&|FNEu+*ok4o@R3FYL7fU2s23mBRg%8I5!{@9Aycp#J4HVw>P zO36k)O&I?Pof+uLmk>HJrRJ$O2%A6Fxd@GVui|-&do13t?KYZbUC8alhPc8D7U*-V zhKUm-Y%uY>C4ILqk!=iR%TNk;$ZIaN^xQe7WuZz|>XZWp2F) zz!9K8fHX-)_%!TzY?+|VhWPptU$Uz<RzuvW&8}U{g-#B-fg0T&)>CZaO|F%*7O@?g|R>jgPL*iqY~`+7sz}5z5}pg5XodG@psk zn5axYBI>shFsc;zBH+)gDDpK~klbWIa*57Y% z+TM(ayZ}}eC;|jk=y((uJ6>H1#Qkn1f@uI{UH%UfwX zDA!>aMkT)06MNK@t&~mP%6EQVuJ8)ya#WZBEF+*OxjDL4VT^oVMT2F2mId( z$FI0vm9u7pG^M21+c*mWbU10x1=tfoD?)OvE36%l%M1^;CsR{#s&r4d&EX&U?b zMvj<9osF1Iq1P-WOGS)GdcVw*m zICRHL8c`?xZ)nKLO;_yRpJm*5Gp1>g5dQvoW#;*$sLoX)mc# zOoiBjHOjY)>s6Ii5a5YC>8JW31A|;3SUW3TyJ3}5;IF@wvleM z!;MTS!aMZzUvArNa{Eq@mU#(Anbc{F4!!(O^R z&gJ0iz$mpPS0wpP@uXTL?SrC^_p_fNh7)r{DN@a!_zE!n*Rw{ zr5QZ_HXaW*6nEK|l7Y+PujKKjSp4*g6yHc5Z$dnW6_dRCu>O**n=s`0RNWOe-&hXy zr|aTSS}c}%UC}Q^JQf0k%soIt?Tgk~o0(6Ww-Y&uTy7nN^PaaN2yy%&7*tpPq(e+|^!AWs-h#KMuy#$8RinVZjxVLAI#);uEh znbxmT-AWd3%-L5M@`V7Fg=1zaXU@Vn1(L7#Ak=})99m+)%)`}lb_#vTe^6Y< zaV+T@xut-&>kH`Kq?DLoe)t6WkDD~*hAkv^K zXJWD#>y@_JzoC)=-YJBQE4Z&mZihESx@cN&_7?c{b{bG6(f0rkEYKTun4`c)6?b`% z$Lo3255*>slZ{!kms}zmSXC8sQSil>$^@Q*I3C?+LU``_2R!Zs@W?o@?pYz=G5-L3 z4S;cu2Zh1{F>=9=j|e}4LvKL#Y_)x$O4&x`!Vw%Kl+!G)g1Pa%+#`@4J%R_e{2?(k zAIk+n-HWr8yf|_fo6P+(l-0zYKB2AT*C`HdC09-HTx1DtC1)E;1EBmZ_TIqe7#Nb< zXJ`Eyqcvf#o1OI=B}ixy+M)1r5Za0D*LvJ8-D`!o-MaG!p(foYgwWgGhzssree6>> zE%NNFJ=kK6+z2(ZGqBK{hoP5AdA44nejy$XunG-}<4%C524hn(P{;eBt#%~X8W)uN zxS+sJZU?h4hLfZWZro#FnJy#`!p`DC(g&=%Tl6u7XaZwEB@d5 z>9~U~hVmy^(v5lPyeNl@d3*y@%)jKI-9Y48+K&ES%AVkLrL{~u&0%^1@nS9e*OF znvKEXp+Q6D*iz<&9+uk{hYF0`LLEGY^U+bg13cs-ZXj7G^$B>gE3V=;DMqv|(^yKw z-WLxmy8)Q;_u~`e&?Tc6TH2RH2GxSG7^_lI;^Mq3X}w8bZjw*jt1s1|udYV34y?0{ zz!IG{$?ba$d|<Y} zV-7;SKa+1yy2OM|W)ET#G_bO+OZEv2D9fVjpto=mTGqdO^o5H;sdKy{j84(U)E?;OxaoGsDgG`<9z zK!C2#UPQV2c*=J;(g3NZH4tW*Lp9LW6QA&OG8Si{E*q>*$C{9Rh`9`R7x_6#s%@z9 zctt9oUY4j z#$F`zYbR0c+ly7Kvd}haDza11J^L!ZV&?@gAwDpGZV%G|8%pD60*7B4M5z+DiZH!ED46kW2o z;PEEXH#J={K=Q?dsifL5Z`_Gly{jVt)gnhCuKlpT@EyhzuXpLS7&E_5pe0J#<5$Fm z?~YJWGORh;ZV+`b#(&O z^*HJbOEKhPKy}>Bt^g|X-rH*bhzxM7%dU=Skn&>U%JY5+2)z&Bm^8@vH00_=-cQ}^ zv(YFj7{1?D`xDAr*&UsyXFSC-{xXqqHP84_$km06AGz7jkx?)70bXdA)R*MHt~wPP zzWkZd^WXwHlK*O4B;?PD_Hf?pC*H)v$RtF&@c;)=X(0-aJ%x#z(GEO7{CQ48PJ)K% zoQ8uTS0`vV=w?@e26UjMw%X5-L2-4`)C7mej93}n6l)8$8UZts)peLFo6vhp*&mTl zXUE#m@)V538Ho0%Ruq&i6;1)n*Dhz}7FrOgcJFt7*wzB2Y3s4+Mn*e~#gxh?mxJHcZLVMf%; zZoP$XTfuKKd(VgTv>hjKrFUx0!+z1%Nwd+51(WUx>!_yu-y<(sbBTE4(F zKPesX3vh&N{jZ^#@4`c^phBqD|5YL4Adif0&E@`!Qj>teLTFIxjDJxoC0)`q9=WYp zp5N#8T@LwX8?gxHVb>OL`Ip-uVd=~|8_jY%QdNs@8UZZ=P`TVSu=zm#gNJW?m3p#c zdtXCulgSM!EyfO5OnLQ9ux0Ed1}nK2v&IQ%#@PPX>*e0ivhJ2XeRH_J4Hn%KkX#r% zWo&j9(KA}^9b~#)D}NhW);V}jtcPtLl*g{;;VAev*)sO`Oo+hX3q0iCdOV?KqEv2! zXJ69fdzd295phXdVBD$cA^nIQB{H7`g@T)bq{0o4 zhR=ZwwQ*aB7T%^J1rmo5q!e{kvbeoLCN6e=Y%M^d9L&QLimW2dqp!amM9b-_aI{B9 zfX;>P#$JQ=qPr*5k1A3;zQw3D+n#{UB7^gLfCxR6QU<^IE#Ra2Dn+hAB)Q(q42{t&HqSqzLbhA?##2*J~ov!xaX-Jm90zgK@ z{u-EK8=s)q-&z5`q_*Qv)a<3~cMv?9LD_=)&`yYc4$+})^YDz9_(P!Pc-buj)IsaO za3fADoa;J(72g=d#VfU)#4|)HTR9`U*k6zr_KAOCXeSYm`7>xNb+d&K0uDzRlpsN~ z6u|0L*BvDuH<$NPmH|?m;16jp?-#M1?V)X_QHI+W0*r?} zhM`s3f1}6u3O-o~ZKYQUu0&-k)zHH&LYW(f?6dB;cqIG6$N=?s=FiAif_%%BAoVb1 zEA_BJnfS`aB{~Mq-boP`P+{$qHkzU*!y?041I5J7s6<>{XfW7AWEJ7nNiQrme8{OD z1tHKoZHhGiBXjgUN=)%}@x*gbF9V6D=&O3-F`oFROA?Jyg%VSJJv=d-NOXh>QwJNX zO;kZxiQ@9N4ACE>FTpB3%kykb*3&nGPGz07)r)?SM(w-FLIa6T9{-8b7w8eWe^$24kV!R$`FdsL?e3lM-2{4VDiZ5IVSY$>Fe zY9eNzdFC0!;0!F8AW~(wu+bz}c5{6t_aEs_adoO0Qu~c_q-Ksp-1}(cMyZL1ZMD}T zkFx9_RjIZKok^>o-+d$;bamQl|Ae|@O2GxdvI<2|h%MitY5Ank{ikVbk*#(Y!p<{s z3U7Re5Ignr3-UKdx`7HCmOZrJQXUQjQrnG15(q$nN7-;7liQ}bI{d%UalRo{b_wFb z0esV7eG|rg^w8@RLpt2&1Rv#ml2+zRg9egZ`)^cS`#E}Sv;R;j`Bcv0!i-zGmUV!F zEq8%}xv=Y^1qeLq>b}uJc$N7dH4>aWmv#U_zhpQ1@Tp#>>xHXOL%O6PZUJ*L)QJ%b z0g-L3xIWFb5CVTD=Kco%Fj$5MG1q3Re~Hr{Oa6KAq^n^<+p<9eW^bXrw93l2z28pp zT&MVGwjl?tNC~-KtU%C?peN+oAK^-G0o8q5A6hIDyg*8jzV}iSMS^BLefW+9(-GRh zLzxIYOEAIF2(fXx&BY7djFMM!x?IlR_xIa6sD4j)sxPoULQhcDzT#v#k*0rOVYL z%1$ab`Y4DC>?Ots{*(Y`j38z<(WGU7|IzQ^GZZ8!H#4@P<<)f_W=FuozSF`B@%I{u2zBs{ zqL|}|LF!wn2zMb26tsVsJ`d2Rg9;g|7qSI~P;L%F#IRTN+#pn7Kc;Z9&rabjdi*E~ zKaFsr%{e=eR931B%a3@S|9NoBIHU&l-lNbVO$+II7l2{hHqr-wg7 z2l8bw4EqjrEaV6rEP(S1xt3DVqhb&f0l^A^-+4Id1j$Np3`j<2M-Fdnp~JY&X4@UQ zmf}MU@oEN2G;=WetPf@&jGfa6qi`Y2Oz@@SI6S_QFA0f&C*w^Hbt4Wl13aTY1t=~U zpiH(}qFM=2p$d_e}E_Y5Mrfsnm-M>aMMbVr|k-k zLbdj+K*@0Pt@w=e=mfzMbd5jO{{&YK`EN<`V3jZ)uQ|6FpZKIp$g z>RY8+r9KfiGWKl{+qFAF%Z|I@m;n=LPdJ7%jK&`aDvt~P*Xj*3aRM!nE2yWGWTfIl zeSwE?qq$)wih72kPUF1aL>NWrZ@oHoI2U(fgLRsv8$OFobgCfjk#GU}ouzwAGR~KC zLmZu98Lkl2J|FZoTKl}jc>rrfC04#`&2O5io{>8)$zcZ!`VnS3nDvRN6&dU=puJq3 zDVbK?odJNl-pX)Tcs~dXOBp2$N~xeCE~G3eiyRcQ?B;VxCXMA zv7l2OavK`RP^1msSrnPux~YO=jwGyVX@f)XCsi0Vw_~xd0W!--%sJ4KSegN8OW8~m z!#kPOmx@i@QeQ@VdyV*o?;Xmx92s@Q2w*3Oyvzz=(`z!3AZJ0Q@!XOXH^&LYR)0Sh=Wx!Dzqrc@z9ew&t)~ zElnhFfm!9hsybcjEB9YPQgf@?K_WAZZd6-~uRSC?JGI+G%NS(mB=zieGX%%OXmSll zhWbO>t|Y{{`MvFGs&+d*SQ#}`^t*V*w~5Oq7}$9}UTMID87yCw>1dszj5L>=KN5Aa=0xMeRqO;NU#;Jx%3l2G{wyM|>r=*#) z)X!)S7-uK2Ds!*LU7e<7+UIw!su>664!w&o(7)7}G;Fc59PwfgNw?>=1Q(wyXGFC%t|+!mVKDfOqU8y%Ya zlBA`Q&cL~(ALyr@uMgexS`)ykoriNeVh2Uep3Qaju6Mu(U1WPRV(7qBNPUwZ?6^X= zuSb#4#O68}tl;=lN1y_wm^sq@+DIWF@S7v) z(rW5rC3f^OWqvyLu3cVlm}=5lX^*oqxp3y)wBL~~fR^6Z_|G0d7tK${?aQ-rKdHQ3E+K2j$Gu%FVoF*VPsoi{;@RotjO2!)l8X=tvv)+>RhC7X-l@v|J zEcIKoBbpX#GNe%~1FgmPmZ^rK`f;^K{WvVr2E(6tjS*ahYJ#jGE_Nc5ewo2a_bOw| zy|#WBytCid9`M_zV)b`cVSOsX=Ba7wx4GZ0;}T>kP=B8|%?YN$2E_Ef>IN_uL4-q@ z#_Cjlp$P7*REIT?X;5>LPF>?Ww{vZ*U9gUbc3BqpV7@T0;SlOOo$pBf2?-5+BYsD& zXkD8se~fVjcgd^6L2$@FPLn?lZ5plp{nX1BXu#1|_WedDH*;{1T|c#r>R~_cL$qy^x@i9{IP*#tRU)hn1PV zCNQ9HesxM@=4liUbuO_5dkPVfKm5_z{sOt^bVUZb_5#GP+kkbkRE0ZFF4xv|`+kM{ zRGAy~SBiRbTs?GbOwFvw!%iQ-CIc4v<|ACL6rBd$qp;F@R#nYqQ(`WeB z@J+~khwSN*@8Ob{mY`6*($JZML32S>${uR!oO7xrlzAC0qx;wyX79i(9aKviS4foF zm6<*A2RXe3ZgeHnOrk*#VE->1*;MFL7jnKu$sie}f?7lGKa^tTH{MYprT+sP>Z7=;(DmsGY%5_kxa?dL57LppbqLZu7~QyIo-{<&_=t-K@@LQ&bkae% zo+;cOpmeO99>n=d#nnwsu$H{;@V-w&D=l6c&BBy|UuRbP3eC*tU=$yXZ6XN6+|R}s zE-%~PZXV}Q?^8thulIurY*P+QcZeBY#r0DDtit;Aaf$1u^7#>7@k<OqYy1envsykLFsOw~BZ zt^047wt+oi_BC8$1DVi*QssVOLn?|?N>G1$e(;Q~wibPzSSJ8ObUi+F#47IE=|=oS zT!@j0V6Lmj7An_ab)8B-=oT$P3_sDiC2w$A8KvEzBcp{O+R}q_v7h?3*P)(kpjh-$ z+5;4UISn|)u0|%5D0itjq%lw?EgIHsN>R_({ z0xEBYHorrCkWg({7R&oA&#QsW2R{zy7cQvzrxH?VJt`u+Q>Ctyk6}ELbYAzXEgO;~Lal z9TS?j*qM=p$?bD8Oymumj;d&@ybn-y;u%=1RoJtjp#6 z^kxr`t^Vw`Jz55?Eyt-u-l~bSNb0a74kY=8wWOs$yojT77%nB z`_|Uni|BiNzk{i6ToIdr6x*&Y%(F1*Jf9)H1EXvpD;-asNO@`V#ls*2#@$U6UWzbh zt2z!pvZ0AMWowtuK{9Uv>i~fD;;8_UyDrtFu#RAVVr~C!h?9Jg3x!SYx(7E^;pel` zX~O!A+&5rAh2z=vxji=~VMP7Y)pq_-f&LW#2yBzIkV;7@R6oUAyd0O{(d~CHv?4h+ z^A}azh;$4;??m<%zswBhgz-ZjSURkOx^w#)XyQT)UUFSO0j)Ob;*>V3hN)jEtz6fkoS23mDb*j#!B&k?*|20kpU#r8`~VtS$AeRKcKfC=;k! zbo-UGtp8iAS|cal4C`+>Q)o3@vSahj0W}^wG(lVRX!cHjr8wX{4!LoSmga$*!#+@x z=o*l9iDiezV8;N=YQ6ylF;n}d0Wzh0x+Fu`X!rSu&Yxn%l`Z)i%1c)fZ=gK+Vtw)) zI(8@b<@C}IkEF9y2rK3d=$@E-h~s0ooQX7F{p&$cj8pe^5$DGFmgy@Izj!(4No*xDdUZ z*IobV8S-tl#5SO(Ll-Dn)Vd9HJr1ll*rTu=VGNZpOghY$<+iUakg9M)_ynaCzyD{> z{bc=>Ys|SF>$6Nn=_5<+xu2{_TaWK`79c$`NA5Kxg;ry+uE*qJx$SHA<9_}Bl+Fw5 zOws`yKbeS)i~G~#(->}D&vu@H|26b))M$;_AcEECVUj%d86=9&wi@YLMYb485et__ z;(l8rQ4Nfk!2B3VxE@q7(Kdw3O&kbU;x`g7UEC8qgL`|#Kg49&R!eKy&am?g`zu7i zskN|FUV0Nv>iEy<={E)`863f~w+MiHgw1KWZEL5}Z9!r-?lH#g#nL%pJ^XCKx=d4{ zd8Eghdu~lCc+$HLzww3xJ187QE3UT;9qRs?cKjBECjC*fy>T&B=9fiAUjZrXH<-WC zc4Bz0zE5>)uffH1*gEDs16?#+?nU_)ArG5@i4kg&oI!8c5-;EvFepCZj%@jBs^J@T zA)l>AEX1I0xKS`q)fqPz$QyeQLqF4mxLyS5uh9(aC}OeVNq_Q`G5p&R|IVPw^QMSc z79mJ~ja-F{Eyw4+0KT!+Q~nJ5{>J@)5AjRH$N2(N{IumP47$+C`_t=+%%SD!XI#u+ z+gfB%Tp#VB)0SSjC`oa3)fK_1@o8OAO8h9Me}q>tO0D=IWfMPud8eSla+!k(UXp>6 zqThN_Rl^M6Ar51K9PMj^(0CsL?B~zILEb<&P~q3GxUN7f|HSrBh5zQ{zAO{AF3{eDdMCY^D07^%MrR1)f~rg9D2NZ;%^EUXL+HspFLv0~pl z4#8zf=ZyHFf?*Alz*IH8;YNB{8Ybh_cs(9+7K5$HC-3kEG!hgvNh5(ZPzsL5EQ@0G zN=x{srJm6k)*IeHxwdyZxn7b>a34sfVB7Kr+9^6 zyV!qA?CO9Aw#I7t9_Sv}{48gY^&Bgy1JjtG2G?)?t0;L*Y-1sve{zPSlL@)YUO&Ir zxGoDb#m^86lT z&p84#M~+P!OB=95F92<_AeS81w?@dH!0wqQ_F$4SANE2`3#CHs$n%f;gw-&7i+O$Y zb44FOi(p2F_8)Y&Q$Chhh4|P)w5v0KuX-%cURpLN`{qRUn4bsRK&XmXzX3(An?hXU z%;sg_t}c|s-h>Mry+_UAB;t6qVGxmDLI3G>yo5+%(z!O@JxsSa}>%?Rq<>YkHpj34erz5v*-6)*wDb=zlKaVQPp&xuu zPhe+EEE=Ejdw51O1E|F)l2ek2XhR7$?a(TTV5;ol^7-r&7@_EZCASK|t$3f&J+S1G zgd4lk9z42XL}>POt)(v|WHwE+YzEP5hS6=yl#w=hs6}!wZjMK50>;oL#qKYeC@ zjmrbnxI93OO99csFMr}ECBR+%HoFtJMJ9&V6GLlY6F6ErmX)a9SgPJNau<$rPN5Ez zb42eAbc;d!SOV|$gAE(3z*eSvaxYfi1Pd8`++*Tb@50RxtL&9fA!rj6WG|{|qaz%- z7dQPOh9~y>bh<8qcbFe^hQaTDP|4U263(Kh!GgIkHu6seT6iYSKx3|(2c=brK?H*eN zqNVeu>MAVBLK4x%0Ht4tx1CQ8`3`&k8u_!9FU|Gy{tsdA0v}a%E&k6WGkHM536N+& zkRVu1p~X~bi6I(+0eqm57zk+4wwlgOwe>LrSV=N*GMba)sJF_mdatyk(R=Ovx0P0T z$jbz1f{$t>)KcIl5vZQ=a5a?{B59f5ckOc~lc4QCpHI%5vma}})?RzrqmBm=_JI0*c@GSQ#hf{@+ zxs(gq`2ACzzDAmBl;s#M5rlEH&%Bh)JUapD8m;Md(j!zh%BD8XTIyT!aN-n`f+M^) zdIICtzoW!6=1$c%hh$ihT|^`N>fQQ#oS$dl;Af48rnWSFYdygz7;Z7H&%z);+ca9v z*LTCe>29OxThBOf2*PTbiIqv@y+neL`*`gDw(^jW6D*Fnqx0sV3eka~VHrhX@ zAn`JxONp-NJj4Ns{+mPh!xxaAEovlqIX<|I8w-s2`Nq?eI!Tr~ zTF(iik4w=<8}lbnuw7eo6sV%_iakO(3&Oi|!tvDl^$CoZp0R$|@d2E%scm{LLy9wQ z%+kjhH|85-IQncfUVRoceu(qiC75?qEMX5M>yT`N3$&)7RHHhlQ8rch)HQre zm7M6qw+hXa3+Fl-&-{WSgb3{A!nqN0b*I++Ey?8r-(A79F4qf^VAEV@B3x_uCNL3J z&WH!Gg3M109%wJ-XqO|uP}^VIVAJqT{}OzE4uFF1!Rg?;w)qho+3V^-^gm*E((zG7 zbi!pV;q@c~$rr=h4Mp;&6nfKx`EuBQg7K6>@f=b7*(jdb4~EkYLGk+GD6ZB4>$^^w za~Q0|XIS0tQ)cH*rjt6tqNr2%;$-irZLhR~_{WlMlq*&z%E)aQ)q5Pfd2LmJMs?ZJI zojF#9yxr;D`RU^1I*LISq}f>_`)vuEI%K8JgUcEb9Xt=NjKVQKlZ7MtFWfi!rPdBe zLlJ)EwQ(823NsVu!PR*Mk;UYwOY1O>?DFRF3RW?VGvHeDornr`YB=eJvj}DBrCLOc zrlU8zLl4T8khe+SN$6w=z0a)&Gg_9pn+|DBa`#?nV7hXU85$^5vU9Dehf+cVHL|)5 z_!Fz!=+MA-gL4~86MLM%w_4`A5p_(8UX#K`q;tOePBsX(kwNDiH}0!4VjRG8&Av03 z9lbdAX&(VCqe7o6*q;x9&D9kb4S{`LbiM!$t&ZO*TQpg7MBgn{7~3i}u#J$@ zRpYI%Fm3%ZUCYfyy=XA(z9PM=iUy#L|C&UGFhfjic&?M_S)IZ47KI$WAmQxkS|n8h z^Q2>w0BBE}gy4#V`m|i{j$YF}o71jMZZ|?DSPvYdbr_=C>P< z$`Yj3s%VAVnrug2L{*{{DXI?I&be+9k|bM_>XjL7QVW2GW)%i63YSWA+`-)BK^PmE zzyz1Aa?F7ODR$(N2$HLefEOBLT_DmchC&dMesWYA7;_I_%^bvSYF|?EU~RZGi`1A4 zDkj&Vb6ArSSZ-ebmm!P0%+s2!JJVm?35zUN11T7Y{v(|&;b&XcU={nSVx^#Y?K#&z zc)C@`QhG%%+I(jhB4{*AeZsUd?RyL=E24{$g_SZH&)@-dcbt? zy&ljm8roDED=(e zP=AGGw6ZJwzY?`@@nK=%xOI{&w&pY1C{#wY@8!{J@F;Q(CxWl(=SY3OU$#R2W_buJ zr;smx-`{O=qrYj6hn=#0>uHS0OO}UvJQN6{jj)~P@BoeV7C4nV& zGi^%DAYz3`yiFPyJYUr^$;fI=bIB%`#~=-jQ@WtLyv06|2@S)iE*xkRv@?9iq4Zv{ zql~=XCTOHJ?Iji4^QI^H{i3tr9}#Lh3)Y%`ASrAH+&(~+@MwbdpjVukl>5ttdu}=? zgJw*WZit2xoPzRBJfL_5xwVjM27iiZI5rNTMW?JQ8`U9vwHvw;J%Z-{9-!n32Xm%? zvpu?m<-U$5rHlds&1wKFtC9ut&x|4ap{?WubzYJbXa6L%NRYgyld$p0MK*Sn{x;T% zs2PhE-UG`LjTxnF_I+l%ST5ch93P$YZI-mRNa#Nf*m85#A7$cZS>uv1H~T+OQMak6 z96Ncrd5~3ng;nxT9W)0D;u{YGIJ$0+fH#3rVdet^Uuk4j;`+pP1G(`$Wk`+8ZbY_P5uvgnw)Pbc+DIJ`w$g{38DEb{LnGwLz1{JZqrmzv}WSGbXBnD~o zX#660yVV$(N{oo1K!X+TLz))=GtZkmQQo!Hpf+d$5#b$ai3g{cNNxKmW*U0$Jo5`?If zH~DLm{j6|hT4XJs;P6QQ2|?eh!Gl{JZPzx@e?dP}mCxY`oXk?H`ZvLFQGPXyFjCp@ ze4lN4Rd~0D6HC@Uv+hcO#AXF;F%?Mm*$E;v|yjAa{s@dUE#h__T7mzI3^>zjrt}+_wqzPuq8J@`3 z32BujSWxsHAt>UecckAV)c*SSge;y4+uce0hJKl@$#pm`B?1w%spaz`-+6gY*$ z9m5{$JD7AxXJS#1TDdn|Dy$+Npi7jS|KK;pBM?siTNs(cXui%IQsQt?i2KOrcJj}JJSl`yJ9P(v-?wmx0@50*dY88 zBTrH2!M)s1I`AKF@8+P;9f6r@ylq@1v&&pU5i3GlCW*O+)^rJBoyth0uroB7Fjq{r z+0KAYlqUXYKYfn&?dQp+{slnErXJ%{Bl#8 z7Lnz{DPWcqFpdJMY_u$(Rmz8Spe_MFaL*F+=leK`>+U3XAoa!}efT@(*D@xU>cikX zyI?awYIkR6+6?%4XCmx{p{h!DLSjWpIANzkuFkXqNv|rFi(-EP`9T?HNzG(1-IBS~sL`hEHs;ZU|q0grU zW)14&%FPY5h2yM&doa%Br=~Q&TO~?ikJhA-E^^92ikO*f370DHVPs1^O0uPk z>Ms1(U1j7+s^WL+=Od4K^I|!YQ@ERb2_@7|i#}|NpQVS}BwefYa9Nu?OXhgi?269G zXp>0m*Sadr+R!SWMxIoF{U1<_D$lfulA+^RW?@h9$@&!iWUDxOY7=G5(u&3GG>BD@ z-A7VW%FWG4XWbJ80$i258r+nW@>lr278wJA3{}0HJ}?Dy^UDS~fKivV+p|N4+RA6~ zw>#2k_A|6jcg8;$99216Re_vBf1@N@h7v_q$H$YxZ^kpb@ddAX5(CczBHb5}wi=`|3T``Alo5m)gk zCfJ9DdMv59d9jh5Pn6n1>z(0_5qf`5FB&pCnD3sC^!`_6?6C*dUg}$7P66&sX;Ydjc9@a38P$bcO&b0rtLGTkWtl0MWU$AaAZuY@ zT=c0BX^n6dPxIT1tH{n*3eKqNDUejA%d67UTMEA9iHX~7ZTsHBPWS7ui+Pfur?(5}!4l|ySLB5A(G@Xy zBa{Tkoi{FM;;m@k^>#(|1Jv^L%u5*=cF8QV5#dyNKJ56!Ypj)5ZF^^P$BjK_^zN-L zx;NFEOVTMDC92GvuXsSM>1pbKDd+(kkOO(`9?}3^A#~5tjt{;1yB)Fg#$5tOQ2AGq zz<4}^Pj^(kN91Wr1qG3>0;&xwG2#3nstDqAD3~2)x{Z5+xC@gwJb8D=vGnL;yHyl0V_= zRxP!q3?qt`G0~>HzfxcYuJp2~E)_INRVLqG-TnG!MW;HO^2M|Uv7OAT==HQPywwkI zE*#Oj6GT$)RGmk(zN_bG@oy)PAi7o{bG4zmUvaTA`$yg@3!D7i&YUZVZKUN6HcRjI zdWC$l18Tq#wp1o6Sca2do_bVp7}zet5_@gxG~u8V^giDdteMCni#Oj(|()3g1Il&j_Y2u=@Z;-R0FgHY!+uRR9TrhNfUr0ps<)2SsgNp_w)Bz#8ja3_3l1ZyR(bcfjLoB3C8ooi6sx4GaXU?5M~Hf9o9BAm zDk!{FzFk_=BVeQ)oUTTJGvA*^#-f?94x=bCZdE|9n(U+>_ zw&ug`9-Bk>x?DlQ@w^?10BJw9Z58q(uh(aAh*xEgZxn#$K#X0El-sga3TwV4HNzMw zx01E7Y$WnW{*QdvJ^6*gw8&~=Z5-53+x^izDmE5qgN%V=nR!b>h&9Oj)Y<|@{ZCw_ z`h^Qr7k%LZ)sinzsR6J*R~fOif~}N92CIbt>{pBZJC%u zn0FtRSp++zHHm3gsIG${_$qHThVQi+-S=y4bGx>^z3tMojK!wP4sAP!;M=D2MS?DE zb2oN(!BnGi{}z`DtA3*fhk51sh#hxnn|s+HQ(OXj7t@#p>m&>ydCvTM<>R1*9 zN6R_vJAq*C5ASH3$_q|y4%HwKjw}&W^c_Y^FiDr|#rK4dYGP4v72(=Tl`k5;=V_Q! z2{TEa^cv}VnE`x&<67HgyjTnIyNlP_&0MNK&(6zwL7bftMj_V@ z70$#7C9RsN`d_romA{tBistmnn#Q_cyHbMRFtVk83;!aG=sCvCfCa76Cd3`}=V>pg z+HDnnR<*js_hP*V!v7!_?#Qru#2`hQVg5TZFPqb?Zj~0{els|#@vaS2S9_IOYt~fG z0%Exu)GihpLKrZ88?5Y$<$&a?E*^YRi`R|H4VfL`H!{MnXK-`b8?t}B0*KhU#$R@W z++rs0Tsg}%yj;gQi&*x5&iRMPA)CW_aF#Jq#xk+X5k_S(9!Cf=k0Ax3wzeMP7j&-8 zf#?Tg&&kNCF44Pt`q5q}!V7&{)E8Y1msFBH8vu1!gUhe{=@ZL%L)7xPPxAWMOG=dX zxNw=OFN{1%p}o|t_e`58O<6qx`?FGE?CML|=k+LSQKy&NB*C+VyH9_f>Xn}LyH3di z45>we{#Co;GK2msWgjr|q_^MghlMplk~FA=j=2M=-29_D)*2B$gI_Au=OqeDwCGFZ zWXjgFTb7|-<17h6NMld%Xp`!;N+ZfRN!%tcv9B?Zt%50bV=yoNIAvP4OfH36Jx7~6 zQq>$0e$n1m(&36DtgyG1i_LrB8Qs+xh3~toPZTBhlyQ-FB=(fCmmzELjE*cIkj)j7 z`>afaEOLlfAMQO~$$PHYCKYd$$sv58Z!cfs&lNZviD~B$K>pS7l!piGJFE3dBDPlaeXOD@S0mprRDv8%8JMFLo_>$XzkzHVH@ws8F7 z9hU!G#U%ZDmy!Sl(?WIc%n1Hpqp};F-7q3gxV@a9mJ;D6By@jm0sIhr1h!fQw+7Q& zeEZS%U6GKNOtm>hXQgQF7c{KwZt=Y{WZgw_5<5afOXZQ!87+8U^R5@mII4g2YTVNx z2mXG0c4x@-nXHMMd>?Q&j^GmC9+n+BbCyu#dn}dB%1wat?3*5hK}ylB89w!>)PXLS#wH2c(u?O zHjL?CZ-#ERcYlnSIEC=L3mlk=P-tkL0OU*MKs$cPHyqiF@ zVs5;mrZ-I0cFvoL)8J*`LGvS$lu_WwSYTwiIfX3nIDz*%Rm9he4$X(74G*L=TuiQs zhe;v1nl5y*33ia}1c8$658(lK_vA)3?YZ@;xmg&Qy%L?v~1Tn$gN6I8;cBVg*_4Oepy$+NSCwXqer* z^gO}u*u@~okhTAx$UPz!v?0szL@sTos$%3|OswM7 z$i9<8dXAM$lwe*ou9Ugu%~ z8Ds2YX~F3peV5)j`5?ykMqW7q&F}V{4WAv^prMw4+PBkNEa3NN7!##CtkIJXrsiG2 zTXcDR%ETLZ(fiB@2qc=h)z?m|?kgTZ$TuL%pCZQ`gtI%{-liX2Z2mzc_jpG^yr<-R zNoowCE<6GwN0*$tE9Zb`^6vCkg#GpSr5Dv)Y89jjw`alWNN=`@7Qo(W;bd}<)`v?a zgW66Fg;jRWc1n)#>verX_(f(Rg#Xh)!oP95y`zHgf2s(7AB4Zlcbq(+(eV1O%4ue+LXz$&zT?zDH!!jx4;v&q z5sZvNArL6NRpC#*190*#2aV>$r+5X8lmJpq&JUNEzwJ&;nQ_S(A#JSuv^j^RWwTVH z8czWxR^XJXwpza9;jQuk13O*_{?M%qonWtW#cY}ad6;B+MJmmSpUdbdME=VgCY?(+ z2NRjw*hnlxS*ta5fa&=EBwznFX9bA-im)#&OpE+jQPw_VWQ*_9=JePt!$~G0vr!G1 z7%nNhMDf4j$dH#V!LPKD_e-!t->q%mrFTURJveAuuTBnB+arfMx_+_#IdaT?_ip^p zOz!;6NWK43SnI@Lf(sId3C1ub6UPZ2+oJlHqjv<_Ckh4+6x@dFVF)>?NZPLi<_{9{ zljN6Om`%(v0jGCiZ##mu*5uam<}_RUt51~iuyr(ocnaUG1&V_bQI_9DO2urNX^fbx zMq&dYq3&QlXAT#kIrO{vG_$r!jm7eRJ!|G99Jwc4UL|z+6VQk}N77_*^emPF!I5$7 z(<(DUSI)3bqGFSZ$eb~i3m3D+Gnz?*3JZ}^=v7CBB~d;zG}}ER_#U<#aO1|}5yrJC zm>27ddL#R^$3KPy$+_iTzw60F8|EOKoF6V_p*L4xe>%t*GxnXqH=h#0LcH;_%s& zl?7};YZ}*l<7`P$FgN^33dvSx6}5-fd?WsKc&Wlp3c?gv+tg9GD;449kB&sECZF2v z4x~k^E{gu>eP<`r>3g3;-l^InmkBL;DAgU{?v`dzzSy^0AV6@JYnxK}pUd5X6{6Lh zyGbFE^$=dkN^ivXN1(7FvvjVHm)otH(#4B;$t*3e;%ADrB=k^;2Qwdk3tUB$%>thB4P8txb~9Kz6CCjA}gH?rv}P9U=KyE0eSrtV~61 z8mfEW6=)DRgES(TC~cCaA4jpyY6f;|o80aW?D}zE6uSc= z)p*Zw*#d^~vKA9pb<8AaZD@85^>s+y>QTv+0<-Az(ImTN*2t98nq*Z_6l#!?h^7tJ zglqP)!lhDOSKwadD5+NIL>+Y|%t%*9d?d<4h6xW9*KLz}B=*!v&0(uRfOfh2E6g{~ zIHcpZ&Tg-7fz4Qm#a?2gXZ@B*kf;pji1E+EX(N0QEy^f9xaNWe4g%kwm%1otY;|t& z!G@7*_7lg zR)@N&lCfn~t>m2aUfcZA$h(E2G0e)Y;+Ny>JYB&l#cycQ|Dsd0oev-Q4Ln${caFE6 z7hNTf{Ypi7^Pqr4d4&=dzfqTiOP>@;YNxWkO?!xGm1zCl%#Hxp+wtlb`GqJcr4v=; zkk&lBm)7j`jwW53)QE$=JQ*sgk|#)K1s@8}NzFm9!oR+NBi!x9H=j)%ne06lCyXLej6c47fa4vMxl`Wf@g6oa+oZG9JXB3l0*o@&K$66rX(twgSF-@6 z;*QO?e@pKM2!qCyX9FcGU$C#}khW<~s=mu%9`!#G3`XC`5piP<{g%F{J09%S_qHs0tEc~2Ey=v&7d)$1?k%p|vPNt07W-adFH)JMR~|-8v*?v+i@NnihZSJ}2oynW zGjPMvr@io*0*5D+fCF*6YV$PTcB8tloHksaRdgtmBf&^%rK9x9c9jFi-u48Y)+wa# zFco&gqz%%NLL71{(rf*wr0&F;V1pN$zw!r^ulMOR!!9>b=pNM!+~U1LGqx00?zNk- zXRsM#rUgyupbu@ra7xEdQ8liLy4?p*R@zo2hd7!d{yAOqskr$%47^5oz!FEJXaE^WJ&_q73p^Jc9`CdqnRi>`Q9Q6j=pveujX%{ z*LtK~vPI=72zCt!#+d(6@60@6tW$B=D!z}7d4kwH8nO$_glXNLB;oHMf5Go^48 zh6~j!anZ;LRjjIM)bj@yye{4;6iHXe6Wv05s@)3;i#XlCZaZN^$kQ?VhGsHF`-n*_ z1%8=q>ac;0s2inwY|Q(Oog;P`GYd;P4=0f#@ilo3)s1ImT&zsK(i?8#CZ1K}@a{~$ zCH`KTU2e|XK<|DAD`S;K;tgM0lhJtgtOm<7#Yv_sePnr(cQ8d|cB{T?MS|s28q#$# z_!|Ww^o=s&C?0vvz{GYCUmDK{;D$Vi9|s}yMH$UaUzJ325EdT8fi3_o$B|?FQanmWmfs)$O7RU!=}7nty!)?}gtAdq>j$N{ zTKChdU0zuaXCN1IwkH`Fz!04Z1H!`*l??Zy;ZHU5B|@zIgK3tU zI|;ylw)DBDn8hGtMfh#yZF(%oN=9o&mH-CiBYPK|8AB@kUgQ&RRi{BxieBd-Lc7*9g;Sui%i` zs~ax;!rJ|h*VHJmc4sBmZfxD#E%t2A9zVGje?dz+&9)GWUK3(xy>j9|G5^AM;;!Ir zFfEFUaId^sv3j-nw*8k~1JbkyW+8|YZnCstEE6ZQ^a=SHWnl~-0Ka68TX3H8F6R&7 z#9z0(uL{~Jw#N;(zSuD=Lof|o7zl2@gKyS5D;jX)-sBpE3On`&Il`Z$Lzc+fa5cx% z#rQ!iUZWCIdbc2RAZKdj`OXF|(&svf>nwp)5Pn-kQX9sMJanVKJgS4#9bXB$)+rxbm*Hfkw8Q~MNK z;y$8SlBj14=S+4aj2o3!iaDF)Dy;wfmoiVs5-FcTUXx+6jX&%+u@WJOFl7qBo3=SG zjll;8WTOHXN7e+ge(OAYex5Ba7f!QlJEA1L_J3C{;ov`li=teP@Nf_=dUSeK@B7u8$lIseG zUNC$D8jO^&W0+ZusPWF}-q;4h)EYNf=c@m<7p_Z&cSMLa?Aq3IY-rx29Hzf+mvfFd zik&cRb|k&Y9xWqisNu|y>0DN|gbU%Z%7t*xf7#2IH#9IK_#v#}5c{*Jm{FBvE9)2z zQrgxrj$t-ywyXKVLA#i5O8u1a6&P*ivlb=C9*O=aHH%COco;*BO-f^%FJuM&Tq?F! z3WI#|Y!!N9&yVO0?v$uK1yxi{SbZQ%Y9bS+FX<_byDpL$8to-#=e%@0W;3L^vg|RR zrFDZO-?l!2@K+(#8gQt7k&-po7BFf8{1XcpG5Ik+hm&8fYS*$>ifg_lJ*CFbYQzZU zZN@je!v+x%0q-zju2Y;A`EO#h&7Xra%@@X=qn{G%f^GLp)fd;ILdxl7+HJ}%;0LQ( z(?q=xa~#4i0z3diA<#8FKsC*mlaEC`%uO+GyTGP*o z)DO%p?p||Pd5&b|#82E-VeetJr3%V_ISNRv=}!V^V?Xi5C+og~Ex=l-*4*N!BeF3F ze82dl_8d%nR{tp`KbRc=s{W-44#V>_~^VM_mqe<&)iARinjA1;1&;s zo7)ZCu@?7mNc9U3Mzj9iuD-EDz`2i1*&zT@OQqB8>T*($km$V2QYLqEkqGbH49`;u z>1=s7*QXPZ7^9E4WN}M!Fl}ja;|Y_I>Wbu$FhsNM)wW^fea;m@{r4yO*9_J|za8D5Xt95bXujA~;odZA$zSwt}+wXDC@smN>s zzs;AOQa}{MrKiga=U)HlCEeUb=IEffqvI?sam>nx>PkOM}qDqgU}H9E!tOu zDUbH(3zE8Rf*KZSSWVkSymP0EYUTFVqt~2n&Yn!r&t;-)aor(y!3%5Jrt(!gfu6mT z7xPV6KVz+ALCq=?b5B-Hsq4a3dCuT%k>y`ZO7|6a2hzERM$W7ms%|x1YEH3YfVpzf zV0gzBQco@N0v~M(VKz!r*|N`+smOurzT!SDvO@K4E-_o#>bc5MZ(hh`ztvcmPuOcR z|3LJxxXsWf%7ir{lDJHdWF4WNk=()g1M49)F&fDr9#7}~HW~BwR(mkCCwc*Is9eP= zmlkW0iOf6@|l3qA~4oUj*_+c zga_BeRT+&yO>?dKZgk#HJf-rwGP^6Cu=s1@p$jkM=fhNXc}k*^^?{3xrf2~#*XVMu zh8?K=SZ4R<$=Q9#Nvx6higyx;t=L@ZI(c_Y-R`Bzu9>F#i18IVmza4wWOmtzT(l2r zBcEzwnZIX0f4eQjG$PZfBkYXe&*GweN_xP3Cvr+>t`cg3aA`Gd7ZSbd8#N1qg-}yT z3&#>tWeJukwj1+W3F10sh5%Gjwy+TKp>9XuP%dlf!+u3MhLBlojojiA_y_eh8!jDE zxT=ie@mf>`jERyAYvbLR8$O&8N^^0R1y^!nhFsjEMRo#9nL<&pw7qzDV8Pt*>~-^a zcLhG)Db*%yKGCY`yBo5^6fe3#BCHvPXPq=cKWKXCUcHk;YHX5(&#>$}7o=&TA+=a? ztvVxD0e(&Dq;0-21rcfS8~VJT%?oC9@g$oIcR1HaJ@4Y(Zr)}2rrb0vTH!zkW-ASt z_ozlW!w`K&S}`;XMWKRRkxRKvIa0?q4(`E(j@o=i%yvRaawYgaaB>JQpj5q5Rs`7%kz?Ra2 zmxq6ZE8VY!f5dUwOY}TxnabU=$kH}1{<0QYW5T=g=UT5M(S)tQFmI!5M`j8jcpjrP zOEvvOalI#4q(pmVIQj4B7?^|)94@p-$9oV)Y+1&VEZ*S8m_Il_O}jr2XQ!j}Gp!lq zH~&9ID7H)pW5U&loIkTmX_XR+=XlsH4L_C-#|7Vc`DPApth^yw>c z-o)wNE>176;5=tSg%f)gG>dw!tWaWs+t#T`920IbS(mfJ>f#PQ)NxNAN>zn@J$Lm< z&HT;9RcEPsQ=N*%q%V+!AF5U?QMER6HVC7fs2a;Z zx+nJ$TknL_HjrgKWnRL%5nCtgmUDzu)ML}|ke+hxxx&U1mwIHa7uHlJ6TIHw+kwHi z{ey3^&0}OpCo2q#UV;l(J23Md3YK+m1-zGPq_#Ozy5k5`gx~LRyAFtkNiAr*_V+ZOMNq4nlTqi9;5$DIRvn;yGYo34$aL@G@px>A)>B z|EX9qg6xe$n_wg6&^(hnH1h;BlohZDJ3{&AV+7I!sJi`>bNy0?1xnA+~rcZA4Di7Bz@% z-6J!!CcOGQcQ8k0zxXJS-eCd?7dqHvyS1v}W-1MhZK9%TH#6K=VNhyacFulKW+my_ zNdQx%obn4h&a-7q^V(1O9Xwj`%V!jiDN;@e7b&Mo-YGL*Z44cOnu=9Q1L_?Stds6D zzk}FMaA}N`nXPD$>ZszIArE3Fr)|D@jDuv?=5PxeOQ$;0fItpo_f=Ufsi`w%qBTd} z0p_U%qdbA@J5zDI$+51Nsa(ri32z>|d|7yh!u0^2rW!6i*BVE%nBQPG)uP}ur&d|q zjS{#jt_llx<%D;11IMMGv>sJ7C9&J}SQ)D{>!BCBj@Tyu^%GFq#~NzE%= zZ555B9-~1nB?mfUPkE|SN-@!KC-#7B8}LNaO?N~U!-980-V-~7W4OMBL?{;*wG3Qz zoha;Vs~?90|HV%n9zC&HcqS3RW3`3po_?VxWr)xxjrK z7$|K=4jvEGz#_<7bWTpO?dkN|q&+7aWAh02N7}oj%WQMbaqe5j;fLCzvMEjbvvzf) zLTyrAJx?lXjTF8{m0~?3V!zc+?Yq2doVTP8(IM8Kc`R9;-`(5JqM7^q06(!l0Ndt# zt=)VN3efe=5(N}04DFu!>=(EZk)WRH8 zbScR3nFCA9mzeJ$gCTJpi29jFbfq`VGJ6OT>jYy*h{^UHw$Z9+klVBTxm|;)e{%z%<+*8 z1U0IezVGE4EL?BKvbGI z=qbyrT3pXD7ENeGmzb?c3IDmxXmysRE>HiL0@R^KqXmN&qoQd^Sd3;YZWXJ~XSt=E zlR4OoD!b5x4e4%_cgLo^7nCR~~5HPOc$H?bTk|ZRH!;69_*2E+3QMoHG?kyS%y7_v6MQ~ui6}!38Yp|y zMSY#zOgw0B`mEk#7pQj>_ozbeFT&A$$NkfW(rT?)mtq!)ooC`Cgre1>WB01^k5BOm zZYopMpMkH#O;P_Yw7D~~Z}kt<-cL+XFBxKriZWQW8Ah2}98|RcZAW7H;~1x&-zw0j zcop7y72cj}o9gK3mzWv?N;PJ|adw516SWz?4l$WdOoCzdsn`^Tx5)m*r8SA-VAujY zXrels@t4~HlUAyW&6a<+mxq64rJDC!_!MQOY5-fTRAq@RC#OiEv`Fxum8eCQ69p;3 zPPOt=7QyD6*rDNz+n1QC%98ixz7DY07pDh5r3Zpo_0wL*qaMq^0d5(zmjO~q)Z1r% z^*%c9AwCMo@%2QGa`V5*kPx8WjPnkN9;hJV@K$*@IRzZY-+mT(Qj+ec1#7GYepmY- zq%QCCB)^noT;|9V7c6|spE=L2QsS$h*pro89%Jr=HdX8` z6pPo2uiLXPb^&$5aZNCFzSXavw%iL^(zyi%g~6EFGo16vQ=U*m7&zXU?!qZ={nFv1 zf6@_a&ycG`vbh!S_fcoaC!Wg+Rrr4?lBBN37}+XPwvmz{<}gY%wF;L?Gqn2e8`;uA zW1_U%$deY?EtEDJ^WOB#S*WYf;$17paJN{p(QPW9%3ZXtBzr2YeBg4`m#qTD8O&7A zo8?#-so`vuBK2Km9Y?)w^2+)1cKWRc`LnuYp8H+&v(4!^8!K>H{a_~EclNiyzFv~# z$>7K?4Aq?!eaKGV$#S#L?gFi8H2A3q#ktE_uA`q*xKMP+-0=@*SiV*!1jE+Y;rwP_ z>vURCzl3e_2bs~vcHkB7dSFa+t0dz}vw=>Zg_)tX027ps!mifYq$Y@sZm%&@I-u~K z!Z-2rPj18wns~@7eg|hE$hiM(jlrkQYXV4sM4u7hkV+OeJnSn+2HMV`RieN=@J%`6 zP~G<+Tfsgz4iR=^Kvl6ce#PGeC(W%$ri=-Hle*$Cg+puA$C)hitzC!~hBSSs?c)6x z$R#F8+r?EQ<&u+Owu}0^m8UO0AtUtXilRgAy`v8r*?oKtH@LEWoM3w1+4^@$`^RS6 z13=Hw>nbLHrv2({&!>v`>1XX*bgdVK0)$Uoiba8Uy&ScCJ?BE@aXA$8PuxLow+ zoVDdEK2yTX;`IujYr=KC&}iYZ#U)v7MttVdqAhQcEPE>i)B*@vEOB^$}(=s zC~8k+I65+(E#0I&|K`Y!4@RntCm%V|u{-CHBltjhzay3>=2n>p+x9wu;*%JGAx^XZQ7>~Q_eR5=3SEmnHSb$ zE!yS+Myu2>Z02{Eo~Y+{3JYaYIdq*XVw3(D=P8+Es8r|*G?>*F)ty)9h~jDP(CL86 zEVpBj5&JnvWh`oU3|mtd$tH*L<5-58OJNFQ-<1ULHw$x(a{SjHH}Z{pJ#hFCUn5Vt z$(C_e?#B=ogVmNr`lJg=1H_O1Y&iAQeOs^;)hoB_zPGUR z>@Kd{et*^~%vHDC@8vL_m1fj!nO1i|?Q+NtXJ#9!ex@H-s=aW~-V8WqsvA^orujBN z1;NQzjB7HCo3qRnRHoeg$$zpF;)2~hIfb0@8nAeD+@kh+D6ZpR?iuIL`SqNAr(V~x7M=a|ju9@39+bb_MX{kXN2G6LgR+}Jsm z-2|s-{Ux=!cWm&uUTx|@u1Cpo)#sQWQ&G$@Idl?v6sqI2rhUk?P+QSlQnbzj0~jsF z$F*%g@`GaU6@;w01!XwDs3rDkO$(u(xIW<9yqrmAWeiQo zux|SUZKd5(U){as2V|P&GxeK2*7sTu$h^u{#rTeMZif>`SnpJxh`b)0TJ*Y6o^F(- zQi4P2DRg*YT+l%RCz_%-s2ARyD%TJk=ek^qnC9yZw~uU-V${jlR++cO-r2Nk&3GKD zDbr>St@AA!tMJ|&HSV<>hoQ&SrL){VC0(`4bGxqIs^GvSG9H{-(<-_VMNz`->EYh~ z=)He;&lJRodcM&n*{sJo*(GL4W;Ua##wyVmS^2Xi>Q;w_3C&l$z=~}GpW5qgE&vhD z6a+imK1LOA+CF<|?qIH`&Xh8u^S#SeVaqtmA6JN>AL#UqJ!eG-pO`0SfA~|xNxy49 zAdNgBi{akCV-?Oz;U0DB%f#Y5I&Z4RXoP$Fbk5pm3oSG-z~-rk;Cfa`sdoO zPWF6qs-pk{@RJ-LuHK^u_bOFg(JAeP_tnJe@`*o45MYaxO~UtC6RWqkEZSgHZdYlq z(}V3(Dv#S)KDKA0lMK7~Jx28_dT`72=45mvQ>u?EQCobbP;l*~iSkoXZr+2yaQ))- za;_rmpNxRLw2yGews%+F8TRGQp6i?_s>fMB{}uNZU* z9*WueZibscooT3dHGZTN3~^h*AZHrlz60U90~y0q3tthXge(OMpDli`A#Kgr;@$T< zst09xoJPDpQRL=H2|LDg-R2P_(MEOe?Jy6E4p%{OjB0HEk7M(TqAy!5WfNt<2qV%i z0+nqpZaIx$H$KeK3pkg&AH}+!8*Ra%jMx>zt`8IVKZvee^ve?)<4WK^FJ7&nE4EAh}V}_&b32|;u<>hY(of@q@Cc=J2 zr;2&8ri1;m4u(qa;^}S^8fOzenh_T_xt=y59kG$5PS(3N$DX|E;_NMRzA>+Axih}S zN+}+^Mp1#VnPJcM3_JPV{bKo`oJ6i@m3irmzLU35d;v&dA!==8%R*YzzBNOd@T=~g zkL~S3ciRM#m=A)fFuB0k66X~4BYSGF*~r@Rm&ALp=%3N`e?rZ|gXA7!HnKrLpg0g}@^QE<8E*yAQG?<)^ChQKm#zGggU>uITC~Za&oi?3Jq?tJ@xSLv^2I1OuGEe(`AVo)Su`{(9ZPH-n=`}HF7~*nsKhk|VC}UaR{DjumaXu?N z1Okp(w4rS^d0{WwWK7y*0L*Pbw>=3nZ(ZhB)MuheYDDbKrqj>Gs<{}Nm$tu5vkU01 z3zX}OF0TpzhQIwO;Lf8y%c_h#3B_TGgmKVLz7j&U#uMwoCp{v(Zq)ZY_FTM>-&H#g z7eHN+d!0{x?PI)|-+GjJyh9Qj8zlfOtsyo-@p+NwZw&s`h)7_u?|H~>wQmJLCO31oQY**wNKu80kbuUJv&+&0%AS-ne?bgR(RLND> zs!P~SYJ_nX@H}jyo|a-?i5%yrOt(Mhm#9v=ALB`>pb?d-ojzD}syHgm?utkrRn88{ z))fiyls|o~UwzB2PvW~G0Vicwrx#USLN$bDO+DB<>-+rp2fRYF*NdKm(~@zg?H)tY3mde zRWQS_R?_smAhBioS^-e3lCGR*sNcEMRLX_LJ-YffB2umB4Uy*`xQKpzSLHO^P9|+` zp-NSvinb2hO}9t9=LLbzHdpfJ{!SL5*2l)ezIB6#Fmt-rXv22Joyk9{h6JrwC`Hw#`z_c84pb0dMmoEMpwm;Yd_u1 z8DG0b)>lPsoHI>S;mPW>C{eLe z-V*Cl_XVtXJ-8=-gXy*q94=K$q!#%JG@2W^NskHZPl@3YR5GB| zaIzUQWr0P)o@xFOKI7$#%uc=U`gcDG_qy988+LfBa?I^SiCf^z&hYLG%hLP8R!X=x zRae09UDURQq`D2NJ@^1F8;|veKS=NSBs`#zz3z+Ib2>iBK>)~tFEzE3Ejc&Y>28&z zSS|R8t2>}bE;5I$9J@ff65&#*0(T|+m1q`^rbqzxNv3mI=@UHb|98ui{5aus1mQ9q z_5WLXJ_y(_%85yr7|SZ1G&E3wv8=5H1V$BL|64ChFUnJL`1kPQzax#udU?1>XzphS z?R(xAIKUYUS6R4!V*RIE<@A&Ts#}4Qr^NgB3aDQ8`Thbxq5FEwhO@BVu?Lk7uyW$6 zQ!vmNn;3uTfD|qAypZft8C83%!vk0{nrBWsBiLn+V1L;1c6{m$_fGOkW%Y<3^t6+{ z^G}mvt$e3SmI}ldznIL^@u^3okDMil+)cv99Rl@2;G_Crw#bL}6XkGJi}X_OqEjUs zCE)|JacBn2TZY3layOQxgIN9H-t_q$pQeVbRK00!6B+Dm_rD%KJ7!g$;Ze!v)5{V^ z_qePNw{mce9+rSF8!VBg){ZqVqd+xAdSneLwa9hU%21ubLQaStxtC|F4740xb4hg~ z0fM?Bt9eRUP$b@18F^~q5UnklDCr-_F{N}hZ&a_FkZ=N81z9GaiRO0ec{14Aru*Ic zUkXoZoA3AZd>THht(w4kMnYH=dA_0=LElT5_3z=cIlM+d9zA?d)I{Fj!I z&S)?uL(9k>QpRCc8oP`ehm1?26^FwEX^i)s{|tCT*h=sCG#%h06AjoP<9YuG)qsY7 z4ctt}(NODgrjJb=qU&TJ+GJ2*W_ZPikbLNBntbWxJ)fG{leff(N|x4Mz_rONHP#AZ zL_LOIzP>nL5C7H4nlRx0@(J52^Oem+y~F5BszD+?mc=B}-YUdB_#=m!>z!();ml+M z6G{%s1ioorL}B{L`OV?=Kx-9Rx-inNXzCXd~ z&G1eveBbH!UH0h5rckfO7X%RmMGb{K#S!^lnT;S;vH5&hBb^WFYC|DO@tdnsbhcj- zQm8_vseJmID5+-{>iuS~3#v&SbYBt^l-z z1b{QH_J~?NjXNZ_R4$-}cgWDdDSe9;SeedeFfE=f2%Ai)MT*hd!L^f`T>(!$Tg?uI zB}P<`u}vllmJ(0#%$8Z9s~OHfBqFy>;8H0hgdz%X6 zr{RH&Kwd+7cpyCxu!_P1BLey1f$YEq*2S#?6lbH=3)|$)s*HQ3IBQXtSH9)Xy2h9( zVMd;WeE;q8*5{bM?svKPb57;~U4_=@O|Wt!xxC}1`Z0K(Oy+KrtPnh&`Srzqaop@* zPfEWeM_MM~6k^_R4<;h*G>x8P2QIM%=>_R!r5_Pi|GxX;k` zRSiV!mZAT7q$*AI3Mw$wUM`GN6|9b}B`x~|kuIKb2Qu%^lY2-q5mG))W38;#C*{Z6 z`V2p9(tbVfFjXG}CaDCNBx{uzMAOwV?1tl&ugZY219^>ogKLT2Ut!FAOj1{KYt1J` z`<<7}L$z*yKoG z_vl^j?(j!fx5-!3bAI$E1rkgj^;v#sM!OW#7!4WE$|AQc91!x$Zn+n>6>vCLyX%*(vgf3I3;zarJxH!l5&p>C3 zJ129$pXPT~O$#1gZWRuO?j%%BwFX8^1A9Be{pt1IowDOIDi3#hzA+UY$n%V&Un*iw z{5RD+11n!~?Ib-Rf99>yv!9_MH*e<6jyC7>YKm)s+MM#J?|8X+grbIldz*kSz|sWP zf#{M{(<`v5d&7Gmn>qDkwu(FxK<59_L9jYjOg|`}@5^FT-5WVnFFJPd(3qO)>wR}X zb%WVXtaZ$s4J@RRU9~w&qjkrZnic2PWex$9lx&nLPVZM9ADtEjfVCBZ!6ZLI=qJhiZR5o}Z zI&V@IyV784bb(jfgf4R4q%??XW{0-PGYPlSUB3NNoy-pAj4^XP<0Oa>EyMbwJ1~(z z{f+R^tHsCdTj=h@VW#h`D?R50@~qp@x>p_u_g>xNNo!8ABRgVgn1RI??dK%PuaPTz zw8tN!La! z0(?=owp0AZI7dsLB$=QVd%q9V)3X}e7eWwl1s{#RDk*?3gl$Q9Tb_qYMNP3 z)0K~sv8@tRbg22s8h*>#!&~o6-j1g8cKn;XeVEFHV*>PoTZ7!^B!I)8r_|3V+PB`%`>c7DW^h8w zyvo?mB~kR6v#RXqHUB90{~H0;Oe}@cR`!HHPp!YY25yP4qV}5NTOtR7g)Q?U2c2yH zaI*cq++Rx)|Mz&9i|vY9X+mgLzMD*%MX0px+gp^ zK2Q-JxFE2=`gY^M9!WE!VNBz|Yw~ts<3PLoo@eXX z7bOgd{8_W&-T?310VqLmqL(aelQ(NpxKw^`tk0>Nl=fHMgEd4 zIHxFX80JEFvz&a4@g2jmJN}_NlpU|$eI2cZlDe;P@3y#5Wp~1YSB!FDEjkyM`(G17 z@t>|xGg-Xed=Dzoc-8HT%5TTbI`5(S3`DK-d25-UIor*3LbE;SbThkObZbpB2)5Ub zKJyWJPBhmS5QeKc0lNUO%d}1NGjBEOJ>~w9pAmLBVO1^jM=m#3cxI=so)>l6}uq1AR`()j*r15=4!M;!rU#$iB|9L^qp|kW^tduckIwkU#|=P z?rEvX_S;z8HZQnH5-*(|>sJWoa#XtWKUcSF8mpx5q=)1h9iit_C{qAOdRFFjdcQ-~oKEjb`{zl1+(e}WM|FBP@DcCyX3)2B z!qS83o!<2lw)GC4TbL|zCBtgL)W`3jP1>e3aZ}!Of{2DpMqq60DuNN#X-%oT#KhG# zD9jP@74Gs1f4g+%4{sGtVSXx|`Jy|R?mtGLH7-=2qOAlIq%XGXJmMh=`p%HV=|Gi6?UnezI`s7 zTg-Qt`?LN^juvvzKF>8D<(n zN2fc~nqp;#J4K%pdkU4!kTdSDN|V+0Q`+Tk$L2d(6Hdxt>Rt>%R9|wzNLZ!qwI}FsVXg)BEIFF?HaTej;e>_ zM)-_4SeJ*VONhzmTo#^gzkV{u`bgiKG+x%bTJL5FR$0QU3tWM;T6es>0H0%l(JICX zOd;^rrCi#&ZYfJs!8YN3&E32+DlMa&dzQlk3vKyu4sStE?RYCw?pmI2rPLP8HP@1Q zS$N>O`gfMrUT0SFRi#Q;ZY(T-`oUAn?uT_rT_QZ>)>}ss!1)v|j>r;!nRvtZ^_5{{ zit4w#c9EF@u-hZ2ssf(cd@0NcPL&j?hnuB6unGNqGKwas8q81``NfbYY;Dj7y7CRHY z@-2hQxqN$>ez=3*LsE=7+vP`%#HlimCpeOWv-N3l-=3SSzj0hzXzhbw_I6$bpTni{ zhO9Eghq)M*Q0X%Re>ERn25%S0G=EmfeMT1qxYk-_Uj3mtom3^hy@A7a(m!C|0}S!@ z6$O;;+sjoDBN4-~6S-(n_ik%R#Qtd?fO+O;5IfAZ0RoTFgYQe42gg_zo zmj;*F`7+FUdQN$Ll-m!oYF)5I9}`6H#WDq266KfGrgEYDPEN{IE#J0~#`%REG>=Gt zU%JZN&npA=nO`_arSvyDBsTg$>JqYsc?Z9NT(^C1bb%ea?URfh1S=6Co~?ONef)Fsofc3f?~f3M6j zC5ua25EF-7;rNJ#tJ&#O#33vlR1pj8BKr9rQUfu!AX=?1b^@`@04-Ky!_7TF#lDRC zd!P&!o}ANz7liNGll9=d)Ve(mDbf2+cX#wpn%rg02%k+2&JFu8wyWF|op+_wY|VJ) zBd7mykZvc#EL{A{?12ILBATVsc)@Hz;0wcNN2nHOJ1y2CVQ?{gHZ8W4ZVaEjQ^o$! zi4Ah*@g^-IN5BXBA~MN9^bR`COXlm zrncSg0inp|(_$HMmIEd2Rl(_ym1(~Aa)ZnCg6+7_FE{UHE*X{WRKGK&pc8}WurDix zTV1Th?3P^hH{i(09*!G;gN3gz3sELEdRdw#WCYeA8fe8{G3djZ~hF}sB1SOCtc|s&W zBtbzyGD#+6V3LXRAVhhDPEs?ZvDDhr*R`T}T5H>*eVmknVjvi(+KS=>#rEKP#!;k- z5szmHeXsScwf835s^TV8p^Lxmm_KO?Ekb&5 z?4^kQ35|umBy!AqaRPnXuH`f&i1%WpspU$FNYP?y4FCxbkaU5u+CtBFc`r7YS`Cl} z@D7s+!8{jV`!nL2lXwYUFmA&bNX0rlTD5v576coV4Wi8dGb}=I0%FF7$z`>FBG5xv z3wRGJcv&c3yIku3B{31Ko)|n=?D+t%3B_}Tp*e?%-{w&3rG8gJC{%}A+ZrWe9wxG#JN~$dEz%<2A{=?k`WU-dj5h%2@vSt@)@uJ zqG&ICJcPIQujtxoOlTWYgid^z&yCq3Sr9VI+}!N`gz$<$hfPWbDACGh8!v_#9s zxgk`%rv)d3W!(?NVyGJod$u5D0|v0j2y~!FwbbypF;C<- zXJ-h{IeMj8{C>hf&k&`j$bhbP;c>L+!pBn%EhoA)oGA4_4&;^LB{yCE-ynAN+Q$vF zsW(3G_BkT;DpTt?FeH84Jl=0dCs*GVcp5qWPM{2v976Y3@d%X&KCAl_=)j8v6R3Yj z3Awihhu2P_yM1(rZyXBGXfE(9B%r~cO$C5Ie(_}&aBt|{(}hX*|Bjl(TLIif50L1^ zi(Yfuvs-r~xI(AAL*6(!sMfak71D=AQlT77J+CCL$#O4A6fc9IgpHx zih!a4hy#}^aqnC5#gW`EhzO44(rOhKlE}iBd*(>)2fN{b_W%2c@Pq%}59ZcBi(>v; z@KQl6`P$&1Ufr?etpCTTu_s1+1NTQ_;xVc8+fY$Uq+CnM{wNTljOCTkgeK6_{F@V+ z_fsyuRI?g_Z*lPS-U<}#@p4VP4??lpssrQ+eG-!)s~CC*R{wx@^!^3{1{x|NF zKDKR%9fi-(n;!31?Kgv+$Yh5$?CMhk1-Wh0iFhA@`W(tvV}Lpzr|)BO1w$abWMAlz~AB<4wCT<_M$Vb(N%9_P6~_-{BvIJ^1tX`W$d zk}`ws&7UiL2n7J})X*oDJit2}Y;7YdfT#dmup#8S$M3lCI#|d=CRwPho$~Sni)fO( z6vz2QQwzNrsg~~iyH|lcyTi!g7c-jxjqg6-sQ#*@+pfe88$Q()U3jL4B*Gc&Mq-uH z1*0EY53jf*#yd>=l`GD0m7w_(D?=en8wkXAa9w-hshy*++{kT92o-+N@`C4dfL=|A zm0{|`@B!>WTr0O5 zhCZMN+<%Pa138wE=L1@C(brLEJ%l}_c908_Ac%46%^|*nC4XvjdFIIj6EPgTDT(+K z#5;3-p?}L1^}RwjFZT8rJ9a&UtQg8)Uh2<9O{gZ{d)f&1>9!tk4rTD7L$kB+CX%d} z7D(|ex$R?E0=%#}?EwPYL#Z%*bjFX<7{3W$fY!>BPmBQR=YIoSfk$CLH{-C@^}Ox> zF;Kbk*1&4$vi!h<_zM)^!P(FpD&jjBz2t+N%KX3kn0pzRgZveL*xiX7+Mvd26wk}< z919h6$lJTdJ=NQbcbEJH?d%-l_2*_^-WXfdW(YiogdW3f{7rcPw;k`uJC;4HaVp-# zd7%5?n?|ocW7wgcL)yBFI`WaRDbO}*X)eD(kn6R&mv7JX_7=JqZy)3B&2ZldCwFhE zdqeOJZ|^*JZP0~Q-M3KU8u#L$)!SR?o)f&y+v|i+I^Nq`<4*PV*5lR0i@m)rcapc) z?H(1pp~o;GnAKy53(oE_j0n!`F$@dN=rP0wlX?vCL8Zr_1Sj+u)&$3*-@#EmhSXqu zk6~VLXpf;e7}Yi^H|wJ5n??}-Uc!a8TTG`f%KUdNgiJL?L-v>X`R#RZTz9Y7xBK^f zkv6j9Rs;M4Mc&@|+cUhqGq>9D0bh6d_5={k?cUzYw^e$3C%EU)c&>(Py?4e|^gjt7 zk?TzhD&F3;?ra)d?v_Gt@9J$Cly2FQMa|IV5 zmWL3$t}V{@T5wiR)NLKPxrikl?2Sb_PJH@a^LAzAwMDlb?dmn+G%=Ep&=!@~kxPFu z?r-Fhh=2!=M$~uc-zo|ZJ&r^J58d|;HjkmzYHQ&N^zQ&MfZ%at;*Wvv0##5uwYw+- zPB;Oi`L`jFpLeO$?NsxQ6Y8{G5 zUQa8uLrCJ9#Wt#8iJ$cyQF2u4LGHXRP8m> zsJkRzj?56uYkq=<=t&J`bmS8Mr)>NljU^5p?I@2rh6fgKx8r;Q?QRZL>!&usb&Mp# zPQJhi1qJ6lgJ+9Ly|rG3Qq4~=!rYnRrXx|Np;5)v&gcUV0#^?*!qfqc#1j;#2oG7{ zFLVOGAzKay)@nQBe?E_H>kvG3LZF4ae6N`f072E;8-Zj~2YE)kz1MFCPiLDthGG_o zcV~ciO&y+PKq_!cK6%dczk>-jMerWTTxkO#pAZ*QroWjBG31f!c; zIyqxm@D|LG`(_Be;1bM`yJY)hZ?DbN@(@8nP^@=50>5NXyL*new=S5BDRf`89kbft zo<~zVS#5fYyN0CZo$h79ZQkB(?v=sDP+@a$u6Jvj*fzXXf<$ACNKR zbu2pO{d`#CGT)N6`Ab^1E%YsE3Fcu*7tHYQz81o9yWaWCYNl_!3RUCX+B|FxgM&U_?M6X{-q1PTiJ(yXHeP`j1G571R8YIs9Xz^*bvFLvcvdT2O%yv zM0S*Ul@jK2apG0#Kk@2wrUM|#DNvoJyIz5L8#1?MV>R{w3H^>zY?)PH&XWS2$a;XL zpWcnKZQLSB3fW8|u)FaDJ`u_Cpo4+-jRJcBZc<-3ycEXBa9Djr`3^1jJ8wWIuo`^g zFK|X?anb!>r)YPX|2ir<(OgSno;w>u9mQMxu4k8={?4cBo0*Q;SS z-T@hyiDHqxFrgRiiLDbUFA+UdYmb$+Qx1?6IB!&^&~)G?1F`s+{w&Uu+R+ph_%kX| zwKot&O|fY@dShWTDEftk_y!LSFg5QS7krny%^3S3A!%*1R%zfy@FnNc$D9TrnRq4z z3Gr1#g%gc|>$SfB59>;KI`9eXi+@D7OpiVv_}M?GuFR9z>>BDj_QP|Z`?|vzU5HU@ z==4owbOmnuT1~by3DUb~wvE5>5_&W;J%W?*>6o`cqG&eoI<9J|Kcdw2*na8DbI|z@s_Oo(U~-r~22(cJE2LL991EKNKJ2*{7>4E4-!NvKB30vtNjdNe za^O^lANOAGF?cTS^=>^1Z)_KmLxn#GV82}=i|D^EHM-$jl-yxz{SLsO6PgUoP51;3 ze?+eNh9plCUZ0YEg9qEm6SC)f@FK}=8y5!?vaQmWb&`Eqo|S+xc>gN|BP$3mvs#I} zgen-VS1=3}#Gry1izC2cbmPE~C+gSDn(l6EBbDeIL#iAVy0Q0j1H93kE%mzCOAwl? zQ!Me=-L^`H!!3%OR%>2afw0h)G(Nq2bMLb2QGJ)4!}JBsTp>#fPk zMys>lYFFG2hf--O-gc|WusN8R6*i|8WW15tS+JAX-TeB#btGS8geo=Cv8UD zc88UtYvaVG^_Cn_?{L;x?84&ODC(?rIb1Z!g>oXzQeT}`ZE;&fs$zFosx8&kPPG=d zb+bFk#W%>zM<6)uzS5;eH3t8pT~}RnV|isrS@XTAd2PD>j$nYOq$>YHZeO>c68= zan#$J7&xK=#Zrlx4QEk3>B7^{V08lbdPG^Ax2n9bOcXhsRaRx;@)dcQb;aUxdFrgF z(xTQNp_Gj_yMsrqIBFEGOF?B0P>027MfY89i`{OmPFIxN`Xv_CW zQLfrrKNVE!M)Qiz?NS;nPPdIvsJNRNtV$J+8!2|HaNFvvMDCb2H)cV*GG0YF61h^E z3C231J6&0Xsx27JMk{daP@EueXMH-CB}&yJN>Oo1p;&IURC6t$B^z*3<*0Wf>LP>@ z0QJ&k-DGuI>`Jw*rpD?-uF_~}0#fR$0bYmxTU}H|9r(_nP+z&i8k^m!VwA_El!H1j zng+}=(S)PU+DP+NK%&J>2x?H)}7V{htqAX=GKV5YHaoBN`)=!C1aSDYQl1@#igud;8lwCc8|r5PSsio)6{6S6~%3CE65K6b=ffA_3l&# z#}Jz!RyI;zqrTI;Rtf~Eoh{&{w z;G{Z`-6H(RVK#wt)ENaW@}P7wa)IaTlif5ZnsIeVmzD(uFh?tSxn+yeNL(mZq!Itt zSS^sWRvkIe7Z%X9>_u9dN;A~G1_(@Gi7LXK#yN~so>&aM&H*$N2M~z?&zR9_S3i_7 z(e=R@X{*h)I!~RZfWfc~)vu%^PwEPIjd|7u<;Y5}4w?@pl?yK{C(B6wC8j`jjcs#I zLGf~?cu17>)>%1a<+%$BXRRYm!O7@yl{L*?X<4fjFGXfa$-08Vn~U=cmDR;d0IJ>* z?Sp_DSj4Dmn9T?hF|5=r9=C%miz+DSChC3!rqF3tIKUF{U1PUyCIO-&a;jS4RMK5U z)|Hm3jaJAel22-$OSS?j03i&JYU?H&?1{d8X0nd#HeswU%hZ!Tk_wc&Z6kZsr8TV8 z8Zq(+@?}9sjcc4S)d|~I?aI_tl>@6R^^(;+7+4aM?eb)yv~ zC{;u^5cFCU>1wT|v_XUv?n&Q|5HJ1_wCa=XXjM*T2Dz^v*GwW~&<%Xr3X zZQKxb$Zm1fQs1~2J&ZnXRfUA1;UX&l2(hEz>VRN{xa^K9Ag5@h zGJPe@pgI{T00ezjV{mS%D+kwMB(mLddNKWENDx(#N>?u=BR#M!b5<-ZE@xRtESFQd zY`MGxQ(3EX%1R3h3pf{SSDkaqvgPs)^9J3OgQY}q`6^YwIvOBemzDCJlq5NjrE5ho zT0y&5tYRRlGMD+V$Iy7h2&FvGL>81BEA>8Q2%5FPbZh$hbR|Q{$x-r`Ey+yLxx5}7 zCtiyb3oK3~mC{^8-_u z*I;-^$*+o8#sn`)@)Hd$4;$hfk4>53)F7Nw#FDv%f@8Cnydj8jczfbD28D-o?VMlKZT z8&KC%1KMRgzZT6>0AjU)fwR~!Q5W%)Lp@~paAyd|ge?dwTGVKr)Y{bw3DRlx4y>+h zHBEhPl+~JLu&5xfIJayqhG(m@LDmtmRZuxhFf9tJ*)+4bu{dwwMc4pJL^Tm)r)oTQ zHlCnZAcO0n0;soG|BzNuMK8^TMT^5$+bDU3bqNszEhuI4Aa6GCXu8!kp%S5~scMKF z=%H$8EhiyrDI}e&j>=%YSqH6wse)_*D}l1)=u~!urm_LQN{!P2=Yt$28I)93j+9Nq zrOV2tuGZJ3>5NbQGY~StmE2|3?(SnE5P}CabNzWgVqT0UA2@AlD0$dr90nA8M((9PRRLQlDRpC}j^GVLA zZWw8fSh#wu{L{iYm}zJd=p4*(IXWkW2;32pf~gJ|AE=pVLT4>9G1(T1=&(X=Ff5px z6t>fNgqqf8DS@@Ds!Q$A@-QbbkiM)BT1r=nfLrTkOC45=yuJp?07k9XE5&fWF=3OE zvnXZxWyO3iwI16>s-IPobDwdNI|?I=D1_U3nmSZfk(tc=C5H_%w6fQBIbWpJB|Sfs z1(y^3QF03kmW$;SvnbchN+S;#OGQcdnp+MFP1XHI@KQh9Tn%>k1yBHFRBPR=PHMVn zu%JKkFPxKwWo1}lDCz0xc0l>GQhkIcuSo z%F1pjP*(FAM_{4LJ1VRtvCoSs?x&9g@R_F$WCd( zgPg%6EeTpy1>|#0GzpwbSqj$104yn7D)PY{P!|?LV4VfpJj{o11Td0lqDZ`HtRV|? zw<%vWb5I#<6dDU9a`(6wYFjkv0Ac9@G!x1}XJoR%lx@J&JLO+cdP(lWwW8dyem!V~ zb9iAW>y9vynNkRt1kQR8HYr=^HxQNNY$R7ecY|c$f`;M79b?BnIgGTD6>y{KFg4*_ zgmeK=c*^RrWW2-H(DzO{r&s4LUnm*AoQR25ejxY?Sq^n#O=TsMfxJn&M*+g0+>Ye# zP+f+)t43`@z4ULR1gwR5V)IHiAt6WuS`>ZnMHNpHju*7bbYP7I09tkHjt-h8=0_r7 z@G$%aw7TSF5Hkt{KSW9&FA*;;d8yCNbE-n!{KA}S3m}XeOL(_t>k_MLmJZ1hYKEi; zNME%ar>et=lsND}uz!o1sE}x9{U({OF~)}4y=!XYw(R! zMp!w*D-TDhODR}Z#_Ceuvw;XC!8nApBv)s>qdrZFcJ3F3i@iiCyxDU_JyT_Qm|Io) zmZl*aln!=HB)g=34X+D;e+|=!+F|w54hKfOPL%=clt_z&);#DGT;5o$qT+Os2br-E zNm?z|&DJUps~|{Y;Du2KJtYkh54sB(DGe7Pr&7I;mV-|e+BZ!aGrZa)*^xuCV{LyH z$PL?uq-eMuO>Qw?NP1^emb8VG$X`K#SQu1dl3@7CPES>-SsNMAD|}qMKPQP4ETTGC zoL06KLB%y>b7>}E7`y%S0gFWBvH}OTU7q!D)$ zGzZR{T5ok%x~jn`Q){s6qDDb?^=cHo_iUzY>`KcxOUSA0;U|1yXyu?KeKp!=E+Ul| zdC$-%Vq4663Dpa_!n|o^b@9dyQ(<$+&0F=VNN$r`x5YD;DYQ;kF+t*s2wJir1Ever zwWnQ)PX4~jm%YK6%IfO1in_Mrlv&DZGUh;94G8(mmKGH+)Lh2P3v)}>MJB<$frel( zsg;5BwbcnL7d01Rn9L44w(!_ApqV08R~rO1!QzcDXlQ^cmMh>f02Pn|09(jqh6K%2 z%?&&6Z`vJ>u-U;%mOqG@6$tePV&PY=mrOeQNl=0Me*4NDR03^`SDHL1;9 zX8IhO9kh-AG?vI(Ba5XF_E`MTE(;G`og@^DsEwJgKgA7<2dzW>5f+IA>e8iy<4*Q( zM{~ur}E& zns*#xgyuxuswax3HJUniPD>-qCGruFNZ`XFysQWtUL|Z4VdqtPCBX-E%qt8gEhCmz z16V~wDC9dNJi@8!gvhdyB>_^B%V=US&XqL)7F$N_w?VpGF``>_4K69`q;#X&ieXRL zrA3A;vJ`;0GIryUBz(U2|{k(-HZeLfaK`!?BQwV}XfN(28PK@8~#Ia-=q zUS7C-sWg8J)HO1}k@xG;gEf^N8+Mh+tH2xeSeL;|#Vb=Sg)mDSLUcq2%P?p;c+436 zn&9N7lkq`l_}BT5YCc#R>eh-yNbIxrCkd2Wx`e3PvdLm&v;y(GgUagx)z)utG)8D| zE0-a!2<=y}F+=iAlWa7*;qE|PqHXkOy%oMBxI*=aRCv%ftFS9yP`F%KRG3?!U^lgV z*>c(d!q((Ec?Z8^DSHd3>PWmv;*Hdbpex2lq*ItJPsn_YkhPv@93;zIobY!zK}K>j zQ$Hc4iO42c2k-;JMCAeM8$@t-U^#zDs$9GQub{tv1>6p3Pjz(%0FWv7%%NzQNM%%{ zYPg^(BGCa&W+h~kqk=k%Nu(jNGoUXV8s>8~nu@|!EeS~Efp@gW)*e2_b|!^(fy7^NdHu)!@(Sn`_XLgiTOlF;EZG9Yxa zA%I?8FG*}c#Hjm^Y&xj;mm*H%ZCZ}ODaoCus?h~hMlN_^#ksa>`Bybi*3D7v6H!Qc zTu4e;sIM@LTAe;|Y_TrMTTc30wUt;`F}d(Ap;}@pNg=jFol{lW*SADbQCWD9=}MTE zRsTJPsI@A$f23iBemknFJPmZN2Yul4N-h^OHIlZ3v%ICr9E_XR6ycX zbTD_IbbXQ4caOZ%4(5Z$51VMb?Q5;awsMmNf3e?!?QM9kz_I{vLUobf0=hVDz0=YJ zAFRc>QH{!ES&0UMvvL}|tWaifwKA$#-UKH;y!Iq8!AP`YoCp1=pJkPnvz4cZhe(GW zXc4K;eBMHN$c@sm`oM7-EDV9tjcHS9Z3m=*5lPrKS|Fong@Zg|86exb-pSSm;~FGc z*Fb@ZIFtX*68Z8hCKCe@yPBzc1c}UNarY(vNIucebgJe&x`1s7v_RezDR&~{r18<6 zDjaE}`XmD}`RU#lD09kU5>$cvS-60&=e0F?c&Rp=-@#OYmXRYDqilQ0=5a22J+^e{ zY!zrsUAB?!hBYzzX>n7Ky$K6HlHu%9Qzg8P5I9dDP5wr#Zz1?VhX|kN5PY0N&}j~#ALbA+WyS5{CUJ`>7pueyVH3q-nJ5(z$2&OAr#rM% z*+BSghX5Mk8zzL} zr?^$D6q`^dY*9fr9-#qeI)r+pLuj5%phceE5Jj1yXqG6tMik8!MRP>awW8=cQ8ZT+ zWg#mAT7V95h}B8esr-MfNEJ!0r0T1asEgIb}<=i%W4^+!({#AzFR`DJ>JOkc()ru9UWk?EP&@`m6g@M?NN z|9aF7M4XM3n;#Ovaf)8g!0843;KfphzT8lkbC4^%n#73)$k1wFrm(myS6Lz-8({N; zR+r8i9EysNM}W&!-8baY{wlZpUgNvp7{*L613Tk0wlqE|AIu=2HV%@3lC( zo5G-IX0_JNaz3+G5Z+`5qdM7~tEo!EAX%x*UYMs`%{QrWa>7ga^bXDFB_Q&FlQ@xE zxO~YXp(N32pEjN3vV=`(dYl4dnqC9OOQA?DB4EJCICzn6i!dFk#fg7M&CF?<+Lm`Qx zt}Jxtp>8nq7C~J22@N?;_C``Uc^ftsH9rv6dbI07b3iyj&)D}bq+?sCUTvYew1wuz z7P1L`yqEE)w!3m zg54-|L};8Lr}t($bH&3V!m6)MnWxg1MsM>_hL7ywiX|_O=OMzU_HgC%d6a>ZW1KEe z=!trVz?m~ar_F?tPi{G;L~I5mxu#;{4Gw7+jvy!yz@UtJ2ijilsi!GcrZUNcVx}?x z)RRl7&xw$rkpf4Vu6aCZ_G|Fym>txQBUZC&Tw9nmasJ*(z*;Pvw+a2D z9C;0=Z>B{238w(t@>IE)N%r1M@~eoMa(HMG%c68UyaN%wQUyFG{{f9jF8om%=npU% zMzhKkNR)^UF}tIDzNn zW(j_7k+m}m5Vy9TAPGnh(qU1|rvj3y)1j|a81?+T)KyD>EFRT>xn)>xk=Fy;KhOy} zsO0Sd8-W_Grw#pjQ4TH_`3rM#u-VdpwTKJ&kk1N*Q%dcYdf3mUSP#Q=Yp`v$+F``h zr}08YnVqW4nscpOXTuhy$Jdm6TAhnkD{dB2MUzN{HuG%e{}^^eH`Vb<$2N3V(UiD25m!i0C<2L6KjDe% zb$EjieYfCcJl;)VJ>t%Y`;w1j`dblcE){mVdezF(^_LNFbUzkBQTTZ{xCS6tNKBEs zq0>9cYGnz;G@ezCcrJ;AmwwU=6C0jOg^vxASs=|!QgyI>a`Ol!MJJY}FQG&w_hxW1D z(wh@YY%Vy_cvm%?s#79-2~rhGjW~;aEhJegaqgi}$y}0mi3Adh<%96rQ3ZCOz#T77 z%8`ymc}?EP9aEA_aIGLwCy>aaO!A>NoM55HIN_|X1|YRO45v9-*S3;iGw zA)oH$$xy45rxIzj`LZ5)yjpvVG3-Xi1_M2si2+urJ2PN4ex4V;M)`zY7+cuhBZVSL z=un1s8f)MgkXxwX7ae>xG}JOZC>rhzeBv9i({Gh41GY731;jC^) zGm$pIu|{aZ=x8@gE7GAx3LK4%hcxl+x4t0^KF` z3fCO#bc*o=NMfbdNaHG{`e_Nw43r4!6RYVwd!Ga6*de%NDKFpOfb}_m`_+=1RE0B- zyc)fvD(T(er@|uNHXtn{G>NN)0}G#WAaoPl%AKT*U>^(CcB5#%Kw*D2%U z%j9t`rR@|5czE>4h9uXIUCKwCHi$S_fP)06kPS<9T#$`!mLWXhSiVZ}k7ml`dnWSv zM7DM=hR>fRk-rH)(pUhL5K1{qNO-}e*$EDtN$P@+gy30UIfsK5!xIcn@C947(=h6A z3x%8EBB#eL`ZqN|)lgMT#}KSIMy_=_!r>vSE#MRHglzJMsF(oSmgFzzorlumd~vhQ z>Bfs0lv|*Rd9=AmC7TTu&!c5DJ1D2pfJ*SRg&iI` z30qg*qrI|Rlom_!`NH|?T&?EHpoTG9AUj;v!gnPKP$I9SupmxM%K-YJD4{Fh#|uyL z^t`fCazkO$2W-jZnb#?a4%A&zFLv~#Lr``8V(H4g)t84Au;%z7R$h&<|A&{na2}v@ z=#=VVTLBY`46CFnMjb?be|M=IYwWh2FQ(T+6vii;iefY+WRU{c)-?> z?%)>4C#J|}E6CJVyDyKTPETGYdnzrj6h@eiYXV0#aPndJPB@n3Lw#xu{lG9Qatn!o z*JJ9i@}nqGM4biwXPOalapg$R%j(1cN|KA9LM9K~YR5Hbw7^840~v%5fIvse_YHsu zsoDsNBHExs*XkP}zFsA27Zz#T*Jw7PgYXwfs`;P&9ek}9Sud25O3rAuh+X_sRK$Pf z>VuE`5UFCFA_W8qx#T2QGM0nk1eLBpmo7IlggE;PgUJ6?IJo}ZAZ9&c5I6oToOaX0 z2C+}QAA&f+-=|(9%l^IiZD?yW!p|exto?booxfK;GXF)CyZfhKUG^@FC9;ebKZ@~b zaqUX56wdup<|V4*wX638_ez)3*z@8jC#xIt}8%7iE24AYT4^gE;gD^!s@U_eaFvM4+#)&iJ!T zn~eCk5!M|*eb2~tHzK|hAqQVyxEg6w(3cw#w;}wf%OI{$)9y#S6Jbg>{8N9Fa1@`8 zkd3e&X*7;p#1|v{5TOWZqmXt#;=e_B8(|6FSUwtQA0i%q7&v~)Ach^0{p&@1c#lEM zL+~G#X?cj>hVT|bpj)N|5dRFJ=?HL$H0twRh(Cl7M3|Cml4V~)eE2gc_pCwu$CDE7 zam1fSIEygm4>Iiw#OwbAd374;zn5i)K99a2`~=}uq){6be;8pjXyMmLBU-xx@yr*% z4+y)F7D-oLq<#3Gvc5LN_aKZqj`r2Gv4~%Vum@q1n)XY?-#}RXl0m%pJJ~M9D-pIM zocxWfuLbdY5Taf-h+?EgwmTeYmp>-UjzT;c;S55>qp~c;FCchcF^Jy(kZBZeMxbw* z>_b{)eLq2Z3(^<|h(CnTg>ao(_8G)aBK+D9-uacpi#UNkAbj^V!2Uv({XXJ9L--V- z`4QQ!;Uwe}!hHx=sA&%%{s_V}(BU%pUZ()h6n_qBok76kJ@S+m!u`nC<@fRMs^t)p z2L0s#j(!s`iktoh*@*khDN*9-_b|t(XV!vf@h#BMVx(U)%_zQ&_|1sVHphs25MPV< zoTMS*dx%>RzxKAFV)z+@*ogRbSH+4SBi)1e+!@2fPY~aRc-Hhd@gU-Dh-ah>7vIJ8 zhX`rw;>AO_K7x>Q^$77OuJnr)BgG%o_%M8T@(IMBM7aH?1hD`-brA8!TSkd5AqSH% zf7Zgw#7(Hb7`SmRA1&_3IJyDjE>9Fqe+B;`-n43r*a5mbg1BeJSn)?(pFyw{j}wi* zF^E4Q?pQWn2fuH4XuK2BrLq%kXEy$O@d7@R1&lhcaJX^Hu@f>lt9=~3EM~~ki?$zT9#P{`h zuK1B2&lC6Q@qDpcj~9rC)cAH$ruJpv%dHsy4uo$Z`~YDO!mki25NZ%^N4OK=n+W$H z+=uWpg#Sc%9DznkJUSj%{s?)$W_AT6E>_{&1XJ!7VhF-w1S^6UVeWY$>LdT-cj5X%upAZ$dqAE683fBO3- zWK$QyNrc!BAR`b~A+#a<0^u0KI|w5||0xK02pbU|MEEtrafDA0lA(ugLTE;~58+XS zrxDH~7(asiL&!w98DTxbW`yq|{2bvh!W#(ve~JAQa8FP&J)uu-IGsWCJW9tq>P3Tk zrMUK^xuvzhU_zMo&1x0we@#P33iprp)$HS7H(dc9oDfc@{j+;>AUE+zksbu?NBe2% zg^-JjA-9*vbn8uWe{JPTgLvsy$UR)OAMMB8H3#!?Eo94FnO=-~X&>&6b+9!n3}UP` z3{U%d#^nYvq}(8eu8`?@sE_vdveQA|vtUExs{LsHuX;N4e2PK5Fhiz)KP{ZE!D&}R zbj;9UBNHx596NsEm0BXMR3a3WF47~?BBPvd7%Z0{0ikFmjLd6*#-38&A8{gmv^yIA zjQAIWe?#zZDE`Ib-!S~c-k%tbfARP?0{`eorKm&<;D#Y>l(-x^I8)>bi`XF!3WH&X z!4PGLHW&><46%lILxN$vK`~?)78okHf_{IfA6j3u{%C#D`bB-iPAL8fwQcGr^^y8F z0vd7@?A3A5>62lLT`jH=^F==7Se0-Iuh=8H#akkZ5QiV$(~ojr^@ELx+D)kI2C*G< z95RHWLqkKR(B#k!q3vI7T?j!OME3M$Y7?=z5`R#e)Hd-3jb=Cktw-V!q7ewYWNVE? zpst$KYb1|RJ(K=L*_?y&B&|du5Gp z>Zn~CzkB-+zPvlX>8Dd-e^*?YbmeCYe!HOSrdw~j>X9Rzfwc)UUoJ~5h}!Y)11FAN zIR4(de|lre%R{g0zH7uwXFp85wJ;{|*3WzQeDuYuQI7RHOJ;QBWt|W0`0Vz(rdsZ+ zi=X?>mj&-1c?=P};fA@>-RjaM{JRAS*t!F<9J-@c4b=kIu9jD$+ zy_lG9*z>@s*rngtR(5XA$Mc@p|H3OXzH^);^H={WFi{x*>B0oEj!KeqgfqZAf8yWd ze2F(y+xQSsZ}=A(52yZ}*Z_qLf{$VtMd&e!-*JYPqIM(}lHXe3`v zArn_@3JD|i*%UI=s$X2EYU#(Xx|Pwd{5xTFk}atrGpTxhQp2pI>P3SAPguQZ!s;6b z%MGVbSbbex_-^pngw!bIB ziARj)qqU;T|0aAA?FD9~eL+UMu~jsSE?A@0Vby8Y{YY?b>BBOggn!bakKKAT}rgES?3$eX0MpjwSx6}VN6B?n5?*z`b=8cPXetFak@S!(R+z;rd18XylFwU!njKPSb~10TsJL>7X}9U&$Z_~imF{iH5M7~TD@{K)Juq~#WyfK1=R8O7R8j=U(MK^uKv82+ zfw5{VIuNhMi~;gK5nN25S1mgva9WKG4ZO{<*ud**%CNu-9E%G)&DY_9Lwt?rZ^)hB zFe309z8@KQgs)LZxmtN_>U+j>_i|`EG2po~wzaSdTxX^CS9nb!?%QGsH z-2BHu!{^U}XVAF*^L~)+TVqc3xy>2AE#}!iyLqmubB%dX`xbLSyW6~=IcGZ9&)~^_ zAOTk}=)@;75NR(I#H{;LDISIIzJ|smB6{u^K3R>7*h}-v%@bu^QJ#s-7oyzb9+)UA zG(Iq%B2(2q_XPZL<^ZZ@muCsOW%SKfbA#8nr*TKL#6GQRpf3dntG#U!4aYZ! z`t8f%kzn)~Xa)v6yB(wV9?tHDkb+=J-9!CBBx6skjLhB>FC%mJP$!U;y@xu0h_Z)9 zfrxnzjmy+oV4nV<0kI=73jPwlkHna@7%)V{@Bn4CkD+9r(d;WX8~yf+`1E{?K#IY8 zcw)Dy6Nv}kG*W%B-czPw$GFn&6}Q}6=Ka8kPLFRdF)Q9JX0z~Y?Z^$8IunPQI`7#5 zY5LirIQI;E-|(uAc+-JqBzXP!qWDc0QRgfJGELv>ZtXJNf5;m!v>f-m*+B*4KHEV> zkC|GC^^tw|gSduE--rfEG7X;{Jf@aD=zZVN@{H%rAR0&Qi9=0s1w`Ep8&q#u5FJ7M)D4T zMM6MYs&HQkw8tCH5YhTd%tp-MM9hW%$Cw9SbZ|U!qJx*UM`sPrCGBzg~z=gGiKBqD7*(iBst-8`{vP{BRs=}c&!LcOZHNY`>8>_`mscU7`?3C)EPqr%VAN*p$>E+<}m|J z&V}gAZeJn1hYVTAwomJbAL=_FU2dLj>df?g(sl)?1ALCmc8~D(7_xe{zU#|2`-iUq zItqdIiHvqB)JjlQ1!kxkRoAwDXlk2{scAiFYD>j+K2xvhE;5JEtbIOHoawFv+=G-F zgsCk?M%{>FA7A)-Q~VfKHbJMHKy0o*e;$$#A|cz*WqK4T`v51-{SBG3ec=6ZP?U&g zAS6&RT;nkXv5+Z7U#i)k^(AD(U!f{fv(}jH+iwUi)HnzdC(ND^{G+F96ZK!)pCvrF z&Gv0^7;9?QN89%YKSX0%qwZ+*iyB5+1LE0;$0F{=m4sA-4;}qBI^y?aVWR}2n62hy zP|kx$^d2rzsW}z>;|+LR6KJfO?v0naS5{3;lle^m{szcDu!BC$Ys?v@PB-Qm4Mnpe zi)LZfl-NFkn6@KvxbHZGo8jrKr#F8p)3RROKGyfAbAR!@mhv<*y9|c+JF?@lKHv6n zYZs&3wCGSfvw7B`?PF4obu2JY-%B8yxr3Bb*Wu6hG0hiZO|3^T(vII`w{1RIs@Bj|SDFCKa15#P~sZytOPZJ^0)UpsyhroItcYr)s1Dw0>g+~xEDL+7CZ1&JHB^U*AV&$% zF7t>awd&C{xQBWo`*sloW;&oNJ8Jrh1o0>FA^?gG;hKlx}L-O&Ocr_1P}EcPp$J0wYkh zx5sEYQ1k`$>wXde7Xq&W7OCwr@f{!liHBt(;WQ4>4k=ePpxa^la}sL#ohiw`T7lQ4|;Ba*= zpZtR7GV3pv#bDfILv;Fj2ERM-Qh1u^r zcF+&@d-=0NXWf@&S8N)YeMe&))(Kv}0{%j;Kq#q9Q~v!R3}3g}hxzD(?*tQ()C{R0 zlLDf0jXqgnCYt>-Z$@KSun5!L8?cf51oaOvEb=hW31Tm)to97HcG~9?>Ih^2P50r) zp^#SVSdy+)_{uhy_GS3=f=~il7yKuo_?x$wCm1fr>c`s^Mg1F~;(Jl?KI(;UmM@1m zQ$y6wWQi!k+rfi@@xE@~p@Z)yc;8>ue13%Ku1`RBrp^~a=I?#50Yk8x6Mg=`CM+I+ zi$or1pcZ#bq%$y7%%sXu;eATha|hzon|fS3wuaE5sbAHbG$3_&bfqT3S5fbA%c5n0b~J*^Rd9Y+;?Uj_(;vgc$^bQBss>we6wP@~9@ zT_@B*W@-g*BPzmzfQ-)G?NeFTfmaq7PIHr3)y0o)iysSns3Sfh>$$BTX}CKNMhyG_ zwVFC#HFbWM*FuM0H?{2Gq{9!Nb&qU$p()Nc(d=J{#(f82)Fpbx5Q5QvYQC)`A=G1x z62TH8O5q+sRky`YCy*d%Zvv#zY*h#xHX1Ek5`8_U&b&}tls9O=A|)%h{fzGnR~J8n zY6J3vG{K2jcNJ_)z*rLl4}(2f8V93%-M|J@8hVDPR2~PRjER4xO^p%I@00E_o&nQ? zzDcu*9Y$o+-!XIXcP}N7#)w5VWHJF~Wd9_X9_%SHiz7t})o`R}qP&ck7iriOv0dZ4 zIo`K4)_0rHHw68kXhsD_@8Q@(M#!Rg|As4|ZXcL{Kj+}E^QWL5@8S4vVkKkqUP88L ziiTABq?=Mqox3Q>`{sgH=iHbID|>`^e3Q9 zj6B=eh%t3_EDEt$IezNhIAq}df_DF+4j7HRcVFygmHzJQG8s0(kZgk|Avjbf$IHu! zPgJlGKtnu?0wd-)mh3XLhNX1#h3HKwWXC{=xS?ed+Ln03xq5fX5Yuqil@8xlFU})Ju$gpHUq|$pfVe; zaO_0VCFb$_E0EhUyMsE_VH|1d+~SSxNWB5ACPJN`pM361c_C#vu?-fk1ToOP3PDi? zS@Fm!X_sn(i+)b)zyh8qAqW`6<~yD|JzGY`Nu6UxJQ{fPj)Oe?jt>M z{LNvfQ{MR8RtGn@>mz^h|yI8-O zV7vX(aOp5E=$JS@nBY&4U_-g{K{%Uua>0i0$Z3}50l0vK>qKx~A~=sNc;5-wX0W_l ze}pcAwanhr2H%;3{sc<5ML&mI08hR;LmFVTa>qrY%4b>^r`7{9NPp{PB{3EamPDnxNRr|a@6`St@ml})$GyquydyGbq!F9rcooNk{7os8D;{ZOonSwtFMRT2%%q7%tU10t7%>G%p!8!q^iB{gro`;E1XQ&v zFbRJlQ`lv}K7D@+@yQ|Yo2IrgZnV?oH$F)8XzCn6%`%U(cs@YX4eND$^ZDrJS3~&g zS=?jHi0Wy!BO|`2ndoe2PjkJz)Z#MiNOLtVyP-yUnjMJE=xJ`irL?Enh6{>rpgT4} zVIX)Gp*}!TeX+7WldKOHs_!yc-vX##S>FU%pS^E=!NtwzV?0HuELv6uXzJXRvNBw# zGPA6#d2GMR%KKL4?Mn3aPB*ni0dZ}Nl9oTZWBmE7oZgy)>5D%P=G($IvEQaRgt32tk+E6q^H5= zp4g7wCs>DKm80^y?}CQr zw~H7X@q1yC2;cjseHS9x@6|BieihL7J_+*4g9F|p0plcKK_6*-(myH{&2;+{a8YH_ zaQ~NAlT51F6)Bb8S9{8w9GszbcaB;)Qw6#k92=GuCj*aS3?v|f$0T7y%ApH|G*C$o z;ZeQAsZ9x*M0pAKeNpgI@FTVHUH;!oXq|L^hWkj;kroNeZ(4eJhDwDv#*3LSz~wPM z(bT#HGKJ|&Qw;v=Fp-*+SwOUr8$lab^+k%3tmjSN{57Zps%?U)^AL3NL``Lo`8*1X zINb9hi>0~mBW=Ee8UoM4;09Zn_6`NEq&W8lBd7djpALIe!j51tn)L~NCi8^9Uo*16Z6M^T5A}<7=n&b8&S(^)8Q*mFn{u zgZsYYi=5B*@);SIX|w+d-+QJ<>Xa7Y){r_JDav5%L&aZ!M|72>TwMwI-OD~kdjJ~tBJq;xJyG@ z<4J51o4tSyH^t|NG(gVG4&yz50&yf#iB$Lyh){g*&l^KJ$u$e3Wt$_AN3%zLCY8w2 z4n(vRPBiaZ(2uBT*a>NL@VH>?VUGF1b7d#>)~=>v z$(IyM?py59{>4(M*j1MlyQ*)o&1$i|gg6}~NtYB$Vke-f^Eaev`ylmNS;GV}&E=;2 zQcSI^>PZ7?jl}NLEc!98po7QAfap_IaDfyATo}tMxmO;cVP9s2+^5X%Wtq#^M<83} z^-^T3$JsqWfcpZFV+l&p_UIy9$x)f@gV;F@ zv4cf$#SUzj;&DzvL__-r2^1kncHhaO7!MtO0Imgf`U%pYa4a05(O{Q%3$~m=A}q8B zQ|eCfCm)4ELGmj#AdylVuniJ15&zHSuPtXF`TOTHe_#H-g`r^dBu4zd`(R-CI~=vM z{O$Q~$=?^@=%QlG-GuwECx7qjU+nA2-y2yI~b`xMb$fx_}P9~WKzX5eOE`Kw9V+vo8#ocU^b zyjVi%@_0V(zrH*kAxrD>_{*&SQ+Zq#mdA_!`|@~OP?yJNfwBDvq}&IQ#{*0H|EqF$ z6BGvIE_BJ)mbdIDRFww{SqNcYw%MOH7n-ZD9G*Ua9Nzf;U~>3U|2Cv_BK8BZBMt8` z`3}wAUgP%b_w9!IsqvK@it_#G;D-smVB4BQM(oG7l^hys`hAIcVvR5UkoUbaSPM=( z2%>q*H0%OEhTwS9nnN)Ic(Sn>UUMYoC~6&tBO*`ZN-bb;2{d82#;aFyMz9x&uj=_5 zTFnzIEm#QlNAem=T#9>MJ%IR0ZTrXfgS}^9SQhOc$R&kd@A-jYX%*n_>IeJrz_8R8 z|Gj|qFFOXx#9lrUfMNK8X_Mj<<2C-+!9W7gdu#}D;wci|ke*M?y}l_-qw4^t^&rcgc44+3MCFjEQUSA)Q8k}%T<#y1E|vxG4d zjCBy0oe~CiF7}`Xfw@=0TtzUG27&pBgh?it&tX^tAD4{%VF^R1^uII+40b_j<1B?> zemw}x;}QnG0paf$1g1yAz!@a`wn1QyNtjfEDI5gmH3^eOFjEGBd0WDy6U>*iQ!>EV zPfM7Y1oJ9+@Fd0JR{asJdV42t9}bBg3j$sM0+##HoC-3g6axN)xCHE@wC83ZuW@R- zgvKf7%g71_`UZPLEsqTXbE|}jp+0|W5SVHSGlXDj2Z6y+5^9UQ zSN?)QU^Yt_;&Hz+2u!ntp%tqC3oIZ88v9NO6Gt#727$Rp!oaBxQ+yDZA4wR}A^u&1 zz~D3;jcWwK*av}mM8b?Dm_>uY{6@l<2*x}J%;OSCCqq&IR%H^Kw}>(VX)CJ{ErU;gBP_>TUQXw4+epmAz`4Ngx@^~%xnoWkzh&( zfw^A7Od^=nL0}e1m@5e;b`TgGMWa4XCYZP730+dt{G*c~@~{t`KOl=S!FQT_ox%x6idP^G6LDpZ1C_VCz~JxgEbOZl)EpOde}L-kv4p|wo(Sep%%CTLhn{+ z$ysW$@5H+mZIfQaIP|8t4h?RUR{X<0#m_@&(oq>I&IS9OjKGne#%q0NvL`oYXf+*C zi|obmzKD)IrY0YJD`wbVeP^gTI)g!DM#&07NC!Z&A8{MAzwmsJ{e^oiSjb2+68Wr> zn#l}SJs9U;pZK4_A8Er?YjqT(4qtcndG~45^giwX{*-{I{&%bSC^k00PCcoPhIFOc zIBhOvKVoWWg+|JLq;YHZN>j_H&~n);8?&-UnOa7n3)!P;b~TP}=`yuEhWg~W;=uQz z=CUu_Woo&NAh2EYO(fLp3eeg-yAkQ{Q7w&)qqA4heuSyDM&?^6c^mStqzb(INTZqx z4h0s{?RmK3_}ZA6{f4_C`;Ep?*{68F($sntmk%z?KF#&D94EjtrdE2z63&0!l6_I8 z@2B*Ojj`EZn7;8bYM1@>{~N5Ey=QrD0zUu<_7PtovN&pZkgkE2$TXu&YluvXl4)zg zX`tdXwHgo$4#mU}-*}H2AEav#PBNKr>VizbJ_Wbg2RK&d;RKBee2x=(7*Yg2#0a!v zgEVL8-`vHoXl_CO=AP`++_s43jP7EsTP-yPscIqb z(O8Kwi0!{OgoOS>_~N_aLit-ypP|zp6+Az*5ab~Aj&gFBODcXZ$X&` zM{9JWCjJ?TD!No#-v2HPj=f-4$Wp1Q@LV#n6)rS5Txec!A>q#JRI<^udO?q*1N|Rf zMH`A(J*y8Q;%FO|#pAlt#4hMBEN&wTP?G;~6lkB{zM5CX1WDc+5^es!z8ng5{I(X; z9lXMOXM({qsy#oJ79{-mp#OE4>)!71-aF%kXNdRCSm8Eied2lf;73s%E!)MharERB zyW#PwLw^-2$nfCm3dSbX}gfng)hZ+wo?;%8Fu z$eQn+_QF`x)ULJNCgp^F`@h?}7bvODIziyoO+x@1izFoCESic!0(nUy8k%5+SCa(u zzyKyn80|nc^aQ%Gy9$DngvL&k+P2rs?#!IsqoXoe=RK?AI1rwy zPr38E#bl^)#Cdu%!*r?E?kLI zFmV@Xs{O8Sm(I!Wy0ky5I6L9n-f~HKTz==0#yQtDmhy25wr|g6)~8+STI z_UVx+-FUmaawxy^p-4J0zpFI$qDVAlczpHBg-9?ej-*YFi)-TYl=nXrODO7&Q6Xp+ zO`R5BYbWJ*jZ4*>Q#mwyusk8ZD^7-12G5TJadDGM%;&W1!^EgD+Aw`!(U``&9@={P z@JF+IY)7>`b^Cyk4V-C(~uf)AH%coA;enVrJ74ogIn#9$Pg@L6< z4yAjxszpSO!a&niu_&hx%$+^ZeEq1ar%uoBx;V@IuExqgZ@(fd?xOa}#c?0-{KkRq zxGwVi;7j~79&6ci`t?k332j9(vnC{fGO;dIz?d61-A42R~X&{Euc6H6fOBV3;U zz;8y#$a%mhsp+1dL^p~;##XXEH2B2$!J+1R{y75gNgZzg=+w>9x>4&3W22}kgU>Wa z!wZ8yY~GQgD@{|=eOZ5*md}N$|5k?XOIaG8i(5aM`Y)K8-+5!>;P+zzj~(~TmM?Ff z(DJjMar@>q=Gym1s_5cVcFua>Y#{y}xrLSH8Nv?{|KYE4Q{h zQ#vQ`o{jPKlq^T-6>0U@AGb|6-WjV>d*AF_>0lh$7+ZNmYS!?px4-#Fe%C4Om4(09 zcSWl0l&CGvhVC8JGHdGQd-~#1*K{LzTBAzwjpE0H&rIxpQ?^IvB*(ow65QS$Np5dOv-jTgFxK>qVdx{V zVHq4cD}BRAJFMBB^U!~cz{;L&Ux+#GofZXdz4P1o);$3_REn5vZ@GH5c1kpHX1eIM zITqHe!Ka$zKA>l&49q<>R=~ItH`a%yti`cbO|Fg&{b!_R#0oj7^7-MLqBpd+j4hv9 z`SF|^8_VP4D^Ik&e97?3t8;YOq^aHCjlgV7%5I`Occ5uytfrG=(5gJUeQDep)(|IT zCdDlWKRZ$$AB>+)iz&X03^ug4d}Z_4xPmd-uxUbV*~e9v?;rl_N;XPGizijG*2LB$ zBTw@by>D`wow#gjaJV@RuEtXvl6iG3?0-|%`hD#U|4^C~tH;3A6LPUC?3*9=nZz=P zYubhy%1>0s#!8kpD>xfl)4)1BWgy*67I1I_bBO{k8qr*3~+V+@Y> zq@{gyXsy8M*6dc4lLUGi-D$w{H{0~ePiQYM@pOG z(&=nXdURa%dWZXCK+a`NP9tY*ga#(XURrnK;K69nY2*Gr7F%pNFO2I`<9?ng&)GF`*$S2R1>&-$ zkzA82XQV=R>fz#}EiOh}*4Wy`n$_!t_Yb`-(p5emdpWUxlN z=WHOFb|e}xaMN9p{H|!t@#Oz44sfRJQ{w+vyx+Dj*=_q}TJq)Wf}q{$wu0trA+z4M zzv+F)6)|h-&|4$hKwmt~dS2F7Bjl!3(B7<|7o(uv<AvdR|&1HdK=yo!wO_Jer>3I^uo*ln1tbKNrVz zVqRtq4vnAo^EgV|kXF3xZvK?4F?N;fi~Lq>Dzka%kCw-nQHZuqjqUUF?95%{OgkQ9 z$4$)E-t_jlN6)T(n7HkGNAkJem!*A*YS6T(dux`m?}@D1roJbdYM*;+uZ{84kKDcK zsPDnT!H=d24xSzVk3G2K-t?XL;Mv)=Yw;<~^ue>^O}xgN7&hW0;(d?LIxSbb1gNt2 z-Z<5lJGd~8H_eMa_Wam*nJ_k%+RD8+Z$?8hmm{e1> z;;a?fKE-oCiY-%fjqGSJi;&$8J0vgw24eir+*>8|RRRT*Or zDhCd}tMa3`O8&f&+^ZW-n*GfUBl+X*$2T`rmrJdH!+RRbx8`>)YwUfYdDGQdaTmu| ziGd|Qxo>TIdwV?U;HkkE8Y^EJJaSg$;Tg{lOzLfTbjBlmvf=SG_v@5|=@z~S$W z%)p*_I#M?G(ey`Rb3GhQU)FeB{-e1^{d&1a-8-hXh*ATO=5G4+ayMm{L8k?LT<+1o zUhdJ^VTTiPkNNd-kGVI7(X4YFSNAEuUhY%wy`(O8?d$c(K59Gw$#hbcE^zw>i!g29Tn?Whd++sxaTF7Y2QEP2Nt#FwvRg65l6DVrpUNz6J=%XpYMdDHf4a2Pp3Tcu5t@dsp>+1LvVY{$ zzW5Yhum_fYpl^3?JlkY2n~UmosD1l;D=)+)je}23Y4}Fp5Arj=Qof=dxx6Z=6v6??`BN!}7kqU2O={?2n^pgr2f zM`rMKsqB3x1W!Iz_Q5E7@%DwIj`r`7tUrmfY>_p#E5|L3??iB|S+%T9M?3dO)=yWn zrqinR3-XUn$U6FH&mPHoM>Xq6haU-EdqUPRN4xb%nuXP@BfWhj_=1;Y9WI~1F)osv zjNnIcGIIOE6X)-nS@?;KAI!o}Y}ub>;itrQrnY~Pj%^hxu{-j^*mvDOI&E;mDjf{V zHZQ*wd-waYjaWn4Hf8%g|JLnyV-$1ruXYM#LoCTl;(Kvz0~po+UJ5!Zg5rIy6z@+z z79DM#n*ZFydwaLV7I)I!Y2Q7z%!T~tPU~;FJI&1baeg-ywe9IC(fwoZB)e)j?WOFG z&09PgV`55mW2CB&J3Cr6aOc#Cv5KbXmQ=`Rrxv1whOOzEz5}UA@BefhH@&?7&Z%j| z>Yvw?Qg&2#BI6uvpPefk`fywhnRbFBc6w*T z{$0cleJ};?9r{n{W#7=Y^b!vnh~3QWKx!ntG9}%Sl5RSd|Lzp{{uH=20`J^?@6?!~ z`)0>~wF3_uvzpU+wKx=-?U7v2e|vMK_(cC1pNd5_u;{c`$BpAN9t@YW;!UOX$-5rC zZqoNP&ZRo$EDH--ReK=MArKmi8`?@U4blZ3PoBlAhVnn$s^0!C+ zDC@>l#oJRAFOJW@FMe7ncVy}x-doO=)%p~7c{Sa(^!}1~e<=OrQe@ni3OTzj@{GF3 zkEY0`y2$5u9?SV)iu^$YL@8OZ->!?iJJs`ry2uCWB7dH8{#9M%j=IQ28zb`Wy2v~0 zBJWAX_S8kLt&99n%K6s1$R%}=Pp8P1y2uObA}78pBB#_vPK@{Ul22A8Ka;Be$=_zP zyeGXMiuWUu52t`{)J1+VMW#g&K!2Yi@2iXaA1QKLHF936{txRSe>X**U5)&9%Gp~N zSxS+wsz%MDFW!1>%Q)F{pWG+Rf z?{YCKxv&`e;irxvd_UeF`bD*?XOfTBMed9DndGyPAo}FQP1$M|kBiI-J1rIVN2!2= zDImIjE#fsPqLL!MbdrdTDdJNniMSy}eDEX@m#2vL93OFS(wi0$!|Us6ZtjlId&D~$b`&jh{ia*IV zk+q{JF(%K8FSLvLo^RZmo)Pi2l&v?C9*Qfja&d)k`K(mctSF&>VRm5bPpU_f(!qdi zw20`*@iy1LFxzIlCF-y2OQ)`4L|K$R#QBMqefjszNy{^~P$_LX3=);iPVG89DjT?C zV#_b{ed8iYHu}Xg2woizLrWW{#VO4XKN)lPrtIeKfh98se*1>L7slnU`_kNxY<^jc z7_slzw|nOBxRJLv#IgR70sq>R{S%Qr9jtwEV)bS}xRkSjN zzBg5LdOB-Z-L$Mqf$ut&{VS0$(_EFpVs0AlyQlx6`$BPIdiX@sEsvhr63;p)zach& zlN-txMe^xAQN%@&Jhl$mp_PXpkE~BO#YH-=-c&j_QmjdpG)Ibf(&nV@Gb+D4^mrV^ zi-@eDKmO}z()MFVPMU|7{6!S-V0O%Wb`&~2NxvoCsuIr)i^sJ_V=l;^g%w{Jvt!+H z?00g!i36rz>!0-dyVH;!&u*>GRcsZ%i$|Evl_P94}I4kEn>Nw~sxg z;u9&&jghAB!P(W5V%wfh$C!rBd@klR&aFiA*QNQI6=_lr%0*-)4p?>6b;-#Qm%=Vf zdjb0cWND#vN_H?{_~qG49M|rhduE~Z+(6Tru|y^gENN)@%GOiTDfrxQ%fO_USH7OT z&+lxUTPTm-7te1xHLjqa(EIKTElhZESD*PT!H{yYuh+X5=|C_5QhOL}{A(L^l7Q zi1p<3*z+3tY3w0n=go%BJRI}CDR=1Su?W+3GB;FT52Xvp)93I1v>Kllar%6IE&lJ) zYpo&a@Y7APhk9t&O9F2X+(Um9fkV&45LxS^8x!-FJ{~dKQ_Odw0dbwoZ7<2XHi8eW zeM#V_qA`ckd9o3Ln6oXZxI0pDEfJBV(qDFZBF;<1fv?GN&}&NHFB(ek?EA&ktt8?A+?b1B-HyG|FMqB#l!w21bfAiEeO%2qr0-7^5mBA#=b{tdwY&Um9B95QDVYa@N;~Cux8V)a- z+%PfU`do|`F%(4p!;4-vo9(1Z}$z)96tT<;Jn(0ONYl~fj7iK$AP9%Sz(d?i}4Jq^w{!3dH+$C+G+1} z;_J$6BprTZ<+}q-m!{K;XEp47Ufsy=W& zR-)Ht-DK2FaocJ#4oY@d`K>D_Xm``Nm$hd1@NHuvqWeJNZ% z^|gK9`{&Av1Mvm%ws;@+LbXnAX^kg3j*4%8k@C66Dy>gM*r?V?br+Ddel4!9skA=W zcYAZL^qT$^U(0`dMRP;-%wGSh1O3tScQ#Ml-kepxZ}YSLt?3bkmDb1l%aigSFE@`W zKNw|JS|5)~16m(z7*%fWZ+$F18o2ezme$Af@86wk6QJ_W#uRH?@xQRwKGRqrmf$vlppVp)RFX> z$6Ky>a%)G{X0X>u(zD=!$H%(u3F zt;udHcgzMOXE=hD~d8|EdS$v0nW#Z|TE|2L~oitX4K6l@%LO z)zA^bQQMm*ruq`$s>fsCtvq&q>!kh_lh0rAWXr?1rxR5Z!#11(FzqMAk2GYbiqqnW zJ+HB8^BLdXTPF>lm%w8io<9Cd$-kLSSFVa?PHJhLod3Y+v_-D%lE+!G7+z&Hr=GHN&DlKl&dHU=#k};+ZOoOQ`|;5Wqe@dJ zWm}j0&MB`*W5NU3Gc;!$NEZT>pGpH=F1z@k+QVa88yob~YdMS%D%zIxO|}e)0J^eRUGhm zdgLV+SAWHcu^8N<<=Y$QUKY<)iP?^QxipfduozDx@IxtZLHsiP&IMV@1&wnjSD&>O z*OEo(l2M<(|bAi`sVvS4%;GkR|Grr+4NU~~#e zk3HSKV9earo5t>2FecZ#;FN~!wEftD=H5856jv@a-J9+WiC-v*hp5Gl!O+-Ge*Ky3 z!9Jh-+B2X0dOY1Son0Fnr+eZ&Ogv4rX~)c{F-Di>?afP178QF-Ck@ZCT)i|qiTKju z;#^!r^gVrb^rgbmXimINjgw-zeetc~l=yJLe_xw@Kc4y3>g%j$s;{%h#7_xD{M^^1 z*QTkpyiF-@G&^0WmJS9s*RoHnWuH{bKDm~CO3FTT@Pn~e`Uf9Qz4hw7(_TAs;d$p3 z7Ppn!))!j4ySuvQ6mk*RTA0>T7(XGmsAE${Pe)g0VZoNd+l$>@h1OeF7dMt7B)6z| zb9rsu=LOxxwp%uKb##{M0Cnsx2UUp^ZH`6ue`p#*adBC3d@%*tIM~nxOPJ^s=l_XR9M`CvB zwRKskZS^fDl(MvK?TJON=)9$~YjbDes?JieySu!xzL>g}olw~P^&M+FvnDKDSB%Pz zRenv|>UACQLpLuCzdl;oy{WjSE@|%CpuVQ9=a#lK*C%U2Eb$2LDl96NimOYJ`MOQT z?)LRvo9j!-bpTIc@rskz-7VmkNqW7FmF zc~?wV#dJe@e_A!}7x6x&YmLv9GjhA%5z~z^wa1h`cgM6PruW2D?R)1HQg^F%z-V9U zfGaxJwRNspA2S!7skRWNUv=&BY2_I)``OJ#qs*?p0>@G#Lv9nx~4em z^|@SOQ+uiV4Y^$B&Fj`~d1J(H`0etgvvau%Zt3Wn*%H5K|GM>;ZM-nT&&{oTQ@o5H zzbbcAyvA>~#}8b`52e3u)}`@o=0%sh;f;|kcmC@yJTI~x_c!j2>c_X79j|X+Hvfis z(ZOz9)H?OGQU6;PFTXwp`fC?ldBxj)E8?$Nvf`Zc;+BjzUv=G#>ABqHzj^hXrSFLF z*W`ZZ{CF8Z{`TB$@%q21Kl;St>pBZty2{;!HN~D=E=axP(vJ2NQdrZmrt{oVp|h*h zvAP()8I=aA_=^+^7RG-Im&bqe=cgQtUw_HX9iIL&xRm-2hetltC7S>aUv2M);h4o#l z+tNDNRw}fuSrem9PnL7$tv3DJf^L~cxxtt)G>t5V8BdslZgDn^Zt&NZ>A zSW}L<87UzVjGwSFk}g;s|1B)VfAiZ?IrC$Lo`3bmb@Su>rK<|d)^%-8?aQi3h1N>Q zX1#S4{1rc0(-5sIcwkuGqGe))fm~N0)9-wsg~-%ZoaCHm+~m(vu}vUGDBq z+k^B|y@i;!!kSoW7v-Yz+4BqQJ4)$Sdy8$+F}e%IwQCF0d)CEY>Q`&JQa>vtnzqg@ z@ndDF=vrG+&6_&9OKFZbRG0GVt{ASOo|}uM&BbD8R(H?F;_8m}j^di}6UL3Jb&_Jw zMTPn{c69cXy35(<+moRdV~a6@a6utJQf2Eq(hsJ!r*cMw3$a3Urr%IITFbvU?>(iq zQn@E>i&I(E244`}cw<+0>cKZ}N#!1kDnuWMtz&m8@A~NLkuz13_5MP8ch`nOY;!hl z+!E_z&n=NCEEkS!)7#6P*}P;e&z5PdsfCUW8`l@p_OZAo=04e9+jVo-nk|L2xebu{ zv0PGj=&XjO1U>7z%Int@im}~_MUmOBDQ~Ft#F(M((yGGBV&|GwDdU3aUD(@vBN*j-H(^jX%tt+e9Q-xWN$ih-l)sXIE%l7Cpi{6*A z&RpBF$i|~1ORRb$&CBK^wWHdn7cN~<*c3I#QtmF6 z%H5sW(kMjmRf`HEl*jT^mp~L3t*N!*ftnVF@Hwk%9_{41Bq!i8P2s;n** zdbV_y+HRdw9d1U@7gyEZQ6tIN7pDbqEF>W;oE~ipr5V}!9|5z|4p}xdUK*=W;g;f- zlx%h^p|r+ybe8KDQgxtj?a3BXN>aSFqjXVjdDoh@EolIYjEkrB#Q&FODHq33nm$Co zJ~3umIYnh7ae8xY>?Dnp5HYhaos(rb{_U~!3*Q!-nhoh!3R9=;F0_rTk!QzzOwlYjQDgL}N-(NbG?}Q;W5& zPVc6 zz%1+hX{%#bAv2smepQxY{&tJ;*U@q>4fetAqAVtQ{(ABib$x7+>Yn4XO3g_tHrx`9=>-5-wW zo|yhNrq9Rp^_c!CrWaz$|5k4IjF{dK(>r2X5>qt&xWAbfU-J4{Z+PRSvs>mbSh%Ql z@fBBIwdBoLUvuqsOW$(+vgIq@dc%!xdwXt4TW7hgdrNL{@#gOA%{6V^tJme`Z|v?^ zpSz}QOKwTIvl#!a-;$eOUK>3abL&$8;b*e?DHn71QCEPK(bM#I)#NIc07Q zBY&gP-^hn!uVcm@|2OmKUoHHd+26dA{8bZtH2dp4$zO_3C;$I%{{3D#p4lDODW=OV z)76!~AD`2;k{^uMkH(ZPa7@=Rek|Vqc}$;(DLY75*XWOJ%I*HEn0ChW*_igkv@fPF z#`JJZ--ziSV>%SmvoY0W&ECEkVU3&P_-#z5#`GUzni|vjG3Cyha@MQkU-n;0-J9-) z@<)IG0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N k0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk|Gx|TFYzBujQ{`u literal 0 HcmV?d00001 diff --git a/kernel.bin b/kernel.bin new file mode 100644 index 0000000000000000000000000000000000000000..e26c061d0d84910b3ed580f33bed0a27d9eb1c5e GIT binary patch literal 48534 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%0AxLC* zwLv@dimo=SONyXeC|XMq-W#C^AH3NUO4aHq^W9Vg4U6|+61;Eh*o+vj%9&bkghbsm z49w-}soZe2r>CO%Mo&+Q>&6Y2dU`H5wLXek8-{_~Osx+f83eZ_M$m}oaY4IEhhEWb^&U&JjVocrG>kWB$-Y|MXODNc03GPJIUHE4KBoUH9$oWbymdmL=DWS`ns$Idl^YsCWRssfBc7fcHegL>nEXR93$%8x z#M(9aPjlH7rdB#**bw9Cnb>_NXHAj6uEk%^kBKm~lC*?82sU_nicGB!5%>r!bW`hA zE?5v;j5%`M451e+#0SVst}8ZRRvTP1 zX=*2^uGhJ$NNWDTwII0O)3e^SB-q$%ZV6uRX>J$mhxy9d_vAj%5f4_U+~xQI8AG;z z?tahdp^Xc?h3&HnTi4I=7Pbbnv84-UdUi%B?hmGAZ^|)1sAG<=$leqc{K{i)2^Hd7 zfOw5~np+JU@H^(MwB$BL!Rz>LFRt75%;KeHy7RA4HJ;{{q3Z$DLaz?sM^7f>t2X>g z4W4!W-NF~|pKWvv#k%#D_;&|~$i%(4&uDJ(mA0nuZ;tZrPw!l}58i0D|3TH}R^d+c z6}IHBy&P+~#DA}+XVixHF5?T2Y{x-?ck~MnA)cMzbaV?sfnmgjgV?n%KbSYbC#Sp5!G@h<fw9DepNZhbu9H3?b5}RST2Y5V>w8!uYWcB3y8= zM3mPmWz6F0v{ng!TC1;_c7Q1-LUo$%cn9Wf@8q@&?8Y{e(DxVN$ZRF%JfV9liZ;{q z(|4n+zi6&xg$!m9*xh&opO|D((9S^HM`C#Z?$W++_)-`n!(sOk<=wd`;J6V;U^n>O z-{6c)=c>>AJ5_fT2d<;4<0sdUm}g|82~m8D-wmu)BD3NEYG5sPOZQiUVcPG=GT~H$<%g9wrKy<%Fn|UmZ?q`tLw2*6OKMzChI+$W< zhx~J&mz6u#kHgn5d&lrP$#{#_4-selTSOf1c)y0I`!=-f&weoDV$&T}j19N&;J??x zL--EJ?rEqNiG>MR_(r#lr?Sz&P_-T-Tc;8bsr!skO`&PWLIW-FG5wb~PpZEus{2(m zqO>;%MP0FJI%>7K1sr`~4t|3N7noW$T@?I?(PoPMf{0YsqBq)o6V@e{(vLX}z%p^n z3KHVGmZ+Tp(JnBz|@EFJ|8ybV0@@_x+3eWqvzCr@uz@|EKPh%js67ISI zHTr^?TCYT&4r*#0k0*9gcjGG@{v#7S@uluP{~;D0`cn70|4>tDFLkH=hnh-%se3y# zqMV8U+Zs)O3Et`hMgv#QivWkwjSEBWs6Vyny1TudRHAnbsd6;v!r9M_@J4g7)azm! zLFledQRuF9*~;y9m&kKit=Yx7!dhD;=38BqTwUv~thNeEirwuJTCJ_#y;hrYdw!jz z+B!vBZFSUJYc-eMu9e%WlQfs3Nt;qSCe<<3x%v#HKyDc1{}E=TBTYPqE{5fw8CubH7gHz3Pd6M{<8 zto0ZuHvo)jTpd**YvpF?qgSEm|WwTZi z{`N-AUSHe9z!42-mU7H&xQN<&qFhqb}(a9Jz4H{!1MJsV!mPrJD6Nx1|5St)YR#RD{-LcvU2#3R3;li`iUA_t_=Cp{4pivd%heTH`0Cd6>aJnlhtkz0M z81CMpRom^AT0LZghE5v@86p<-iAf>MElP^fR5|KsWrPyivgG7?OPw`yepaDbOHQtE zJDhe$vSQTCV)H_RU`|VRRzP;vQ(hTmVtiIdGWfi{60|3=U=5e8wYdf;DigUxCR$G5 z2TOyc+*S()#Uz6#n(S@|Mo0)+YE!gQCxKxwV1zni2n>peY}Kq-F5qV;X2DutVFe{H zxpErn?JjMND=jrOnfV7ozt)Qf1%VMHjAhYDE2CPUhl}>8NczsAjvr0%WCSJWg z*;-L!52Y(@E>5d;2}0%+a|YCr)tOn4Ki@2$onXv*f+a4q*IJQsS{*h^EfO_WM+HQ) zvrH6QYl*8Y5%gS4yjn+kumRFrM@k|cF|bAp2B@vHMN~Q(FVmMovVElm~L!B+WxpN8$vMp%1U|^2Nj?X&8^y(P(p8lln0c zv1t>*Np&F6BKpW-Heuzc83ix$ph9fq#G0?4;-W#(jH@A?TNfO_D_YCWDxRB6;zF|` zkJfLM)dERt4G{u6`qh-|NvL40@tSo)IkM8LgXV)t<-`}3lVv3T(xO0d zm2GWiZvG-5axlB_xA=_^Q6a5hk`uqM}*TgtTj`6w(XSdnYKIX}m&Ez2(i zsCpva2Lm^-h*4^o%?J`Ptkf-Tmz^w&3Ml9%LO+61K$;Z}s04af)mqn*00|Ltl4@`g z=`LdHa!bW(D`XSNCspQ@y+8^;2m_?jy2b{3qA$+O){$rv#riIpdeTQyfil`QvPYeI z$9k&~BadKT7If6PzA`2`VEZamCMBsASYfG`OAX8^jV7I87<>{VNsPL>9+p*j-DKx4 z0OQoy-L;j_Uk#*1wSw#{*0PLhrQPZzmM3LL2vZ@c2iRzAuF1}nTwR%*9GcoGp)M6M zB`w|cl`#2eJk<_&Il8t&ND#>hIgEmYzPrB84za~hVY{ah>si@yihf{47+B}SMDpGg zR-n|0v;xsF*#jCWN_0fXpl64+pqP0X(u<4%8VunImKv}^xy3rVXAR-T?ZUjkRtwUJDPgl?*wrxlxK{-UL&Hf{00>eGyw!kUg*a>N6(COD z5^d@dnn5)gi2wwDR$_22sVmQ~!$@Siw+SFl9D77vb0R( zqZjmx%_;_>l({U2J%-LBMkwWhF0!EHSgH4^L(r@Rrdm^~Q?yhqGgHf1P?(k&TIKaX zoYq>TSYUA?xs>J_8lS}z)C2~dqVX`PWm+M*CFW!Vs!!UG#;g|+5iqIs)h6+@qxJrPO zl4~$Lq~up(mMOv8Q>8n?vP?%IOidbGSmdA=SaL8x^tqsJU<+Gd&1q{awO~%Rxrn$) zTKcuAsY%-P^V7gamNixd7n#bZ^8ypBFaRNNL9IO z*?59tfefyP3LtE;{~@iSL@&*SMNh+4TP@cL>k?uH+EB{w!QO1((R8alp%$U3scDEE z=%GqzEe8>5J|vxNj_P2)SqH6wse)|6QUYhm(W&JKO=SapwJL`l&IdV4GAOC894VWI z^B0szT^-t&rZ7GE&p^b)s$`Uv-QCB!VBN|5$###N3ASuOu>OR`+Qy7jtME(?K;Yg8ih83m>G>m8RQ=l=umD`Bz>N_bz>HLqK14Z8mE7xCHSVP-hvbZM z!$@<)!p&pnpByg1Ohc1E=U|RYfSeQ}a7RcErZ!-Fpk?BT(9$9klWn00gf()5VZ+>{ zv7N>v)U`fK3G8K+F0F-@hdF_P^j-Skr4%g>w6(6a)M2;C`)iO4VAOlPmJjC}Gd3wX zi&mUdoX^iv>#=R5{H&6l`;3#^Q5a!FB|O&C)S;=BX;XN8$zg*Ht?ad3#F4bRr00i< z;BulrT2^lEBC&{47VYZk$>afJsVMngcgta;soZY_FZHv{*-#6=04jiuYOHJ3q^5`l z3-FPD;hZ!V7h{K^rKF^gj}oT6rm_@YM{JtqW)@`PO%J9MjX0g8jY0|1=XI4c%Al5t zix=l=%Xp6?u+e4qRq8?Rhp|6n?*pp4rXS;iNjIDbX?25yL3h_##mZ64COJ>VVyMPz_*2Ya?+}l?}U8GLflq z7&I=hyaZ*bS4>+vZF)%W+v{lIqsNf?pcWM|xyCB8blvr2T@fj5YtVQ#OE`G5-Aof~ zTG_EfBGppsv@-|EnWUzrfPe+Tz_cw7ZF|6JfMd}I2R!pzY`p-t?mtYk8fH!0*%fbb``Be^@2 z%P{1sQGKYWe;)-{T9_v`uVfbzf;6B-3!S|v@g(7RL#s^%)mQ+aS69fVJm86h!^4YNR?ZF26S z{F}{kH_b^=hP`Y(a3 zux&_+hWpXw7OxA*?`+DFwvZC}I~WifgK|s~3}1=#B*o48$cSIzJ(SHoEc9Yf+l7w4*f6vKrh+eb4bvh{AQ5V7bE zD|1r4)m84S#7db|g;N)m1mD%GB(Qg{rDB{)%QQ>KN$lY#dSPfK;HA)Rw9i~bDlhV$ z0Vi6vnD+u|7kq_z)9Z%B8#_#e%`OjbRjkR?CXa6Or!CNEpROoD;)@tsEHaj3+F43HrY&)}jx5p3 z;;N|8ttB#Mluv^-6xj*72}IMxPFPhUEl)SeVoWA0JYIpyoefJ7`wTf%ayO~ZTw2Nu znjQ3w|1_4!RwJt=67^X8&?yTKT}=`yMzqF@uRq5POa~pI{sfC80-<#7;26pNot!fr zk^XeTAj0{g?;3b}3EuHh=I)609M(oS7v<(rAJ!V1MfZ+F zjL@8@qk7_K+M}ttb66T-E|HIbL;_zH;cZ3O@G4-V2q&-7D~WYb$7_Ybq-Dg?Y5=Q< z7=?U?L`OJP9S~VIvLwJtavMzxj7wz;fW?s!`)!afcZ@)*uE8l~os@3WT0ZQlT4|A? zh%5yVu2|keff^(}OiM|l1(B9=O}{yW16*y9BuAmSHSo^b-A*m1s8si%0t<`?4t1ai zxeU)AdD@{c>bZ!&rL;ANbfym1uv^NwuOljahB#0p$AxDd{N=nR& z=1cQ8SM8Arj=W#zUaTp1+ioTip6SVRXv zIGS7`pWt^aVs8O89Z5IIypdWFe8u#LbPBWO37M}mvW|(qf@FP*1O5&N*hn5`hHgmd zBC-kA0sMe4QF(x&10uLPu$@0AS8m=wSMXoI3NAaer`p{C0Bp*b*)^RKNlc0)ofgzY zBsrkTtVC>bR1mV5L>eMH1Ny?DW4>3Tt0)}R;$j1N$8cstn+r@fA(u04?zCcETl7(0 zDWVF}#_7`cnh|n{FVVo@gWRDLR{q1rC|!Yp4Q_G3lGiO4s>foNgbv@40i%-*0rH0Q zlB5d0(?QW+ia333({>C_Nk*QU1`245T=2q*du^5SuQE_p%ux1;FjE;qx6S5;kKz@_M4FXo^a)nJ~b(^N-YUFm496J@bz)7YM&5OfY4H?Y4+lHDZC!O+Zi?Sdpq;*FQIfVq4cL)g* zChRVaSfv28mbm5~h|-9%5L&+JWUxbeB9vb){35s46RldLi+t zZ&+%eV`^E?5FoWdyI(AEuE&?cVAzAffkWiF4K>DsM0RSc$JUG1s_YM3q6VnA;)MSctD;^bSJ z@!#npN8ZI`W*}x)g&~h1vH5gHU#=gyPC|D&l{pU-a4dly$eSYNPGp)iKG3Pal{RWm zE+A&VkoN`3oQjwQ6>vWb7x4AGw17m<|P~ap-Ug{9~oelv7Ca-kJ6yLWH ze4#^x?{f&g&LQYFhX`Hf5HMxMZDOHVEK0;uQ7UXAUn~$sBI0@nr}=h=o+~>D-|Y|} zBYeX|P~5x}d14M;slG|f69po4$peE4-Rj`}`BDe&FXK*!aMG0yi51=GK*}L*5lh4x zv^YO~)oaTVoMlPjWULMaexx;_?guASo)4Vm8VC=mC3J~oX%Zosr7}rm zh04L2Dop}QB_Xd=N{K5WrIlbw1r{bLBeY!7m8=zMDUny6%(SX1yge{*QGKkuk{|}s zy)$FAo58Kn7}UaI6+;XW;zYe(++xJ+$3W+d0S;-c90017v6=C}Ykq&e96yYXfY4(C*Svg-cNp z@(6HQ%6&sF?eBss;Qfx=zRuJV-1CyOQhLone>Gt$bb(YRFrOO8dauFN-9!dOH_P;X z7V(|6-0&eg7OI2Ixw<->BEk^I)%7ae9)r@Fs-!!q<7=-WS|{Q~kW#*(N|u*c1ZS87 zw-5xTB*BRZ%7zKA4+)R_0?88XnmO6pRs4_?D<`~wZ|~5Io&zFZIEfWm=0$~bg_c0O zeL8fK+Y&aV>2(T>X=)V~ULqxGkiY_rOk*w5V;-hMS)ABORghi;57VVb$-v)H4lah* zMC8mZ7IHgAsLoUylT08sjsGXHf9_nfnIMutl~{-bx#L6vW-R0gCI#8pN^6Bh#SjkC zEMh+wtLt;P2?DB2mn?KoRxGwS>M@p?QeepI(Bz>c_aZrc$$F6YP)MSvokhrb7&4go zh#)rnhK3v`dn2iyd<+|lx*rI8Jv#NEIUt$DU&^t1XmETj*|V5prNll7N}j z`GJ_6Hd&-hOHG@8^))lDz3%$-tn8dzbKab}`8UlgD4f5bXyKyblG2+OFIjqvrMv<+ zma1!Pt5(<6)!Q3x!_{*4n#Q$Fw+nN z-ka&p6%UITtG+UErs6N1-)5o?U)e*9EibO;A;Guy5cB;!D!|P#&X+gzM7>?$&Y7Uw zWxehDt-#Z9cPle0Y06!{`aX5c1W#Ugb z2h^6g%EdIY_ok6wMNE^!LzmbVrPRVZ5aBD;u;%1HkTJoDKUxF*0VTs^R*M3elF(rq z=hCGaTE_H>2O_Lyy6&%1xOst;{&EMBwB2#iCJAZoSWYdn-gFN^7~@ZgzEuYRxSQ1-bm?g-j)WYTJot*%hJa+yWV zu263V5e&CW^T2Nft)Oi(15(2SWG^NK#9rc=nuskTPe0Zn-|9&_Cuch4%!S*^>PXWv zrLK^71pn1TtdP~F|G%wPXjx0TAa!k8s-+@zre@=JBE#>8kvxbMcu#J+;P)0;JF@_B z>H7(ifb=3AHpP4^AfYk^`bxp5`}0y)6@pkissT%jvE3rC2abQB6GEVJZ4cN9)Nnl= z=+}!9ta6bvCkq#wEe+UdWK=>WP9}%8M*oE*q!e0@B2%jN*i!kUP1~Cd@Ji;`DYZ2xk%tI*o z5MMoqP>x_jXh3L0SdY+#fUO9hMPMlU_eHyw%Yv{#`kL1kh%?2-XL!v)(f zbLN-I*9XEA@6@!Z36=A({Uf*ZH0b_$eO?_+jExnsW_m*rM3njoZ(OgyHwe-17QBtu zyD3y7?TC0T_)O-17?I~xuv1m6*QNOJ2snDa5JA)UeK@!VAXrFDk-DMVJK8d>5Mmnd zDo4DRM8Yd{(+m?Eo=c6d4U$fs5w)bNNIF`l(QcdsRtiKn>`;>XH;`mGuh>jU5oF&{osf%2 zox{VKVkrkdxcTJBRl_itoY3xEWaB)GdL*AgB`*qk1DFgQE;|n&gQR9B#O@kL^~dJ5gwJ!imPG zs^Q!aC&HH?RiV^~)7jTTlBFE?9vZc@!t8S-keDZ5gx9Ysumc6|czIKfbS&!Y@#+-_cPIG%Fs}Pi!})56DmPq5FTg0> z5&g((D||2{4QHNYW#sEbmT&d(E5UI3$@hp@^)!aG5?5nunI#wSAQ2(o?&Zl)P0Cw| zG};{5j=Wy2zs4ALqvL>qUd_Y+E7ZvhmKwj$3tyvr!!ArM9Pg1r5e0N9L%)qR@C?W! z)bJM_d^a@IGQB7oMg~6d)i~+5%AEn*nzV!ETTG#I4k2Zet*WWwm^ zG)!(m)!`J8R4jnjuc9?IAkjiPA~hxbI(&y1?FBj9(05ZxZ|@7BOX?M_Io9cv;t7z< zO1+WB)rvy5B``BkB4|%6qxd>Vty)I>#PL_vsoWGTiOszU-%HI$Q^nwrKY zOLzt8Mi=yMqP7UvdKTI6T_3pg04i!L6DlySSa>M%oo2_?c}|s@9!iB01=*l2wgOr4 z*&}iW=SJm4&ox|QEGD5ra+7bR(TK_C44Uiyi9Ft_7Zz!Gke7U2rAt*=%TdCT*kHK{<&ARDicFYT=jo(&=aB(wyu0ef5lm- zEedlu;&L@t%eXP9VayiT4pA9=S0WcRvJ1?)vEuSnkROT?x&nT@@FY*oE-oTB6b^l` zEV(|fb;_a(b?3B;6Fun=RL);)T^ZZZ_HZSvIev+icVq1T;Vmzm2S5%;DGysIOe`|2 z5-OO4i10=#ytj~Otfkbs1$qDY?e~ZSJKAvYM_N{@BV29Nk3d4I53fjpr>5YR7}}L^ z7S%u9Ipi1hP$Dn;Gdl9SEa07loub}-CsXv_?Jh~1f-ml&&ajE5232oLhlE~vQAP_N ziBGAR!b>-F@s)SzeLI~}&aG0lbGlFj1IMdg$ZiXF%~a99uL6|^><#&L?ty$_ntZo{ zOl^g}yox$?$^wb0w7e3TU?Ex)IGTZz55srBu`FNeQ!VrZ!>q_7Bm%C+)M4jGN#ck) z3-D*25wWo)$OzR9F#|YBZi39r9(dHRYtU#xi9Q!Hh#mlej+Eaw04AhnBRGn9gDzdG zZ-Dss8c`_B)sL^yZ3Kew7f7!8zx_S`UN5p;C?&URc_^ZRgc{PMEpiF$Ya&v)0o17nG-qo?;`e0o}s36{dC$7R`Q zHQrkFOmL5*JYL~TunQvkKZa*t1T4W5jNZN*?KP`@HNZuF9>p*7+>6kHP>ZkxAr~PP zVLU<%!dKrK#1Vvj2-^@ILAV=X9YPI43BqiIB!saDMuZdJ7{pR)mSW;GcR?!clrELIy%L@@O1cNY6v~ z1wtP3Mk4P)r2iM;C_*8=v3wNrK0!KeH)#BVK@8m^@#{f)SeHS}L&jr2)`rahn`@(AZUkbVRqh;X^e`vU2hz2KP_!5cdz9HlQsn2pfYDf4oXUXC#6 zCGelhqx1-bmcM~M$TOf1O5cOLR}n7ikagcedf3aTx6dH{@Vtb37U`D|zCsxDw9NYk z>H1e7uRcZoQ?l-m*MSSdeygd7u16 zw%3mI7KD*+pnsKjA<|bMY(cnG{tw`U45cRe} zZ#gNTjDAoIqIlgse;HuMynu7(~w>WFDnk5a_o|wj(dHz5hafEAp5I zNI!zmfpDFw`!dpp5dIXv+WEbti#P}z5PteDV1Fm;{v7GwAp8@d;Sl5#!UG87 zRNiK!A49kte7FF<*NLDrrC&qd)*#^VJ@S;-i{}xC2@V;OKJ+MzQd7 z$VNP;O^gyR9m5=>o$0d&i95kV^N@e_1%Ht zB8HtXh}B46cSVf&74qFkUw`FL@n1->6KtaupdcBE4ihl!se{sltvia7BI;>Qp& zuNp3%Kun()F+x18(nImPlg}ajJi=`Y%H9J>JHDj6-B{*LvBbkou?Vk7u&57O?^3&o3wUq-OyUnCm;Y!I&?ZC@}}WMhrJ zhIB*G#o~3ue?wUIgK^>*;;#_OnlBN(i0Kn6#*1k5D?gWtWglR@zHbngtjoj`pzS@7 z$IjvjVh3Q>LWfo6YQpoOK@7)pRo+A~A+rz5OfpD1obEI(HYGtvtX zman@CK6ZmBM*8+!l0-LfE=79nl4S8u#2KJzMNW!XjC2?Hc+Jhz#4{N0V;E0)cB=Rl z=(!woP(MFS(!*Ae7D# z4~5dX;t`eJAc_?(14p-D{2LMOM7SSe3&QUaRw7g(+=lQ2gdZW?gYW>tZxH^1@GJt2 zl-B52#QY=V{kplkThd}Few$$8T|x{-n1^6R@E}}&Mu=L3-y=ky#<;b8>*bH8dgV;%G(>QcKmHXFnugy9IQ5gtV7K={9YegxUnfp7>R<~U>o z!cv5Ggx?|TNB9TA2=IR*LN>x`gohFSgzyH!mk3j!hZZ8VAUuHZ1j0)QUm+MjgZx8C zL%12C8euKMPZ55Lup8lhg#Mq={WI`PP%=NhPiZ)xK|*DekMF1#4JxLz{-L?0y}o9M<3^;e0wjyEhYZ6F(`^g`j`vJT1ixxi}AUyHMs^ z7s~UsB})wAty>`X5bGa0kGo?A=Hpt(mg{AHKH8;oxZ792)?8^27h1#cbgpMyWDtW( z3}Q&B%+E%9biS970{)&38yd0xq4U4WsnGL@265m@ng8?TaJder$A&@CLxzrszhLx* zW5-{nXCkH=y-_J5B_b~}$>oOgl@cT%G`)tA*BYR4rquUCE0KP*dl3E^@h=+x2IJol z{ENZAq4x-Fd7CM zVhnMHc*9tOW=J*6Hmu|Z`u!n1bX;_Nbewd&2sfOB;-64`6P|=4;Wr!_awP24i=fjd zz!tkoTrFma9LTW>;S?URMeGtEiYOu+KKPz~)cdXvY)rInLR&YA4dCNmL+_y8A-$&F z3B5P=ZuoBNLI_$xWKUn9x`;tc>x25FzG-dHXoexsek2ZI5CTz`Y^@OpgsMr!k!y_F zNrUb(TyC!R{_d5}&K}-=|C*BN@q=ScV~oS%FNz*IV)T%>krx8&yq~p?ta|6>r}hL6 zHE5GRef7D{Crs=9d1cofb4KN*K5Dox@7sg-x7eOImFxS{GW;&uJIlS3M&7;pr?=hz z?Oi!d|1&Y>$^7z!%TCVz-`O1tZ@Kk~$M$UPE{mV`cJb)ksEr?OKDhVmH;#Su%KH=F z9&+8TJBGjY)hDBGF-LcQ_}iW>pMCS!D0}s$f-C*m>1TR3p1kdjNtOrd;;#S4x49qh zc;vUQ{e9lbdC#0|c=q`nUF&}}^~{vbAGf7`_Ga{@?Z))|Z~pZkzc}vSZ{uO zckZObuYTTpWzKIdzxQ|P5B>C;T}zi)@7WjkwUefwQa%rN9{*GN;*3_$FODd z$e8&*Twi=@#uqc6d*;A9SN`M;lFZ-zS&4~C1xN=bkabjooFm);=J^vplk+9sSGMs^ z;@lk#JCx(t-dK)@^$z1Wt~ZY3;l0B-9??63V^gn*8#eU{ zBjIf7HPonIT&HH~!(VkPli&IGl4S|Dgod<)%2^2w(-SJ^o)7qvWpgiCcGLMv!}*si zyRI($bpF&O%l<7exd;cCm-Dy$|BsRl=7KzfAv|!B_Vm-IZSquN+swB|p( zf$u5sJq5m}!1omRo&w)f;Cl-E-zlJfuWo9rdN)8ziw%D_M=WyjP1#y4eo@HojODNY z!uw3AiLvUdq^8L@rQB8@OXuaZ-TnUaJq5m}!1omRo&w)f;Cl-Ef1CnQfBgL= zVA0Ww;Khb}Mt#`x{ma*8b9~Qhv-SMGF@D#+*mr5n-SMLBkSoVG+=$e+0KA9v^Oxe( zm;SgIFK2G1lFZ&^S46KFzgZyd=`d`emQN(p_|e;?XZ;VdygNM~ zM0rb(_=att&=y?i-Fxa|?>n8n(cZnCJrff5tlm>OwX?nOnD>j;1Fl<4Tjvek_6lm9 ze7~wQ5YrJDZ^S{R%WH#hky=(AP~{UkqYs zIYT2WPEi%T1>6{&3j{_X&(nNFxSP=Ake1VNYvy@h^1Rey+IqlyqP4?y6^K&NMC=lhDDJDD_!0K|}i3s4=EjNbFW zM+}S(T>>9`i|$UGv>wwN4^5V7YvHk}osk{T=}h2HRH4WF`2f@FJuRIQROiPD>)DBBd3u&DL|fV!@G_rVLEkvEpk1(la}4OVqo??gP)@B z$G*pq^*nLL#63L!%XF@L6$S0)WBTLscB5s7xaSxKJtr8a!#$1?RHw?O);B>y6wujR;HT682?%~_3pel)8pvzUiAE96 z_9`8apO&8kI2eG;0$DmBKV5weAjt~mi?KQ&KgCKwqLQ)2gWj*n^Ii>5W|mLRsA2Nc zdw9Yy6)2B%bw_2e2+%x==TRPk`5*Z)gx_X<3}JB(9!*0)*uBcgsC)SK*0Pjx20oM^<=?Q?vuCEj@NTw~czBT<5i zO5?Urp?3@whF7tq5A`V(;O7Qz*SmjEG=a-Hucq%^ccqVOdS5)u0*F ztLdrX6_5qn=p@_w(x?8V2JZp~AOix5p zOKlylS=$L)o)XDBUB)cvj7xb+nVH(hkHma>c1B6IF+DMyXSTEPwLLs!R2Si)1#+OV zq%A@A0+dy(IgWeAbSTXePHoB#`b>B!<~6SEz}gY%%unkFdzm%bI@S(P zXS%JAW+ImD0v6zqVjpUh#rq0Jdz#}!Q@K9}>#SfL{&+jl!^zHA*CqI=>x(=AgK2AA zR7AG1tz$!XpS=A8gYI`RsHex^IoKP##h-(gmXE`qUvUq+P%V9L^F^SUY3q3O5Xv^D zcTx`#c|az;6Ug)fjdd}oq#{Zx;~ALC_;&M4d(1~^x_!Jn)IuuVj|uD&Vh5G%G4G?uU;4Ip^yI+P zxZ?)KH$7#3yWRY5gsSISA6;$!($%YrlD)Fx`baiKHKvqjuni8A7yn zxa09m_oV_U{On5fnU6y6$N9|r5XJ0)2?%EE#o(y3v(W8c^S-@&Q~K_-_OtC)=T%nZsXQb2`$8Ujgtcpsn%yw>t?i`My;3bn^k($)S3{{ z`VVF6V|Cmec=qlD9+)Utw-e7D1NS1wFcZD_OOK-eI2xfGs8J2@GZgZ#+cUvh{|MxC zf(@6QUZ{8a?bSf8Y@a7+fW>a_rvakU4VPx6`=G_65y8pjEmr znAy_&vT$8z+F^eAWD7C8!F{E|7}Oxb0dc+Z22>_u1&1iUkaE>mx?hUVS?;6j$G4qa zKlT}ng$AP`3ec{@v&)eF_YI%;+(%Uv^L}3EiWIn9Ci)lbBPRIdbZ>87yAGZSPa~isv4{K<<~T(8})qdssNLwbiS!|18`}XDNLvs zr>)o2dIQS*?l|TORE8xpE+fGeZ`#p8xY7Qmdjvp$AQ#zOw`bTkOv|Wn&C96RFfQYA z{~C1gJ_en!#MBl8$f~=$*VALAsqHjkln3WzxJ|8e$s%K|-*pAP)-c0qYCBAYa=u4< zx{RhBdEZcv@6pQpHOi3ZlUYv^5?+}FK@>xLMMYqKzj-fJx)n-TCGP-ma0Mz8B<=M3 zLOvUYEF;Jn3i8}G?+HU*O_0M(TL-gJ^{+AVbeZm;i3vtC=^(WCaB1KVr?83-2BS&v z!qzI#Csb#j(zrpTG0ZW(!ua;MBB`)h<(i)8TL_LiPbuc&d=*VwbEz6S*FU7IJ;x`L z3@6(jOiCqz7YNZ^luKrfp8EuHODF5=FZVp06)+A4XYRGBT+x?mP^eNw7I2Dgd)+V3_3uGeN?PT`gfot9IhK zPtWc25rJ{*A|0F+FoSvZh(6Mp19Za z6fu)l)ftR3J$1--=m(?GT5u%zZT!>9b)vhX{Nq~;huR=3!BA3tAc5i<&{NyX--$w)n@nPZJN7O_zp4JPHLd*JEDWaAu(Xy`nunftC z7Y}RMuwf|(TTKwzfbe7%K#Pd=ZYhPYc|gM>bxnH*L{0fNA;tqKD5WB)Wn8e z!89lb-x893M!JWq*FN|qYA=t(ZyPOv-OwJM-SNwAm2##u#-E+)zv(*9nW3fyot&rC zN*QeqJUvkxO3`whT7fZ)U%02^)Z}ew5-_3Fsl%$(s*9kcYQUNS+g%7R%^vf97MDFn z_hp278;0h~i6hRQa}##39j5y_h_vSYKKP@Mdj!nsH6QlnF!vwer#I8hhfQ~!MMHbc z2QhXL9OP{#38eQ)d4X5I03~)&?r=Qn^x1}7CH8!!hcTlOGucjb{v}kpulcZNPkegw zVUvem!|;_I_BJ0eZ5;#)H<21tLXf+u<_2|UxQCipj3$E1$v{3iGfjHSWx&+F8Cg4{~( z{oBaRe#&|nPGc_&_jkPe6AyaLM|h8x{_gtma4ZC3uM0D=p^MFj4aaWxNd>I$d z?q56o3)8PVJb?vd<3Sku%=;0MdgmGb6C^zbYcL=7)EzXqVt{P-#b_@?ruTplkx6ko zS6YWkOeW9n4Bg;iVTbbypF7TT)?oVaT~yCF`G05%3jiNjj_C_5&cGz>3S2-D$xt9f zjjOf!YvP9q1e_q@zMVB7+_MCC3KBB#B?0UTY#SKv2*JGuxNe#r>gZXZqh!k8%rr^v z*`Bje8)%IX%LLv@ha4HDiA)_+wMKW+u-s@lSWV3y4mbNF*=z=m}r3Vs>^8({dFPn}j% z8lX1*4&l#x2QmZw=HoPkw{PT?W!hSH+-LrZ2IDiIP?dsI>9?rVddN-7>nuJ00?&|; zL1?{0CwCcK}`^xL?@iu=0)}y8OX$}V3 zGkQ&YSI+2^uAET_7a)w`*^g9_e>qN4fhZj*b|0kNJrVS01iZ)%$w*fIA#)=_V%|w( zu>dz;*;hVykFWU~$=4i1o-@}N7AHHf#&kTds&SMX^625#&A3Q4(N3ur++AH_3l0_xM7F*$Gw&dsgr4SPDYu?H4_MS?93{xrxPSd{(~h`NCpVG< zD9Rm3-|1TFj~nH^^Dk5r(+P+K(~djG5H>p0=yPkjj;HT5{kpSxyyxtM4Hx0ib8G)f z{@@na7e;>@qXZ@@MvL8-fGaUQFkYEy=>Xd2j`yDO=biQROlmBnDl}Js-$ydnd=yWe zfeCPijqsd}br0QF>jQA2 zbr}ZRAYvm!|8k$8AJ(cIcgy$4k{-d(1x zKje;#BT(Ww-Ru64dm0SncnNwBMsx#Dt{ME0N=L}arh7ZFi-5b=v~{Hami_EvY596+ zsIHOIU=Prd8?yybMVDR-wbuZw+!|9<_@t`s{yMx@Bl za%Qb7mSud)nI-P%r^%Kv?Dd*YFgn5MH~?rp7xX;O@j5o z?dU&m;y~5WYzFL2VL)U9UQQiNIcyV101=`X~*QMF?7WgTNk@V13B;CWFmZ ztsNq;jS{R6*?!MpxeDwUf!#6yZa-qMxeAQwcJ%r+RV+Fk_5nY1@Bwmyg&Q3qx>@xY)}sPH5z^rzsF4>@lnmEViSrXr;WC_)|042bXrOpKsGqx+w z1j1g)K2qm>6u=7dd|l)|s!V3k0(t~e)n9a^Wg970fjb-01wu0aZp!j}Fxx*@Ydc^v z!x2L8uozHgh99XgzU9o2#yohDdMDp^C-B{l7DaH{cH+F?)a@|iMR4Nw4vNNY-%Zh| z?RzPT+rE#Y=_B?GrPHn>yqqd_dn!256j<$DFG;VtrMWeRAL{Z%K zS1F3#jt%NSZ4=H{OPu#nyB>m`xc!F|joa>{Xw-Icv!kU=6h&{}h)5#X(i~&F_(01C z*HmrXc~G8V%L3Lt9}VYG$n*#`B6Cc}kj7CNTLcdz_P+f$%0iOH7!{E9XcgZn!MUTM!LV0R{ zUE$`IA3}A4LTiCA&V8s5&Z?n-zu*}b+VOB+f`kP&G%#9T)ERLyI-5+`+z&~rV}m^6 z;J_&C8uawrFc+yVRuk7nM0FYNIda3R^dA)5OTFxKf|6oM^ zPm$*CuyGzeP*3TqCp1KT1rqV>**#hsZ8z?FmML? z>3w78#Qoa|{!_lIHcoDR{l@2g#up9(UBYk(mQ8SMWXWMw@(EmF#3uUMQ7kr>SZoFa zdf;MI1#h0}vxIs5()x+XFf`7>B{zK#!)XvE^IkH~jb5CKz3@6Z+J1`Bi<=zywd7D9 zo)5RnnBsCPqguP|8SOw*2No=bE#2z|F?(vxt_rlmyc16blOEJ0wRryrAq;rwn&hnF4a{V!l! zGKo|AHbm_OekL2@v_&?=>4*9@#CfX#8{%{HPVyn}%>j^TXUE6JcIHCdihP*5YB@7_ z{g5smjL6_5BcKN4o}mzOClLqr6H@on)O>lQ54E~ApfCWp?IqYffCV2Bt-x=y;SR-a z&Nu#rqhKJShT3cJn!NvAHk2T$X>T7XsrS<)t&>d=vj4KF!t*wDn3_sMQ=k$XH3>)u zNUjEE!)=1xdx>`6;>agZjSNW^<9ZS^7f{KEC_$RZ{tnWTToC{}B>>Cht<+31{)7aF zbW72)fMmr`OXD*jHOO!4&$thN#ZX*?>fz-=&TkyYy!kH|%n71&*?W--hPPkWqhs5X!-kkl*|fh^#N4KNE^U+_<~m{E>^+k1xU{!zdRJ%I)UY5HZ%U&_=fx zzKUpUd*LfI1}8{DLgP}JA-c7J$orlt_cWaZmhSERAWGhJH}CE;zZ0vAt>Y>lBb{1!4!_qIFqym)p{41s70zZ@G8=Q z<8a0K%ij091A%0;(mseBgI~J8z$AZga%Yr_PTl%1r~(?)!+!(r*MXGp^M!_!JOAPy ze6n*dpU0Jc==q?Lb%e>h6XGq(J)))V9h@1^CFDI21rgUDNMWbqD1a0li!;_p`7|&6 zG!h&pd(2+}a~$KHkP*IE3_QptTD+f4v^YPTXffn|0w>bK4U^cL46AM>m$f*s3 zi|ns>IzJm=_SVrrpFRvSkrxwmV=JO8Nr;3Fbe!3OKd$INAs7*AkVFIFLteYPKwFB- zBg$oa~L+?>BTbpBuQy)TB=f}*n|AVAY z^6$e)b{SuI1QD`EgS-D5$$V_C)^>F*Ql(U|mtHvm<2(4qk#0 z(@yloU1wH_Ra($S(ZpamMU#TdD7rjYLeb=4Aw>znJc_Oe-bm5^)85_3S5e=2|DTWq zLX0LVDBd4L6hy;40-^;%xKRR;1aGJqLUJHSlAL&MxKXiSV9WWXTx;*U`{-_U?ONB} z-)`-8Et+lx?Ey%_-}%m*`A)9to@yVXy2snc=aZkjLpX@*;xrTwJ&AAXw4 zEzS6T(tO=dGs4oG*-x5p`)RDeb{+BS&QtR9sGnw}rTMph(mdg((OP?5kMxt~Nk7e1 zmS$r=X?FN&jI!&Fe$qVarx|T&CijzOx1Z)}OLKNVX@23S8DnYwV8GpSFIhiBckMoAND^Yerr`jdR|uSy(7mI+qb+UzYo3*IP$yTTmF%kgKq^# z>`JJmD?IXS@NM9ce+j+~I`a4KThWn6gCT?6kCUI=U3}!rZpaz#$H`CbE;+K<#bwj?K3!2bs460?+U=&e)1`UGPooN5 zH%0Z6=0iV?JASV1C(WPyH14>$q@OfJ(_Mb7V(lvLC(Sv28oNB&RoqXSi~Te@GUFoNBXY@e1KYd>jj^3&L9N7saY z(k$`QxI^q&{iIpur?De?*E?z|o^G4g`DxCwG`ssr)99zsp;;#d{iIprr?K{0*8}~e zN%(2bwlvH7NwdLE!-Qc()@crX?FW*F0nLE^poZnews@y&7bv?<`qB9WtL{8(zvQ$ zEsgdQmwlmF?KCw&X8uKQ1H=ZOp;m|uvsc&((dk3SZ2dfZ*}98$w6L+dWlIxZ(G`93 z@L*zll%OZpqtV^-wFHo=}fjLvsWG6b=KJa=Acb>1CFjMKJ>7TJGxE5^IkqY z`2B4z?7lD<-sy(Fo%zl2{lj1I#|7s#!8uL#OiQ2IWb@LzgR7^*_qn{gOUN_z@X_vk zUCmG}+o*+gosjF}1Jup!)%1~`>o7{HliKA)>QOgiz`BdNexhdN4&6m^^6-kTALt`< z;P8rVmmJWw{dWB%AIS8sp#5HASA6r=Mcn}#9H3u*ywa~fKlngq_oj_yc^ABT{N?ty3%ahhS?ULPo8_hY82o|d zs_*=4m2EvXefnnUmLF(!^<~|{O`kqcy5;*WdSKl}n?Ak0bjwRFT35Q|Nqx~h3@eWO z+6{Ta-S1PnrCvvpO`jf2MK^ugzQc|xrE?A(`Dd5pzt)Z1^yz2G@=c!}O-94nL#)Xe1mS4joXs zWvphpz2@kqPg+X9IKnN!eo&0Gm3f^t%KMR04ePwqz7^Uxt9p-os{cA~v2VxhTeW?& z22ZC|Dz3rP*=pac!PB|ezFC8((^{LZ!P7b4zFC8()2b@h;OVqV^vEMNY@U7lrhS`c z-?rN~+X0WX+qZH0ulxSah<&6x@3xQDPCFWQukN%8t9wOfi+$YDInzFtbk^I)&7D@% zyXSPSu#X!$@3N06optsxwliuUqdHgH$MDW3`?#>P!9LFIywyHRI#=39VdqqRJYJBx z^6|XVujyKzU5K?Gu5Z)eu3>6SZu)dxdirj+jlAyh*{Oox2|v&^(`}bLsf`wFgunT| zzPBGd;WlK??&tq*v%+S3hpJdxk}j!Tqb7E^?PjK~u-mvJ_FJKSDYIV%+Yh>X(SK+; z8EGZs*`C&I=PCQWrx~jt_1*8a|8>2jJnm4rRKeU`Xxa0EHQJ&4c)MNQV$T(6KT(!G z*0X>v`=v@2F4N!DrkL?Ws$j-v>33&*w(6nOGS&SB){syN6(q0g=l<1Xm3y!2OZwhr z-Tik&6drC2=W>_kl6ii{C#m-|uXnnpTZ$DfMOV4L>t3mY&mLZJYHM6Qz`pouX4j8* z{-(^^{IQX?CN?>i)#J($&-(~Us>i=H+@(Ccg^~lRolfQM+}e5)t~Qe zj<~-jIz6%|o^pTZPJe7nf0MgOe>S*Tf3ny9@SXlhS6g$ezSSS^{zh&hGAdfWy4?LO z=+Wiw3FKN}@Cw?yx@2)s%X>pDkFL8cC)?iBHBsG9*!7qCiN#KVwUuwsSP2|VDCPI| zDpBEq@UlWUJ9o~kD`xX`-K?aey2xD@Re%38rtSC3rGA}pb+WrQt=}LEQwm#~bn=uU6|Qx~vcYM^Bf{wLEV*df^T~M`-Fc{1gchu;7q*MozF}8XKhX(C z=6!pNj`r{N!+CC7*_saWyv@(soK#x!=ao%6uH{Z^S;c| z0}?K>`pcB(s*+PThxQXEOSk@3%kH>&NT%wQF*lcGs?_y-h(Xx~$@`@xzF)`Cj*1~; zD$3Lsy!}2E?d$B6T9@r#vk$k@ndOJv7SvCpGgVHeomg9#*^^1XrW;pv*Zs7k>t0v$ z?TU`{D|-gIEkD<`{EK7MC1I|=={4cEba?8%M0bv=7njP`YX5K{q%?WZ}hRu{GvS%zN@dc3YiCw>YHkZ z(Nzbx|G*M-m%4@d8L!pCRC=}-4D4CsyvzedduEoniQCk@=wNEn_Ua)WRR>3Zyl3VR z$1=OX%iN?@EIx64#gL@_aG6V7UEplB3Td4xZJ%4BUZ*CX_4`=+yYqYQ1+b>`ay{We zzs&?i;aPodpZ#HGPsdH4ZNB$In`!CRCv4!PqV2by$Si$j^8+XRp{iQc( zTjk9w3bt5A^@?9ytN^9YIWkf zGObCl`@1bPPr`#vSn-;ugLubnDm#Zp@0#|)y3*`CUeO&Lv-HsRf&r?XEPb#s))#bF z1sN~tzA>}$z^S>u(a-g7IyBNUuChFBZo%5~?9L+F0kz=CO440u2|n1g@og^^aa&kB z+gDXHbf42_Wsi)}A*D}^82q+l9mF5~vDyx+;h8J z!=c!|Kc(-kNzwjp)-gg?<~FJ((HYw7yWT6=)qP$^!FP0p?hNe$x_Gm_;QQUTxKgKM z*nI!l2G%OGnyl*qRhXHA?`WAt7WdR>TG1V<(X^G?_YTTz`Hqdu935%%+jVe2e!+M8 ztd)-6L9Mzm`-k^D%W}T5YzHDOagxO!>~yPB5Yf_C>3Wa5`M=1*?1f)%)#+pt%1qv& z|F@n@T^}Bm`y2_5s=9EwmtOV^_Nrj|M}lc@tb4)6gv~3Kr; zXZBwXX0N%q+1sa;f>_V&H-GARWjoWZTT1pK&hXdsBAflmXSF!hlb+@l9tAX`o|j$Y zSL$lu>vR z{M!*_?Vse8e&sp+be=c#MU5Feto!PoWWh;qX8(wy_K)@WBTLY}|76B}IsVe{GXH$l z9+Q&Uucf%w)5`~Uy;In6i7jSC!B_nhy8r%?y&AAfm72Ak^z6M`I?l8t9eK~#y6GU5 zn%G_3QSfE^Hd?nU+R&%%zsGemn9Hwj$j`j~^5Lz!)BkBtb1NLYx4XppM*KFh*UdDz zGe4)i+v&5~Y-PHMNXKda(G*=V{a|Z_#d2#Y z?C7l&J1oWLl|mOM+?2MJt%A~q&S;Z$oU60+ybFHT{$@eugueKv-R&>r>4_Y>4wnpm zf3TiDr>0d-A0nMxt2!_0$ajs2lKgE< zxn?f;sr|2b(Ds6@mRHM={T+)(9r93z|4!ldAzybR)fBRo3KwxgUo6fplxzQ0L^|Z! zaQ72k!4-#G`PcBCvn#t1z_py07wzgU$?R60lJ~mb?sR>8^L9`BAbGyc!tD*J>>Jf6 zv6}Vub-F~NXII(74OFIG2Myg(pmvVR#<_0m>p4B=Z7V5rn>hV`uys{=xLzwIs>fVS zrQKb3H0Xg2=e7Sa&kdQnKXq}pZhBjoug6@}4$RXDmIe);x?j%@+?&@uc-o2dTP|VP z0m3?mXeZLu4INNZC7E5@E>Kz1L#xss$venj`@0c)p3o(BD&+R2^Nv678m6~ze%rN5 zU0bsIrtJlnK5A)lJ+J(+&biJ{X)E2Sdlyu?!urE1bCs-%HL5F5iR^SBVr#p-VB%@# z^qS5ZcG$BAx_=nfrq=`~CXZMJXfuE0hyIr$^)P4$qasOmO~^w=Xj=cV+HS7CQ7Or7b&MMxM6yDxI@S2fiWU>RFu-6tiFr z@3b|%OjCBx&z;|34egoRGydG3>wiuU+nj#&jBnNRR6?EVyG}Vne=2^rfpruct7k^0 z&#~pX!mj&t%C$dr57Q94*3o+)(3pSJnBb84znzmS%SwMpWx4O1!ZD5EoZOyTWlc5R zqM4nqYb{^y_WCeib{k$MzuN$NH;I-qO!Mm5;r<)*3-jQb|5@`3hwrsLFubibs7W^6 zV0p`1SDw3J+MZUXf(!+f?uNFadYjtB`RV)ml9M$AF;a0)mx8PH8iHs z4kJ3o_=B`jn6wTrdAGs{n8(x0hlf8^z*&gi(kNXK!_qkEZlsBxNCSH14e zbx%wjZ&8h+(x(pWdb`N)B{=v4KYi|6->c(E&RWk%Ypqw>aGkfF=t%eJ{b>&c(uIoxhe zj+?eG@k;l?+aMr_ovmKldF~KK-B0?62Ti)uO4q zu0`Q6g*MEZbkoCOx;Na0eKuIP-e_3Z@X*E!3W&AS?f7O@$bI(Xl+87w&P}@bZ{yzA zIOX2`SuTARsYd*zt&KH!{2c7;TKLD4Cm*$XDR(u`uvI9y;xb#ElTX=wcUBq)6QodS^Crq+cxjhD(IlJ%}q9a=xe%kU;5w*jon>nGqUTE zmgMoBrCV>((8tSCy5V~0ehu3Ef~V$0_n;trJfdeaJyrOU#++#*jvweA9K^>Dw0|<_ z3um@}a^mR|8dJJxznVl=VYQ#I!6(AO)}XS%`9ojSqBHLQ{K9?u{;2)eapo)ff7%Nh z2dd3x@z4Vn?^8U~#y@gUnV(i@qwX)#rLITq+arhEKpXE5bSYm`s3+Iyf0Y3{!|A$7 zo9*~M|JrTQBd3l(rcLmOzf_w;IN7;L=9E5y^aTqQA_d`Q=HoAhyi(sKJAQ5wzW!mKIAXo}49 z?LQyTRbnY@E=u9K1+^c1gg zUr(`it&WmMZ3|`GcG2mpu5~vdwik z6Ka`jCLL~*>Jpt^+lJ}spPA~Sc0CWq9s=6i##&zDTGj2J<~?x5lX*J#yVOo5E^Gg^ zxb$mw8Zdmn|ImR?)dbSzocA+(gO-=yM9Z4|JU4mSli{PY`%K_+q5rhM>7cArm42_R z>Q2Gls~T!y=_!RONj?5g4^h2H zSKaiyzr;)3MW;;Hr;l^*;m{CWZ)#P@cFa+I>`rJ3T&D&V!H#pMO?vPdeL1OneNT5d z)8rKe*H;uJYdUI5w6ojcE0~AY)D8j{+H7tvn6@{0#nzvtBHM>-cbi~h$NlGhmYH#$ zb^hL)9Nhj+fx8s+`;K$%WVGbLcJ*_~I=a|Ztf~^%R-1N9!P>%(ypDp0T&WLBn=ND4 z+N-u#=S|zc_CmE9I?mWWNlp5KjuJg_Q`N8~*sqg`BYByd)ulOTukX;M7w>T7@WaaP zVLdytD}PN&>y$nj&D=XXr8L=~!H zX4*+skv`NidrQSGJjSSq={DLT|6#HI(^Aq!y9@32Df^|#K4+Xv{ipWg;3q5lIY>Vm zy`~C7*ZXvv!JB$ShyU!(J1kDPIHh)@y1H*#q2DmNi~a8h@6jE(1Gn9!yXbBAzAJdh zZ*W;<`DvFrxzAGd(}sHvwOjDuoCSY;&@z%bE2I0#RU!C`E(s%Bc;=IB=WeUe;7aVJks-Jcj(`pum>dWF|8G_U3UQw((Cd9HursXp`XyHh~F3bDQ! z?^^5Pj(=2T{^1)sE~wq31JEZQ+C2)cn(6KAsNCsZ0v+Mg`t8E5L7W>qx#_(rY9A~g z5_@&UJG$O>@nxky+IU{xry4mlcGCU~LEfi2@7!>PUyEmMFX&#ZlCAzwrO$q8@PM_l zuR5C9ujdBsI&$gu8O80t&maBE*vS?Z=KPIE+uzIc+qK&#UAO(Fd|e!#zh95pkG=FS zY6se*Z_6~pQ>(_Hrc&)$*`?a|>6fckmSqkce^bjjGBCEwa+P^~)#%-;GU?ZUlG(Ox zo1V^jSl4*gyfkCf{%uvidph}p-&ckcoYi;aYtKA+|M0JCq#oxvblcLsoyqUFoYzs= zb^Ptj%QpW(v7cGyI?`RE|2=c;nfebd(4*Opzm+*Udf)!8yyr5%-t}HlY`3l7=v|qr zL%X^MZLj_7yv)*rPusPMj*W*h8{chzD_^%^n9{D&AAQ?1rP60V&HUQ!*?L~~;7uRr z`I|cL#I(wH?|nx%S+>GEjTsOPpVeOF%&`7`+_YbJUY zmpudYMjh_9EmBiNj{~=Fg(`8Qeyizj9jISw_HLW2R^HOrw%w{SQ2D!Ua|f$-czspo z)?(Xf-6^ZT!}x{dEW0FI`s~-v@s#=PwP&B)KHnZNT)JTIu8#-!MB7V>-GO=6JD29^ zR*wA9`(iuIC2yBo9eZMGW^eAwtQx&*`<%1=UodTF8S3eF<_`DwE&4nz+U-Z~uUlk> z+8?#>&$sNaWVmmd^wFN6{oRu7mF~j&_f+=XkA){XmVWl=E2_}cj?w>0o?mER9<~4c zzoBtU36Z(RBK$miP<(Q9Wlw>8x-_w>W`;+n|XXd)Sl zw@!~JO|sY$m5(c*G_u)2)^vEA&2Ih35z`|!<8kBM>>EZlMD%yzi;K_H z?Eo8+u?GGA-x6(!CpJV{>f1DZeRFfX!CMklK3jDsKz(ClBAQIv(#NeIxxUz2m54^Y zIq}wLd9gRL(YyVIk&Tf%?7!LRR4U$@yuq8%sSo>etJA8KaT6er8HBj3(5vdO|V{`Ghai4jtt3S0&j8dT(ZRsz& zq|7VVd#c_y>Ag(vR=pq8`x|=yt=|8l_wL|5Zv2FalO|8OZtAr9l@0piiL0Apcduz~ zX^pqtlSro0YuBycaIcx#vy^NdBBK^8svVggt-yWpqV?-pFl|yiMob(W7MBRP=H-f zY#CPj)>JO4z1{}iwq!wVW!>WH$|bXE7c5@nhE-HAty{3D zZfQ;BlDewJb1L1y1&eBGmn^NYM0Im3Yb)k!=$zQvm>nx3D>p>$jV9vWoaoB*>eW%J zs9RO5CD*t*GG^N~k#0+Qvz47SZE+3o7OTox)f`{v&5o-=PI_TUjJMgUc&aWE@doW| zst>Hd)Q2^$YQVHrysPSUlT@E%$>?gUA|g6QXlboIb4)285!D7M?R|a{9a;ROHfJ3G zlbXy^WzeuDnC-l1tE#bPjfvy*v?4pJ_^RzR!_ExEOF zPMs@ODo#u8s9St%(jANBq>yHWE@%DnURo~HLDdRu&j-edHhpttJyIfz%ALx7Eko5zUTG zEpgRv<>hun=rf-sQ60}?EB#}is>_s)eQi3nq{ogQmz#D`Jd#YewZ#*5I8(t;Rw9kI zCP^Lsv@_^n(P!RsRDm~~l6JbkEwb`i6OFD>0XlW*IrB5BvFj2s?GVA?+G>d0EceYr zWg-#RL8LLJeMyDHpE}q*qK!t@H+@CCRa?d~y>Rxd8?+Hr<|;Nc+qd~zynWVarSxeB zfvlBSqP;O?+zvT1a>S~}aW`1i>$&ga{qNS$@g|o~n0$F;;*@b~g0JJtCscV8%Qf)2 z2^#3WjW3@xDHu4ReCpJy$gHXbk=Y9t*Z8B|Fw4RGSqoixXjM(oZ2Q!_Ikhfpr;J$8 z?}(ZuYA~N}UJI7o;*XgycEa+&s%O4I<>)s!v~*MROPDk5N#`0@+Fzo!`b9hb~-C*bPF)pM{`gIdLuVH;-bkaoq__TIaDlysfT30r$-e8yKTJBC?H`Vj5Srdzo zo921tW1FvUyH>-m@;!#$aJmS8@BC$}2`_`M1ukT{6=17R{bN?~c1PzUro>S6;23if&%8c=RaG zyYX`ir&rr;@t1q|jnRi!ywSVgKJC^2@@F+SN7ROB+)y6T@jBtEWi`K(@#d)QGH&my zineHfsBE>iN26N6tF1CA)yv-u3Zz_Z`a=%OQh1-Cu6NT$S2hFSFNu){azin zb^H%^%t)n^xBP{3@x)LMuqba^CaC9dfy5aAO2s{vXUozdHQxMjsZ)eestmwDHF%e?j8H@$!H zUhzKg&dwW`wICdROXw zlirKHQtOpV0fC^?pY0pXvR!-beK=S)*$V zdS9>iJiS-wZTDoa(dSyd|4i?%>3zy8FMQ?OD-3!+2Nv~xjq7;@!&kW1%+tL51P{B{ zrqjG^{QnJ&r-BNqk3n1%_X)XI_N*={?we|Af9_zKI|RT>bcD^Vi-Jnvl^CJM$`Xulm=I(wwg zOr@Ktbg!iq1g}W&IZ2Gu zk>Km+^l9@O7sQrMS8#e>HqPF5FPWQHFy@@EdfxotyM0(1d)a4JcD#4LrU5D^R_^BL zZRJh5c5(Ln-hIOJp0Gj}yu$f~ao6P!6t}pWNW9<-G zuYBoeFSo!uc2d1tvxXfzd70wg^*eUbwy&*||2lTkuG00^$;VD!r&!Mnu;QZEv6FTg z?)c&*hg_(5uKVKW$Ch-f#WUSN{der-3jLqfV+H(IzPCnSwq?clDz?WCgya8AU+iH7 zVf3D@@MRu93oZ|CJNlgF?cWE$_^n_}rZMlAQR;oOqUEdvd7%%J=5yj9-)!*XG3WoH(5mTithb zO7Hw1&Kdt$PW+tWSM?;JFh4KljJMA1;mg+lP)=;mbO~QJ{-d1Oo&^)WZ2Va{@vxlu zs+@RoPF#@_-;xvGkrOxM#4R~-GAG`U6K~FmJ96T$=fvO1i666A<$0z)&Q@QLA1EF* zP`^nkK1VgePQ~{0DSPQJWPAG++taba_$|dtSCn}X4Y2e_6x*N3Hs-Un2mF`ft&uWM zSL5CIvsL9>IZF=%3F6_3x8GXk9Sq{BitV9__Oj*OsQ8OR)XoaV-=x?cKDsD~mnj}_ zi|#55;=2|9&0S@l9U3e@3B|YTz6Gm;&Q^S%;(w^^UH(?ZUtV0MEAW2$uPV0tS2qRe zzoU4aZX&mO%jWkz#n0+5GF%zNPbs#COZ)3v=-D6RuwH)8YP~J}zbRg;_5D#0|4+r~ ztIJ$_#m2v@*dCy1FI!)GZvD6PG(SBh#7$qQjIUIFZwg{-kW7^4k|4fZ@ebVrrw_ON zCg_Vjv_ro-xanspw!0lKbmQ~An-qUvOR{>~mS3ybp1Nl*TYjVB*W_#Uq>WE2w(g<& zaPwD>esBNiGSBL58~>1Ed*YnEZ2CtON8~Y3v6ZLqDt`FNGWWBJrT@O--zk5VAB&$? zY)=NXmreh&;_Bh*`=w7Ce^8%I4P{<&kp5%EpJ{%TK|EB4s5fW!#$yz3%3A(7#V5{J zFBNSdo8LUe->xh3YJ=%-Q@sAHGS?ok@lnO!Quzs&*P_@vTje8|{$9mntI9k(Zdm$l zimj7@9rrALMDY^kSBG>L+nuY{)l=Da9zRw5ipuNgVEoS&+fxSZW$XW{;)l*udn6eD zd&M^_)BTb`{GsA2i_5&(L7XS(pDX{vf_RAHg-gr4`XIhg@q_ug%`zx|BNf|I;Ou3~ zo1*y2u{wVV($7--&)OfFgSb}lS9G7jB|#ij{EzYu_viZ+kJk1Gx2GLHXUcz+K5hGN z(Rh1mp}lN*Usr5T`wQd86#x0f+CKu{A1VHU*2m7>%yX~euW8DQgLuDUd#1aRyZQf0 z@zDvr^Lt%!WK)@UjT>L!y{GsW^05A;Howml7is^qpYtrXKW#io`=8Ch;`0^TlLqZ& z`5mR$9^e|r<%*9^?v1A?e*MDU?OCDtH}bTHBHR2HDz*o=`S~sIRw%ZIy@vB!rTA^F z@54d*q~a5r{|qIt>FtRM4{QIkDa`YWitS;#;q==T&(!)%4$^;Hu|0G(9RH}|D($aZ zg7Hr({!Ll0=Pt!(%q#PL5sd$(VtZ;~IQ>Dz_Eg0%KBm}uTUp!L^7E16&$8;%JdLoY zZ-(j5R=iXD%cNlaE>~>b8hnpJZ?fV;+CJg_c9Y_>Y7__QZ&$o`na-m%L-SZ|(`Th$ ztGHe36PC}diZ4H>%!>x){mY8W)SkI7nEu;}uhaf%4NjZi_Z8cdK<#DQd#B~}=Uyl(~LFI8-R(Z|k(Ed5x; zmsOW})^4=;bBfom=sg}SRD7rEqv^r;I~D(}^7mN~uU7ov_%hFa*|O;qimm;wY`E>S zS#hoM`%;kpD~c1!Z@54Fy<&S{vb}8mpHys5g$?6fivKXEcYpu2;(|@#{0qFd6x;Ir z^o8E<6t>>GQp_70=T6aDTtt3WAOg75cFC(Ji6gZ?m@d z48?OVE%QDN#?Mzg`OebCce&!9jw$nQRsx%TlHy!T9?WTSp>)e7^T3#oxH7x4rQ##Sd$L zvvYJ?-s6hDy`s1L?o?cKtL|?L#{XLJ&P~d{R><0ezf)`vpthHJ9a3yhz76C5RBTU- z4da0-IHlK=dHE<1bY_>pE@!VEc_$yezA{O;CKxk}_|2F#R;e9rBwO z#0wSMlT*X_Emv$$b`9fJ#TV*$c$Nm(@*h+@Li>|lkFfY_itX8d;r4n=@!j)#_y4C9 zZ@pF>W|hFw?@??WF~j}ySBn2a>-TOjzc&@%xxCDa2l0oB?Fqy7GB5i>+4kV=Fg`=E zJ@h+_&#@g_-YQPc`y$12E>rnZY|AfK{8+KBQ3hT!6;D-p`CKr5p5ptoe~by@Ws1K$ zsmz@R+Vo9|tv9p3z6IWWivLON)v*2XkmA8B%Djca^xssRlE1YJZ2G@dT%h`|Gl-v2 zd|dnckRbkr;z&`Mw={^4C|;rUsa9;|=R?I0TYV!yE59cckJ9#u1?dOchEg2X-xn%A zq58vw-1;kiFRMP8t=M|khTG#d#S63iniZ#&pEbes8x&ux@@AJ}Y^DFTFUa>uG*er7A4qw*8B zH>wo>llGq_!TfGl{HHs5&v#;qcW&19Rspc>agSnqu2MMv2Nl~Bgv0rNRq-!Ymg#}* ze*PX;Y>#F1#~(ZS|118o>hGb!_+5(Kb0!qq_T8`eO4ZL{`S_J$d$O=UeZF^C@f@{3 z?+m85=db;7naXPr4^YwU6+P>rAMVeh^z08Qgy%c6 z75`lRVfj)~^4?w8d%TJ(J|`=GUr^i@TyHY(t%}ns?@d8|{z|d?6Ml+qeg8qRb)yPB zpI2;u7{OjP{m=BZy1vZY7}O`PDz@h(gy|0}K41B(RC+59A1gju*So%2h}l zB0;=N@rT;~?+D^1#rA}Gd)fM}SDd;)?)JrO*NKT!Ny*81dWNB^VduWH84 zf0$zXLnrp=Xj{LLitXw9;rdQd+@#mzNKtGp_E*6M8CNEQ4LP*Xcg zBNi;H^yceE_-JB&eeLtY?@%XRXQa&HFYd2wZ5Mw zLE@gC*~Jp~s2fU4OT4vCU1wH$icd2^GLh_^B5560vZl~TP119JbA#7X?@V+%-L*~8 z`ZkTUufaW?L7@8!{ow(PfA3wLyOYu%p+0tXuFsR3!XmpRuXmi?BxsTKanomOx+R!Z zJfS{giG+r=#TwlImM)oUjM>ylbp_D9lkQt0m_oPW1@pG^E)y=_u;Wg3J z!pb>GuP%_V4laqc(K`P&LCaCyb(*Q`Rb`#-dM2Fjx|1Zls%T4fQ}6AGy3??}Q8V}I z7NxB_X3|^J;&kiU{G{`uskzqAtY=2L*Vapmu{ql61${IY_&3&jx}D#v&|aWSs<(z$ zr#=MM&8IHeP~Yl${`h?}YND;ls8-6l@~GpG<$0X9K;gpF4_0)GX)wEDqwEWy={ULHT!K9uQ3YI!so%pn#wt79;Yz!oG zrX4@gTixc(X{pzWR_IpTRJe4%p3%^BTh1gCy$ai_tHhyV<<+VHN!B5>);FvB;63SR zYr}?Mrj_f3qv6#`yCk|={poDWWR-y>(Y9!PYKiXm^|bG{d38ZXZR@J)O6jvjD-yUZ zTv=ZmuV_-KaeX_q3%lwq)@uD!R))o8vFj{aY{XE6Xsy7>LS^w&aGOi zt$@}uTmcJh_pS49!FIKyLM!2YcZI289vYhJRTyor3`rsi6;93~64S<*7ABCNHt zZlb|jXjZFYtJ5mV3mQ`zHP3D9KGn+jX>Q+{YAF`RwUA(juA~LCS#n$NYG$pY?Q_$@ zeE7SEW}>xsi%~(-hSyfMWaGm*X*JYky51i+IT&g+iD1K7DWiTJrd4vgqi*OwW!IZ9 zDTi{xI8P;OZBNyslG_)5iW-MjEVJsZaA#OppH#h|4&YggZhI$Pe_Bqhs@?sc}Q``KnwvZ!ie_xgKMVnNb6 ze+LC2Yb}EvIIH5DA6*~PC+-PrN>|$5-S>V`_d8(wH<5eQG0S>y6{Ea`yPRLqxdN)g zreEjOrEFiWYt_vXb?fXPshvp6wAIvX!X3VMc2-7mH>eH+{+^(o`0C}kD7sEPr>*0s ze~h%%uCqHZ9J^oot>*K0PpwDJ=ASsu#=72PbDLvrmTPZ~Hf*f5ch_+%?m&a3RN3go z3Ecn^ZJd=z)NiP6R`=}Qy&;+kin&UT%ZFcTdJ+Uivy^LhG@WCe=EF5m32|%YI(7#W z21VW~9Jh~5cK=Uwa^Z#wrnlY1pMF8_VXtS&u1JT6%)TXS{5Y#+8KAtauGrAf9Iafh?XT`b zt|7KmeQR`b)7%`E+oW2nDsG+)1UtNWr2Zbhcb=DP4sKQW7s1N1RHr;>~ov${< zI%}t?4H!>Us8@K>8Z!Ro(^PI#^scHZpxU@UOy>Tv(%-snZ_63xj-qbOs#NQ@q+5En zK$sK1L?`{WTR5;essna!(F#}HN_9d<7;Pbcp7rbd%(HLt(gw>$Uz|=^8_TP6cbx_0 zMbv6lg;K8C?o%G-M4Qzs*e`~DnW?g#$(FZMHcYk7K%+X6<>W$jPj4-+eMF>H*7e@4 zf!g0a4ck?XwK~bv>5Ko!l-~Aq-x*Gr=BlxZ`sRjov$o%D>W*v=TyYJ(?6N#3mTZgb zX(BCZ3)&&q^|Di`(vvoF@;Ffi$YpGn|5Oe?Z>p*MriZqQ)hc%K(^Jk}?yZ!&c1Un~ z;7{kuunC2mEjv>SV&XUP+6(XMe292bK~<+jh# zT?q&`@d6z?vyWtk;_^{v&myT)$4H%n>)fgDto2YD9UPNURSIq!>10mDrcOszD_Pok zE7#gRp+N?;`mQaQU7TjyJ*gXl4dyO!@gD*RAbjIWwZ_{w`d6-8LteRZm2~^s zza61_it+!{RZo3&+y1w%cDfbY zUb&KxqVYz_(ARRK=~l)QeClD#LDON2jKk0WrvJ!Ki|9R^nLOGI-eOAB?)d)k*Rx0W zl$GxYJkz@QkTd>`PQuTRS4h#-;*ONf^?`w<49|gt+2s$4xJ1CA-WP4#DJn6aQ0nf6sm`X&rn$BqZvl+TYj_hT;?T6mYEFJVk@QS#V%EW&gx|VDK7CbADPZBRrC=#zVIE$)(Y2g?8D3=RY2v>R*Yzs7~K>6eE){Hw?IBY08^%^|be?^y* z7@8e)qHA1fIW{sfGc`r{W4hInmPXbf9!cjhGn2nKudTU|$#2K>>*|csoSjkkP-P__ zj7$>wWJ^#e0w_6|l*Y%`vtekgr)O*lDIMO0A~bt?V?>&J=Tw$+U%!*)tz#ET5*pwj zCA|TT8(Qg39=;&?9s_G$8-MA2Q&yicQ2a5W(a>mg^ar6)Pnv!*S9CM!-VM2Hs%Sx8 zettdyftS3zJc0v4d_DX;UHyZwB@*c^+F~-FU=hw$H1a$tIWdtpNp*U&`ZQu!Y2*FE ztE&)C6rq4~Ixs|p{(D47OoVQGcgDjO$;T8^)0Nz)=Sfx;7K%oy#c?QYC#Q#FY!dXy z9T}@kEISDxqf1RA(5B7gB`MOkJkG zNY|HbOzpxaQgr?61E#Q~5&0TFiD0sZT)M)>?3oky8s%$$c7xjm&YQ9-*WtDoazW@UvM&p{g z3fG@kn35Qhjo-;V;uA{bd)3pH99p52!mkr~Mk`Il8KQ4$ppE*wK59HR5szA1D_y%I z4Q|xHCO@a!q;>Zak!G)UppXBcQs;10lb%!KZ2Ml4R-@sYYjh-K0}a*CI9#9}6lAJ4 zK}KI33VN2a2apFM*)7(LU!`I`EM zUAcETRFl;soa57ros$<0ZpaMq@dz+UB{L)e@d}ShcB`Km8d`E04xqM+iBZrHz9@ce zzLGNG;_7_O__I%lhEX}AL+1@G^kJQJ5B+3oto zT+ruYB{1O&fLq|C?fSn~Z!hFL3%xuZ?u$LPR-IySevmLd1@Mj~9%_@d6+JyU0;i+s z`HKU8)D@%>2gMJdEvmN~>f_E?R2!Hp=e%9aEApIYxb?->8Or9IJicFQK3)m2Y`}QTkWaizT_(yaj>!w;O8JU2 z@*{l%O=7LWnb3@B93Vj^E<6Dpr=18)v`dU{IU|a)HJzRyvx6Q}kf{^e--Mg7r8QXr zU5G!q0TC8GUiX62iF4j{$=)bcrp)PeUBACw4dGnDxky(%eZylyfnS1Uda@bMTCTBJ zGN$;#cTx9k`DZiGXi)0e!lGt3eUkXfdsI&{=}e}?o%J(fdHXP-~J zV&sL(jlwXWH1ZvT$4DjS;C0H2^2D;tSnMD9yAUoMt9QS)E^n7o>) z{-Jr@z|yG-m4FlRCyfZ{nK%WZjc$+%lX?!Z^jyAXHmEOIyN1G%hoZKeiO8%#WyK4YLxY(krFHKYr61O=WE&mQcQN)fp1Y~>usn( z`7+??hm9$kweg@ojR$Rob!@d|=ijx97Z5bkExs)j#34qmbPaL%cIv8^`|{MG%y{$M z#qnu*cFSD#!MR#a*q}o3`B_NXKXtJe(xai( zqyZj~7%#UHRADVgqu1Rkd`0YAr5u8e=1*g&M}2zhKX5zo4HwI5cyM`qv^RX>F-|o? zJH!X(VUtLO8L3j2T4;W2fc(LDdL{u;Z#_IVQVb@AXX2RMboN=aJYq{`^?FV<;Ra5) zOhX**i>ub#rU{0IX|LYCImKn`BHKswN>X|Z?ti|irtmJLwP)Q`4Txsnd3f?Y?pjM( zecI-|FDne6j5I~C-WuM?xhOvV|2$YK{?xyA%VAHzdYYs#Y8oXWtgvTt{4JIk_r>It z2-7Gcs+G`s4eAlq#B-CAW4Tlu+n8uGm$6>^j&r-aAm5bSkX$jI%SI*r!9U z+1sz-DK$AoffjU4P0mp5s=Wz7JovG@T4CK@KqxFe@EjA%qpbYfIyS|<_ zjbc@^&W$U}B^piP!h|QkLCSY#%(q!DR4HMI!w9PeC`}G{J0`+ae!lHb2x%r#GIY2( z*UbR6(({w?Rsprz%wOcFa9h7PLZ)C<1o-wN^0+-WVpVM4XrBqziTv9bV-zEDaI6L?H>HWu?2P0R#zUl4#Iye|N zxrC}1sA&$NBml-uz;bQDl2At%r6*>5& zpp6AY)ytTeA9|GqWscUL>@$q_6prz;7+02AHC3w>JMZ^I8S(cTm%jwoRqy2`SUd<7Fp@&Cg&k3sBmJvUp{We+7dR_ZXL#vdaCR+gTY)Rm0V7+aT) za_(9C6VsLJ7@`fBG6iKGnM|b%3m;;yj!o>ZjI7(H74TMcbf}@LHS1m*yl}p&MXloo z$+vb(IYhlINbQBPnDfmUS!6V$(m0^k*b_SK`_QE(+8E2{KmBVn(?VHr1nb5Bl*FL; z-u^y*fb*C3$xt3n)a${Nf%1~-+_-|N`ae8zs5s&&EJvSVZi_$uYB(cZ-n;ELj9eJk z9lNCIM7wuctHke#t&@h_SYOTipveO2I2TPUr>KthgZih)6k23j0FS`&J7=hc^Ki~+ ze#mTcO2BXJ@L_{9W9KKCqs7sqjnSjN2$2!ubrWS{42)C%phl$CJgY{rVCi3h15;OH zPxkgHG^91UQp6!8A)~6NgF+;yEZ@^vg%2nurDr)92SG4Gc8kmRtx}J@df5&C-hB(a z;f3Vj-1NQ+UgXJVxXVehxHW;Vd(Ty+fz8ZNolwO}`i243dd zJ<%@A`b5ec&~kfVS2<@G2BhB-tPFs``?0+)b0Evh&D{JAPvb)Vnas+RMPhV>v1duXd&MK-aQ(vS#)18~2x%&kEp|7P$BlW1-HKLpl;19zP`nGYysduGiKu%roi5G#5I$!%s$vncxq@A!9qcyR9K;uXD|m)6#(^9e+4*d5)PUzklV0J$$*+S)A@VtbW%L2D4-X+Gu+v}8B@auCwI=e*^#3jYjT*w2B8YXqEbYS z5QVH0&@;b-`K0#&Q9OlKJ{z2MJEu>3v-*Gs`JR)B=zo^^j_t1~?z<+kdN|@vHGM3y z(ii89Ul`+OEj8aUm0KH9%Q4wXcc=pAm9$77Hg}L>U%w2_haBg5_p+5*UYL&Us`IBP z7}uXwC6Hq21^mn2A1}ar*CvYL z=8))2*z&MCBR+$}fKu#p->T*q zZf?N}ma)TBrjUwkq+VQSg;jB+K=!r3i-riBz}YxjA-OL6Dc+>J@S3-Zlk4})-Pz9s z=^90F)bFVm(JYI^5y;u2&|YgpS7XT6BNIqtw^KtntS9z|qgQzzs`_lFleOUfuB?ep zGXgi)U7^cr^>?ZnjBvECoM{G^s*WD$TJ|?e2jsgN~?>% z*W+qSaAjgb4bpN2!n{LhH&_qS%5|>EC0iIui>6ACp$!GFa7;tqQ@J@8gPn_=oXe7( zU5l%tz*(GX^&>|M0YH$QQ3c%o_V+5wxc|I;!K>W`TAhy$#`P?DhCrOBLZ-~iqJ$EflG z1UL8k^GltmxdoMgZ%N%-Mz9Ij*^w~r776uZ4Aw<_%d?GbLBcdsx0hz|G(5M3-5U>F|Q@>wx8^s`F6=ekV)(iH1&PH5PRHY(UXXb^8q1fW38Y z&(6(hl8h*y(OvDoBj~`_y&?b8^&m?&>*V2|CF+~m{0(9-llp>57Qd@|=QxAaXWt92 zO$~e(qHCg|>vdv*rr+%0>Axe(`uV0>SJgvkTk3NV4pq%A!#@+By!1DCWDHCysJC); zlsSHzw_@;8UAnGY;iRk0wtHY*YktRdgD8bqFEv88`!HlcMU`dt z?QpR*gPTz*%OYw2=$t8bF8koGO!1RRMI|Zh(WJwS z?0Fg-Hh1#px@R|jaF0kdZ;+feUt1aa1;q@Qh>MHW4qadI3LYAtO;4RX>F%t9U2X(o zh=~Y`$jSOVb0=PVN**TQ%i-?#vGAWd|zi3zd{_y>jAs>fBs!zEeACy z9)8+`40=t*(n@%bm8!JQbe?qoovqDQzY;O;nuh4*x|JHFr1%)!tiA+DzM=|s$#@rS zQRjIo4iEgDk)Btoy*E4>+UJ3roY>!?hPF61m~@PL@XPIYMp!bj5(aXlV(mydHP&=m zuNrC%tkPD*mRUScW}xqMJD&8amP<|3)2US@BIe zFeI3EGsxEsWhB0tl~OAt%(`jq6{Lr@z`?XC+A!$w0HD$2l<4>9{ou2)Yj75v*CRapE zn?>;?t?rth^-Xlian#Eyf3s%93l*Q|^P9HIq3bJW!w-5!0IPe}+~8iMwTjn+2x^Sf zgXuKKXP*ge9JCoY0f{fc{45*b{t*Z+tIwCxA=GetD2xs~h~9b*cKo(+^XU(#1;(iz zbMYWmO>HUJBd2C5SCIsw|>0fc5u0)uy7%{zfEtD zSdo$DLmDmPFOvRead?O3E?2aq3|kdl42f@aqlvQGlO`ERI3B+GPx;~D;gym?o3YDJ zac8(d$tq>QevL@Dx|{+NO}h;H>+p zl@(q8>ToMsAQPwlhZc>r>Fs;mJEv_9HA^GYt1}kPjwEZ6>}C1dSImy?P}&E+atG%EY{_ow*mr>SuFW|KSBXVqvnk?&h|Z{EdPS zc?mc74^(ZR!_Ku|y{hEmnVgrq(`#d$!p3mwHkCAHyXo@I&7zpIZEE$sW8$(oC¨ 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 Ef-#$;QUCw| diff --git a/preview/floppy.png b/preview/floppy.png deleted file mode 100644 index 4b6abe24c39786d193019fc726e99d13466c08f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26829 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 diff --git a/preview/help&input.png b/preview/help&input.png deleted file mode 100644 index a47cc40c679312e8f62bbc3c95bfd68d8da9c96a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14085 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∨9a%AXrcL2uQ=&`3GoZyRG2X zt+4r!2k0W-uOasiiakL%C)nI=mWqPi;9=^S1(2g z-GF!_-ogba03FQcm@5QG3yP7D4Bg}ps4|Aj%Z&`Dp6(eLcN|+6X5i{@$cbMqNf1C-$cXVza%#fG#h_<(mc4fH^-0cCY2#^6| zP*PP9US*Iz2lLCC=e!TX(%O{2>GGEgf8hO|8&^>c4n6vDt-}C5!TYm`H$rkhGK8S- zg`N&Mi&#unBNME^i^+Vc)ysPcP9Ut={V*7}3RE4X9gj{q2w9fG7UQOR2>MgS0oCmV zsrx2>rjWx9O#PfXKU6jT4gM%siIiB|_4F;pk{ynUC9Nv?U3(EXam216#;f{Mks9mwzm-xYVlgjcpkmXNBp>@7_MHrPNYDtt=A!2i2338#qzs*XjG3 ztoW0RYWX=1ohwVa>8m%rnb0{-O*@NR7|yLuruK50v6$JN6Ryt6$~s zlii!V6K<4+;Yb-HDS<8WIb?m0vi*gFcFIXkw&LXEkBX~5teSd!unn z4qxAEFK(4qaq`mFi8jPiN^5-Y*bfYBY;n?Z%(qOSMyn#BJZl$c)MC+#Q=P}!`&v=Z zz4lUeHg3Ao<7$cAnc}h1udexTl2pUq+8_P_KLpJBNby zI0skF?{{lNWq$YFeZP2y+`ix5ARB`XqdRjJV-GTw99HT)c(c&7L0z%6p8d&6?Y7Dv zvvwq(lsQOW;lbJj#4H9<7JuwuS*DVGt}`op@OoX(-VT&n40>sC*I$}FTndFanHl~t zat^%x(7*-!a>!$+Jq_5#G@;^rxqAQ!N25UQfx8ZP+q`;V-kz(@5A7PhlX6zw{#%xMJpb2A zAc0Aj>@2FxlE`wLv$T)oq>zV9#H}_>rhyjZ(DUK3e(cdSm4IsWdAHGT=X?z5b*zEB znTef`p%8o&9~;JxYBDXOl`bM~8yljvkRaBK-9?`uujr~~z7D6ztoCaDFef>CxuHl< zpHmz#+V>hgv9K@>fg5AOqER)G0J<@TKp9=EP)l~H6Z1}~kBi#CSc;K!hMw)OlQCcg zu%14eqjXJlW<`t5xo!6py2bLOv)G7Ydrs$Og-{iTk` zmwG|B+1#tZeh-ZjMZ$9UNZ>3)kmP!&-oA6^=Y;*rxNZHl|LlkKmOVoD>sr*i=+M%reSj08HX#uxD-c0%Ek zb5|eo=(y#%V;!Wwoe;YC&TXyL=R1Iso+6+DJq&1I1NOuIWGqc{?T8{e*zYYrhxhP- zu0Z-uSCN0q3Sxpc&WZTSljdK`{k}jez%50NM3JI6#=txx?if@jlBV4%D-BSZ!$g+wR8S=m#1A(_jyVSKBf-hUC5BumudxSRU45_zW@uX9E@ zMKkPFbCyEbn^SyQ7V^XUBzJfL4p3S6h+xMrJ_Ch3nq=gsO^1~#BIkK6B+6bazp9_&DrljW@@@h80oG^O))B6G_Reeb)4YN`!R9?8C)H?UefQ=r8D z$zt=lAHw*aD_#Xe1xcM$P*&`QN#seNkCVQ47Lws!#u+cKBU~vo%|A~JvN>RIKKwH$ zHhgiMZWJ4p4K@-KLncjEb35|cOf~n;r-W(+Ky|A+UK%161ku+oueQd%G_|B^_)EsO zK_y)3EK4{WjCrzeT%5Y1Oye@YQK&FA3+A@M&TS8}#gbmcToRj|ul@Yw+6 zZWCQ7Z|Lh@ElA}m^r3pda&+rePav|d8gy6<>TpbT=`Z$sDd8egn==;Fe5*LIlQH^@ z(4&ztznTnZpI%HPgzfY2aoVLBzBqdwZKwK5u+WP_`)x}f? R{&fvxbMC^~@-uGt{vTP-*X;lR diff --git a/preview/help.png b/preview/help.png deleted file mode 100644 index 847614bade76ed3a2a88a179473bd5fe00c14c38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10770 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

l4i<^PbFTRRLp5^{c(l{D=1-lDDkHpGqBZba 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