├── log ├── build.log ├── delete.log └── 20190324.md ├── antz.img ├── screen ├── 1.png ├── 11.jpg ├── 2.png ├── a.bmp ├── h1.png ├── h2.png ├── h3.png ├── my.gif ├── 虚拟机1.gif ├── 虚拟机2.gif ├── 虚拟机3.png ├── execute.gif ├── runShow.gif └── load_char.png ├── assic └── char.set ├── tools ├── antz.img ├── usbit32.dll ├── usbitcmd.exe ├── USB Image Tool.exe └── USB Image Tool Helper.dll ├── include ├── golibc.lib ├── fdimg0at.tek ├── fdimg0tw.tek ├── harilibc.lib ├── haribote.rul ├── stddef.h ├── errno.h ├── setjmp.h ├── stdio.h ├── stdarg.h ├── limits.h ├── float.h ├── math.h ├── string.h ├── todo.h └── bmp.h ├── .vscode ├── settings.json └── ipch │ ├── f65514a71e818ab1 │ ├── BOOTPACK.ipch │ └── mmap_address.bin │ └── 8736ca6c7f95e21 │ └── mmap_address.bin ├── 色彩对照表.txt ├── .github └── FUNDING.yml ├── LICENSE ├── io └── fifo.c ├── log.md ├── interrupt └── int.c ├── OS-Build ├── IDT.md ├── Lock.md └── Thread.md ├── lgdt └── set_lgdt.c ├── thun ├── thun.c └── keychar.c ├── boot ├── mbr.asm └── asmhead.asm ├── Makefile ├── asmfunc └── naskfunc.nas ├── README.md ├── windows └── graphic.c ├── main ├── shell_1.md ├── shell_2.md └── bootpack.c ├── load_bmp.md └── task └── timer.c /log/build.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /log/delete.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /antz.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/antz.img -------------------------------------------------------------------------------- /screen/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/1.png -------------------------------------------------------------------------------- /screen/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/11.jpg -------------------------------------------------------------------------------- /screen/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/2.png -------------------------------------------------------------------------------- /screen/a.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/a.bmp -------------------------------------------------------------------------------- /screen/h1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/h1.png -------------------------------------------------------------------------------- /screen/h2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/h2.png -------------------------------------------------------------------------------- /screen/h3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/h3.png -------------------------------------------------------------------------------- /screen/my.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/my.gif -------------------------------------------------------------------------------- /assic/char.set: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/assic/char.set -------------------------------------------------------------------------------- /screen/虚拟机1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/虚拟机1.gif -------------------------------------------------------------------------------- /screen/虚拟机2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/虚拟机2.gif -------------------------------------------------------------------------------- /screen/虚拟机3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/虚拟机3.png -------------------------------------------------------------------------------- /tools/antz.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/tools/antz.img -------------------------------------------------------------------------------- /include/golibc.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/include/golibc.lib -------------------------------------------------------------------------------- /screen/execute.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/execute.gif -------------------------------------------------------------------------------- /screen/runShow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/runShow.gif -------------------------------------------------------------------------------- /tools/usbit32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/tools/usbit32.dll -------------------------------------------------------------------------------- /tools/usbitcmd.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/tools/usbitcmd.exe -------------------------------------------------------------------------------- /include/fdimg0at.tek: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/include/fdimg0at.tek -------------------------------------------------------------------------------- /include/fdimg0tw.tek: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/include/fdimg0tw.tek -------------------------------------------------------------------------------- /include/harilibc.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/include/harilibc.lib -------------------------------------------------------------------------------- /screen/load_char.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/screen/load_char.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "stdio.h": "c" 4 | } 5 | } -------------------------------------------------------------------------------- /tools/USB Image Tool.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/tools/USB Image Tool.exe -------------------------------------------------------------------------------- /tools/USB Image Tool Helper.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/tools/USB Image Tool Helper.dll -------------------------------------------------------------------------------- /.vscode/ipch/f65514a71e818ab1/BOOTPACK.ipch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/.vscode/ipch/f65514a71e818ab1/BOOTPACK.ipch -------------------------------------------------------------------------------- /.vscode/ipch/8736ca6c7f95e21/mmap_address.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/.vscode/ipch/8736ca6c7f95e21/mmap_address.bin -------------------------------------------------------------------------------- /.vscode/ipch/f65514a71e818ab1/mmap_address.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CasterWx/AntzOS/HEAD/.vscode/ipch/f65514a71e818ab1/mmap_address.bin -------------------------------------------------------------------------------- /include/haribote.rul: -------------------------------------------------------------------------------- 1 | format: 2 | code(align:1, logic:0x24, file:0x24); 3 | data(align:4, logic:stack_end, file:code_end); 4 | 5 | file: 6 | include/harilibc.lib; 7 | include/golibc.lib; 8 | 9 | label: 10 | _HariStartup; 11 | -------------------------------------------------------------------------------- /include/stddef.h: -------------------------------------------------------------------------------- 1 | /* copyright(C) 2003 H.Kawai (under KL-01). */ 2 | 3 | #if (!defined(STDDEF_H)) 4 | 5 | #define STDDEF_H 1 6 | 7 | #if (defined(__cplusplus)) 8 | extern "C" { 9 | #endif 10 | 11 | typedef unsigned int size_t; 12 | 13 | #if (defined(__cplusplus)) 14 | } 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/errno.h: -------------------------------------------------------------------------------- 1 | /* copyright(C) 2003 H.Kawai (under KL-01). */ 2 | 3 | #if (!defined(ERRNO_H)) 4 | 5 | #define ERRNO_H 1 6 | 7 | #if (defined(__cplusplus)) 8 | extern "C" { 9 | #endif 10 | 11 | extern int errno; 12 | 13 | #define ENOENT 2 /* No such file or directory */ 14 | #define ERANGE 34 /* Result too large (or too small) */ 15 | 16 | #if (defined(__cplusplus)) 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/setjmp.h: -------------------------------------------------------------------------------- 1 | /* copyright(C) 2003 H.Kawai (under KL-01). */ 2 | 3 | #if (!defined(SETJMP_H)) 4 | 5 | #define SETJMP_H 1 6 | 7 | #if (defined(__cplusplus)) 8 | extern "C" { 9 | #endif 10 | 11 | typedef int jmp_buf[3]; /* EBP, EIP, ESP */ 12 | 13 | #define setjmp(env) __builtin_setjmp(env) 14 | #define longjmp(env, val) __builtin_longjmp(env, val) 15 | 16 | #if (defined(__cplusplus)) 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/stdio.h: -------------------------------------------------------------------------------- 1 | /* copyright(C) 2003 H.Kawai (under KL-01). */ 2 | 3 | #if (!defined(STDIO_H)) 4 | 5 | #define STDIO_H 1 6 | 7 | #if (defined(__cplusplus)) 8 | extern "C" { 9 | #endif 10 | 11 | #if (!defined(NULL)) 12 | #define NULL ((void *) 0) 13 | #endif 14 | 15 | #include 16 | 17 | int sprintf(char *s, const char *format, ...); 18 | int vsprintf(char *s, const char *format, va_list arg); 19 | 20 | #if (defined(__cplusplus)) 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /include/stdarg.h: -------------------------------------------------------------------------------- 1 | /* copyright(C) 2003 H.Kawai (under KL-01). */ 2 | 3 | #if (!defined(STDARG_H)) 4 | 5 | #define STDARG_H 1 6 | 7 | #if (defined(__cplusplus)) 8 | extern "C" { 9 | #endif 10 | 11 | #define va_start(v,l) __builtin_stdarg_start((v),l) 12 | #define va_end __builtin_va_end 13 | #define va_arg __builtin_va_arg 14 | #define va_copy(d,s) __builtin_va_copy((d),(s)) 15 | #define va_list __builtin_va_list 16 | 17 | #if (defined(__cplusplus)) 18 | } 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /include/limits.h: -------------------------------------------------------------------------------- 1 | /* copyright(C) 2002 H.Kawai (under KL-01). */ 2 | 3 | #if (!defined(LIMITS_H)) 4 | 5 | #define LIMITS_H 1 6 | 7 | #define CHAR_BIT 8 8 | #define CHAR_MAX (+127) 9 | #define CHAR_MIN 0 10 | #define INT_MAX (+0x7fffffff) 11 | #define INT_MIN (-0x7fffffff) 12 | #define LONG_MAX INT_MAX 13 | #define LONG_MIN INT_MIN 14 | #define SCHAR_MAX (+127) 15 | #define SCHAR_MIN (-127) 16 | #define SHRT_MAX (+0x7fff) 17 | #define SHRT_MIN (-0x7fff) 18 | #define UCHAR_MAX (+0xff) 19 | #define UINT_MAX (+0xffffffff) 20 | #define ULONG_MAX UINT_MAX 21 | #define USHRT_MAX (+0xffff) 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /色彩对照表.txt: -------------------------------------------------------------------------------- 1 | 000000 0x00, 0x00, 0x00, /* 0:�� */ 2 | FF0000 0xff, 0x00, 0x00, /* 1:���� */ 3 | 00FF00 0x00, 0xff, 0x00, /* 2:���� */ 4 | FFFF00 0xff, 0xff, 0x00, /* 3:���� */ 5 | 0000FF 0x00, 0x00, 0xff, /* 4:���� */ 6 | FF00FF 0xff, 0x00, 0xff, /* 5:���� */ 7 | 00FFFF 0x00, 0xff, 0xff, /* 6:dz���� */ 8 | FFFFFF 0xff, 0xff, 0xff, /* 7:�� */ 9 | C6C6C6 0xc6, 0xc6, 0xc6, /* 8:���� */ 10 | 840000 0x84, 0x00, 0x00, /* 9:���� */ 11 | 008400 0x00, 0x84, 0x00, /* 10:���� */ 12 | 848400 0x84, 0x84, 0x00, /* 11:���� */ 13 | 000084 0x00, 0x00, 0x84, /* 12:���� */ 14 | 840084 0x84, 0x00, 0x84, /* 13:���� */ 15 | 008484 0x00, 0x84, 0x84, /* 14:dz���� */ 16 | 848484 0x84, 0x84, 0x84 /* 15:���� */ 17 | -------------------------------------------------------------------------------- /include/float.h: -------------------------------------------------------------------------------- 1 | /* copyright(C) 2002 H.Kawai (under KL-01). */ 2 | 3 | #if (!defined(FLOAT_H)) 4 | 5 | #define FLOAT_H 1 6 | 7 | #define FLT_RADIX 2 8 | #define FLT_ROUNDS 1 /* nearest */ 9 | #define FLT_DIG 6 10 | #define FLT_EPSILON 1.19209290e-07F 11 | #define FLT_MANT_DIG 24 12 | #define FLT_MAX 3.40282347e+38F 13 | #define FLT_MAX_EXP (+128) 14 | #define FLT_MIN 1.17549435e-38F 15 | #define FLT_MIN_EXP (-125) 16 | 17 | #define DBL_DIG 15 18 | #define DBL_EPSILON 2.2204460492503131e-16 19 | #define DBL_MANT_DIG 53 20 | #define DBL_MAX 1.7976931348623157e+308 21 | #define DBL_MAX_EXP 1024 22 | #define DBL_MIN 2.2250738585072014e-308 23 | #define DBL_MIN_EXP (-1021) 24 | 25 | #endif 26 | 27 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: [https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_pay.png,https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_wx.png] 13 | -------------------------------------------------------------------------------- /include/math.h: -------------------------------------------------------------------------------- 1 | /* copyright(C) 2003 H.Kawai (under KL-01). */ 2 | 3 | #if (!defined(MATH_H)) 4 | 5 | #define MATH_H 1 6 | 7 | #if (defined(__cplusplus)) 8 | extern "C" { 9 | #endif 10 | 11 | double sin(double); 12 | double cos(double); 13 | double sqrt(double); 14 | double ldexp(double x, int n); 15 | double frexp(double x, int *exp); 16 | 17 | extern __inline__ double sin(double x) 18 | { 19 | double res; 20 | __asm__ ("fsin" : "=t" (res) : "0" (x)); 21 | return res; 22 | } 23 | 24 | extern __inline__ double cos(double x) 25 | { 26 | double res; 27 | __asm__ ("fcos" : "=t" (res) : "0" (x)); 28 | return res; 29 | } 30 | 31 | extern __inline__ double sqrt(double x) 32 | { 33 | double res; 34 | __asm__ ("fsqrt" : "=t" (res) : "0" (x)); 35 | return res; 36 | } 37 | 38 | #if (defined(__cplusplus)) 39 | } 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Mou Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /io/fifo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define FLAGS_OVERRUN 0x0001 4 | 5 | /* 6 | 只需要先加载出一段缓冲区供之后使用即可 7 | */ 8 | void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf) 9 | /* 初始化FIFO缓冲区 */ 10 | { 11 | fifo->size = size; 12 | fifo->buf = buf; 13 | fifo->free = size; /* 缓冲区大小 */ 14 | fifo->flags = 0; 15 | fifo->p = 0; /* 下一个数据写入位置 */ 16 | fifo->q = 0; /* 下一个数据读出位置 */ 17 | return; 18 | } 19 | 20 | int fifo8_put(struct FIFO8 *fifo, unsigned char data) 21 | /* 向FIFO传送数据并保存 */ 22 | { 23 | if (fifo->free == 0) { 24 | /* 没有空间了,溢出 */ 25 | fifo->flags |= FLAGS_OVERRUN; 26 | return -1; 27 | } 28 | fifo->buf[fifo->p] = data; 29 | fifo->p++; 30 | if (fifo->p == fifo->size) { 31 | fifo->p = 0; 32 | } 33 | fifo->free--; 34 | return 0; 35 | } 36 | 37 | int fifo8_get(struct FIFO8 *fifo) 38 | /* 从FIFO取得一个数据 */ 39 | { 40 | int data; 41 | if (fifo->free == fifo->size) { 42 | /* 如果缓冲区为空则返回-1 */ 43 | return -1; 44 | } 45 | data = fifo->buf[fifo->q]; 46 | fifo->q++; 47 | if (fifo->q == fifo->size) { 48 | fifo->q = 0; 49 | } 50 | fifo->free++; 51 | return data; 52 | } 53 | 54 | int fifo8_status(struct FIFO8 *fifo) 55 | /* 报告一下积攒是数据量 */ 56 | { 57 | return fifo->size - fifo->free; 58 | } 59 | -------------------------------------------------------------------------------- /log.md: -------------------------------------------------------------------------------- 1 | # AntzOS 2 | 3 | ## 引子 4 | > 最近在看一些操作系统的资料,最开始的为什么是07c00h这个问题就让我对操作系统有了很大的兴趣。所以准备在看象书之余顺便写一个操作系统(Anz)。至于为什么这个系统会被叫做Antz,可以参考Antz Uhl Kone, 日语为アインズ·ウール·ゴウン , 与之对应的还有接下来准备写的自制脚本语言AntzScript,因为准备是用Java实现解释器,所以如何把AntzScript运行在Antz上是一个很大问题(其实问题就是引入Java)。 5 | 6 | * Antz系统更新地址: [这里是链接](https://www.cnblogs.com/LexMoon/category/1262287.html) 7 | 8 | #### [mbr实现](https://www.cnblogs.com/LexMoon/p/antz01.html) 9 | 10 | #### [保护模式](https://www.cnblogs.com/LexMoon/p/antz02.html) 11 | 12 | #### [显存](https://www.cnblogs.com/LexMoon/p/antz03.html) 13 | 14 | #### [硬盘](https://www.cnblogs.com/LexMoon/p/antz04.html) 15 | 16 | #### [进入保护模式](https://www.cnblogs.com/LexMoon/p/antz05.html) 17 | 18 | #### [引入c语言](https://www.cnblogs.com/LexMoon/p/antz09.html) 19 | 20 | #### [shell实现](https://github.com/CasterWx/AntzOS/blob/master/main/Console.md) 21 | 22 | 23 | ## 用了一个简单的字符库 24 | 25 | ``` 26 | char.bin : char.txt Makefile 27 | $(MAKEFONT) char.txt char.bin 28 | 29 | char.set : char.bin Makefile 30 | $(BIN2OBJ) char.bin assic/char.set _hankaku 31 | ``` 32 | ### 我把char.set直接存放在了assic文件夹中,直接拿来使用,不过只是ASSIC支持的字符,中文字符库找不到 33 | 34 | 35 | ## 去除鼠标 36 | 37 | ### 在鼠标存在的情况下,移动会导致后面的界面发生变化,图形化界面虽然容易保存现场结果,但终端部分缺会失去部分显示结果 38 | 39 | -------------------------------------------------------------------------------- /include/string.h: -------------------------------------------------------------------------------- 1 | /* copyright(C) 2003 H.Kawai (under KL-01). */ 2 | 3 | #if (!defined(STRING_H)) 4 | 5 | #define STRING_H 1 6 | 7 | #if (defined(__cplusplus)) 8 | extern "C" { 9 | #endif 10 | 11 | #include /* size_t */ 12 | 13 | char *strcpy(char *s, const char *ct); 14 | char *strncpy(char *s, const char *ct, size_t n); 15 | char *strcat(char *s, const char *ct); 16 | char *strncat(char *s, const char *ct, size_t n); 17 | int strcmp(const char *cs, const char *ct); 18 | int strncmp(const char *cs, const char *ct, size_t n); 19 | char *strchr(const char *cs, int c); 20 | char *strrchr(const char *cs, int c); 21 | size_t strspn(const char *s, const char *accept); 22 | size_t strcspn(const char *s, const char *reject); 23 | char *strpbrk(const char *s, const char *accept); 24 | char *strstr(const char *cs, const char *ct); 25 | size_t strlen(const char *cs); 26 | 27 | void *memcpy(void *s, const void *ct, size_t n); 28 | void *memmove(void *s, const void *ct, size_t n); 29 | int memcmp(const void *cs, const void *ct, size_t n); 30 | void *memchr(const void *cs, int c, size_t n); 31 | void *memset(void *s, int c, size_t n); 32 | char *strdup(const char *s); 33 | 34 | #if (defined(__cplusplus)) 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /interrupt/int.c: -------------------------------------------------------------------------------- 1 | #include 2 | /* 3 | user proc 4 | 5 | */ 6 | void init_pic(void) 7 | /* PIC初始化 */ 8 | { 9 | /* 禁止中断 */ 10 | io_out8(PIC0_IMR, 0xff ); 11 | io_out8(PIC1_IMR, 0xff ); 12 | io_out8(PIC0_ICW1, 0x11 ); 13 | io_out8(PIC0_ICW2, 0x20 ); 14 | io_out8(PIC0_ICW3, 1 << 2); 15 | io_out8(PIC0_ICW4, 0x01 ); 16 | io_out8(PIC1_ICW1, 0x11 ); 17 | io_out8(PIC1_ICW2, 0x28 ); 18 | io_out8(PIC1_ICW3, 2 ); 19 | io_out8(PIC1_ICW4, 0x01 ); 20 | /* 禁止其他中断 */ 21 | io_out8(PIC0_IMR, 0xfb ); 22 | io_out8(PIC1_IMR, 0xff ); 23 | 24 | return; 25 | } 26 | 27 | #define PORT_KEYDAT 0x0060 28 | 29 | struct FIFO8 keyfifo; 30 | 31 | /* 键盘中断 */ 32 | void inthandler21(int *esp) 33 | { 34 | struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; 35 | unsigned char data, s[4]; 36 | io_out8(PIC0_OCW2, 0x61); 37 | data = io_in8(PORT_KEYDAT); 38 | fifo8_put(&keyfifo, data); 39 | return; 40 | } 41 | 42 | struct FIFO8 mousefifo; 43 | 44 | void inthandler2c(int *esp) 45 | { 46 | unsigned char data; 47 | io_out8(PIC1_OCW2, 0x64); 48 | io_out8(PIC0_OCW2, 0x62); 49 | data = io_in8(PORT_KEYDAT); 50 | fifo8_put(&mousefifo, data); 51 | return; 52 | } 53 | 54 | 55 | /* 只是接收,不做其他操作 */ 56 | void inthandler27(int *esp) 57 | { 58 | io_out8(PIC0_OCW2, 0x67); 59 | return; 60 | } 61 | -------------------------------------------------------------------------------- /OS-Build/IDT.md: -------------------------------------------------------------------------------- 1 | ## 中断 2 | 3 | #### IDT 4 | 5 | 中断由一个代理来处理(Inter8259A芯片-PIC-可编程中断控制器) 6 | 7 | 屏蔽外设中断,进行优先级处理,向CPU提供中断向量号。 8 | 9 | Inter处理器支持256个中断,8259只可以管理8个,所以需要多个8259组合级联。 10 | 11 | 级联的话,多片组合在一起,只有一个为主片,其他为从片,来自从片的中断传递给主片,主片传递给CPU,也就是说只有主片才会向CPU发送int中断信号。 12 | 13 | 7n+1 14 | 15 | 两片时,15个 16 | 17 | 从片要占用主片一个IRQ接口。 18 | 19 | ``` 20 | 主8259A IRQ0 时钟 21 | IRQ1 键盘 22 | IRQ2 <-------------- 从8259A IRQ8 实时时钟 23 | IRQ3 串口2 IRQ9 重定向的IRQ2 24 | IRQ4 串口1 IRQ10 保留 25 | IRQ5 并口2 IRQ11 保留 26 | IRQ6 软盘 IRQ12 PS/2鼠标 27 | IRQ7 并口1 IRQ13 FPU异常 28 | IRQ14 硬盘 29 | IRQ15 保留 30 | ``` 31 | 32 | INT 选出优先级最高的请求后,发送信号通知cpu 33 | INTA 中断响应信号 34 | IMR 中断屏蔽信号 35 | IRR 中断请求信号 36 | ISR 中断服务信号 37 | 38 | IRR中断请求 39 | 处 INTR <-- INT PR中断选择 IMR中断屏蔽 40 | 理 41 | 器 INTA --> INTA ISR中断服务 42 | 43 | 44 | IDT本质上就是中断处理程序地址数组,而中断向量号就是下标。 45 | 8259A初始化: 设置主片从片级联,指定起始中断向量号以及设置各种工作模式。 46 | 47 | 8259A内部有两组寄存器。一组是初始化命令寄存器,用于保存初始化命令字 ICW 4个 ICW1-4 48 | 另一组是操作命令寄存器组,用来保存操作命令字 OCW 3个 OCW1-3 49 | 50 | 51 | ### 初始化 52 | 53 | ICW 54 | 55 | ------------------------- 56 | 57 | OCW --- > OCW1 用来屏蔽连接在8259A上的外部设备中断信号。 由于外部信号都是可屏蔽的,所以还要受标志寄存器eflags中IF位控制,IF为0,可屏蔽中断全部屏蔽。 OCW1写入主片0x21 或者从片0xA1处 58 | 59 | OCW2 用来设置中断结束方式和优先级模式。 EOI 60 | OCW3 特殊屏蔽方式和查询方式 61 | 62 | ------------------------ 63 | -------------------------------------------------------------------------------- /lgdt/set_lgdt.c: -------------------------------------------------------------------------------- 1 | // lGDT 2 | #include 3 | // https://www.cnblogs.com/LexMoon/p/antz05.html 4 | /* 5 | mbr 6 | GDT中段基址和段界限不是连续的!!! 7 | 为了兼容当时第一代GDT引入时的土豪机。 8 | 自处只做加载与基础寻址,不处理内存段或门的子类型的响应。 9 | */ 10 | void init_gdtidt(void) 11 | { 12 | struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT; 13 | struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) ADR_IDT; 14 | int i; 15 | 16 | /* GDT初始化 */ 17 | for (i = 0; i <= LIMIT_GDT / 8; i++) { 18 | set_segmdesc(gdt + i, 0, 0, 0); 19 | } 20 | set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, AR_DATA32_RW); 21 | set_segmdesc(gdt + 2, LIMIT_BOTPAK, ADR_BOTPAK, AR_CODE32_ER); 22 | load_gdtr(LIMIT_GDT, ADR_GDT); 23 | 24 | /* IDT初始化 */ 25 | for (i = 0; i <= LIMIT_IDT / 8; i++) { 26 | set_gatedesc(idt + i, 0, 0, 0); 27 | } 28 | load_idtr(LIMIT_IDT, ADR_IDT); 29 | 30 | /* IDT设置*/ 31 | set_gatedesc(idt + 0x20, (int) asm_inthandler20, 2 * 8, AR_INTGATE32); 32 | set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32); 33 | set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32); 34 | set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32); 35 | 36 | return; 37 | } 38 | 39 | void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar) 40 | { 41 | if (limit > 0xfffff) { 42 | ar |= 0x8000; /* G_bit = 1 */ 43 | limit /= 0x1000; 44 | } 45 | sd->limit_low = limit & 0xffff; 46 | sd->base_low = base & 0xffff; 47 | sd->base_mid = (base >> 16) & 0xff; 48 | sd->access_right = ar & 0xff; 49 | sd->limit_high = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0); 50 | sd->base_high = (base >> 24) & 0xff; 51 | return; 52 | } 53 | 54 | void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar) 55 | { 56 | gd->offset_low = offset & 0xffff; 57 | gd->selector = selector; 58 | gd->dw_count = (ar >> 8) & 0xff; 59 | gd->access_right = ar & 0xff; 60 | gd->offset_high = (offset >> 16) & 0xffff; 61 | return; 62 | } 63 | -------------------------------------------------------------------------------- /thun/thun.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // 2019/3/18/17点47分 此处莫名报错,得在void前加一个分号才可以 ,报错信息 7 | // 已解决,头文件的问题。 8 | /* 9 | make.exe[2]: Entering directory `C:/Users/13252/Desktop/AntzS/AntzOS' 10 | cc1.exe -I include/ -Os -Wall -quiet -o thun/thun.gas thun/thun.c 11 | thun/thun.c:6: parse error before "void" 12 | make.exe[2]: *** [thun/thun.gas] Error 1 13 | */ 14 | 15 | void to_printf_dijkstra(){ 16 | to_show() ; 17 | } 18 | 19 | void to_show(){ 20 | struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; 21 | int i, x, y , m , n; 22 | int k ; // 1024x768 23 | for (y = 0; y < 60; y++) { //10800 24 | for (x = 0; x < 108; x++){ 25 | // 16 + bmp_r[k]/43 + 6* (bmp_g[k]/43) + 36* (bmp_b[k]/43); 24色RGB转换公式 26 | /** 27 | * 取得为bmp[y][x],接下来需要在(x*10,y*13)~(x*10+10,y*13+13)区间填充这个颜色。 28 | **/ 29 | for(m=y*13; mvram, binfo->scrnx,rgbnum,n,m,n,m); 38 | } 39 | } 40 | } 41 | } 42 | 43 | } 44 | 45 | 46 | void to_printf_pdd(){ 47 | // struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; 48 | // int x, y; 49 | // int k = 0 ; 50 | // for (y = 0; y < 75; y++) { //75 51 | // for (x = 0; x < 100; x++){ //100 52 | // print_area(binfo->vram, binfo->scrnx , bmp[k] , x+binfo->scrnx-500, y+215, x+binfo->scrnx-500, y+215); 53 | // k++; 54 | // } 55 | // } 56 | } 57 | -------------------------------------------------------------------------------- /boot/mbr.asm: -------------------------------------------------------------------------------- 1 | ; MBR是BIOS接力的第一棒,在他之后,会由分区引导扇区DBR接力,至于为什么不直接给DBR。 2 | ; 那是因为BIOS大小有限,无法完成所有操作,在给DBR之前会通过MBR完成。 3 | ; 操作系统算是一个中断驱动的死循环,在不考虑中断的情况下,死循环的方法很多 4 | ; times 510-($-$$) db 0 _OR_ JMP 5 | 6 | CYLS EQU 10 7 | ORG 0x7c00 8 | ; 为什么是7c00 : 参考我的博客 https://www.cnblogs.com/LexMoon/p/antz01.html 9 | ; 32kb - 1kb 10 | JMP begin ; 跳转到主程序 11 | 12 | ; 软盘FAT12格式专用的代码,格式固定,主要是一些信息存储 13 | DB 0x90 14 | DB "Antz_Mbr" 15 | DW 512 16 | DB 1 17 | DW 1 18 | DB 2 19 | DW 224 20 | DW 2880 21 | DB 0xf0 22 | DW 9 23 | DW 18 24 | DW 2 25 | DD 0 26 | DD 2880 27 | DB 0,0,0x29 28 | DD 0xffffffff 29 | DB "AntzUhlMBR " 30 | DB "FAT12 " 31 | RESB 18 32 | 33 | ; MBR主体 34 | begin: 35 | MOV AX,0 ; 初始化寄存器 36 | MOV SS,AX 37 | MOV SP,0x7c00 38 | MOV DS,AX 39 | ; 将ds,es和cs指向相同的地址 40 | ; mov ax,cs 41 | ; mov ds,ax 42 | ; mov es,ax 43 | ; call doSomeThing 44 | ; jmp $ 45 | MOV AX,0x0820 46 | MOV ES,AX 47 | MOV CH,0 48 | MOV DH,0 49 | MOV CL,2 50 | 51 | error_while_loop: ; 次数 52 | MOV SI,0 53 | 54 | retry: 55 | MOV AH,0x02 56 | MOV AL,1 57 | MOV BX,0 58 | MOV DL,0x00 59 | INT 0x13 60 | JNC next 61 | ADD SI,1 62 | CMP SI,5 63 | JAE error 64 | MOV AH,0x00 65 | MOV DL,0x00 66 | INT 0x13 67 | JMP retry 68 | 69 | next: 70 | MOV AX,ES 71 | ADD AX,0x0020 72 | MOV ES,AX 73 | ADD CL,1 74 | CMP CL,18 75 | JBE error_while_loop 76 | MOV CL,1 77 | ADD DH,1 78 | CMP DH,2 79 | JB error_while_loop 80 | MOV DH,0 81 | ADD CH,1 82 | CMP CH,CYLS 83 | JB error_while_loop 84 | 85 | ; 读取完毕 86 | MOV [0x0ff0],CH 87 | JMP 0xc200 88 | 89 | error: 90 | MOV SI,msg 91 | 92 | putloop: 93 | MOV AL,[SI] 94 | ADD SI,1 ; 给SI加1 95 | CMP AL,0 96 | JE fin 97 | MOV AH,0x0e ; 显示一个文字 98 | MOV BX,15 ; 指定字符颜色 99 | INT 0x10 ; 调用显卡BIOS 100 | JMP putloop 101 | 102 | fin: 103 | HLT 104 | JMP fin 105 | 106 | wait_key: 107 | DB 0x13,0x13 108 | 109 | msg: 110 | DB 0x0a, 0x0a ; 换行两次 111 | DB "load error" 112 | DB 0x0a ; 换行 113 | DB 0 114 | RESB 0x7dfe-$ 115 | DB 0x55, 0xaa ; Mbr标志魔数,具体意义参考博客 https://www.cnblogs.com/LexMoon/p/antz01.html 116 | -------------------------------------------------------------------------------- /log/20190324.md: -------------------------------------------------------------------------------- 1 | # 自制操作系统Antz(15)——实现启动界面 2 | 3 | # AntzScript 4 | 5 | 🎓 The language executed in the Antz system. 6 | 7 | > 本节不涉及OS底层内容,只是关于图片放大显示时效果处理的。 8 | 9 | ###### [Antz系统更新地址](https://www.cnblogs.com/LexMoon/category/1262287.html) 10 | 11 | ###### [Antz项目地址](https://github.com/CasterWx/AntzOS) 12 | 13 | ###### [AntzScript项目地址](https://github.com/CasterWx/AntzScript) 14 | 15 | 16 | | 真机启动效果 | 17 | | -------- | 18 | | | 19 | 20 | 图片来源:[phodal/daily](https://github.com/phodal/daily) 21 | 22 | (orz左上角是在处理原图时自己签的名) 23 | 24 | 为了节省镜像空间,我将图片从2000乘800左右图片压缩为108乘60的24色大小的图片,计算为RGB值之后也有近6400左右像素点。但是要将它写入显存,展现在用户眼中,效果表明是很差的,我们的分辨率为1080x768,数十倍于这张图片。 25 | 26 | 为了解决显示效果的问题,这里有两种解决方法。 27 | 28 | --------- 29 | 30 | ## 一. 像素点区域化 31 | 32 | 这个方法是我自己起的名字,大致意思也如标题所示,就是将一个本来应该显示在(x1,y1)位置的像素点区域化显示,将其RGB值覆盖在(x1,y1)至(x1+x,y1+y)的这片区域。这个方法实现起来非常简单,但是效果`极差`,最后显示出来的效果就好像是`我的世界`中的超大像素点效果。 33 | 34 | 图示大概如这样: 35 | 36 | ![123](https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_12310.png) 37 | 38 | 附上简单实现。 39 | ```c 40 | void to_show(){ 41 | int i, x, y ; 42 | int k ; 43 | k = 0 ; 44 | for (y = 0; y < 60; y++) { 45 | for (x = 0; x < 108; x++){ 46 | // 在(x*10,y*13)至(x*10+10,y*13+13)这片区域填充RGB值bmp[k] 47 | print_image(x*10,y*13,x*10+10,y*13+13,bmp[k]); 48 | k++; 49 | } 50 | } 51 | } 52 | ``` 53 | 54 | 在虚拟机中效果如下。 55 | 56 | ![img](https://github.com/CasterWx/AntzOS/raw/master/screen/my.gif) 57 | 58 | ## 二. 双线性插值 59 | 60 | 在使用第一种粗略暴力的方式实现启动动画之后,第二天的数字图像处理课程中,听到老师讲matlab中的图片放大缩小函数的原理,了解了`双线性插值`这个算法,于是想到用这个方法来重新实现启动界面。 61 | 62 | 双线性插值的基本原理是,假设源图像大小为MxN,目标图像为AxB。那么两幅图像的边长比分别为:M/A和N/B。这两个比例值一般是浮点数。目标图像的第(i,j)个像素点(i行j列)可以通过边长比对应回源图像。其对应坐标为(i*m/a,j*n/b)。显然,这个对应坐标一般来说不是整数,而非整数的坐标是无法在图像这种离散数据上使用的。双线性插值通过寻找距离这个对应坐标最近的四个像素点,来计算该点的值(灰度值或者RGB值)。 63 | 64 | 其实可以理解为通过其周围的四个点,`中和`出这片区域中的其他点。 65 | 66 | ![2123](https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_213123.png) 67 | 68 | ![s](../sreen/1.png) 69 | 70 | 我们想得到一张放大的图片,现在有`原图像`和`目标图像`。那么,有一个最基本的问题摆在我们面前:是遍历`原图像`呢,还是遍历`目标图像`呢? 71 | 72 | 在实践的过程中,通常都是遍历`目标图像`的。因为这样可以确保`目标图像`的每一个像素都是有值的。 73 | 74 | 就拿上图的例子来说,右图`目标图像`中的 [0,0] 点很顺利的找到了左图`原图像`中与自己对应的 [0,0] 点。然后 [0,1] 点就懵逼了,它应该找 [0,0.33]点吗?没有这个点啊。 75 | 76 | 插值这个方法,就是为了解决这个问题的。 77 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | INCPATH = include/ 2 | MAKE = make.exe 3 | COPY = copy 4 | DEL = del 5 | TREE = tree /f 6 | Antz_kernel = main/bootpack.obj asmfunc/naskfunc.obj assic/char.set windows/graphic.obj lgdt/set_lgdt.obj interrupt/int.obj io/fifo.obj thun/keychar.obj thun/thun.obj task/timer.obj 7 | 8 | default : 9 | $(MAKE) img 10 | 11 | # 需要的 12 | mbr.bin : boot/mbr.asm Makefile 13 | nask.exe boot/mbr.asm mbr.bin mbr.lst 14 | 15 | asmhead.bin : boot/asmhead.asm Makefile 16 | nask.exe boot/asmhead.asm asmhead.bin asmhead.lst 17 | 18 | # naskfunc.obj会放在asmfunc目录中,如果在bootpack.bim合成时候不到,not find naskfunc会报错一万次!!!2018年9月9日15:46:27 19 | naskfunc.obj : asmfunc/naskfunc.nas Makefile 20 | nask.exe asmfunc/naskfunc.nas asmfunc/naskfunc.obj asmfunc/naskfunc.lst 21 | 22 | %.gas : %.c Makefile 23 | cc1.exe -I include/ -Os -Wall -quiet -o $*.gas $*.c 24 | 25 | %.nas : %.gas Makefile 26 | gas2nask.exe -a $*.gas $*.nas 27 | 28 | %.obj : %.nas Makefile 29 | nask.exe $*.nas $*.obj $*.lst 30 | 31 | bootpack.bim : $(Antz_kernel) Makefile 32 | obj2bim.exe @include/haribote.rul out:bootpack.bim stack:31360k map:bootpack.map $(Antz_kernel) 33 | 34 | bootpack.hrb : bootpack.bim Makefile 35 | bim2hrb.exe bootpack.bim bootpack.hrb 0 36 | 37 | antz.sys : asmhead.bin bootpack.hrb Makefile 38 | copy /B asmhead.bin+bootpack.hrb antz.sys 39 | 40 | antz.img : mbr.bin antz.sys Makefile 41 | edimg.exe imgin:include/fdimg0at.tek wbinimg src:mbr.bin len:512 from:0 to:0 copy from:antz.sys to:@: imgout:antz.img 42 | 43 | # 指令 44 | img : 45 | $(MAKE) antz.img 46 | 47 | run : 48 | $(MAKE) img 49 | $(MAKE) clean 50 | 51 | clean : 52 | -$(DEL) *.bin 53 | -$(DEL) *.lst 54 | 55 | -$(DEL) asmfunc\naskfunc.lst 56 | -$(DEL) asmfunc\naskfunc.obj 57 | 58 | -$(DEL) interrupt\int.lst 59 | -$(DEL) interrupt\int.obj 60 | 61 | -$(DEL) io\fifo.lst 62 | -$(DEL) io\fifo.obj 63 | 64 | -$(DEL) lgdt\set_lgdt.lst 65 | -$(DEL) lgdt\set_lgdt.obj 66 | 67 | -$(DEL) main\bootpack.lst 68 | -$(DEL) main\bootpack.obj 69 | 70 | -$(DEL) windows\graphic.lst 71 | -$(DEL) windows\graphic.obj 72 | 73 | -$(DEL) thun\thun.lst 74 | -$(DEL) thun\thun.obj 75 | 76 | -$(DEL) thun\keychar.lst 77 | -$(DEL) thun\keychar.obj 78 | 79 | -$(DEL) task\timer.lst 80 | -$(DEL) task\timer.obj 81 | 82 | -$(DEL) bootpack.map 83 | -$(DEL) bootpack.bim 84 | -$(DEL) bootpack.hrb 85 | -$(DEL) antz.sys 86 | 87 | tree : 88 | $(TREE) 89 | -------------------------------------------------------------------------------- /OS-Build/Lock.md: -------------------------------------------------------------------------------- 1 | ## 锁 2 | 3 | #### 信号量与锁的实现思想 4 | 5 | > sync.h 6 | ```c 7 | // 信号量 8 | struct semaphore { 9 | uint value ; // d 10 | struct list waiters ; // 进程P() 11 | } 12 | // 锁 13 | struct lock { 14 | struct task_struct* holder ; // 锁持有者 15 | struct semaphore semaphore ; 16 | uint holder_num ; 17 | } 18 | ``` 19 | 20 | > sync.c 21 | ```c 22 | void sema_init(struct semaphore *sema,uint value){ 23 | sema->value = value ; 24 | list_init(&sema->waiters); 25 | } 26 | void lock_init(struct lock *plock){ 27 | plock->holder = NULL ; 28 | plock->holder_num = 0 ; 29 | sema_init(&plock->semaphore,1); 30 | } 31 | // P 32 | void sema_down(struct semaphore *psema){ 33 | // 关中断操作 34 | OCW1 - eflags --- IF - 0 - 35 | // context 36 | while(psema->value==0){ 37 | // 如果当前线程已经在waiters队列中 38 | ASSERT(!elem_find(&psema->waiters,running_thread()->general_tag)); 39 | if(elem_find(&psema->waiters,running_thread()->general_tag)){ 40 | // error 41 | } 42 | // 加入等待队列 43 | append_list(&psame->waiters,&running_thread()->general_tag); 44 | thread_block(TASK_BLOCKED); //阻塞自己 45 | } 46 | psame->value -- ; 47 | ASSERT(psame->value==0); 48 | // 回复之前的中断状态 49 | // OCW1 - 50 | } 51 | // V 52 | void sema_up(struct semaphore *psema){ 53 | // 关中断操作 54 | ASSERT(psema->value==0); 55 | if(!list_empty(&psame->waiters)){ 56 | struct task_struct* thred_blocked = elem2entery(struct task_struct,general_tag,list_pop(&psame->waiters)); 57 | thread_unblock(thread_blocked); 58 | } 59 | psema->value ++ ; 60 | ASSERT(psema->value==1); 61 | // 回复之前的中断状态 62 | } 63 | void lock_acquice(strucr lock* plock){ 64 | if(plock->holder!=running_thread()){ 65 | sema_down(&plock->sema); 66 | plock->holder = running_thread() ; 67 | ASSERT(plock->holder_num==0); 68 | plock->holder_num = 1 ; 69 | }else{ 70 | plock->holder_num++ ; 71 | } 72 | } 73 | void lock_release(struct lock* plock){ 74 | // 锁的拥有者 75 | ASSERT(plock->holder==running_thread()); 76 | if (plock->holder_num>1){ 77 | plock->holder_num -- ; 78 | return ; 79 | } 80 | ASSERT(plock->holder_num==1); 81 | plock->holder = NULL ; 82 | plock->holder_num = 0 ; 83 | sema_up(&plock->sema) ; //V 84 | // OCW-> eflags -> IF 85 | // 先释放锁再进行信号量增加 86 | } 87 | ``` 88 | -------------------------------------------------------------------------------- /OS-Build/Thread.md: -------------------------------------------------------------------------------- 1 | ## 线程 2 | 3 | 4 | 5 | ### PCB相关 6 | 7 | > 定义 8 | 9 | ```c 10 | typedef void thread_fun(void*); 11 | 12 | enum task_status{ 13 | TASK_RUNNING, 14 | TASK_READY, 15 | TASK_BLOCKED, 16 | TASK_WAITING, 17 | TASK_HANGING, 18 | TASK_DIED 19 | } 20 | 21 | /****** 中断栈 ******* 22 | * 用于中断时保护程序的上下文环境 23 | * 中断时按此压入上下文寄存器。 24 | * intr_exit中借此恢复上下文环境 25 | * 此栈在线程自己的内核栈中位置固定,所在页的最顶端 26 | */ 27 | struct intr_stack{ 28 | uint vec_no ; 压入中断号 29 | uint edi ; 30 | uint esi ; 31 | uint ebp ; 32 | uint esp_dummy ; //虽然压入了sp,但他是不断变化的,所以可以忽略 33 | uint ebx ; 34 | uint edx ; 35 | uint ecx ; 36 | uint eax ; 37 | uint gs ; 38 | uint fs ; 39 | uint es ; 40 | uint ds ; 41 | 42 | // 进入高特权级时压入 43 | uint err_code ; 44 | void (*eip)(void) ; 45 | uint cs; 46 | uint eflags; 47 | void *esp; 48 | uint ss; 49 | }; 50 | 51 | /****** 线程栈 ******* 52 | * 线程自己的栈 53 | */ 54 | struct thread_stack{ 55 | uint edp; 56 | uint ebx; 57 | uint edi; 58 | uint esi; 59 | 60 | //第一次执行时,eip指向带调用函数 61 | void (*eip)(thread_func* func,void* func_arg); 62 | 63 | // 当第一次调入cpu 64 | void (*unused_retaddr); // 占位,充当返回地址 65 | thread_func* function; // 调用的函数名 66 | void *func_arg; // 调用的所需参数 67 | }; 68 | 69 | 70 | /* PCB */ 71 | struct task_struct{ 72 | uint * self_stack; // 指针,指向所在页顶端 73 | enum task_status status ; // status 74 | uint priority ; // 75 | char name[16] ; 76 | uint stack_magic ; 77 | }; 78 | ``` 79 | 80 | > 实现 81 | 82 | ```c 83 | static void kernel_thread(thread_func* function,void* func_arg){ 84 | function(func_arg); 85 | } 86 | 87 | void thread_create(struct task_struct* pthread,thread_func function,void *func_arg){ 88 | // 预留中断栈的空间 89 | pthread->self_kstack-=sizeof(struct intr_stack); 90 | // 预留线程栈空间 91 | pthread->self_kstack-=sizeof(struct thread_stack); 92 | 93 | struct thread_stack *kthread_stack = (struct thread_stack*)pthread->self_kstack; 94 | kthread_stack->eip = kernel_thread ; 95 | kthread_stack->function = function ; 96 | kthread_stack->func_arg = func_arg ; 97 | kthread_stack->ebp =kthread_stack->ebx =kthread_stack->esi =kthread_stack->edi = 0; 98 | } 99 | 100 | /*初始化线程信息*/ 101 | void init_thread(struct task_struct* pthread,char* name,int prio){ 102 | memset(pthread,0,sizeof(*pthread)); 103 | strcpy(pthred->name,name); 104 | pthread->status = TASK_RUNNING ; 105 | pthread->priority = prio ; 106 | } 107 | 108 | /*创建线程*/ 109 | struct task_struct* thread_start(char *name,int prio,thread_func function,void *func_arg){ 110 | struct task_struct* thread = get_page(1); 111 | init_thread(thread,name,prio); 112 | thread_create(thread,function,func_arg); 113 | return thread ; 114 | } 115 | 116 | void k_thread_a(void* arg){ 117 | char *ar = arg ; 118 | while(1){ 119 | put_str(ar); 120 | } 121 | } 122 | 123 | int main(){ 124 | put_str("i am kernel\n") ; 125 | init_all(); 126 | 127 | thread_start("thread_a",31,k_thread_a,"arg"); 128 | return 0; 129 | } 130 | ``` 131 | -------------------------------------------------------------------------------- /boot/asmhead.asm: -------------------------------------------------------------------------------- 1 | [INSTRSET "i486p"] 2 | 3 | VBEMODE EQU 0x105 4 | 5 | BOTPAK EQU 0x00280000 6 | DSKCAC EQU 0x00100000 7 | DSKCAC0 EQU 0x00008000 8 | 9 | ; BOOT_INFO 相关 10 | CYLS EQU 0x0ff0 11 | LEDS EQU 0x0ff1 12 | VMODE EQU 0x0ff2 13 | SCRNX EQU 0x0ff4 14 | SCRNY EQU 0x0ff6 15 | VRAM EQU 0x0ff8 16 | 17 | ORG 0xc200 18 | 19 | 20 | MOV AX,0x9000 21 | MOV ES,AX 22 | MOV DI,0 23 | MOV AX,0x4f00 24 | INT 0x10 25 | CMP AX,0x004f 26 | JNE scrn320 27 | 28 | 29 | MOV AX,[ES:DI+4] 30 | CMP AX,0x0200 31 | JB scrn320 32 | 33 | 34 | MOV CX,VBEMODE 35 | MOV AX,0x4f01 36 | INT 0x10 37 | CMP AX,0x004f 38 | JNE scrn320 39 | 40 | CMP BYTE [ES:DI+0x19],8 ;颜色数必须为8 41 | JNE scrn320 42 | CMP BYTE [ES:DI+0x1b],4 43 | JNE scrn320 44 | MOV AX,[ES:DI+0x00] 45 | AND AX,0x0080 46 | JZ scrn320 47 | 48 | 49 | MOV BX,VBEMODE+0x4000 50 | MOV AX,0x4f02 51 | INT 0x10 52 | MOV BYTE [VMODE],8 ;模式 53 | MOV AX,[ES:DI+0x12] 54 | MOV [SCRNX],AX 55 | MOV AX,[ES:DI+0x14] 56 | MOV [SCRNY],AX 57 | MOV EAX,[ES:DI+0x28] 58 | MOV [VRAM],EAX 59 | JMP keystatus 60 | 61 | scrn320: 62 | MOV AL,0x13 63 | MOV AH,0x00 64 | INT 0x10 65 | MOV BYTE [VMODE],8 66 | MOV WORD [SCRNX],320 67 | MOV WORD [SCRNY],200 68 | MOV DWORD [VRAM],0x000a0000 69 | 70 | 71 | keystatus: 72 | MOV AH,0x02 73 | INT 0x16 74 | MOV [LEDS],AL 75 | MOV AL,0xff 76 | OUT 0x21,AL 77 | NOP 78 | OUT 0xa1,AL 79 | 80 | CLI 81 | 82 | CALL waitkbdout 83 | MOV AL,0xd1 84 | OUT 0x64,AL 85 | CALL waitkbdout 86 | MOV AL,0xdf 87 | OUT 0x60,AL 88 | CALL waitkbdout 89 | 90 | 91 | [INSTRSET "i486p"] 92 | 93 | LGDT [GDTR0] ; GDT 94 | MOV EAX,CR0 95 | AND EAX,0x7fffffff 96 | OR EAX,0x00000001 ; 97 | MOV CR0,EAX 98 | JMP pipelineflush 99 | pipelineflush: 100 | MOV AX,1*8 101 | MOV DS,AX 102 | MOV ES,AX 103 | MOV FS,AX 104 | MOV GS,AX 105 | MOV SS,AX 106 | 107 | MOV ESI,bootpack 108 | MOV EDI,BOTPAK 109 | MOV ECX,512*1024/4 110 | CALL memcpy 111 | 112 | MOV ESI,0x7c00 113 | MOV EDI,DSKCAC 114 | MOV ECX,512/4 115 | CALL memcpy 116 | 117 | MOV ESI,DSKCAC0+512 118 | MOV EDI,DSKCAC+512 119 | MOV ECX,0 120 | MOV CL,BYTE [CYLS] 121 | IMUL ECX,512*18*2/4 122 | SUB ECX,512/4 123 | CALL memcpy 124 | 125 | MOV EBX,BOTPAK 126 | MOV ECX,[EBX+16] 127 | ADD ECX,3 128 | SHR ECX,2 129 | JZ skip 130 | MOV ESI,[EBX+20] ; 转送源 131 | ADD ESI,EBX 132 | MOV EDI,[EBX+12] ; 转送目标 133 | CALL memcpy 134 | skip: 135 | MOV ESP,[EBX+12] ; 堆栈的初始化 136 | JMP DWORD 2*8:0x0000001b 137 | 138 | waitkbdout: 139 | IN AL,0x64 140 | AND AL,0x02 141 | JNZ waitkbdout 142 | RET 143 | 144 | memcpy: 145 | MOV EAX,[ESI] 146 | ADD ESI,4 147 | MOV [EDI],EAX 148 | ADD EDI,4 149 | SUB ECX,1 150 | JNZ memcpy 151 | RET 152 | ; memcpy地址前缀大小 153 | 154 | ALIGNB 16 155 | GDT0: 156 | RESB 8 157 | DW 0xffff,0x0000,0x9200,0x00cf 158 | DW 0xffff,0x0000,0x9a28,0x0047 159 | 160 | DW 0 161 | GDTR0: 162 | DW 8*3-1 163 | DD GDT0 164 | 165 | ALIGNB 16 166 | bootpack: 167 | -------------------------------------------------------------------------------- /asmfunc/naskfunc.nas: -------------------------------------------------------------------------------- 1 | [FORMAT "WCOFF"] 2 | [INSTRSET "i486p"] 3 | [BITS 32] 4 | [FILE "naskfunc.nas"] 5 | GLOBAL _io_hlt, _io_cli, _io_sti, _io_stihlt 6 | GLOBAL _io_in8, _io_in16, _io_in32 7 | GLOBAL _io_out8, _io_out16, _io_out32 8 | GLOBAL _io_load_eflags, _io_store_eflags 9 | GLOBAL _load_gdtr, _load_idtr 10 | GLOBAL _asm_inthandler20, _asm_inthandler21, _asm_inthandler27, _asm_inthandler2c 11 | EXTERN _inthandler20, _inthandler21, _inthandler27, _inthandler2c 12 | 13 | [SECTION .text] 14 | 15 | _io_hlt: ; void io_hlt(void); 16 | HLT 17 | RET 18 | 19 | _io_cli: ; void io_cli(void); 20 | CLI 21 | RET 22 | 23 | _io_sti: ; void io_sti(void); 24 | STI 25 | RET 26 | 27 | _io_stihlt: ; void io_stihlt(void); 28 | STI 29 | HLT 30 | RET 31 | 32 | _io_in8: ; int io_in8(int port); 33 | MOV EDX,[ESP+4] ; port 34 | MOV EAX,0 35 | IN AL,DX 36 | RET 37 | 38 | _io_in16: ; int io_in16(int port); 39 | MOV EDX,[ESP+4] ; port 40 | MOV EAX,0 41 | IN AX,DX 42 | RET 43 | 44 | _io_in32: ; int io_in32(int port); 45 | MOV EDX,[ESP+4] ; port 46 | IN EAX,DX 47 | RET 48 | 49 | _io_out8: ; void io_out8(int port, int data); 50 | MOV EDX,[ESP+4] ; port 51 | MOV AL,[ESP+8] ; data 52 | OUT DX,AL 53 | RET 54 | 55 | _io_out16: ; void io_out16(int port, int data); 56 | MOV EDX,[ESP+4] ; port 57 | MOV EAX,[ESP+8] ; data 58 | OUT DX,AX 59 | RET 60 | 61 | _io_out32: ; void io_out32(int port, int data); 62 | MOV EDX,[ESP+4] ; port 63 | MOV EAX,[ESP+8] ; data 64 | OUT DX,EAX 65 | RET 66 | 67 | _io_load_eflags: ; int io_load_eflags(void); 68 | PUSHFD ; PUSH EFLAGS 69 | POP EAX 70 | RET 71 | 72 | _io_store_eflags: ; void io_store_eflags(int eflags); 73 | MOV EAX,[ESP+4] 74 | PUSH EAX 75 | POPFD ; POP EFLAGS 76 | RET 77 | 78 | _load_gdtr: ; void load_gdtr(int limit, int addr); 79 | MOV AX,[ESP+4] ; limit 80 | MOV [ESP+6],AX 81 | LGDT [ESP+6] 82 | RET 83 | 84 | _load_idtr: ; void load_idtr(int limit, int addr); 85 | MOV AX,[ESP+4] ; limit 86 | MOV [ESP+6],AX 87 | LIDT [ESP+6] 88 | RET 89 | 90 | _asm_inthandler20: 91 | PUSH ES 92 | PUSH DS 93 | PUSHAD 94 | MOV EAX,ESP 95 | PUSH EAX 96 | MOV AX,SS 97 | MOV DS,AX 98 | MOV ES,AX 99 | CALL _inthandler20 100 | POP EAX 101 | POPAD 102 | POP DS 103 | POP ES 104 | IRETD 105 | 106 | _asm_inthandler21: 107 | PUSH ES 108 | PUSH DS 109 | PUSHAD 110 | MOV EAX,ESP 111 | PUSH EAX 112 | MOV AX,SS 113 | MOV DS,AX 114 | MOV ES,AX 115 | CALL _inthandler21 116 | POP EAX 117 | POPAD 118 | POP DS 119 | POP ES 120 | IRETD 121 | 122 | _asm_inthandler27: 123 | PUSH ES 124 | PUSH DS 125 | PUSHAD 126 | MOV EAX,ESP 127 | PUSH EAX 128 | MOV AX,SS 129 | MOV DS,AX 130 | MOV ES,AX 131 | CALL _inthandler27 132 | POP EAX 133 | POPAD 134 | POP DS 135 | POP ES 136 | IRETD 137 | 138 | _asm_inthandler2c: 139 | PUSH ES 140 | PUSH DS 141 | PUSHAD 142 | MOV EAX,ESP 143 | PUSH EAX 144 | MOV AX,SS 145 | MOV DS,AX 146 | MOV ES,AX 147 | CALL _inthandler2c 148 | POP EAX 149 | POPAD 150 | POP DS 151 | POP ES 152 | IRETD 153 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![screen](screen/11.jpg) 2 | 3 | 系统封面授权取自于[phodal](https://github.com/phodal/daily)。 4 | 5 | # AntzOS 6 | 7 | > 一个随心所欲制造的操作系统Antz。 8 | 9 | The goal is to build a very simple UNIX-based operating system in c, not just a "proof-of-concept". The OS should be able to boot, start a userland shell, and be extensible. 10 | 11 | #### 开发文档 12 | 13 | [https://www.cnblogs.com/LexMoon/category/1262287.html](https://www.cnblogs.com/LexMoon/category/1262287.html) 14 | 15 | 1. [主引导Boot Sector](https://www.cnblogs.com/LexMoon/p/antz01.html) 16 | 2. [进入保护模式](https://www.cnblogs.com/LexMoon/p/antz02.html) 17 | 3. [直接操作显存](https://www.cnblogs.com/LexMoon/p/antz03.html) 18 | 4. [从硬盘载入内核](https://www.cnblogs.com/LexMoon/p/antz04.html) 19 | 5. [深入理解保护模式与进入方法](https://www.cnblogs.com/LexMoon/p/antz05.html) 20 | 6. [内核1](https://www.cnblogs.com/LexMoon/p/antz06.html) 21 | 7. [内核2](https://www.cnblogs.com/LexMoon/p/antz07.html) 22 | 8. [内核扩展](https://www.cnblogs.com/LexMoon/p/antz08.html) 23 | 9. [实现图形化界面](https://www.cnblogs.com/LexMoon/p/antz09.html) 24 | 10. [实现shell](https://www.cnblogs.com/LexMoon/p/antz10.html) 25 | 11. [命令响应](https://www.cnblogs.com/LexMoon/p/antz11.html) 26 | 12. [显示图片](https://www.cnblogs.com/LexMoon/p/antz13.html) 27 | 13. [实现内置语言词法解析器](https://www.cnblogs.com/LexMoon/p/antz14.html) 28 | 14. 实现启动动画 29 | 30 | #### 环境搭建 31 | 32 | `makefile` + `gcc` + `dd` ; `Windows下dd可直接使用exe版本的。` 33 | 34 | 为了方便测试建议使用虚拟机。 35 | 36 | #### 快速开始/如何使用 37 | 38 | 1. 下载仓库内tools包中的`USB Image Tool`启动盘制作工具与`antz.img`镜像文件。 39 | 2. 准备一个空闲的U盘。 40 | 3. 按照下述图示。 41 | 42 | | 1 | 2 | 3 | 43 | | ------- | -------- | -------- | 44 | | ![run](screen/h1.png) | ![run](screen/h2.png) | ![run](screen/h3.png) | 45 | 46 | #### 效果演示 47 | 48 | | 制作启动动画 [图片来源:phodal/daily](https://github.com/phodal/daily) | 真机运行 | 49 | | ------- | -------- | 50 | | ![run](screen/my.gif) | ![run](screen/runShow.gif) | 51 | | 显卡的直接操作 | 进程与时钟 | 52 | | ![run](https://github.com/CasterWx/AntzOS/blob/master/screen/虚拟机1.gif?raw=true) | ![run](https://github.com/CasterWx/AntzOS/blob/master/screen/execute.gif?raw=true) | 53 | 54 | 55 | | vim | 56 | | ------- | 57 | | ![antz_run](https://github.com/CasterWx/AntzOS/blob/master/screen/虚拟机2.gif?raw=true) | 58 | 59 | 60 | 61 | #### 介绍 62 | 63 | 这个系统在我最初的目的中是一个半图形半终端的轻巧OS。 64 | 65 | 完成了当前的工作后,Antz接下来需要实现的则是关于任务调度相关的。 66 | 67 | 目前实现的是在Terminal中对命令的响应,还有一个简易的vim,可以用于右边界面的文本编辑。 68 | 69 | 对于按键中断,对全键盘的响应改良之后不会出现之前说的bug,但是在shift按下时的按键模式却是有很大问题,虽然我已经想到了解决方案,不外乎给shift的按下一个flag,弹起一个flag,但这部分感觉现在实现与否都是不怎么重要,所以就先忽略这里了。 70 | 71 | 最近同时也在读Linux内核源码。发现其中的注释也是很有意思,甚至Linus自己写的,他也不知道这部分为什么这样写,不断尝试之后发现可以实现,他就这样用了。 72 | 73 | 这个镜像文件可以直接使用工具写入u盘启动,或者在虚拟机打开。 74 | 75 | [AntzOs](https://github.com/CasterWx/AntzOS)需要更多优秀的开发者来实现,无论你是正在学习操作系统课程还是其他方面,我相信AntzOs都可以帮助你更加的深入了解计算机操作系统底层的实现。 76 | 77 | | 历史版本1 | 历史版本2 | 历史版本3 | 78 | | ------- | ------- | ------- | 79 | | ![os1](https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_qq_pic_merged_1539834568688.jpg) | ![os2](https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_antzos4.jpg) | ![os3](https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_qq_pic_merged_1539834611072.jpg) | 80 | 81 | #### 交流群 82 | 83 | Telegram : [https://t.me/antzuhl/](https://t.me/antzuhl/) 84 | -------------------------------------------------------------------------------- /include/todo.h: -------------------------------------------------------------------------------- 1 | /* keychar.c */ 2 | char* replace_char(char s[40]); 3 | 4 | /* thun.c */ 5 | void to_printf_dijkstra(); 6 | void to_printf_pdd(); 7 | void to_show(); 8 | /* beaginShow.c */ 9 | 10 | /* asmhead.nas */ 11 | struct BOOTINFO { /* 0x0ff0-0x0fff */ 12 | char cyls; /* 启动区读磁盘读到此为止 */ 13 | char leds; /* 启动时键盘的LED的状态 */ 14 | char vmode; /* 显卡模式为多少位彩色 */ 15 | char reserve; 16 | short scrnx, scrny; /* 画面分辨率 */ 17 | char *vram; 18 | }; 19 | #define ADR_BOOTINFO 0x00000ff0 20 | 21 | /* naskfunc.nas */ 22 | void io_hlt(void); 23 | void io_cli(void); 24 | void io_sti(void); 25 | void io_out8(int port, int data); 26 | int io_load_eflags(void); 27 | void io_store_eflags(int eflags); 28 | void load_gdtr(int limit, int addr); 29 | void load_idtr(int limit, int addr); 30 | void asm_inthandler20(void); 31 | void asm_inthandler21(void); 32 | void asm_inthandler27(void); 33 | void asm_inthandler2c(void); 34 | 35 | /* fifo.c */ 36 | struct FIFO8 { 37 | unsigned char *buf; 38 | int p, q, size, free, flags; 39 | }; 40 | void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf); 41 | int fifo8_put(struct FIFO8 *fifo, unsigned char data); 42 | int fifo8_get(struct FIFO8 *fifo); 43 | int fifo8_status(struct FIFO8 *fifo); 44 | 45 | /* graphic.c */ 46 | void init_palette(void); 47 | void set_palette(int start, int end, unsigned char *rgb); 48 | // 区域绘制 49 | void print_area(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1); 50 | void init_screen8(char *vram, int x, int y); 51 | void print_font(char *vram, int xsize, int x, int y, char c, char *font); 52 | void print_string(char *vram, int xsize, int x, int y, char c, unsigned char *s); 53 | void init_mouse_cursor8(char *mouse, char bc); 54 | void putblock8_8(char *vram, int vxsize, int pxsize, 55 | int pysize, int px0, int py0, char *buf, int bxsize); 56 | #define COL8_000000 0 57 | #define COL8_FF0000 1 58 | #define COL8_00FF00 2 59 | #define COL8_FFFF00 3 60 | #define COL8_0000FF 4 61 | #define COL8_FF00FF 5 62 | #define COL8_00FFFF 6 63 | #define COL8_FFFFFF 7 64 | #define COL8_C6C6C6 8 65 | #define COL8_840000 9 66 | #define COL8_008400 10 67 | #define COL8_848400 11 68 | #define COL8_000084 12 69 | #define COL8_840084 13 70 | #define COL8_008484 14 71 | #define COL8_848484 15 72 | 73 | /* graphic.c */ 74 | struct SEGMENT_DESCRIPTOR { 75 | short limit_low, base_low; 76 | char base_mid, access_right; 77 | char limit_high, base_high; 78 | }; 79 | struct GATE_DESCRIPTOR { 80 | short offset_low, selector; 81 | char dw_count, access_right; 82 | short offset_high; 83 | }; 84 | void init_gdtidt(void); 85 | void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar); 86 | void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar); 87 | #define ADR_IDT 0x0026f800 88 | #define LIMIT_IDT 0x000007ff 89 | #define ADR_GDT 0x00270000 90 | #define LIMIT_GDT 0x0000ffff 91 | #define ADR_BOTPAK 0x00280000 92 | #define LIMIT_BOTPAK 0x0007ffff 93 | #define AR_DATA32_RW 0x4092 94 | #define AR_CODE32_ER 0x409a 95 | #define AR_INTGATE32 0x008e 96 | 97 | /* int.c */ 98 | void init_pic(void); 99 | void inthandler21(int *esp); 100 | void inthandler27(int *esp); 101 | void inthandler2c(int *esp); 102 | #define PIC0_ICW1 0x0020 103 | #define PIC0_OCW2 0x0020 104 | #define PIC0_IMR 0x0021 105 | #define PIC0_ICW2 0x0021 106 | #define PIC0_ICW3 0x0021 107 | #define PIC0_ICW4 0x0021 108 | #define PIC1_ICW1 0x00a0 109 | #define PIC1_OCW2 0x00a0 110 | #define PIC1_IMR 0x00a1 111 | #define PIC1_ICW2 0x00a1 112 | #define PIC1_ICW3 0x00a1 113 | #define PIC1_ICW4 0x00a1 114 | 115 | 116 | /* timer.c */ 117 | struct TIMERCTL { 118 | unsigned int count ; 119 | unsigned int flag ; 120 | }; 121 | extern struct TIMERCTL timerctl; 122 | void init_data(void); 123 | void init_pit(void); 124 | void inthandler20(int *esp); 125 | -------------------------------------------------------------------------------- /windows/graphic.c: -------------------------------------------------------------------------------- 1 | /* 关于绘图部分的处理 */ 2 | 3 | #include 4 | 5 | void init_palette(void) 6 | { 7 | static unsigned char table_rgb[48] = { 8 | 0x00, 0x00, 0x00,0xff, 0x00, 0x00,0x00, 0xff, 0x00,0xff, 0xff, 0x00,0x00, 0x00, 0xff,0xff, 0x00, 0xff, 9 | 0x00, 0xff, 0xff,0xff, 0xff, 0xff,0xc6, 0xc6, 0xc6,0x84, 0x00, 0x00,0x00, 0x84, 0x00,0x84, 0x84, 0x00, 10 | 0x00, 0x00, 0x84,0x84, 0x00, 0x84,0x00, 0x84, 0x84,0x84, 0x84, 0x84 11 | }; 12 | unsigned char table2[216*3] ; 13 | int r,g,b ; 14 | set_palette(0, 15, table_rgb); 15 | for (b = 0; b < 6; b++) { 16 | for (g = 0; g < 6; g++) { 17 | for (r = 0; r < 6; r++) { 18 | table2[(r + g * 6 + b * 36) * 3 + 0] = r * 51; 19 | table2[(r + g * 6 + b * 36) * 3 + 1] = g * 51; 20 | table2[(r + g * 6 + b * 36) * 3 + 2] = b * 51; 21 | } 22 | } 23 | } 24 | set_palette(16, 231, table2); 25 | return; 26 | } 27 | 28 | void set_palette(int start, int end, unsigned char *rgb) 29 | { 30 | int i, eflags; 31 | eflags = io_load_eflags(); /* 记录中断许可标志的值 */ 32 | io_cli(); /* 将中断许可标志置为0,禁止中断 */ 33 | io_out8(0x03c8, start); 34 | for (i = start; i <= end; i++) { 35 | io_out8(0x03c9, rgb[0] / 4); 36 | io_out8(0x03c9, rgb[1] / 4); 37 | io_out8(0x03c9, rgb[2] / 4); 38 | rgb += 3; 39 | } 40 | io_store_eflags(eflags); /* 复原中断许可标志 */ 41 | return; 42 | } 43 | 44 | // 区域绘制 45 | void print_area(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1) 46 | { 47 | int x, y; 48 | for (y = y0; y <= y1; y++) { 49 | for (x = x0; x <= x1; x++) 50 | vram[y * xsize + x] = c; 51 | } 52 | return; 53 | } 54 | 55 | // 初始界面 56 | void init_screen8(char *vram, int x, int y) 57 | { 58 | print_area(vram, x, COL8_000000, 0, 0, x, y); 59 | print_area(vram, x, COL8_C6C6C6, 0, 0, x/2, y); 60 | // print_area(vram, x, COL8_008484, x/2+2, 0, x, y); 61 | // print_area(vram, x, COL8_C6C6C6, x/2+2, y-25, x, y); 62 | // print_area(vram, x, COL8_848484, x/2+4, y-25+3, x, y); 63 | print_area(vram, x, COL8_000000, 3, 15, x/2-3, y-3); 64 | return; 65 | } 66 | 67 | void print_font(char *vram, int xsize, int x, int y, char c, char *font) 68 | { 69 | int i; 70 | char *p, d /* data */; 71 | for (i = 0; i < 16; i++) { 72 | p = vram + (y + i) * xsize + x; 73 | d = font[i]; 74 | if ((d & 0x80) != 0) { p[0] = c; } 75 | if ((d & 0x40) != 0) { p[1] = c; } 76 | if ((d & 0x20) != 0) { p[2] = c; } 77 | if ((d & 0x10) != 0) { p[3] = c; } 78 | if ((d & 0x08) != 0) { p[4] = c; } 79 | if ((d & 0x04) != 0) { p[5] = c; } 80 | if ((d & 0x02) != 0) { p[6] = c; } 81 | if ((d & 0x01) != 0) { p[7] = c; } 82 | } 83 | return; 84 | } 85 | 86 | void print_string(char *vram, int xsize, int x, int y, char c, unsigned char *s) 87 | { 88 | extern char hankaku[4096]; 89 | /* C语言中,字符串都是以0x00结尾 */ 90 | for (; *s != 0x00; s++) { 91 | print_font(vram, xsize, x, y, c, hankaku + *s * 16); 92 | x += 8; 93 | } 94 | return; 95 | } 96 | 97 | void init_mouse_cursor8(char *mouse, char bc) 98 | { 99 | static char cursor[16][16] = { 100 | "****************", 101 | ".*OOOOOOOOOOOO*.", 102 | ".*OOOOOOOOOOOO*.", 103 | "......*O*.......", 104 | "......*O*.......", 105 | "..*OOOOOOOOOO*..", 106 | "..*OOOOOOOOOO*..", 107 | "......*OO*......", 108 | "......*OO*......", 109 | "*OOOOOOOOOOOOOO*", 110 | "*OOOOOOOOOOOOOO*", 111 | ".....*OOO*......", 112 | ".....*OOO*......", 113 | ".....*OOO*......", 114 | ".....*OOO*......", 115 | "......***......." 116 | }; 117 | int x, y; 118 | 119 | for (y = 0; y < 16; y++) { 120 | for (x = 0; x < 16; x++) { 121 | if (cursor[y][x] == '*') { 122 | mouse[y * 16 + x] = COL8_000000; 123 | } 124 | if (cursor[y][x] == 'O') { 125 | mouse[y * 16 + x] = COL8_FFFFFF; 126 | } 127 | if (cursor[y][x] == '.') { 128 | mouse[y * 16 + x] = bc; 129 | } 130 | } 131 | } 132 | return; 133 | } 134 | 135 | void putblock8_8(char *vram, int vxsize, int pxsize, 136 | int pysize, int px0, int py0, char *buf, int bxsize) 137 | { 138 | int x, y; 139 | for (y = 0; y < pysize; y++) { 140 | for (x = 0; x < pxsize; x++) { 141 | vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x]; 142 | } 143 | } 144 | return; 145 | } 146 | -------------------------------------------------------------------------------- /thun/keychar.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | * @author : CasterWx 7 | * @time : 2019/3/19/16:37 8 | * @content : 此处添加一个说明,keychar.c的目的是为了解决键盘中断。一次按键分别会产生按下与弹起两个不同16进制中断号, 9 | 过去的Antz版本中使用了起落标志位[buttonFlag]来让两次中断产生一次效果,但在具体的使用过程中出现了键盘输 10 | 入过快导致的标志位混乱的情况。所以最后选择了强制根据中断码来使一次中断的内容为空。 11 | */ 12 | char* replace_char(char s[40]){ 13 | char *chr = "" ; 14 | if (strcmp(s,"9E")==0){ 15 | chr = "" ; 16 | }else if(strcmp(s,"B0")==0){ 17 | chr = "" ; 18 | }else if(strcmp(s,"AE")==0){ 19 | chr = "" ; 20 | }else if(strcmp(s,"A0")==0){ 21 | chr = "" ; 22 | }else if(strcmp(s,"92")==0){ 23 | chr = "" ; 24 | }else if(strcmp(s,"A1")==0){ 25 | chr = "" ; 26 | }else if(strcmp(s,"A2")==0){ 27 | chr = "" ; 28 | }else if(strcmp(s,"A3")==0){ 29 | chr = "" ; 30 | }else if(strcmp(s,"97")==0){ 31 | chr = "" ; 32 | }else if(strcmp(s,"A4")==0){ 33 | chr = "" ; 34 | }else if(strcmp(s,"A5")==0){ 35 | chr = "" ; 36 | }else if(strcmp(s,"A6")==0){ 37 | chr = "" ; 38 | }else if(strcmp(s,"B2")==0){ 39 | chr = "" ; 40 | }else if(strcmp(s,"B1")==0){ 41 | chr = "" ; 42 | }else if(strcmp(s,"98")==0){ 43 | chr = "" ; 44 | }else if(strcmp(s,"99")==0){ 45 | chr = "" ; 46 | }else if(strcmp(s,"90")==0){ 47 | chr = "" ; 48 | }else if(strcmp(s,"93")==0){ 49 | chr = "" ; 50 | }else if(strcmp(s,"9F")==0){ 51 | chr = "" ; 52 | }else if(strcmp(s,"94")==0){ 53 | chr = "" ; 54 | }else if(strcmp(s,"96")==0){ 55 | chr = "" ; 56 | }else if(strcmp(s,"AF")==0){ 57 | chr = "" ; 58 | }else if(strcmp(s,"91")==0){ 59 | chr = "" ; 60 | }else if(strcmp(s,"AD")==0){ 61 | chr = "" ; 62 | }else if(strcmp(s,"95")==0){ 63 | chr = "" ; 64 | }else if(strcmp(s,"AC")==0){ 65 | chr = "" ; 66 | }else if(strcmp(s,"B9")==0){ 67 | chr = "" ; 68 | }else if((strcmp(s,"A7")==0)){ 69 | chr = "" ; 70 | }else if((strcmp(s,"B4")==0)){ 71 | chr = "" ; 72 | }else if((strcmp(s,"B3")==0)){ 73 | chr = "" ; 74 | }else if((strcmp(s,"9A")==0)){ 75 | chr = "" ; 76 | }else if((strcmp(s,"9B")==0)){ 77 | chr = "" ; 78 | }else if((strcmp(s,"1A")==0)){ 79 | chr = "[" ; 80 | }else if((strcmp(s,"1B")==0)){ 81 | chr = "]" ; 82 | }else if((strcmp(s,"33")==0)){ 83 | chr = "," ; 84 | }else if((strcmp(s,"27")==0)){ 85 | chr = ";" ; 86 | }else if((strcmp(s,"34")==0)){ 87 | chr = "." ; 88 | }else if((strcmp(s,"1E")==0)){ 89 | chr = "a" ; 90 | }else if((strcmp(s,"30")==0)){ 91 | chr = "b" ; 92 | }else if((strcmp(s,"2E")==0)){ 93 | chr = "c" ; 94 | }else if((strcmp(s,"20")==0)){ 95 | chr = "d" ; 96 | }else if((strcmp(s,"12")==0)){ 97 | chr = "e" ; 98 | }else if((strcmp(s,"21")==0)){ 99 | chr = "f" ; 100 | }else if((strcmp(s,"22")==0)){ 101 | chr = "g" ; 102 | }else if((strcmp(s,"23")==0)){ 103 | chr = "h" ; 104 | }else if((strcmp(s,"17")==0)){ 105 | chr = "i" ; 106 | }else if((strcmp(s,"24")==0)){ 107 | chr = "j" ; 108 | }else if((strcmp(s,"25")==0)){ 109 | chr = "k" ; 110 | }else if((strcmp(s,"26")==0)){ 111 | chr = "l" ; 112 | }else if((strcmp(s,"32")==0)){ 113 | chr = "m" ; 114 | }else if((strcmp(s,"31")==0)){ 115 | chr = "n" ; 116 | }else if((strcmp(s,"18")==0)){ 117 | chr = "o" ; 118 | }else if((strcmp(s,"19")==0)){ 119 | chr = "p" ; 120 | }else if((strcmp(s,"10")==0)){ 121 | chr = "q" ; 122 | }else if((strcmp(s,"13")==0)){ 123 | chr = "r" ; 124 | }else if((strcmp(s,"1F")==0)){ 125 | chr = "s" ; 126 | }else if((strcmp(s,"14")==0)){ 127 | chr = "t" ; 128 | }else if((strcmp(s,"16")==0)){ 129 | chr = "u" ; 130 | }else if((strcmp(s,"2F")==0)){ 131 | chr = "v" ; 132 | }else if((strcmp(s,"11")==0)){ 133 | chr = "w" ; 134 | }else if((strcmp(s,"2D")==0)){ 135 | chr = "x" ; 136 | }else if((strcmp(s,"15")==0)){ 137 | chr = "y" ; 138 | }else if((strcmp(s,"2C")==0)){ 139 | chr = "z" ; 140 | }else if((strcmp(s,"39")==0)){// 空格 141 | chr = " " ; 142 | }else if(strcmp(s,"9C")==0){ // 回车的弹起中断 143 | /** 144 | *@author : CasterWx 145 | *@time : 2019/3/19/16:43 146 | *@content : 此处本来是将回车的chr设置为空的,但是为了方便vimShow排版,此处将回车的chr设置为"\n"。 147 | **/ 148 | // old Code : chr = "" ; 149 | chr = ""; 150 | // fix :显示bug 151 | }else if(strcmp(s,"BB")==0){ 152 | chr = "" ; 153 | } 154 | return chr ; 155 | } 156 | -------------------------------------------------------------------------------- /main/shell_1.md: -------------------------------------------------------------------------------- 1 | # 自制操作系统Antz day10——实现shell(上) 2 | > 我已经规范了系统代码风格,类似于按照linux分包,把各部分功能区分开了 3 | ### [Antz系统更新地址](https://www.cnblogs.com/LexMoon/category/1262287.html) 4 | 5 | ### [Linux内核源码分析地址](https://www.cnblogs.com/LexMoon/category/1267413.html) 6 | 7 | ### [Github项目地址](https://github.com/CasterWx/AntzOS) 8 | 9 | 10 | ### 在之前的任务中,我们已经通过直接操作显卡驱动完成了简单的图形化。 11 | ### 需要了解之前的部分: 12 | > 直接操作显卡请参考day03 13 | 14 | > 简单图形化的实现请参考day09 15 | 16 | > Makefile 17 | 18 | ### 项目目录 19 | 20 | ![s](https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_project.jpg) 21 | 22 | #### console的图形化实现与规则均在main/bootpack.c中完成 23 | 24 | #### interrupt/int.c 中实现了键盘中断处理,按键会中断两次,一次按下,一次弹起,在响应处理中,只需要处理第一次按下即可。 25 | 26 | ## 一 . 键盘按键 27 | 28 | #### 如何来判断中断来自于键盘?(代码如下) 29 | ``` 30 | // gdt初始化操作... 31 | // fifo加载操作... 32 | if (fifo8_status(&keyfifo) != 0) { // True则说明中断来自于键盘 33 | i = fifo8_get(&keyfifo); 34 | io_sti(); 35 | // i 就是中断返回的值,分析他即可得到按键信息, 在下面我把它转换为了16进制存储在了一个char array s中 36 | sprintf(s, "%02X", i); 37 | // 把两次中断变为一次,看下文 38 | } 39 | ``` 40 | #### 得到了s,就是得到了键盘按键的信息。 41 | 42 | #### 开头说了,按下一次,会有两次中断发生,那么我们是否可以使用一个flag来区分按下和弹起呢? 43 | 44 | ``` 45 | if (flag){ 46 | keyshow(); // 显示这次按键,把按下的中断当作一个键位的信息,把弹起的中断用下面flag的方法屏蔽掉 47 | } 48 | // 屏蔽 49 | if(flag==1){ 50 | flag = 0 ; 51 | }else { 52 | flag = 1 ; 53 | } 54 | ``` 55 | #### 这是一个很拙略的实现方法,而且我测试了几次之后发现有一个bug,就是同时按下两个键位时,屏蔽的方法就会变成另一种。 56 | #### 比如开始是用按下识别一个键位,那么同时按下两个键位之后就是以弹起的方法来识别键位了。 57 | 58 | #### 这个情况留在之后再考虑。 59 | 60 | ## 二 . 按键识别 61 | 62 | #### 上文中已经将按键返回的数据存储到了char数组s,只需要在屏幕上显示s的数据就可以了。 63 | 64 | ``` 65 | int write_x = 55 ; //按键显示位置的x,y坐标 66 | int write_y = 57 ; 67 | 68 | void key(struct BOOTINFO *binfo,char s[40]){ 69 | //在指定位置显示数据 70 | showkeys(binfo->vram, binfo->scrnx, write_x, write_y, COL8_FFFFFF, s); 71 | // 显示之后光标右移 72 | write_x += 19 ; 73 | // 如果超出右边界,换行 74 | if(write_x>155){ 75 | write_x = 55 ; 76 | write_y += 19 ; 77 | } 78 | // 如果超出下边界,刷新清理本页,开启新的一页 79 | if(write_y>180){ 80 | new_pe(binfo); 81 | } 82 | 83 | } 84 | ``` 85 | ### 结果: 86 | ![print](https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_print.jpg) 87 | 88 | #### 很明显,我们需要编写一种转换机制,将表示16进制的数据对应成为键盘按键。 89 | 90 | #### 键盘上需要显示的有字母和特殊符号,还有一些功能性的按键shift,backspace等。 91 | 92 | #### 测试记录了几个按键的按下数据 93 | > 键盘 按下 94 | 95 | > F1 3B 96 | 97 | > F2 3C 98 | 99 | > F3 3D 100 | 101 | > F4 3E 102 | 103 | > A 1E 104 | 105 | > B 30 106 | 107 | > Backspace OE 108 | 109 | > 空格 39 110 | 111 | #### 既然已经知道了对应关系,那么很容易就可以建立一种对应。 112 | 113 | #### 先来实现这几个特殊按键功能 114 | 115 | #### 我打算将 F1 实现为 clear 功能,实现页面刷新 。 Backspace 实现回退功能。Enter实现确定以及回车功能。 116 | 117 | #### Clear为了确保安全性,对F1按键的两种中断都会发生响应。 118 | ``` 119 | void showkey(struct BOOTINFO *binfo,char s[40]){ 120 | // 回车键 121 | if(strcmp(s,"1C")==0){ 122 | write_x = 55 ; // 光标移动至下一行起始位置。 123 | write_y += 19 ; 124 | showkeys(binfo->vram, binfo->scrnx, 0, write_y, COL8_FFFFFF, "AntzOS>"); 125 | } 126 | // F1 刷新本页 127 | else if(strcmp(s,"3B")==0){ 128 | new_pe(binfo); 129 | } 130 | // 空格 光标后移一位 131 | else if(strcmp(s,"39")==0){ 132 | showkeys(binfo->vram, binfo->scrnx, write_x, write_y, COL8_FFFFFF, " "); 133 | write_x += 19 ; 134 | } 135 | // Backspace 删除退格 136 | else if(strcmp(s,"0E")==0){ 137 | // 回退 138 | write_x -= 19 ; 139 | //重新覆盖这片区域 140 | area_flash(binfo->vram, binfo->scrnx , COL8_000000, write_x, write_y, write_x+19, write_y+19); 141 | } 142 | // 其他按键 143 | else { 144 | showkeys(binfo->vram, binfo->scrnx, write_x, write_y, COL8_FFFFFF, s); 145 | write_x += 19 ; 146 | } 147 | if(write_x>155){ 148 | write_x = 55 ; 149 | write_y += 19 ; 150 | //putfonts8_asc(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>"); 151 | } 152 | if(write_y>180){ 153 | new_pe(binfo); 154 | } 155 | 156 | } 157 | ``` 158 | 159 | #### 字母识别同理,当然可以比上面实现的更加完善更加简洁,但我仓促之下就只能先做到这一步。 160 | 161 | ## 三 . Bug引发的思考 162 | 163 | #### 这里开始就和AntzOs实现没有多少联系了,不过在我测试按键中断时候发现了很多奇怪的小问题。 164 | 165 | > Caps Lock(大小写键) 是否开启并不会影响中断对你一个按键的返回信息,也就是所谓的大小写中断其实是无法区分的,那么现代系统如何区分呢? 同理于上面我们区分按下和弹起两次中断,我们可以将Caps Lock键的状态获取到,从而对当前按键进行所谓的大小写区分。 166 | 167 | > 按下两次导致规则置换,会不会是因为中断响应的时间导致的。 168 | -------------------------------------------------------------------------------- /load_bmp.md: -------------------------------------------------------------------------------- 1 | # 自制操作系统Antz——day13 显示图片 2 | > 显示图片只是在多媒体课上看着bmp格式图片的突发奇想,然后就实现在了我自己的操作系统 3 | ### [Antz系统更新地址](https://www.cnblogs.com/LexMoon/category/1262287.html) 4 | 5 | ### [Linux内核源码分析地址](https://www.cnblogs.com/LexMoon/category/1267413.html) 6 | 7 | ### [Github项目地址](https://github.com/CasterWx/AntzOS) 8 | 9 | 效果图: 10 | 11 | ![效果](https://github.com/CasterWx/AntzOS/blob/master/screen/a.gif?raw=true) 12 | 13 | ### 显示图片的原理 14 | 15 | 在之前显卡操作时,屏幕上的像素点我们是直接赋予一个颜色值的。 16 | 0xa0000是显示屏左上角第一个像素的地址,我们只需要根据地址赋予相应图片的rgb值即可实现图片的显示。Antz使用的显卡模式只能支持255种颜色,也就是bmp中24色的图片。 17 | 所以我们需要先将一个24色bmp格式的图片进行rgb值读取,然后再将rgb的值赋予到显卡的相应位置。 18 | 19 | #### 图片rgb读取 20 | read.cpp 21 | ```c 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include"read.h" 27 | 28 | using namespace std; 29 | unsigned int **out_r; 30 | unsigned int **out_g; 31 | unsigned int **out_b; 32 | 33 | void getRGB() 34 | { 35 | 36 | char readPath[] = "a.bmp"; 37 | readBmp(readPath); 38 | // 输出整体图像信息 39 | cout << "\nwidth=" << bmpWidth << "\nheight=" << bmpHeight << "\nbiBitCount=" << biBitCount << endl; 40 | // 图像的字节数 41 | int linebyte1 = (bmpWidth*biBitCount / 8 + 3) / 4 * 4; 42 | int n = 0, m = 0, count_xiang_su = 0; 43 | int i ; 44 | out_r = new unsigned int *[bmpHeight]; 45 | for (i= 0; i 138 | #include 139 | #include 140 | 141 | using namespace std; 142 | 143 | 144 | unsigned char *pBmpBuf;//读入图像数据的指针 145 | int bmpWidth;//图像的宽 146 | int bmpHeight;//图像的高 147 | RGBQUAD *pColorTable;//颜色表指针 148 | int biBitCount;//图像类型,每像素位数 149 | 150 | 151 | 152 | //显示位图文件头信息 153 | void showBmpHead(BITMAPFILEHEADER pBmpHead){ 154 | cout << "\n位图文件头:" << endl; 155 | cout << "文件大小:" << pBmpHead.bfSize << endl; 156 | cout << "保留字_1:" << pBmpHead.bfReserved1 << endl; 157 | cout << "保留字_2:" << pBmpHead.bfReserved2 << endl; 158 | cout << "实际位图数据的偏移字节数:" << pBmpHead.bfOffBits << endl << endl; 159 | } 160 | //显示位图信息头信息 161 | void showBmpInforHead(BITMAPINFOHEADER pBmpInforHead){ 162 | cout << "\n位图信息头:" << endl; 163 | cout << "结构体的长度:" << pBmpInforHead.biSize << endl; 164 | cout << "位图宽:" << pBmpInforHead.biWidth << endl; 165 | cout << "位图高:" << pBmpInforHead.biHeight << endl; 166 | cout << "biPlanes平面数:" << pBmpInforHead.biPlanes << endl; 167 | cout << "biBitCount采用颜色位数:" << pBmpInforHead.biBitCount << endl; 168 | cout << "压缩方式:" << pBmpInforHead.biCompression << endl; 169 | cout << "biSizeImage实际位图数据占用的字节数:" << pBmpInforHead.biSizeImage << endl; 170 | cout << "X方向分辨率:" << pBmpInforHead.biXPelsPerMeter << endl; 171 | cout << "Y方向分辨率:" << pBmpInforHead.biYPelsPerMeter << endl; 172 | cout << "使用的颜色数:" << pBmpInforHead.biClrUsed << endl; 173 | cout << "重要颜色数:" << pBmpInforHead.biClrImportant << endl; 174 | } 175 | //给定一个图像位图数据、宽、高、颜色表指针及每像素所占的位数等信息,将其写到指定文件中 176 | bool readBmp(char *bmpName) 177 | { 178 | FILE *fp = fopen(bmpName, "rb");//二进制读方式打开指定的图像文件 179 | if (fp == 0) 180 | return 0; 181 | 182 | //跳过位图文件头结构BITMAPFILEHEADER 183 | fseek(fp, sizeof(BITMAPFILEHEADER), 0); 184 | //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中 185 | BITMAPINFOHEADER infohead; 186 | fread(&infohead, sizeof(BITMAPINFOHEADER), 1, fp); //获取图像宽、高、每像素所占位数等信息 187 | bmpWidth = infohead.biWidth; 188 | bmpHeight = infohead.biHeight; 189 | biBitCount = infohead.biBitCount;//定义变量,计算图像每行像素所占的字节数(必须是4的倍数) 190 | showBmpInforHead(infohead);//显示信息头 191 | 192 | 193 | int lineByte = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;//灰度图像有颜色表,且颜色表表项为256 194 | if (biBitCount == 8) 195 | { 196 | //申请颜色表所需要的空间,读颜色表进内存 197 | pColorTable = new RGBQUAD[256]; 198 | fread(pColorTable, sizeof(RGBQUAD), 256, fp); 199 | } 200 | 201 | //申请位图数据所需要的空间,读位图数据进内存 202 | pBmpBuf = new unsigned char[lineByte * bmpHeight]; 203 | fread(pBmpBuf, 1, lineByte * bmpHeight, fp); 204 | fclose(fp);//关闭文件 205 | return 1;//读取文件成功 206 | } 207 | //保存图片 208 | bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD *pColorTable) 209 | { 210 | 211 | //如果位图数据指针为0,则没有数据传入,函数返回 212 | if (!imgBuf) 213 | return 0; 214 | //颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0 215 | int colorTablesize = 0; 216 | if (biBitCount == 8) 217 | colorTablesize = 1024; 218 | 219 | //待存储图像数据每行字节数为4的倍数 220 | int lineByte = (width * biBitCount / 8 + 3) / 4 * 4; 221 | 222 | //以二进制写的方式打开文件 223 | FILE *fp = fopen(bmpName, "wb"); 224 | 225 | if (fp == 0) 226 | return 0; 227 | //申请位图文件头结构变量,填写文件头信息 228 | BITMAPFILEHEADER fileHead; 229 | fileHead.bfType = 0x4D42;//bmp类型 230 | 231 | //bfSize是图像文件4个组成部分之和 232 | fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte*height; 233 | fileHead.bfReserved1 = 0; 234 | fileHead.bfReserved2 = 0; 235 | 236 | //bfOffBits是图像文件前3个部分所需空间之和 237 | fileHead.bfOffBits = 54 + colorTablesize; 238 | //写文件头进文件 239 | fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp); 240 | 241 | //申请位图信息头结构变量,填写信息头信息 242 | BITMAPINFOHEADER infohead; 243 | infohead.biBitCount = biBitCount; 244 | infohead.biClrImportant = 0; 245 | infohead.biClrUsed = 0; 246 | infohead.biCompression = 0; 247 | infohead.biHeight = height; 248 | infohead.biPlanes = 1; 249 | infohead.biSize = 40; 250 | infohead.biSizeImage = lineByte*height; 251 | infohead.biWidth = width ; 252 | infohead.biXPelsPerMeter = 0; 253 | infohead.biYPelsPerMeter = 0; 254 | 255 | //写位图信息头进内存 256 | fwrite(&infohead, sizeof(BITMAPINFOHEADER), 1, fp); 257 | //如果灰度图像,有颜色表,写入文件 258 | if (biBitCount == 8) 259 | fwrite(pColorTable, sizeof(RGBQUAD), 256, fp); 260 | 261 | //写位图数据进文件 262 | fwrite(imgBuf, height*lineByte, 1, fp); 263 | 264 | //关闭文件 265 | fclose(fp); 266 | return 1; 267 | 268 | } 269 | ``` 270 | 271 | 这样就可以获得一张图片的rgb值了,部分如下: 272 | ``` 273 | 16, 274 | 16, 275 | 16, 276 | 16, 277 | 52, 278 | 52, 279 | 16, 280 | 16, 281 | 16, 282 | 16, 283 | 16, 284 | 16, 285 | 16, 286 | 16, 287 | 16, 288 | 16, 289 | 16, 290 | 52, 291 | 52 292 | ``` 293 | 因为目前还没有实现磁盘驱动,没有文件系统,我们只能把值硬编码进系统中。 294 | 295 | bmp.h 296 | 297 | ![unsignedchar](https://github.com/CasterWx/AntzOS/blob/master/screen/load_char.png?raw=true) 298 | 299 | 一个数万项的unsigned char数组,再上面程序中我们同样可以得到图片的长宽信息,那么下一步就是在系统中显示图片了。 300 | ```c 301 | #include 302 | 303 | void to_printf_dijkstra(int sx,int sy){ 304 | // sx,sy是屏幕分辨率 305 | int x, y; 306 | int k = 0 ; 307 | for (y = 0; y < 115; y++) { //图片宽100,高115个像素 308 | for (x = 0; x < 100; x++){ 309 | printf_(sx , bmp_b[k] , x+sx-100, y, x+sx-100, y); 310 | k++; 311 | } 312 | } 313 | } 314 | ``` 315 | 只需要在一个命令响应中调用这个函数即可了,这就是效果了(真机测试也是同样)。 316 | 317 | ![效果](https://github.com/CasterWx/AntzOS/blob/master/screen/a.gif?raw=true) 318 | 319 | 不知道你有没有考虑到这个问题,这个115x100的图片有11500个像素点,这是一张很小很小的图片了,如果我们用一张正常一点的尺寸较大的图片,比如500x400,那就是200000个像素点了,这对没有实现磁盘驱动,靠硬编码进系统的antz压力非常大,所以此处加载图片虽然成功了,但实际上还远不能入此,这只是一个思想,当我可以实现硬盘驱动和文件系统之后,我们可以把上面bmp文件的rgb读取的程序直接放在内核中成为API,然后调用起来就方便很多了,对于那种超大图片,可以靠这样实现分步显示。 320 | -------------------------------------------------------------------------------- /task/timer.c: -------------------------------------------------------------------------------- 1 | /* 定时器 */ 2 | 3 | #include 4 | 5 | #define PIT_CTRL 0x0043 6 | #define PIT_CNT0 0x0040 7 | 8 | struct TIMERCTL timerctl; 9 | 10 | void init_pit(void) 11 | { 12 | io_out8(PIT_CTRL, 0x34); 13 | io_out8(PIT_CNT0, 0x9c); 14 | io_out8(PIT_CNT0, 0x2e); 15 | 16 | timerctl.count = 0; 17 | timerctl.flag = 0 ; 18 | return; 19 | } 20 | 21 | 22 | char * arr[] = { 23 | " ", 24 | " ", 25 | " ", 26 | " ", 27 | " ", 28 | " ", 29 | " ", 30 | " ", 31 | " ", 32 | " ", 33 | " ", 34 | " ", 35 | " ", 36 | " ", 37 | " ", 38 | " ", 39 | "package goddrinksjava;", 40 | "/**", 41 | "* The program GoddrinksJava implements", 42 | "* an application that creates an empty ", 43 | "* simulated world with no meaning or ", 44 | "* purpose.", 45 | "@ author = AntzUhl", 46 | "*/", 47 | "public class GodDrinksJava {", 48 | " public static void main(String []args){", 49 | " Thing me=new Lovable(Me,0,true,-1,false)", 50 | " Thing you=new Lovable(You,0,false,-1,false)", 51 | " World world=new World(5);", 52 | " world.addThing(me);", 53 | " world.addThing(you);", 54 | " ", 55 | " ", 56 | " if(me instanceif PointSet)", 57 | " you.addAttribute(me.getDimensions());", 58 | " me.resetDimensions();", 59 | " }", 60 | " if(me instanceif Circle)", 61 | " you.addAttribute(me.getCircumference());", 62 | " me.resetCircumference();", 63 | " }", 64 | " if(me instanceif SineWave)", 65 | " you.addAction(\"sit\",me.getTangent(you.XPosition))", 66 | " }", 67 | " if(me instanceif Sequence)", 68 | " me.addAction(you.toLimit();", 69 | " }", 70 | " ", 71 | " ", 72 | " me.toggleCurrent();", 73 | " me.canSee(false);", 74 | " me.addFelling(\"dizzy\");", 75 | " world.timeTravelForTwo(\"AD\",617,me.you);", 76 | " world.timeTravelForTwo(\"BC\",3691,me.you);", 77 | " world.unite(me,you);", 78 | " ", 79 | " ", 80 | " if(me.getNumStimulationsAvailable() >=", 81 | " you.getNumStimulationsNeeded()){", 82 | " you.setSatisfaction(me.toSatisfaction());", 83 | " }", 84 | " if(you.getFeelingIndex(\"happy\")!=-1){", 85 | " me.requestExecution(\"world\");", 86 | " }", 87 | " world.lockThing(me);", 88 | " world.lockThing(you)", 89 | " ", 90 | " ", 91 | " if(me instanceof Eggplant){", 92 | " you.addAttribute(me.getNutrientts());", 93 | " me.resetNutrients();", 94 | " }", 95 | " if(me instanceof Tomato){", 96 | " you.addAttribute(me.getAntioxidants());", 97 | " me.resetAntioxidants();", 98 | " }", 99 | " if(me instanceof TabbyCat){", 100 | " me.purr();", 101 | " }", 102 | " if(world.getGod().equal(me)){", 103 | " me.setProof(you.toProof());", 104 | " }", 105 | " ", 106 | " ", 107 | " me.toggleGender();", 108 | " ", 109 | " world.procreate(me,you);", 110 | " ", 111 | " me.toggleRoleBDSM();", 112 | " ", 113 | " world.makeHigh(me);", 114 | " ", 115 | " world.makeHigh(you);", 116 | " ", 117 | " if(me.getSenseIndex(\"vibration\")){", 118 | " me.addFelling(\"complete\");", 119 | " }", 120 | " ", 121 | " world.unlock(you);", 122 | " ", 123 | " world.removeThing(you);", 124 | " ", 125 | " me.lookFor(you,world);", 126 | " ", 127 | " me.lookFor(you,world);", 128 | " ", 129 | " me.lookFor(you,world);", 130 | " ", 131 | " me.lookFor(you,world);", 132 | " ", 133 | " me.lookFor(you,world);", 134 | " ", 135 | " me.lookFor(you,world);", 136 | " ", 137 | " me.lookFor(you,world);", 138 | " ", 139 | " if(me.getMemory().isErasable()){", 140 | " me.removeFeeling(\"dishertened\");", 141 | " }", 142 | " ", 143 | " try{", 144 | " me.setOpinion(me.getOpinionIndex(\"you are here\"),false);", 145 | " }", 146 | " catch(IllegalArgumentException e){", 147 | " world.announce(\"God is always true.\")", 148 | " }", 149 | " ", 150 | " ", 151 | " ", 152 | " ", 153 | " ", 154 | " ", 155 | " ", 156 | " world.runExecution();", 157 | " ", 158 | " world.runExecution();", 159 | " ", 160 | " world.runExecution();", 161 | " ", 162 | " world.runExecution();", 163 | " ", 164 | " world.runExecution();", 165 | " ", 166 | " world.runExecution();", 167 | " ", 168 | " world.runExecution();", 169 | " ", 170 | " world.runExecution();", 171 | " ", 172 | " world.runExecution();", 173 | " ", 174 | " world.runExecution();", 175 | " ", 176 | " world.runExecution();", 177 | " ", 178 | " world.runExecution();", 179 | " ", 180 | " world.runExecution();", 181 | " ", 182 | " world.runExecution();", 183 | " ", 184 | " world.runExecution();", 185 | " ", 186 | " world.runExecution();", 187 | " ", 188 | " world.runExecution();", 189 | " ", 190 | " world.runExecution();", 191 | " ", 192 | " world.runExecution();", 193 | " ", 194 | " world.runExecution();", 195 | " ", 196 | " world.runExecution();", 197 | " ", 198 | " world.runExecution();", 199 | " ", 200 | " world.runExecution();", 201 | " ", 202 | " world.runExecution();", 203 | " ", 204 | " world.runExecution();", 205 | " ", 206 | " world.runExecution();", 207 | " ", 208 | " world.runExecution();", 209 | " ", 210 | " world.runExecution();", 211 | " ", 212 | " world.announce(\"1\",\"de\")", 213 | " world.announce(\"2\",\"es\")", 214 | " world.announce(\"3\",\"fr\")", 215 | " world.announce(\"4\",\"kr\")", 216 | " world.announce(\"5\",\"se\")", 217 | " world.announce(\"6\",\"cn\")", 218 | " ", 219 | " world.runExecution();", 220 | " ", 221 | " ", 222 | " ", 223 | " ", 224 | " if(world.isExecutableBy(me)){", 225 | " you.setExecution(me.toExecution())", 226 | " }", 227 | " ", 228 | " if(world.getThingIndex(you)!=-1){", 229 | " world.runExecution()", 230 | " }", 231 | " ", 232 | " me.escape(world)", 233 | " ", 234 | " ", 235 | " me.learnTopic(\"love\")", 236 | " ", 237 | " me.takeExamTopic(\"love\")", 238 | " ", 239 | " me.getAlgebraicExpression(\"love\")", 240 | " ", 241 | " me.escape(\"love\")", 242 | " ", 243 | " ", 244 | " ", 245 | " ", 246 | " ", 247 | " ", 248 | " ", 249 | " ", 250 | " ", 251 | " ", 252 | " ", 253 | " world.execute(me);", 254 | " ", 255 | " ", 256 | " ", 257 | " ", 258 | " ", 259 | " ", 260 | " ", 261 | " ", 262 | " ", 263 | " ", 264 | " ", 265 | " ", 266 | " ", 267 | " ", 268 | " ", 269 | " ", 270 | " ", 271 | " ", 272 | " ", 273 | " ", 274 | }; 275 | int i,j = 0 ; 276 | int old_time = 0; 277 | void init_data(void){ 278 | i= 0; 279 | j= 0; 280 | } 281 | 282 | void inthandler20(int *esp) 283 | { 284 | io_out8(PIC0_OCW2, 0x60); /* 把IRQ-00信号接收完了的信息通知给PIC */ 285 | timerctl.count++; 286 | old_time ++ ; 287 | struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; 288 | // 绘制 289 | if((timerctl.flag==1)&&(old_time%10==0)){ 290 | // 65 291 | print_area(binfo->vram, binfo->scrnx,COL8_000000,0, 0 ,binfo->scrnx,binfo->scrny); 292 | for (i=0;i<45;i++){ 293 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/4-110,i*19+20, COL8_00FF00, arr[j+i]); 294 | } 295 | j += 1 ; 296 | if(j>=205){ 297 | timerctl.flag = 0 ; 298 | init_screen8(binfo->vram, binfo->scrnx, binfo->scrny); 299 | print_string(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "Terminal-Antz"); 300 | print_string(binfo->vram, binfo->scrnx, 0, 0, COL8_000000, "Terminal-Antz"); 301 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2-60, 0, COL8_000000, "|-|o|x|"); 302 | print_string(binfo->vram, binfo->scrnx, 4, 19, COL8_FFFFFF, "AntzOS> SayHello()"); 303 | print_string(binfo->vram, binfo->scrnx, 4, 38, COL8_FFFFFF, "Hello My AntzOs."); 304 | print_string(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>"); 305 | } 306 | } 307 | return; 308 | } 309 | /* 310 | int print_x = binfo->scrnx -70 ; 311 | int print_y = binfo->scrny -40 ; 312 | 313 | print_area(binfo->vram, binfo->scrnx,COL8_FFFFFF,print_x,print_y,print_x+60,print_y+35); 314 | 315 | print_area(binfo->vram, binfo->scrnx,COL8_FFFFFF,print_x+10,print_y-20,print_x+20,print_y); 316 | print_area(binfo->vram, binfo->scrnx,COL8_008400,print_x+12,print_y-17,print_x+18,print_y); 317 | 318 | print_area(binfo->vram, binfo->scrnx,COL8_FFFFFF,print_x+40,print_y-20,print_x+50,print_y); 319 | print_area(binfo->vram, binfo->scrnx,COL8_008400,print_x+42,print_y-17,print_x+48,print_y); 320 | 321 | 322 | print_area(binfo->vram, binfo->scrnx,timerctl.count%15,print_x+13,print_y+13,print_x+18,print_y+22); 323 | print_area(binfo->vram, binfo->scrnx,timerctl.count%15,print_x+43,print_y+13,print_x+48,print_y+22); 324 | 325 | print_area(binfo->vram, binfo->scrnx,COL8_840000,print_x+22,print_y+25,print_x+40,print_y+30); 326 | 327 | print_area(binfo->vram, binfo->scrnx,timerctl.count%15 ,print_x+27,print_y+25,print_x+30,print_y+27); 328 | print_area(binfo->vram, binfo->scrnx,timerctl.count%14+1,print_x+30,print_y+25,print_x+33,print_y+27); 329 | */ 330 | -------------------------------------------------------------------------------- /main/shell_2.md: -------------------------------------------------------------------------------- 1 | # 自制操作系统Antz day11——实现shell(下)命令响应 2 | > 我已经规范了系统代码风格,类似于按照linux分包,把各部分功能区分开了 3 | ### [Antz系统更新地址](https://www.cnblogs.com/LexMoon/category/1262287.html) 4 | 5 | ### [Linux内核源码分析地址](https://www.cnblogs.com/LexMoon/category/1267413.html) 6 | 7 | ### [Github项目地址](https://github.com/CasterWx/AntzOS) 8 | 9 | ### 在之前的任务中,我们已经通过直接操作显卡驱动完成了简单的图形化。 10 | ### 需要了解之前的部分: 11 | > 直接操作显卡请参考day03 12 | 13 | > 简单图形化的实现请参考day09 14 | 15 | > 键盘按键中断响应请参考day10 16 | 17 | > Makefile 18 | 19 | ### 项目目录 20 | 21 | ![s](https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_project.jpg) 22 | 23 | ## 一 . 如何实现命令缓存 24 | 25 | ### 在之前已经完成了键盘的响应工作,但这种响应却是有很大的问题,比如说对于一次按键的两次中断处理。后来我把两种中断都加入了响应判断中,这样就不会有之前第10天所提到的bug了。 26 | 27 | ### * 在替换函数中完成识别。修改如下 28 | ``` 29 | char* replace_char(char s[40]){ 30 | char *chr = "$" ; 31 | if((strcmp(s,"1E")==0)||(strcmp(s,"9E")==0)){ 32 | chr = "a" ; 33 | }else if((strcmp(s,"30")==0)||(strcmp(s,"B0")==0)){ 34 | chr = "b" ; 35 | } 36 | ... // 省略 37 | return chr ; 38 | ``` 39 | ### * 这里是一些功能按键的识别修改 40 | ``` 41 | // Enter -> 回车键 响应之前缓存的命令 换行 42 | if((strcmp(s,"1C")==0)||(strcmp(s,"9C")==0)){ 43 | action_command(binfo); //响应命令 44 | write_x = 58 ; //下面是换行 45 | write_y += 19 ; 46 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 47 | } 48 | // F1 -> 终端刷新 类似于clear命令 49 | else if((strcmp(s,"3B")==0)||(strcmp(s,"BB")==0)){ //关于F1的响应中断 50 | sprintf(command,"%s",""); // 命令缓存清空 51 | flag = 0 ; // 按键模式回复默认,这个看第10天,本质目的是为了处理一次按键的两次终端 52 | new_pe(binfo); // 通过操作显存直接刷新当前终端 53 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 54 | } 55 | // Backspace -> 删格键 56 | else if(strcmp(s,"0E")==0){ 57 | // 回退 58 | write_x -= 8 ; 59 | boxfill8(binfo->vram, binfo->scrnx , COL8_000000, write_x, write_y, write_x+19, write_y+19); 60 | if(write_x<=58){ 61 | write_x = 146 ; 62 | write_y -= 19 ; 63 | } 64 | } 65 | ``` 66 | ### 这些就是按键识别上目前修改的内容了。 67 | 68 | ### 接下来我们要添加一个功能,在每次按键之后,不但在屏幕上显示这个键,而且将他缓存在缓冲区,在下次回车的时候进行识别,并清空。 69 | 70 | ### 先来看一个简单的demo 71 | 72 | ``` 73 | // command数组就是命令缓存区 74 | char command[100] = ""; 75 | 76 | void add_command(char *s) { 77 | sprintf(command,"%s%s",command,s); 78 | } 79 | 80 | void action_command(){ 81 | // 响应 82 | } 83 | 84 | ``` 85 | 86 | ## 二 . 实现 87 | 88 | ### command就是一个命令缓存数组,每次按键之后调用add_command()命令将这次的按键保存。 89 | 90 | ### sprintf()这个函数是字符串格式化命令,主要功能是把格式化的数据写入某个字符串中。sprintf 是个变参函数。使用sprintf 对于写入buffer的字符数是没有限制的,这就存在了buffer溢出的可能性。 91 | 92 | ### 我们使用sprintf函数直接在command后面添加了s字符。 93 | 94 | ### 那么在下次按下Enter的时候,我们只需要调用action_command,并且在里面识别是什么命令,然后做出合适的响应即可。 95 | 96 | ### 来看看完整的命令缓冲区实现。 97 | 98 | ``` 99 | // 指令缓存,但是因为中断响应的时间问题,终端输入速度要非常慢 100 | char command[100] = ""; 101 | void add_command(char *s) { 102 | 103 | if(strcmp(s," ")==0){ 104 | sprintf(command,"%s%s",command,""); 105 | }else if(strcmp(s,"$")){ 106 | //忽略这种错误输入 107 | }else { 108 | sprintf(command,"%s%s",command,s); 109 | } 110 | } 111 | 112 | void action_command(struct BOOTINFO *binfo){ 113 | // action command 响应命令 114 | // ls命令 115 | // data命令 116 | if(strcmp(command,"data")==0){ 117 | // get new data; 118 | write_y += 19 ; 119 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS in 2018"); 120 | }else if(strcmp(command,"cls")==0){ 121 | flag = 0 ; 122 | new_pe(binfo); 123 | }else if(strcmp(command,"version")==0){ 124 | write_y += 19 ; 125 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Antz.version.1.1"); 126 | }else if(strcmp(command,"help")==0){ 127 | // help内容过多,显示在图形化界面区域 128 | 129 | }else if(sizeof(command)>=1){ 130 | write_y += 19 ; 131 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Not Found"); 132 | } 133 | // 命令缓存清除 134 | sprintf(command,"%s",""); 135 | } 136 | 137 | ``` 138 | 139 | ### 现在使用Makefile来生成这个支持命令的img镜像。 140 | ``` 141 | make img 142 | ``` 143 | ### 使用虚拟机打开镜像,结果如下 144 | ![os](https://www.cnblogs.com/images/cnblogs_com/LexMoon/1246510/o_122.jpg) 145 | 146 | 147 | ### 终端主要代码如下: 148 | ``` 149 | 150 | int write_x = 55 ; 151 | int write_y = 57 ; 152 | 153 | char* replace_char(char s[40]){ 154 | char *chr = "$" ; 155 | if((strcmp(s,"1E")==0)||(strcmp(s,"9E")==0)){ 156 | chr = "a" ; 157 | }else if((strcmp(s,"30")==0)||(strcmp(s,"B0")==0)){ 158 | chr = "b" ; 159 | }else if((strcmp(s,"2E")==0)||(strcmp(s,"AE")==0)){ 160 | chr = "c" ; 161 | }else if((strcmp(s,"20")==0)||(strcmp(s,"A0")==0)){ 162 | chr = "d" ; 163 | }else if((strcmp(s,"12")==0)||(strcmp(s,"92")==0)){ 164 | chr = "e" ; 165 | }else if((strcmp(s,"21")==0)||(strcmp(s,"A1")==0)){ 166 | chr = "f" ; 167 | }else if((strcmp(s,"22")==0)||(strcmp(s,"A2")==0)){ 168 | chr = "g" ; 169 | }else if((strcmp(s,"23")==0)||(strcmp(s,"A3")==0)){ 170 | chr = "h" ; 171 | }else if((strcmp(s,"17")==0)||(strcmp(s,"97")==0)){ 172 | chr = "i" ; 173 | }else if((strcmp(s,"24")==0)||(strcmp(s,"A4")==0)){ 174 | chr = "j" ; 175 | }else if((strcmp(s,"25")==0)||(strcmp(s,"A5")==0)){ 176 | chr = "k" ; 177 | }else if((strcmp(s,"26")==0)||(strcmp(s,"A6")==0)){ 178 | chr = "l" ; 179 | }else if((strcmp(s,"32")==0)||(strcmp(s,"B2")==0)){ 180 | chr = "m" ; 181 | }else if((strcmp(s,"31")==0)||(strcmp(s,"B1")==0)){ 182 | chr = "n" ; 183 | }else if((strcmp(s,"18")==0)||(strcmp(s,"98")==0)){ 184 | chr = "o" ; 185 | }else if((strcmp(s,"19")==0)||(strcmp(s,"99")==0)){ 186 | chr = "p" ; 187 | }else if((strcmp(s,"10")==0)||(strcmp(s,"90")==0)){ 188 | chr = "q" ; 189 | }else if((strcmp(s,"13")==0)||(strcmp(s,"93")==0)){ 190 | chr = "r" ; 191 | }else if((strcmp(s,"1F")==0)||(strcmp(s,"9F")==0)){ 192 | chr = "s" ; 193 | }else if((strcmp(s,"14")==0)||(strcmp(s,"94")==0)){ 194 | chr = "t" ; 195 | }else if((strcmp(s,"16")==0)||(strcmp(s,"96")==0)){ 196 | chr = "u" ; 197 | }else if((strcmp(s,"2F")==0)||(strcmp(s,"AF")==0)){ 198 | chr = "v" ; 199 | }else if((strcmp(s,"11")==0)||(strcmp(s,"91")==0)){ 200 | chr = "w" ; 201 | }else if((strcmp(s,"2D")==0)||(strcmp(s,"AD")==0)){ 202 | chr = "x" ; 203 | }else if((strcmp(s,"15")==0)||(strcmp(s,"95")==0)){ 204 | chr = "y" ; 205 | }else if((strcmp(s,"2C")==0)||(strcmp(s,"AC")==0)){ 206 | chr = "z" ; 207 | }else if((strcmp(s,"39")==0)||(strcmp(s,"B9")==0)){ 208 | chr = " " ; 209 | } 210 | return chr ; 211 | } 212 | 213 | int flag = 1 ; 214 | 215 | // 指令缓存,但是因为中断响应的时间问题,终端输入速度要非常慢 216 | char command[100] = ""; 217 | void add_command(char *s) { 218 | /* 219 | if(strcmp(s," ")==0){ 220 | sprintf(command,"%s%s",command,""); 221 | }else if(strcmp(s,"$")){ 222 | //忽略这种错误输入 223 | }else { 224 | } 225 | */ 226 | sprintf(command,"%s%s",command,s); 227 | 228 | } 229 | 230 | void action_command(struct BOOTINFO *binfo){ 231 | // action command 232 | // ls 233 | // data 234 | if(strcmp(command,"data")==0){ 235 | // get new data; 236 | write_y += 19 ; 237 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS in 2018"); 238 | }else if(strcmp(command,"cls")==0){ 239 | flag = 0 ; 240 | new_pe(binfo); 241 | }else if(strcmp(command,"version")==0){ 242 | write_y += 19 ; 243 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Antz.version.1.1"); 244 | }else if(strcmp(command,"help")==0){ 245 | // help内容过多,显示在图形化界面区域 246 | }else if(sizeof(command)>=1){ 247 | write_y += 19 ; 248 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Not Found"); 249 | } 250 | // 命令缓存清除 251 | sprintf(command,"%s",""); 252 | } 253 | 254 | void key(struct BOOTINFO *binfo,char s[40]){ 255 | if((strcmp(s,"1C")==0)||(strcmp(s,"9C")==0)){ 256 | action_command(binfo); 257 | write_x = 58 ; 258 | write_y += 19 ; 259 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 260 | }else if((strcmp(s,"3B")==0)||(strcmp(s,"BB")==0)){ //关于F1的响应中断 261 | sprintf(command,"%s",""); 262 | flag = 0 ; 263 | new_pe(binfo); 264 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 265 | }else if(strcmp(s,"0E")==0){ 266 | // 回退 267 | write_x -= 8 ; 268 | boxfill8(binfo->vram, binfo->scrnx , COL8_000000, write_x, write_y, write_x+19, write_y+19); 269 | if(write_x<=58){ 270 | write_x = 146 ; 271 | write_y -= 19 ; 272 | } 273 | }else { 274 | //putfonts8_asc(binfo->vram, binfo->scrnx, write_x, write_y, COL8_FFFFFF, s); 275 | putfonts8_asc(binfo->vram, binfo->scrnx, write_x, write_y, COL8_FFFFFF, replace_char(s)); 276 | add_command(replace_char(s)); 277 | write_x += 8 ; 278 | // 添加响应区 279 | //清除 280 | //boxfill8(binfo->vram, binfo->scrnx, COL8_008400 , 300 ,240 ,310 ,250); 281 | //打印字符 Only use debug 282 | //putfonts8_asc(binfo->vram, binfo->scrnx, 300, 240 ,COL8_000000, s) ; 283 | } 284 | if(write_x>148){ 285 | write_x = 58 ; 286 | write_y += 19 ; 287 | //putfonts8_asc(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>"); 288 | } 289 | if(write_y>180){ 290 | new_pe(binfo); 291 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 292 | } 293 | 294 | } 295 | 296 | void main(void) 297 | { 298 | struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; 299 | char s[40], mcursor[256], keybuf[32], mousebuf[128]; 300 | int mx, my, i; 301 | 302 | init_gdtidt(); 303 | init_pic(); 304 | io_sti(); /* PIC的初始化已经完成*/ 305 | 306 | fifo8_init(&keyfifo, 32, keybuf); 307 | fifo8_init(&mousefifo, 128, mousebuf); 308 | io_out8(PIC0_IMR, 0xf9); /* 开放PIC1和键盘中断(11111001) */ 309 | io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */ 310 | 311 | init_keyboard(); 312 | 313 | init_palette(); 314 | init_screen8(binfo->vram, binfo->scrnx, binfo->scrny); 315 | 316 | putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "Terminal-Antz"); 317 | putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_000000, "Terminal-Antz"); 318 | putfonts8_asc(binfo->vram, binfo->scrnx, 107, 0, COL8_000000, "|-|o|x|"); 319 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, 19, COL8_FFFFFF, "AntzOS> SayHello()"); 320 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, 38, COL8_FFFFFF, "Hello My AntzOs."); 321 | putfonts8_asc(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>_"); 322 | 323 | 324 | for (;;) { 325 | io_cli(); 326 | if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) { 327 | io_stihlt(); 328 | } else { 329 | if (fifo8_status(&keyfifo) != 0) { 330 | 331 | i = fifo8_get(&keyfifo); 332 | io_sti(); 333 | sprintf(s, "%02X", i); 334 | if (flag){ 335 | key(binfo,s); 336 | } 337 | if(flag==1){ 338 | flag = 0 ; 339 | }else { 340 | flag = 1 ; 341 | } 342 | } 343 | } 344 | } 345 | } 346 | 347 | void new_pe(struct BOOTINFO *binfo){ 348 | write_x = 58 ; 349 | write_y = 19 ; 350 | // 右边并没有保存 351 | init_screen8(binfo->vram, binfo->scrnx, binfo->scrny); 352 | putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "Terminal-Antz"); 353 | putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_000000, "Terminal-Antz"); 354 | putfonts8_asc(binfo->vram, binfo->scrnx, 107, 0, COL8_000000, "|-|o|x|"); 355 | // 此处保留此输出,交给调用者自己 356 | // putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 357 | } 358 | 359 | 360 | ``` -------------------------------------------------------------------------------- /main/bootpack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern struct FIFO8 keyfifo, mousefifo; 6 | void init_keyboard(void); 7 | 8 | void new_pe(struct BOOTINFO *binfo); 9 | 10 | int write_x = 60 ; 11 | int write_y = 57 ; 12 | // int flag = 1 ; 13 | int x_move = 0 ; 14 | // 指令缓存,但是因为中断响应的时间问题,终端输入速度要非常慢 15 | char command[100] = ""; 16 | int command_index = 0 ; 17 | void add_command(char *s) { 18 | sprintf(command,"%s%s",command,s); 19 | command_index++ ; 20 | } 21 | 22 | // vim输入的数据,根据回车来分隔 23 | struct vim_input{ 24 | char vim_char[200] ; 25 | int len ; 26 | struct vim_input * next ; 27 | } ; 28 | 29 | // 初始40行缓存 30 | struct vim_input mlist[40] ; 31 | int vim_index = 0 ; 32 | 33 | 34 | // vim之前保存x,y 35 | int last_x = 0 ; 36 | int last_y = 0 ; 37 | void action_command(struct BOOTINFO *binfo){ 38 | // action command 39 | // ls 40 | // data 41 | if(strcmp(command,"data")==0){ 42 | // get new data; 43 | write_y += 19 ; 44 | print_string(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS in 2018"); 45 | }else if(strcmp(command,"reset")==0){ 46 | // 重置 47 | write_x = 60 ; 48 | write_y = 19 ; 49 | // 右边并没有保存 50 | init_screen8(binfo->vram, binfo->scrnx, binfo->scrny); 51 | print_string(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "Terminal-Antz"); 52 | print_string(binfo->vram, binfo->scrnx, 0, 0, COL8_000000, "Terminal-Antz"); 53 | print_string(binfo->vram, binfo->scrnx, 107, 0, COL8_000000, "|-|o|x|"); 54 | }else if(strcmp(command,"vim")==0){ 55 | /* 56 | * @author : CasterWx 57 | * @time : 2019/3/19/16:32 58 | * @content : 经过思考之后,决定将vim_input结构体来存储输入数据,在回车后接下来的数据存储到下一个节点。 59 | */ 60 | // vim edit 61 | // vim启动时刷新右半区域显存 62 | print_area(binfo->vram, binfo->scrnx , COL8_000000, binfo->scrnx/2 + 3, 0, binfo->scrnx-3, binfo->scrnx-3); 63 | // 初始化vim输入指针 64 | print_string(binfo->vram,binfo->scrnx,162,2,COL8_00FF00,"Vim :"); 65 | x_move = binfo->scrnx/2 - 52 ; 66 | last_y = write_y + 19 ; 67 | write_x = 60 ; 68 | write_y = 2 ; 69 | 70 | // 清空过去的vim输入缓存 清空vim_input 71 | vim_index = 0 ; 72 | }else if(strcmp(command,"dijkstra")==0){ 73 | to_printf_dijkstra(); 74 | }else if(strcmp(command,"pdd")==0){ 75 | to_printf_pdd(); 76 | }else if(strcmp(command,"world.execute.me")==0){ 77 | timerctl.flag = 1 ; 78 | init_data(); 79 | }else if(strcmp(command,"cls")==0){ 80 | // flag = 0 ; 81 | new_pe(binfo); 82 | print_string(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "New PE:"); 83 | }else if(strcmp(command,"version")==0){ 84 | write_y += 19 ; 85 | print_string(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Antz.version.2.0"); 86 | }else if(strcmp(command,"help")==0){ 87 | // help内容过多,显示在图形化界面区域 88 | print_area(binfo->vram, binfo->scrnx , COL8_000000, binfo->scrnx/2 + 3, 0, binfo->scrnx-3, binfo->scrnx-3); 89 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2+5, 2+19, COL8_00FF00, " He was stabbed in the throat.He died"); //21 90 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2+5, 21+19, COL8_00FF00, "almost instantly.Although I hadn't seen"); 91 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2+5, 40+19, COL8_00FF00, "him in more than ten years, I know I"); 92 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2+5, 59+19, COL8_00FF00, "will miss him forever."); 93 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2+5, 78+19, COL8_00FF00, " AntzOs-10/16"); 94 | }else if(strcmp(command,"vimshow")==0){ 95 | // 显示vim_input中内容 96 | char myline[] = "line is "; 97 | 98 | sprintf(myline,"%s%4d",myline,vim_index); 99 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2, binfo->scrnx/2+19, COL8_FFFFFF, myline); //21 100 | 101 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2+5, 5, COL8_FFFFFF, "Old Vim Log:"); //21 102 | 103 | int index_my_vim = 0 ; 104 | for (index_my_vim=0;index_my_vimvram, binfo->scrnx, binfo->scrnx/2+5, 31+index_my_vim*19, COL8_FFFFFF, mlist[index_my_vim].vim_char); //21 106 | } 107 | }else if(sizeof(command)>=1){ 108 | write_y += 19 ; 109 | print_string(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "Not Found"); 110 | } 111 | // 命令缓存清除 112 | sprintf(command,"%s",""); 113 | } 114 | 115 | void key(struct BOOTINFO *binfo,char s[40]){ 116 | if((strcmp(s,"1C")==0)){ // enter 117 | if(x_move!=0){ 118 | // 右边 119 | print_area(binfo->vram, binfo->scrnx ,COL8_000000,x_move + write_x,write_y,x_move+write_x+8, write_y+19); 120 | write_x = 60 ; 121 | write_y += 19 ; 122 | }else { 123 | // 左边 124 | print_area(binfo->vram, binfo->scrnx ,COL8_000000,x_move + write_x,write_y,x_move+write_x+8, write_y+19); 125 | action_command(binfo); 126 | write_x = 60 ; 127 | write_y += 19 ; 128 | if (x_move==0) 129 | print_string(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 130 | } 131 | vim_index ++ ; 132 | }else if((strcmp(s,"01")==0)){ 133 | if (x_move!=0){ 134 | print_area(binfo->vram, binfo->scrnx ,COL8_000000,x_move + write_x,write_y,x_move+write_x+8, write_y+19); 135 | x_move = 0 ; 136 | write_y = last_y ; 137 | print_string(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 138 | write_x = 60 ; 139 | } 140 | }else if((strcmp(s,"0F")==0)){ 141 | // 关于tab 0F 8F 142 | print_string(binfo->vram, binfo->scrnx, x_move+write_x, write_y, COL8_FFFFFF, " "); 143 | write_x += 8 ; 144 | border(binfo); 145 | print_string(binfo->vram, binfo->scrnx, x_move+write_x, write_y, COL8_FFFFFF, " "); 146 | write_x += 8 ; 147 | border(binfo); 148 | print_string(binfo->vram, binfo->scrnx, x_move+write_x, write_y, COL8_FFFFFF, " "); 149 | write_x += 8 ; 150 | border(binfo); 151 | }else if((strcmp(s,"3B")==0)){ //关于F1的响应中断 152 | timerctl.flag = 0 ; 153 | sprintf(command,"%s",""); 154 | // flag = 0 155 | x_move = 0 ; 156 | new_pe(binfo); 157 | print_string(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 158 | sprintf(command,"%s",""); 159 | }else if(strcmp(s,"0E")==0){ 160 | // 回退 161 | print_area(binfo->vram, binfo->scrnx ,COL8_000000,x_move + write_x,write_y,x_move+write_x+8, write_y+19); 162 | int len = strlen(command); 163 | command[len - 1] = '\0'; 164 | write_x -= 8 ; 165 | print_area(binfo->vram, binfo->scrnx , COL8_000000, x_move + write_x, write_y, x_move+write_x+8, write_y+19); 166 | if(x_move!=0){ 167 | // 正在右边界 168 | if((x_move+write_x)<=binfo->scrnx/2) { 169 | write_x = binfo->scrnx - 8; 170 | write_y -= 19 ; 171 | } 172 | 173 | }else if(x_move==0){ 174 | // 正在左边界 175 | if(write_x<=9) { 176 | write_x = binfo->scrnx/2-12 ; 177 | write_y -= 19 ; 178 | } 179 | } 180 | 181 | }else { 182 | //putfonts8_asc(binfo->vram, binfo->scrnx, write_x, write_y, COL8_FFFFFF, s); 183 | // 非功能键则为输出键 184 | char *in = replace_char(s) ; 185 | if(strcmp(in,"")==0){ 186 | 187 | }else { 188 | print_area(binfo->vram, binfo->scrnx, COL8_000000, x_move+write_x, write_y, x_move+write_x+8, write_y+19); 189 | print_string(binfo->vram, binfo->scrnx, x_move + write_x, write_y, COL8_FFFFFF, in); 190 | 191 | // vim内容记录 192 | if(x_move!=0){ 193 | sprintf(mlist[vim_index].vim_char,"%s%s",mlist[vim_index].vim_char,in) ; // 添加进去,但是为了在输出时不超过边界,选择 194 | } 195 | 196 | add_command(in); 197 | write_x += 8 ; 198 | } 199 | // 添加响应区 200 | //清除 201 | //boxfill8(binfo->vram, binfo->scrnx, COL8_008400 , 300 ,240 ,310 ,250); 202 | //打印字符 Only use debug 203 | //putfonts8_asc(binfo->vram, binfo->scrnx, 300, 240 ,COL8_000000, s) ; 204 | } 205 | border(binfo); 206 | } 207 | // 边界处理 208 | void border(struct BOOTINFO *binfo){ 209 | if (x_move==0){ 210 | // 左边 211 | if(write_x > binfo->scrnx/2-10){ 212 | write_x = 4 ; 213 | write_y += 19 ; 214 | //putfonts8_asc(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>"); 215 | } 216 | if(write_y > binfo->scrny-20){ 217 | new_pe(binfo); 218 | print_string(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 219 | } 220 | }else if(x_move!=0){ 221 | // vim模式 222 | if(write_x> binfo->scrnx-10-x_move){ 223 | write_x = 60 ; 224 | write_y += 19 ; 225 | } 226 | if(write_y>binfo->scrny-20){ 227 | write_y = 15 ; 228 | write_x = 60 ; 229 | print_area(binfo->vram, binfo->scrnx , COL8_000000, binfo->scrnx/2 + 3, 0, binfo->scrnx-3, binfo->scrnx-3); 230 | print_string(binfo->vram,binfo->scrnx,binfo->scrnx/2 + 3, 0,COL8_00FF00,"Vim :"); 231 | } 232 | } 233 | } 234 | 235 | void HariMain(void) 236 | { 237 | struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; 238 | char s[40], mcursor[256], keybuf[32], mousebuf[128]; 239 | int mx, my, i; 240 | 241 | init_gdtidt(); 242 | init_pic(); 243 | io_sti(); /* PIC的初始化已经完成*/ 244 | 245 | fifo8_init(&keyfifo, 32, keybuf); 246 | fifo8_init(&mousefifo, 128, mousebuf); 247 | 248 | 249 | init_pit(); 250 | 251 | io_out8(PIC0_IMR, 0xf8); /* 开放PIC1和键盘中断(11111001) */ 252 | io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */ 253 | 254 | init_keyboard(); 255 | 256 | init_palette(); 257 | 258 | while (timerctl.count/100<5) 259 | to_show(); 260 | 261 | 262 | print_area(binfo->vram, binfo->scrnx , COL8_FFFFFF , 0 , 0 , binfo->scrnx, binfo->scrny); 263 | init_screen8(binfo->vram, binfo->scrnx, binfo->scrny); 264 | 265 | print_string(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "Terminal-Antz"); 266 | print_string(binfo->vram, binfo->scrnx, 0, 0, COL8_000000, "Terminal-Antz"); 267 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2-60, 0, COL8_000000, "|-|o|x|"); 268 | 269 | print_string(binfo->vram, binfo->scrnx, 4, 19, COL8_FFFFFF, "AntzOS> SayHello()"); 270 | print_string(binfo->vram, binfo->scrnx, 4, 38, COL8_FFFFFF, "Hello My AntzOs."); 271 | print_string(binfo->vram, binfo->scrnx, 4, 57, COL8_FFFFFF, "AntzOS>"); 272 | // 1024x768 273 | for (;;) { 274 | int t = timerctl.count/100 ; 275 | sprintf(s, "runtime:%8ds", t); 276 | print_area(binfo->vram, binfo->scrnx, COL8_C6C6C6, 162, 0, 315, 14); 277 | print_string(binfo->vram, binfo->scrnx, 162, 0, COL8_840000, s) ; 278 | if (t%2==0){ 279 | print_string(binfo->vram, binfo->scrnx, x_move+write_x, write_y, COL8_FFFFFF, "|") ; 280 | }else { 281 | print_area(binfo->vram, binfo->scrnx, COL8_000000, x_move+write_x, write_y, x_move+write_x+8, write_y+19); 282 | } 283 | io_cli(); 284 | if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) { 285 | io_stihlt(); 286 | } else { 287 | if (fifo8_status(&keyfifo) != 0) { 288 | 289 | i = fifo8_get(&keyfifo); 290 | io_sti(); 291 | sprintf(s, "%02X", i); 292 | key(binfo,s); 293 | } else if (fifo8_status(&mousefifo) != 0) { 294 | i = fifo8_get(&mousefifo); 295 | io_sti(); 296 | } 297 | } 298 | } 299 | } 300 | 301 | void new_pe(struct BOOTINFO *binfo){ 302 | write_x = 60 ; 303 | write_y = 19 ; 304 | // 右边并没有保存 305 | print_area(binfo->vram, binfo->scrnx, COL8_000000, 3, 15, binfo->scrnx/2-3 , binfo->scrny-3); 306 | print_string(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "Terminal-Antz"); 307 | print_string(binfo->vram, binfo->scrnx, 0, 0, COL8_000000, "Terminal-Antz"); 308 | print_string(binfo->vram, binfo->scrnx, binfo->scrnx/2-60, 0, COL8_000000, "|-|o|x|"); 309 | // 此处保留此输出,交给调用者自己 310 | // putfonts8_asc(binfo->vram, binfo->scrnx, 4, write_y, COL8_FFFFFF, "AntzOS>"); 311 | } 312 | 313 | #define PORT_KEYDAT 0x0060 314 | #define PORT_KEYSTA 0x0064 315 | #define PORT_KEYCMD 0x0064 316 | #define KEYSTA_SEND_NOTREADY 0x02 317 | #define KEYCMD_WRITE_MODE 0x60 318 | #define KBC_MODE 0x47 319 | 320 | void wait_KBC_sendready(void) 321 | { 322 | /* 等待键盘准备 */ 323 | for (;;) { 324 | if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) { 325 | break; 326 | } 327 | } 328 | return; 329 | } 330 | 331 | void init_keyboard(void) 332 | { 333 | /* 初始化键盘 */ 334 | wait_KBC_sendready(); 335 | io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE); 336 | wait_KBC_sendready(); 337 | io_out8(PORT_KEYDAT, KBC_MODE); 338 | return; 339 | } 340 | -------------------------------------------------------------------------------- /include/bmp.h: -------------------------------------------------------------------------------- 1 | unsigned char bmp[60][108] = { 2 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 3 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 4 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 5 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 24, 24, 103, 145, 187, 230, 230, 230, 230, 230, 230, 230, 230, 187, 145, 66, 24, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 6 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 24, 109, 187, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 187, 103, 24, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 7 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 145, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 145, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 8 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 20, 21, 21, 21, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 145, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 109, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 9 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 21, 20, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 66, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 66, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 10 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 151, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 109, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 11 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 26, 61, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 30, 31, 31, 116, 87, 45, 45, 81, 158, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 187, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 12 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 37, 39, 39, 39, 39, 33, 33, 33, 39, 39, 39, 81, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 194, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 13 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 30, 38, 38, 33, 27, 27, 27, 27, 27, 33, 39, 39, 45, 81, 81, 158, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 194, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 14 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 37, 39, 33, 27, 27, 27, 27, 27, 33, 39, 122, 194, 230, 230, 230, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 110, 230, 230, 230, 230, 230, 230, 230, 230, 230, 187, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 15 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 66, 39, 33, 27, 27, 27, 27, 27, 33, 123, 194, 194, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 27, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 109, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 16 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 39, 27, 27, 27, 27, 27, 33, 81, 45, 39, 81, 123, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 111, 27, 230, 230, 230, 230, 146, 230, 230, 230, 230, 230, 230, 66, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 17 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 26, 60, 21, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 37, 33, 33, 27, 27, 27, 27, 27, 27, 33, 45, 123, 158, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 194, 27, 27, 230, 230, 230, 110, 33, 230, 230, 230, 230, 230, 230, 230, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 18 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 21, 60, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 39, 39, 33, 27, 27, 27, 27, 27, 33, 87, 158, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 33, 27, 69, 230, 230, 69, 21, 189, 230, 230, 230, 230, 230, 230, 230, 109, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 19 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 30, 39, 39, 27, 27, 27, 27, 27, 33, 87, 158, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 69, 27, 27, 111, 188, 27, 27, 195, 230, 230, 230, 230, 230, 230, 230, 230, 230, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 20 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 37, 33, 33, 27, 27, 27, 27, 33, 81, 123, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 111, 27, 27, 27, 27, 27, 27, 111, 231, 230, 230, 230, 231, 231, 231, 231, 231, 231, 145, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 38, 39, 27, 27, 27, 27, 27, 45, 123, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 69, 27, 27, 27, 33, 153, 75, 27, 27, 27, 230, 230, 231, 231, 231, 231, 231, 231, 231, 230, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 22 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 66, 39, 33, 27, 27, 27, 27, 33, 123, 158, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 194, 117, 27, 27, 69, 153, 231, 231, 231, 231, 111, 27, 27, 27, 231, 231, 231, 231, 231, 231, 231, 231, 231, 102, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 23 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 30, 45, 33, 27, 27, 27, 27, 39, 158, 230, 194, 194, 194, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 123, 81, 81, 117, 189, 231, 231, 231, 231, 231, 231, 231, 153, 27, 27, 27, 27, 111, 231, 231, 231, 231, 231, 231, 231, 188, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 30, 45, 27, 27, 27, 27, 27, 81, 158, 122, 87, 81, 39, 39, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 230, 230, 153, 27, 27, 27, 27, 27, 75, 231, 231, 231, 231, 231, 231, 231, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 25 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 45, 27, 27, 27, 27, 33, 123, 45, 39, 33, 39, 117, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 230, 230, 230, 231, 231, 231, 153, 27, 27, 27, 27, 27, 27, 153, 231, 231, 231, 231, 231, 66, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 26 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 45, 27, 27, 27, 27, 39, 39, 33, 33, 39, 158, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 69, 27, 27, 27, 27, 27, 27, 69, 231, 231, 231, 231, 109, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 27 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 66, 39, 27, 27, 27, 27, 33, 27, 33, 81, 158, 194, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 27, 27, 27, 27, 27, 27, 27, 33, 231, 231, 231, 151, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 28 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 39, 27, 27, 27, 27, 27, 33, 39, 123, 158, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 27, 27, 27, 27, 27, 27, 27, 33, 231, 231, 194, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 29 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 39, 39, 27, 27, 27, 27, 33, 39, 81, 123, 194, 230, 193, 192, 193, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 153, 27, 27, 27, 27, 27, 27, 27, 69, 231, 230, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 30 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 66, 39, 33, 27, 27, 27, 27, 33, 39, 123, 195, 192, 154, 112, 112, 112, 193, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 27, 27, 27, 27, 27, 27, 27, 27, 153, 230, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 26, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 30, 33, 27, 27, 27, 27, 27, 39, 87, 159, 192, 112, 112, 112, 112, 112, 155, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 195, 231, 111, 27, 27, 27, 27, 27, 27, 27, 27, 230, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 32 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 30, 39, 27, 27, 27, 27, 27, 39, 123, 194, 112, 112, 112, 112, 112, 112, 154, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 123, 195, 195, 195, 159, 123, 45, 39, 39, 39, 69, 27, 27, 27, 27, 27, 27, 27, 27, 111, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 33 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 39, 27, 27, 27, 27, 27, 39, 123, 155, 112, 112, 112, 112, 112, 112, 192, 230, 230, 230, 230, 230, 188, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 81, 45, 45, 45, 39, 27, 27, 33, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 34 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 20, 21, 21, 21, 21, 21, 21, 21, 20, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 38, 33, 27, 27, 27, 27, 39, 159, 148, 112, 106, 112, 112, 112, 191, 230, 230, 230, 230, 230, 230, 146, 230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 195, 231, 231, 231, 231, 231, 111, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 35 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 45, 33, 27, 27, 27, 39, 159, 112, 70, 65, 112, 112, 192, 231, 230, 230, 230, 188, 99, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 36 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 39, 39, 27, 27, 27, 33, 194, 112, 29, 106, 112, 154, 231, 231, 231, 231, 231, 189, 147, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 189, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 37 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 32, 45, 27, 27, 27, 39, 195, 112, 71, 106, 112, 230, 231, 231, 231, 21, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 33, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 38 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 21, 20, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 39, 39, 27, 27, 39, 195, 154, 71, 112, 192, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 195, 75, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 39 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 45, 33, 27, 33, 159, 231, 150, 230, 231, 231, 231, 195, 159, 195, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 123, 33, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 40 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 33, 39, 27, 27, 45, 195, 231, 231, 231, 86, 50, 50, 50, 50, 50, 159, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 45, 33, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 41 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 38, 39, 33, 27, 39, 159, 231, 195, 50, 50, 86, 86, 86, 86, 86, 50, 86, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 195, 39, 39, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 42 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 39, 39, 33, 27, 27, 81, 195, 50, 50, 86, 86, 86, 86, 86, 86, 86, 50, 123, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 45, 39, 39, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 43 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 32, 39, 27, 27, 27, 33, 86, 86, 33, 86, 86, 86, 86, 86, 86, 86, 50, 50, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 159, 39, 39, 39, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 44 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 20, 21, 21, 21, 21, 21, 20, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 39, 33, 27, 27, 27, 45, 50, 39, 39, 86, 86, 86, 86, 86, 50, 86, 86, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 81, 39, 39, 33, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 45 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 39, 27, 27, 27, 27, 51, 51, 27, 45, 86, 86, 86, 86, 86, 50, 123, 231, 231, 231, 231, 231, 231, 195, 195, 195, 195, 195, 231, 231, 231, 231, 231, 231, 39, 39, 39, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 46 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 32, 39, 27, 27, 27, 33, 51, 45, 33, 45, 86, 86, 86, 86, 45, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 75, 75, 75, 75, 39, 39, 39, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 47 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 32, 39, 27, 27, 27, 27, 39, 33, 33, 39, 39, 80, 80, 86, 81, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 44, 49, 50, 50, 39, 39, 33, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 48 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 31, 39, 27, 33, 75, 111, 75, 27, 33, 39, 80, 80, 80, 80, 81, 39, 39, 159, 39, 39, 39, 39, 39, 39, 39, 39, 49, 50, 43, 43, 43, 38, 45, 39, 27, 27, 27, 27, 27, 27, 27, 45, 50, 44, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 49 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 159, 231, 195, 195, 195, 195, 153, 69, 39, 38, 80, 80, 81, 39, 75, 231, 39, 39, 39, 39, 39, 39, 39, 44, 50, 43, 36, 43, 43, 43, 39, 39, 27, 33, 39, 39, 33, 21, 50, 49, 50, 30, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 50 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 159, 195, 195, 195, 195, 195, 195, 195, 111, 81, 86, 39, 39, 117, 195, 159, 39, 39, 39, 39, 39, 39, 50, 43, 43, 43, 23, 79, 195, 45, 39, 87, 87, 87, 87, 87, 87, 50, 50, 30, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 51 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 21, 21, 21, 21, 21, 21, 21, 21, 20, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 153, 75, 39, 195, 195, 195, 117, 39, 39, 39, 39, 45, 86, 122, 159, 195, 195, 195, 195, 81, 87, 87, 87, 44, 87, 87, 45, 31, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 52 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 159, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 153, 195, 195, 195, 195, 195, 195, 195, 195, 195, 87, 51, 87, 87, 44, 87, 87, 67, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 53 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 109, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 87, 51, 44, 87, 87, 74, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 54 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 67, 136, 142, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 159, 51, 87, 87, 67, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 55 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 59, 158, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 231, 123, 74, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 56 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 67, 152, 136, 136, 136, 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 187, 150, 187, 195, 195, 195, 159, 67, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 57 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 60, 101, 136, 142, 195, 195, 195, 195, 195, 195, 195, 187, 136, 136, 136, 136, 145, 110, 67, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 58 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 24, 24, 66, 109, 108, 100, 152, 152, 116, 101, 100, 101, 66, 24, 24, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61 | 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 62 | 63 | }; 64 | --------------------------------------------------------------------------------