diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/Makefile | 17 | ||||
-rw-r--r-- | usr.bin/beep/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/beep/main.c | 70 | ||||
-rw-r--r-- | usr.bin/cat/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/cat/cat.c | 65 | ||||
-rw-r--r-- | usr.bin/date/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/date/date.c | 86 | ||||
-rw-r--r-- | usr.bin/elfdump/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/elfdump/elfdump.c | 171 | ||||
-rw-r--r-- | usr.bin/fetch/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/fetch/fetch.c | 49 | ||||
-rw-r--r-- | usr.bin/kfgwm/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/kfgwm/font.c | 379 | ||||
-rw-r--r-- | usr.bin/kfgwm/include/kfg/font.h | 40 | ||||
-rw-r--r-- | usr.bin/kfgwm/include/kfg/types.h | 40 | ||||
-rw-r--r-- | usr.bin/kfgwm/include/kfg/window.h | 68 | ||||
-rw-r--r-- | usr.bin/kfgwm/kfgwm.c | 95 | ||||
-rw-r--r-- | usr.bin/kfgwm/window.c | 221 | ||||
-rw-r--r-- | usr.bin/kmsg/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/kmsg/kmsg.c | 58 | ||||
-rw-r--r-- | usr.bin/link.ld | 5 | ||||
-rw-r--r-- | usr.bin/mex/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/mex/mex.c | 105 | ||||
-rw-r--r-- | usr.bin/mrow/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/mrow/mrow.c | 304 | ||||
-rw-r--r-- | usr.bin/osh/osh.c | 311 |
26 files changed, 2085 insertions, 53 deletions
diff --git a/usr.bin/Makefile b/usr.bin/Makefile new file mode 100644 index 0000000..18f4b47 --- /dev/null +++ b/usr.bin/Makefile @@ -0,0 +1,17 @@ +LDSCRIPT = +USRDIR = +ROOT = +ARGS = -I$(ROOT)/builddeps LDSCRIPT=$(LDSCRIPT) USRDIR=$(USRDIR) ROOT=$(ROOT) + +.PHONY: all +all: + make -C osh/ $(ARGS) + make -C kmsg/ $(ARGS) + make -C fetch/ $(ARGS) + make -C kfgwm/ $(ARGS) + make -C date/ $(ARGS) + make -C mex/ $(ARGS) + make -C beep/ $(ARGS) + make -C mrow/ $(ARGS) + make -C elfdump/ $(ARGS) + make -C cat/ $(ARGS) diff --git a/usr.bin/beep/Makefile b/usr.bin/beep/Makefile new file mode 100644 index 0000000..409f87c --- /dev/null +++ b/usr.bin/beep/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/beep: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/beep/main.c b/usr.bin/beep/main.c new file mode 100644 index 0000000..d64a9b5 --- /dev/null +++ b/usr.bin/beep/main.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> + +int +main(int argc, char **argv) +{ + uint32_t payload; + uint16_t duration; + uint16_t freq; + int beep_fd; + + if (argc < 3) { + printf("usage: beep <freq> <duration>\n"); + return -1; + } + + duration = atoi(argv[2]); + freq = atoi(argv[1]); + + if (duration == 0) { + printf("bad duration\n"); + return -1; + } + if (freq == 0) { + printf("bad frequency\n"); + return -1; + } + + beep_fd = open("/dev/beep", O_WRONLY); + if (beep_fd < 0) { + printf("failed to open beep fd\n"); + return -1; + } + + payload = freq; + payload |= (duration << 16); + write(beep_fd, &payload, sizeof(payload)); + return 0; +} diff --git a/usr.bin/cat/Makefile b/usr.bin/cat/Makefile new file mode 100644 index 0000000..4ecfea7 --- /dev/null +++ b/usr.bin/cat/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/cat: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/cat/cat.c b/usr.bin/cat/cat.c new file mode 100644 index 0000000..b51e6a0 --- /dev/null +++ b/usr.bin/cat/cat.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +static void +cat(const char *pathname) +{ + FILE *file; + char buf[64]; + int fd; + + file = fopen(pathname, "r"); + if (file == NULL) { + return; + } + + while (fgets(buf, sizeof(buf), file) != NULL) { + printf("%s", buf); + } + + fclose(file); +} + +int +main(int argc, char **argv) +{ + for (size_t i = 1; i < argc; ++i) { + cat(argv[i]); + } + + return 0; +} + diff --git a/usr.bin/date/Makefile b/usr.bin/date/Makefile new file mode 100644 index 0000000..09ff299 --- /dev/null +++ b/usr.bin/date/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/date: + gcc $(CFILES) -Iinclude/ -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/date/date.c b/usr.bin/date/date.c new file mode 100644 index 0000000..a47e3eb --- /dev/null +++ b/usr.bin/date/date.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/time.h> +#include <sys/cdefs.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> + +#define MONTHS_PER_YEAR 12 +#define DAYS_PER_WEEK 7 + +/* Months of the year */ +static const char *montab[] = { + "Jan", "Feb", "Mar", + "Apr", "May", "Jun", + "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec" +}; + +/* Days of the week */ +static const char *daytab[] = { + "Sat", "Sun", "Mon", + "Tue", "Wed", "Thu", + "Fri" +}; + +int +main(void) +{ + const char *day, *month; + char date_str[32]; + struct date d; + int rtc_fd; + + if ((rtc_fd = open("/dev/rtc", O_RDONLY)) < 0) { + return rtc_fd; + } + + read(rtc_fd, &d, sizeof(d)); + close(rtc_fd); + + /* This should not happen */ + if (__unlikely(d.month > MONTHS_PER_YEAR)) { + printf("got bad month %d from RTC\n", d.month); + return -1; + } + if (__unlikely(d.month == 0 || d.day == 0)) { + printf("got zero month/day from RTC\n"); + return -1; + } + + day = daytab[d.day % DAYS_PER_WEEK]; + month = montab[d.month - 1]; + + snprintf(date_str, sizeof(date_str), "%s %s %d %02d:%02d:%02d\n", + day, month, d.day, d.hour, d.min, d.sec); + fputs(date_str, stdout); + return 0; +} diff --git a/usr.bin/elfdump/Makefile b/usr.bin/elfdump/Makefile new file mode 100644 index 0000000..b450635 --- /dev/null +++ b/usr.bin/elfdump/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/elfdump: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/elfdump/elfdump.c b/usr.bin/elfdump/elfdump.c new file mode 100644 index 0000000..335cdec --- /dev/null +++ b/usr.bin/elfdump/elfdump.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/elf.h> +#include <sys/errno.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> + +/* Ehdr.e_type table */ +static const char *elftype[] = { + [ET_NONE] = "Untyped", + [ET_REL] = "Relocatable", + [ET_EXEC] = "Executable", + [ET_DYN] = "Shared object", + [ET_CORE] = "Core dump" +}; + +/* Phdr.p_type table */ +static const char *phdrtype[] = { + [PT_NULL] = "Null", + [PT_LOAD] = "Loadable", + [PT_DYNAMIC] = "Dynamic", + [PT_NOTE] = "Note (linker garbage)", +}; + +/* + * Verify the validity of the ELF header from its + * various fields such as magic bytes, ABI, endianness, + * etc. + * + * Returns 0 on success. + */ +static int +elf64_verify(const Elf64_Ehdr *hdr) +{ + const char *mag = &hdr->e_ident[EI_MAG0]; + + if (memcmp(mag, ELFMAG, SELFMAG) != 0) { + printf("Bad ELF magic\n"); + return -ENOEXEC; + } + if (hdr->e_ident[EI_OSABI] != ELFOSABI_SYSV) { + printf("Bad ELF ABI\n"); + return -ENOEXEC; + } + if (hdr->e_ident[EI_DATA] != ELFDATA2LSB) { + printf("Bad endianness\n"); + return -ENOEXEC; + } + if (hdr->e_ident[EI_CLASS] != ELFCLASS64) { + printf("ELF not 64 bits\n"); + return -ENOEXEC; + } + + return 0; +} + +static void +parse_phdrs(const Elf64_Ehdr *eh, int fd) +{ + Elf64_Phdr phdr; + const char *type = "Unknown"; + + lseek(fd, eh->e_phoff, SEEK_SET); + printf("-- PHDRS BEGIN --\n"); + for (size_t i = 0; i < eh->e_phnum; ++i) { + if (read(fd, &phdr, eh->e_phentsize) <= 0) { + printf("failed to read phdr %d\n", i); + break; + } + if (phdr.p_type < NELEM(phdrtype)) { + type = phdrtype[phdr.p_type]; + } + + printf("* [P.%d] Type: %s\n", i, type); + printf("* [P.%d] Offset: %d\n", i, phdr.p_offset); + printf("* [P.%d] Vaddr: %p\n", i, phdr.p_vaddr); + printf("* [P.%d] Paddr: %p\n", i, phdr.p_paddr); + printf("* [P.%d] Memory size: %d\n", i, phdr.p_memsz); + printf("* [P.%d] Flags: %p\n", i, phdr.p_flags); + printf("* [P.%d] Alignment: %p\n", i, phdr.p_align); + + /* Seperator */ + if (i < (eh->e_phnum - 1)) { + printf("-----------------------------\n"); + } + } + printf("-- PHDRS END --\n"); +} + +static int +parse_ehdr(const Elf64_Ehdr *eh, int fd) +{ + const char *elf_type = "Bad"; + + if (eh->e_type < NELEM(elftype)) { + elf_type = elftype[eh->e_type]; + } + + printf("* Entrypoint: %p\n", eh->e_entry); + printf("* Program headers start offset: %p\n", eh->e_phoff); + printf("* Section headers start offset: %p\n", eh->e_shoff); + printf("* Number of program headers: %d\n", eh->e_phnum); + printf("* Endianess: Little\n"); + parse_phdrs(eh, fd); + return 0; +} + +static int +elfdump_run(const char *filename) +{ + Elf64_Ehdr eh; + int fd, error; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + return fd; + } + + printf("-- Dumping %s --\n", filename); + read(fd, &eh, sizeof(eh)); + + if ((error = elf64_verify(&eh)) < 0) { + return error; + } + if ((error = parse_ehdr(&eh, fd)) < 0) { + return error; + } + + close(fd); + return 0; +} + +int +main(int argc, char **argv) +{ + if (argc < 2) { + printf("elfdump: usage: elfdump <elf path>\n"); + return -1; + } + + return elfdump_run(argv[1]); +} diff --git a/usr.bin/fetch/Makefile b/usr.bin/fetch/Makefile new file mode 100644 index 0000000..4b08e84 --- /dev/null +++ b/usr.bin/fetch/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/fetch: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c new file mode 100644 index 0000000..42c2825 --- /dev/null +++ b/usr.bin/fetch/fetch.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +#define ASCII_ART \ + " ____ \n" \ + " | \\__\\ \n" \ + " | /\\ \\ user: root\n" \ + " |/ \\ \\ OS: Hyra/amd64 v"_OSVER"\n" \ + " \\ R. \\ \\ arch: "_OSARCH"\n" \ + " \\ I. \\ \\" + + +int +main(void) +{ + puts(ASCII_ART); + return 0; +} diff --git a/usr.bin/kfgwm/Makefile b/usr.bin/kfgwm/Makefile new file mode 100644 index 0000000..a0fb49a --- /dev/null +++ b/usr.bin/kfgwm/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/kfgwm: + gcc $(CFILES) -Iinclude/ -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/kfgwm/font.c b/usr.bin/kfgwm/font.c new file mode 100644 index 0000000..9873b02 --- /dev/null +++ b/usr.bin/kfgwm/font.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/errno.h> +#include <kfg/font.h> +#include <fcntl.h> +#include <unistd.h> + +/* TODO: Open a .psf font and get rid of this */ +const uint8_t g_KFG_FONT[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0xa5, 0xa5, 0x81, + 0x81, 0xa5, 0x99, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x7e, 0xff, + 0xff, 0xdb, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0x7e, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, + 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x3c, 0x3c, 0xdb, 0xff, 0xff, 0xdb, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x66, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, + 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x84, 0x84, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, + 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1e, + 0x0e, 0x1e, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x30, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x1c, 0x1e, 0x16, 0x12, + 0x10, 0x10, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x2c, + 0x26, 0x32, 0x3a, 0x2e, 0x26, 0x22, 0x62, 0xe2, 0xc6, 0x0e, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, + 0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, + 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, + 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, + 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x78, 0x30, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x78, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x0c, 0xfe, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0xfe, 0x60, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x66, 0xff, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, + 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x30, 0x30, 0x00, 0x30, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, + 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7c, 0xc6, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0xc6, 0x7c, + 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x0c, 0x0c, 0x18, 0x38, + 0x30, 0x60, 0x60, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0x6c, 0x38, 0x30, 0x76, 0xde, 0xcc, 0xcc, 0xde, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0xfe, 0x38, 0x6c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, + 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, + 0x0c, 0x0c, 0x18, 0x38, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, + 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, + 0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, + 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, + 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x00, 0x30, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, + 0xde, 0xde, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, + 0xc0, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, + 0xee, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xe6, 0xe6, 0xf6, 0xde, 0xce, 0xce, 0xc6, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, + 0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xf6, 0xda, + 0x6c, 0x06, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, + 0xd8, 0xcc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, + 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, + 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x38, + 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xc0, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, + 0x60, 0x60, 0x30, 0x38, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x06, + 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, + 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xe6, 0xdc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x76, 0xce, 0xc6, + 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xce, 0xc6, + 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xc0, + 0xc0, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1e, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xc0, + 0xc0, 0xc6, 0xcc, 0xd8, 0xf0, 0xf0, 0xd8, 0xcc, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, + 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc6, + 0xc6, 0xc6, 0xe6, 0xdc, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xce, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x06, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xe6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, + 0x70, 0x1c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, + 0x30, 0xfe, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x30, 0x30, + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x30, + 0x30, 0x30, 0x30, 0x1c, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, + 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x18, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, + 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, + 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x06, 0x06, + 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, + 0x00, 0x7c, 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, + 0x7c, 0x18, 0x0c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, + 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, + 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc0, 0xc0, 0xc0, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, + 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, + 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x36, 0x36, + 0x76, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3c, + 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, + 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, + 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0xc6, 0x7c, 0x00, + 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x30, 0x78, 0xcc, 0xc0, 0xc0, 0xcc, 0x78, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x60, 0x60, 0x60, 0xf8, 0x60, 0x60, 0x60, 0xe6, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0xfc, + 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, + 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, + 0x18, 0xd8, 0x70, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x06, 0x06, + 0x7e, 0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, + 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, + 0x00, 0xdc, 0xe6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd8, 0xd8, 0x6c, 0x00, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, + 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, + 0x18, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc2, 0xc6, 0xcc, 0xd8, 0x30, + 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, + 0x00, 0x30, 0x30, 0x30, 0x78, 0x78, 0x78, 0x78, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, + 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x88, 0x22, 0x88, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, + 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, + 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, + 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x06, + 0x06, 0xf6, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0xf6, 0xf6, 0x06, 0x06, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, + 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, + 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x37, 0x37, 0x30, 0x30, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x30, 0x30, 0x37, 0x37, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0xf7, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x30, 0x30, 0x37, 0x37, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, + 0x36, 0xf7, 0xf7, 0x00, 0x00, 0xf7, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x1f, 0x1f, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0xff, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0xff, 0xff, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xd6, 0xdc, 0xc8, 0xc8, 0xdc, 0xd6, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xd8, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7e, 0xfe, 0x24, 0x24, 0x24, 0x24, 0x66, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xfe, 0xc2, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc2, 0xfe, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc8, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x6c, 0x60, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xfc, 0x98, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x30, 0x30, 0x78, 0xcc, 0xcc, + 0xcc, 0x78, 0x30, 0x30, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, + 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x60, 0x30, 0x78, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x76, 0xbb, 0x99, 0x99, 0xdd, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x06, 0x3c, 0x6c, 0xce, 0xd6, 0xd6, 0xe6, 0x6c, 0x78, + 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x60, 0xc0, 0xc0, 0xfe, + 0xc0, 0xc0, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, + 0x30, 0x30, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x36, 0x36, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, + 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c, 0x00, 0x00, + 0x00, 0xd8, 0xec, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x0c, 0x18, 0x30, 0x60, 0x7c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; diff --git a/usr.bin/kfgwm/include/kfg/font.h b/usr.bin/kfgwm/include/kfg/font.h new file mode 100644 index 0000000..7752952 --- /dev/null +++ b/usr.bin/kfgwm/include/kfg/font.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _KFGWM_FONT_H_ +#define _KFGWM_FONT_H_ + +#include <sys/types.h> + +#define FONT_WIDTH 8 +#define FONT_HEIGHT 16 + +extern const uint8_t g_KFG_FONT[]; + +#endif /* !_KFGWM_FONT_H_ */ diff --git a/usr.bin/kfgwm/include/kfg/types.h b/usr.bin/kfgwm/include/kfg/types.h new file mode 100644 index 0000000..2d17ae1 --- /dev/null +++ b/usr.bin/kfgwm/include/kfg/types.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KFG_TYPES_H_ +#define KFG_TYPES_H_ + +#include <sys/types.h> +#include <stddef.h> + +typedef uint32_t kfgpos_t; +typedef uint32_t kfgdim_t; +typedef uint32_t kfgpixel_t; + +#endif /* !KFG_TYPES_H_ */ diff --git a/usr.bin/kfgwm/include/kfg/window.h b/usr.bin/kfgwm/include/kfg/window.h new file mode 100644 index 0000000..a597969 --- /dev/null +++ b/usr.bin/kfgwm/include/kfg/window.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KFG_WINDOW_H_ +#define KFG_WINDOW_H_ + +#include <kfg/types.h> + +#define KFG_RED 0x6E0C24 +#define KFG_YELLOW 0xF0A401 +#define KFG_WHITE 0xF2E5BC +#define KFG_DARK 0x1D2021 +#define KFG_BLUE 0x076678 +#define KFG_AQUA 0x427B58 + +/* Default dimensions */ +#define KFG_BORDER_WIDTH 1 +#define KFG_BORDER_HEIGHT 1 +#define KFG_TITLE_HEIGHT 10 + +struct kfg_window { + kfgpos_t x; + kfgpos_t y; + kfgdim_t width; + kfgdim_t height; + kfgdim_t fb_pitch; + kfgpixel_t bg; + kfgpixel_t border_bg; + kfgpixel_t *framebuf; +}; + +struct kfg_text { + const char *text; + kfgpos_t x; + kfgpos_t y; +}; + +struct kfg_window *kfg_win_new(struct kfg_window *parent, kfgpos_t x, kfgpos_t y); +int kfg_win_draw(struct kfg_window *parent, struct kfg_window *wp); +int kfg_win_putstr(struct kfg_window *wp, struct kfg_text *tp); + +#endif /* !KFG_WINDOW_H_ */ diff --git a/usr.bin/kfgwm/kfgwm.c b/usr.bin/kfgwm/kfgwm.c new file mode 100644 index 0000000..5a9e7b8 --- /dev/null +++ b/usr.bin/kfgwm/kfgwm.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/fbdev.h> +#include <kfg/window.h> +#include <fcntl.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> + +static struct fbattr fbattr; +static uint32_t *framep; + +static void +test_win(struct kfg_window *root, kfgpos_t x, kfgpos_t y, const char *str) +{ + struct kfg_text text; + struct kfg_window *test_win; + + test_win = kfg_win_new(root, x, y); + text.text = str; + text.x = 0; + text.y = 0; + + kfg_win_draw(root, test_win); + kfg_win_putstr(test_win, &text); +} + +int +main(void) +{ + int fb_fd, fbattr_fd, prot; + size_t fb_size; + struct kfg_window *root_win; + + fb_fd = open("/dev/fb0", O_RDWR); + if (fb_fd < 0) { + return fb_fd; + } + + fbattr_fd = open("/ctl/fb0/attr", O_RDONLY); + if (fbattr_fd < 0) { + close(fb_fd); + return fbattr_fd; + } + + read(fbattr_fd, &fbattr, sizeof(fbattr)); + close(fbattr_fd); + + fb_size = fbattr.height * fbattr.pitch; + prot = PROT_READ | PROT_WRITE; + framep = mmap(NULL, fb_size, prot, MAP_SHARED, fb_fd, 0); + + root_win = malloc(sizeof(*root_win)); + root_win->x = 0; + root_win->y = 0; + root_win->width = fbattr.width; + root_win->height = fbattr.height; + root_win->fb_pitch = fbattr.pitch; + root_win->framebuf = framep; + root_win->bg = KFG_RED; + root_win->border_bg = KFG_RED; + test_win(root_win, 40, 85, "Hello, World!"); + test_win(root_win, 150, 20, "Mrow!"); + + for (;;); +} diff --git a/usr.bin/kfgwm/window.c b/usr.bin/kfgwm/window.c new file mode 100644 index 0000000..3908302 --- /dev/null +++ b/usr.bin/kfgwm/window.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/errno.h> +#include <sys/cdefs.h> +#include <sys/param.h> +#include <kfg/window.h> +#include <kfg/font.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +__always_inline static inline size_t +pixel_index(struct kfg_window *wp, kfgpos_t x, kfgpos_t y) +{ + return x + y * (wp->fb_pitch / 4); +} + +static int +kfg_win_putc(struct kfg_window *wp, uint32_t x, uint32_t y, char ch) +{ + size_t idx; + const uint8_t *glyph; + uint32_t fg, bg; + + glyph = &g_KFG_FONT[(int)ch*16]; + fg = KFG_WHITE; + bg = wp->bg; + + for (uint32_t cy = 0; cy < FONT_HEIGHT; ++cy) { + idx = pixel_index(wp, x + (FONT_WIDTH - 1), y + cy); + for (uint32_t cx = 0; cx < FONT_WIDTH; ++cx) { + wp->framebuf[idx--] = ISSET(glyph[cy], BIT(cx)) ? fg : bg; + } + } +} + +static void +draw_win(struct kfg_window *parent, struct kfg_window *wp) +{ + kfgpixel_t *framep; + kfgpos_t x_i, y_i; /* Start */ + kfgpos_t x_end, y_end; /* End */ + kfgpixel_t brush = wp->bg; + kfgpos_t rx, ry; /* Starts at 0 */ + kfgpos_t rx_end, ry_end; /* Starts at 0 */ + size_t i; + + framep = parent->framebuf; + x_i = wp->x; + y_i = wp->y; + x_end = x_i + wp->width; + y_end = y_i + wp->height; + + if (x_end > parent->width) + x_end = parent->width; + if (y_end > parent->height) + y_end = parent->height; + + for (kfgpos_t x = x_i; x < x_end; ++x) { + for (kfgpos_t y = y_i; y < y_i+KFG_TITLE_HEIGHT; ++y) { + rx = (x - x_i); + ry = (y - y_i); + + if (rx <= KFG_BORDER_WIDTH && (rx % 2) == 0) + brush = KFG_WHITE; + else + brush = KFG_AQUA; + + i = pixel_index(parent, x, y); + framep[i] = brush; + } + } + + y_i = wp->y + KFG_TITLE_HEIGHT; + for (kfgpos_t x = x_i; x < x_end; ++x) { + for (kfgpos_t y = y_i; y < y_end; ++y) { + rx = (x - x_i); + ry = (y - y_i); + + if (rx <= KFG_BORDER_WIDTH) + brush = wp->border_bg; + else if (ry <= KFG_BORDER_HEIGHT) + brush = wp->border_bg; + else if (rx >= (wp->width - KFG_BORDER_WIDTH)) + brush = wp->border_bg; + else if (ry >= (wp->height - KFG_BORDER_HEIGHT)) + brush = wp->border_bg; + else + brush = wp->bg; + + i = pixel_index(parent, x, y); + framep[i] = brush; + } + } +} + +/* + * Draw a window on the screen + * + * @parent: Parent window + * @wp: New window to draw + * + * TODO: Double buffering and multiple windows. + */ +int +kfg_win_draw(struct kfg_window *parent, struct kfg_window *wp) +{ + kfgpos_t start_x, start_y; + kfgpos_t end_x, end_y; + kfgpos_t max_x, max_y; + kfgdim_t width, height; + + if (parent == NULL) { + return -EINVAL; + } + if (parent->framebuf == NULL) { + return -EINVAL; + } + + max_x = wp->x + parent->width; + max_y = wp->y + parent->height; + + /* Don't overflow the framebuffer! */ + if ((wp->x + wp->width) > max_x) { + wp->x = max_x; + } + if ((wp->y + wp->height) > max_y) { + wp->y = max_y; + } + + draw_win(parent, wp); + return 0; +} + +/* + * Create a new default window + * + * @x: X position for this window + * @y: Y position for this window + * @w: Window width + * @h: Window height + */ +struct kfg_window * +kfg_win_new(struct kfg_window *parent, kfgpos_t x, kfgpos_t y) +{ + struct kfg_window *wp; + + if ((wp = malloc(sizeof(*wp))) == NULL) { + return NULL; + } + + wp->x = x; + wp->y = y; + wp->width = 250; + wp->height = 150; + wp->fb_pitch = parent->fb_pitch; + wp->framebuf = parent->framebuf; + wp->bg = KFG_DARK; + wp->border_bg = KFG_RED; + return wp; +} + +int +kfg_win_putstr(struct kfg_window *wp, struct kfg_text *tp) +{ + size_t slen; + const char *p; + kfgpos_t x, y; + + if (tp == NULL) + return -EINVAL; + if (tp->text == NULL) + return -EINVAL; + + slen = strlen(tp->text); + x = (wp->x + tp->x) + (KFG_BORDER_WIDTH + 1); + y = (KFG_TITLE_HEIGHT + wp->y) + tp->y; + p = tp->text; + + while (slen--) { + if (y >= wp->height) { + break; + } + + kfg_win_putc(wp, x, y, *(p++)); + x += FONT_WIDTH; + if (x >= wp->width) { + y += FONT_HEIGHT; + x = wp->x + (KFG_BORDER_WIDTH + 1); + } + } + + return 0; +} diff --git a/usr.bin/kmsg/Makefile b/usr.bin/kmsg/Makefile new file mode 100644 index 0000000..9b76cc2 --- /dev/null +++ b/usr.bin/kmsg/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/kmsg: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/kmsg/kmsg.c b/usr.bin/kmsg/kmsg.c new file mode 100644 index 0000000..2deae39 --- /dev/null +++ b/usr.bin/kmsg/kmsg.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +int +main(void) +{ + int mfd; + ssize_t retval; + char linebuf[256]; + + if ((mfd = open("/dev/kmsg", O_RDONLY)) < 0) { + return mfd; + } + + for (;;) { + retval = read(mfd, linebuf, sizeof(linebuf) - 1); + if (retval <= 0) { + break; + } + linebuf[retval] = '\0'; + fputs(linebuf, stdout); + } + + close(mfd); + return 0; +} diff --git a/usr.bin/link.ld b/usr.bin/link.ld index 9fad881..5e99291 100644 --- a/usr.bin/link.ld +++ b/usr.bin/link.ld @@ -23,4 +23,9 @@ SECTIONS *(.bss.*) __bss_end = .; } + + /DISCARD/ : { + *(.eh_frame) + *(.note .note.*) + } } diff --git a/usr.bin/mex/Makefile b/usr.bin/mex/Makefile new file mode 100644 index 0000000..6c0db59 --- /dev/null +++ b/usr.bin/mex/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/mex: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/mex/mex.c b/usr.bin/mex/mex.c new file mode 100644 index 0000000..7e6f8aa --- /dev/null +++ b/usr.bin/mex/mex.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <stddef.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +#define LINE_LEN 16 + +static void +dump_line(const char *line, size_t len) +{ + /* The amount of bytes we write */ + const uint8_t BYTE_COUNT = 2; + + for (size_t i = 0; i < LINE_LEN; ++i) { + if (i < len) { + printf("%02x", line[i] & 0xFF); + } else { + printf(" "); + } + + /* Put spacing between bytes */ + if (((i + 1) % BYTE_COUNT) == 0) { + printf(" "); + } + } + + printf(" "); + for (size_t i = 0; i < len; ++i) { + if (line[i] > 31 && line[i] < 127) { + printf("%c", line[i]); + } else { + printf("."); + } + } + + printf("\n"); +} + +static void +dump_file(int fd) +{ + char buf[LINE_LEN]; + ssize_t count; + size_t offset = 0; + + for (;;) { + count = read(fd, buf, sizeof(char) * LINE_LEN); + if (count <= 0) { + break; + } + + printf("%08x: ", offset); + offset += LINE_LEN; + dump_line(buf, count); + } +} + +int +main(int argc, char **argv) +{ + int fd; + + if (argc < 2) { + printf("mex: usage: mex <filename>\n"); + return -1; + } + + if ((fd = open(argv[1], O_RDONLY)) < 0) { + printf("mex: failed to open input\n"); + return fd; + } + + dump_file(fd); + return 0; +} diff --git a/usr.bin/mrow/Makefile b/usr.bin/mrow/Makefile new file mode 100644 index 0000000..ae17849 --- /dev/null +++ b/usr.bin/mrow/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/mrow: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/mrow/mrow.c b/usr.bin/mrow/mrow.c new file mode 100644 index 0000000..cad5530 --- /dev/null +++ b/usr.bin/mrow/mrow.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/fbdev.h> +#include <fcntl.h> +#include <stddef.h> +#include <unistd.h> +#include <stdio.h> +#include <time.h> +#include <stdlib.h> +#include <stdbool.h> + +#define IS_ASCII(C) ((C) > 0 && (C) < 127) + +#define PLAYER_BG 0x808080 +#define MOUSE_BG 0x404040 +#define GAME_BG 0x000000 + +#define SPRITE_WIDTH 20 +#define SPRITE_HEIGHT 20 +#define MAX_MOUSE_SPEED 2 +#define MIN_MOUSE_SPEED 1 +#define PLAYER_SPEED 30 + +#define SCR_WIDTH (fbattr.width) +#define SCR_HEIGHT (fbattr.height) +#define MAX_X (SCR_WIDTH - SPRITE_WIDTH) +#define MAX_Y (SCR_HEIGHT - SPRITE_HEIGHT) + +/* Hit beep stuff */ +#define HIT_BEEP_MSEC 50 +#define HIT_BEEP_FREQ 600 + +static struct fbattr fbattr; +static uint32_t *framep; +static int beep_fd; +static size_t hit_count = 0; + +struct player { + int32_t x; + int32_t y; +}; + +struct mouse { + int32_t x; + int32_t y; + uint8_t x_inc : 1; + uint8_t y_inc : 1; + uint8_t speed; +}; + +static inline size_t +pixel_index(uint32_t x, uint32_t y) +{ + return x + y * (fbattr.pitch / 4); +} + +static void +draw_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t rgb) +{ + for (uint32_t xpos = x; xpos < x + width; ++xpos) { + for (uint32_t ypos = y; ypos < y + height; ++ypos) { + framep[pixel_index(xpos, ypos)] = rgb; + } + } +} + +static void +update_mouse(struct mouse *mouse) +{ + draw_rect(mouse->x, mouse->y, SPRITE_WIDTH, SPRITE_HEIGHT, GAME_BG); + + /* Move the mouse in the x direction */ + if (mouse->x_inc) { + mouse->x += mouse->speed; + } else { + mouse->x -= mouse->speed; + } + + /* Move the mouse in the y direction */ + if (mouse->y_inc) { + mouse->y += mouse->speed; + } else { + mouse->y -= mouse->speed; + } + + if (mouse->x >= MAX_X) { + mouse->x = MAX_X; + mouse->x_inc = 0; + } else if (mouse->x <= 0) { + mouse->x = 0; + mouse->x_inc = 1; + } + + if (mouse->y >= MAX_Y) { + mouse->y = MAX_Y; + mouse->y_inc = 0; + } else if (mouse->y <= 0) { + mouse->y = 0; + mouse->y_inc = 1; + } + + draw_rect(mouse->x, mouse->y, SPRITE_WIDTH, SPRITE_HEIGHT, MOUSE_BG); +} + +static void +beep(uint16_t msec, uint16_t freq) +{ + uint32_t payload; + + /* Can't beep :( */ + if (beep_fd < 0) { + return; + } + + payload = freq; + payload |= (msec << 16); + write(beep_fd, &payload, sizeof(payload)); +} + +static void +score_increment(struct player *p, struct mouse *m) +{ + printf("\033[31;40mSCORE: %d\033[0m\n", ++hit_count); + + if (m->speed < MAX_MOUSE_SPEED) { + m->speed += 1; + } else { + m->speed = MIN_MOUSE_SPEED; + } +} + +static bool +mouse_collide(struct player *p, struct mouse *m) +{ + bool detected = false; + bool x_overlap, y_overlap; + + x_overlap = p->x < (m->x + SPRITE_WIDTH) && + (p->x + SPRITE_WIDTH) > m->x; + y_overlap = p->y < (m->y + SPRITE_HEIGHT) && + (p->y + SPRITE_HEIGHT) > m->y; + detected = x_overlap && y_overlap; + + /* + * Play a little ACK sound and reset the game + * if we collide + */ + if (detected) { + beep(HIT_BEEP_MSEC, HIT_BEEP_FREQ); + + /* Clear the sprites */ + draw_rect(m->x, m->y, SPRITE_WIDTH, SPRITE_HEIGHT, GAME_BG); + draw_rect(p->x, p->y, SPRITE_WIDTH, SPRITE_HEIGHT, GAME_BG); + + m->x = 0; + m->y = rand() % MAX_Y; + m->x_inc ^= 1; + m->y_inc ^= 1; + score_increment(p, m); + } + + return detected; + +} + +static void +game_loop(void) +{ + struct timespec ts; + struct mouse mouse; + struct player p; + char c; + bool running = true; + + ts.tv_sec = 0; + ts.tv_nsec = 7000000; + + /* Setup the player */ + p.x = 0; + p.y = 0; + + /* Setup the mouse */ + mouse.x = MAX_X; + mouse.y = MAX_Y; + mouse.x_inc = 0; + mouse.y_inc = 0; + mouse.speed = MIN_MOUSE_SPEED; + + /* Draw player and mouse */ + draw_rect(p.x, p.y, SPRITE_WIDTH, SPRITE_HEIGHT, PLAYER_BG); + draw_rect(mouse.x, mouse.y, SPRITE_WIDTH, SPRITE_HEIGHT, MOUSE_BG); + + while (running) { + if (mouse_collide(&p, &mouse)) { + continue; + } + + c = getchar(); + sleep(&ts, &ts); + update_mouse(&mouse); + + if (IS_ASCII(c)) { + draw_rect(p.x, p.y, SPRITE_WIDTH, SPRITE_HEIGHT, GAME_BG); + } + + switch (c) { + case 'w': + p.y -= PLAYER_SPEED; + if (p.y <= 0) { + p.y = 0; + } + break; + case 'a': + p.x -= PLAYER_SPEED; + if (p.x <= 0) { + p.x = 0; + } + break; + case 's': + p.y += PLAYER_SPEED; + if (p.y > MAX_Y){ + p.y = MAX_Y; + } + break; + case 'd': + p.x += PLAYER_SPEED; + if (p.x > MAX_X) { + p.x = MAX_X; + } + break; + case 'q': + running = false; + default: + continue; + } + + draw_rect(p.x, p.y, SPRITE_WIDTH, SPRITE_HEIGHT, PLAYER_BG); + } +} + +int +main(void) +{ + int fb_fd, fbattr_fd, prot; + size_t fb_size; + char c; + + fb_fd = open("/dev/fb0", O_RDWR); + if (fb_fd < 0) { + return fb_fd; + } + + fbattr_fd = open("/ctl/fb0/attr", O_RDONLY); + if (fbattr_fd < 0) { + close(fb_fd); + return fbattr_fd; + } + + beep_fd = open("/dev/beep", O_WRONLY); + read(fbattr_fd, &fbattr, sizeof(fbattr)); + close(fbattr_fd); + + fb_size = fbattr.height * fbattr.pitch; + prot = PROT_READ | PROT_WRITE; + framep = mmap(NULL, fb_size, prot, MAP_SHARED, fb_fd, 0); + + game_loop(); + printf("\033[35;40mYOUR FINAL SCORE: %d\033[0m\n", hit_count); + + /* Cleanup */ + close(beep_fd); + munmap(framep, fb_size); + close(fb_fd); + return 0; +} diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c index 2f592ad..0e017e4 100644 --- a/usr.bin/osh/osh.c +++ b/usr.bin/osh/osh.c @@ -29,63 +29,140 @@ #include <sys/types.h> #include <sys/cdefs.h> +#include <sys/reboot.h> +#include <sys/spawn.h> #include <fcntl.h> #include <stddef.h> +#include <stdbool.h> #include <unistd.h> #include <string.h> +#include <stdio.h> -#define prcons(FD, STR) write((FD), (STR), strlen((STR))) #define is_ascii(C) ((C) >= 0 && (C) <= 128) +#define COMMENT '@' #define WELCOME \ ":::::::::::::::::::::::::::::::::::::::\n" \ ":: OSMORA GATEWAY ~ Every key echos ::\n" \ ":: ..... Proceed with purpose ..... ::\n" \ - ":::::::::::::::::::::::::::::::::::::::\n" + ":::::::::::::::::::::::::::::::::::::::" #define HELP \ "Default commands:\n" \ - "help - Display this help message\n" \ - "echo - Print the arguments to the console\n" \ - "exit - Exit the shell\n" + "help - Display this help message\n" \ + "echo - Print the arguments to the console\n" \ + "reboot - Reboot the machine\n" \ + "shutdown - Power off the machine\n" \ + "kmsg - Print kernel message buffer\n" \ + "fetch - System information\n" \ + "kfg - Start up kfgwm\n" \ + "bell - Toggle backspace bell\n" \ + "date - Get the current date\n" \ + "clear - Clear the screen\n" \ + "exit - Exit the shell" #define PROMPT "[root::osmora]~ " static char buf[64]; static uint8_t i; static int running; +static int bell_fd; +static bool bs_bell = true; /* Beep on backspace */ -struct command { +static void cmd_help(int argc, char *argv[]); +static void cmd_echo(int argc, char *argv[]); +static void cmd_exit(int argc, char *argv[]); +static void cmd_reboot(int argc, char *argv[]); +static void cmd_shutdown(int argc, char *argv[]); +static void cmd_bell(int argc, char *argv[]); +static void cmd_clear(int argc, char *argv[]); + +struct builtin_cmd { const char *name; - void (*func)(int fd, int argc, char *argv[]); + void (*func)(int argc, char *argv[]); +}; + +static struct builtin_cmd cmds[] = { + {"help",cmd_help}, + {"echo",cmd_echo}, + {"exit",cmd_exit}, + {"reboot",cmd_reboot}, + {"shutdown", cmd_shutdown}, + {"bell", cmd_bell}, + {"clear", cmd_clear}, + {NULL, NULL} }; -void -cmd_help(int fd, int argc, char *argv[]) +static void +cmd_help(int argc, char *argv[]) { - prcons(fd, HELP); + puts(HELP); } -void -cmd_exit(int fd, int argc, char *argv[]) +static void +cmd_exit(int argc, char *argv[]) { running = 0; } -void -cmd_echo(int fd, int argc, char *argv[]) +static void +cmd_reboot(int argc, char *argv[]) +{ + cpu_reboot(REBOOT_RESET); +} + +static void +cmd_shutdown(int argc, char *argv[]) +{ + cpu_reboot(REBOOT_POWEROFF | REBOOT_HALT); +} + +static void +cmd_echo(int argc, char *argv[]) { for (i = 1; i < argc; i++) { - prcons(fd, argv[i]); - prcons(fd, " "); + fputs(argv[i], stdout); + putchar(' '); } - prcons(fd, "\n"); + putchar('\n'); } -int +static void +cmd_clear(int argc, char *argv[]) +{ + fputs("\033[H", stdout); +} + +static void +cmd_bell(int argc, char *argv[]) +{ + const char *usage_str = "usage: bell [on/off]"; + const char *arg; + + if (argc < 2) { + puts(usage_str); + return; + } + + arg = argv[1]; + if (strcmp(arg, "on") == 0) { + bs_bell = true; + } else if (strcmp(arg, "off") == 0) { + bs_bell = false; + } else { + puts(usage_str); + } +} + +static int parse_args(char *input, char *argv[], int max_args) { int argc = 0; + /* ignore comments */ + if (*input == '@') { + return 0; + } + while (*input != '\0') { /* skip leading spaces */ while (*input == ' ') { @@ -97,11 +174,21 @@ parse_args(char *input, char *argv[], int max_args) break; } + /* comment? */ + if (*input == COMMENT) { + break; + } + if (argc < max_args) { argv[argc++] = input; /* mark start of the argument */ } /* move forward until next space or end */ while (*input != '\0' && *input != ' ') { + /* ignore comments */ + if (*input == COMMENT) { + return 0; + } + input++; } @@ -116,23 +203,35 @@ parse_args(char *input, char *argv[], int max_args) } static char * -getstr(int fd) +getstr(void) { char c; - uint8_t input; + int input; + uint32_t beep_payload; + i = 0; + /* + * Prepare the beep payload @ 500 Hz + * for 20ms + */ + beep_payload = 500; + beep_payload |= (30 << 16); + for (;;) { - if (read(fd, &input, 2) <= 0) { + if ((input = getchar()) < 0) { continue; } - c = input & 0xFF; + c = (char)input; + if (c == '\t') { + continue; + } /* return on newline */ if (c == '\n') { buf[i] = '\0'; - write(fd, "\n", 1); + putchar('\n'); return buf; } @@ -140,64 +239,170 @@ getstr(int fd) if (c == '\b' || c == 127) { if (i > 0) { i--; - write(fd, "\b \b", 3); + fputs("\b \b", stdout); + } else if (bell_fd > 0 && bs_bell) { + write(bell_fd, &beep_payload, sizeof(beep_payload)); } } else if (is_ascii(c) && i < sizeof(buf) - 1) { /* write to fd and add to buffer */ buf[i++] = c; - write(fd, &c, 1); + putchar(c); } } } -struct command cmds[] = { - {"help", cmd_help}, - {"echo", cmd_echo}, - {"exit", cmd_exit}, - {NULL, NULL} -}; +static void +builtin_run(struct builtin_cmd *cmd, int argc, char *argv[]) +{ + if (cmd->func != NULL) { + cmd->func(argc, argv); + return; + } +} -int -main(void) +static int +cmd_run(const char *input, int argc, char *argv[], bool wait) +{ + char bin_path[512]; + char *envp[1] = { NULL }; + int error, spawn_flags = 0; + + snprintf(bin_path, sizeof(bin_path), "/usr/bin/%s", input); + + /* See if we can access it */ + if (access(bin_path, F_OK) != 0) { + return -1; + } + + /* Should we wait or daemonize? */ + if (wait) { + spawn_flags |= SPAWN_WAIT; + } + + if ((error = spawn(bin_path, argv, envp, spawn_flags)) < 0) { + return error; + } + + return 0; +} + +/* + * Match a command with a builtin or binary + * + * @input: Command input + * @argc: Argument count + * @argv: Argument vector + * @wait: If false, program will be daemonized + */ +static void +command_match(const char *input, int argc, char *argv[], bool wait) +{ + int found = 0; + int i; + + for (i = 0; cmds[i].name != NULL; i++) { + if (strcmp(input, cmds[i].name) == 0) { + builtin_run(&cmds[i], argc, argv); + found = 1; + break; + } + } + + if (found == 0) { + if (cmd_run(input, argc, argv, wait) < 0) { + puts("Unrecognized command"); + } + } +} + +static void +script_skip_comment(int fd) { - int fd, found, argc; - char *input, *argv[16]; char c; - if ((fd = open("/dev/console", O_RDWR)) < 0) { + while (c != '\n') { + if (read(fd, &c, 1) <= 0) + break; + } +} + +static int +open_script(const char *pathname) +{ + int fd, argc, buf_i = 0; + char c, *input, *argv[16]; + char buf[256]; + + fd = open(pathname, O_RDONLY); + if (fd < 0) { + printf("osh: failed to open %s\n", pathname); return fd; } + while (read(fd, &c, 1) > 0) { + /* Skip comments */ + if (c == COMMENT) { + script_skip_comment(fd); + continue; + } + + /* Skip blank newlines */ + if (c == '\n' && buf_i == 0) { + continue; + } + + if (buf_i >= sizeof(buf) - 1) { + buf_i = 0; + } + + if (c == '\n') { + buf[buf_i] = '\0'; + argc = parse_args(buf, argv, sizeof(argv)); + command_match(buf, argc, argv, true); + + argv[0] = NULL; + argv[1] = NULL; + buf_i = 0; + continue; + } + buf[buf_i++] = c; + } + + return 0; +} + +int +main(int argc, char **argv) +{ + int found, prog_argc; + int stdout_fd; + char *input, *prog_argv[16], *p; + char c; + + if (argc > 1) { + return open_script(argv[1]); + } + i = 0; running = 1; found = 0; + bell_fd = open("/dev/beep", O_WRONLY); - prcons(fd, WELCOME); + puts(WELCOME); while (running) { - prcons(fd, PROMPT); + fputs(PROMPT, stdout); - input = getstr(fd); + input = getstr(); if (input[0] == '\0') { continue; } - argc = parse_args(input, argv, sizeof(argv)); - if (argc == 0) { + prog_argc = parse_args(input, prog_argv, sizeof(prog_argv)); + if (prog_argc == 0) { continue; } - for (i = 0; cmds[i].name != NULL; i++) { - if (strcmp(input, cmds[i].name) == 0) { - cmds[i].func(fd, argc, argv); - found = 1; - break; - } - } - - if (found == 0) { - prcons(fd, "Unrecognized command\n"); - } - + command_match(input, prog_argc, prog_argv, true); found = 0; buf[0] = '\0'; } |