This commit is contained in:
ghosind 2021-04-08 22:45:43 +08:00
parent c39414d479
commit 6606a5ee63
37 changed files with 7137 additions and 0 deletions

70
day16/Makefile Normal file

@ -0,0 +1,70 @@
ifndef GCCPREFIX
GCCPREFIX :=
endif
AS := nasm
CC := $(GCCPREFIX)gcc
LD := $(GCCPREFIX)ld
OBJCOPY := $(GCCPREFIX)objcopy
QEMU := qemu-system-i386
CFLAGS += -Wall -Wno-format -Wno-unused
CFLAGS += -std=gnu99 -static -m32
CFLAGS += -I ./include -I ./libc/include
CFLAGS += -ffunction-sections -nostdlib -nostdinc -fno-builtin -ffreestanding
QEMU_FLAGS += -no-reboot -d in_asm -m size=128
# C Library Objects
L_OBJS := libc/stdio/stdio.bin
# Kernel Objects
K_OBJS := bootpack.bin io.bin pm.bin hankaku.bin desctbl.bin graphic.bin \
int.bin inthandler.bin fifo.bin keyboard.bin mouse.bin \
memory.bin sheet.bin window.bin timer.bin task.bin mtask.bin
SYS := haribote.sys
IMG := haribote.img
ifdef DEBUG
QEMU_FLAGS += -gdb tcp::1234 -S
CFLAGS += -g
endif
ipl.bin:
$(AS) -f bin ipl.asm -o ipl.bin -l ipl.lst
asmhead.bin:
$(AS) -f bin asmhead.asm -o asmhead.bin -l asmhead.lst
%.bin: %.asm
$(AS) -f elf $< -o $@ -l $(subst .asm,.lst,$<)
%.bin: %.c
$(CC) $(CFLAGS) -c $< -o $@
kernel.sys: ${K_OBJS} ${L_OBJS}
$(LD) -m elf_i386 --oformat binary -o kernel.sys -T kernel.ld $^
haribote.sys: asmhead.bin kernel.sys
cat asmhead.bin > haribote.sys
cat kernel.sys >> haribote.sys
image: ipl.bin haribote.sys
dd if=/dev/zero of=$(IMG) bs=512 count=2880
dd if=ipl.bin of=$(IMG) bs=512 count=1 conv=notrunc
dd if=haribote.sys of=$(IMG) seek=33 bs=512 conv=notrunc
all: ${OBJS} haribote.sys image
clean:
rm -rf *.bin
rm -rf *.sys
rm -rf *.obj
rm -rf *.lst
rm -rf $(IMG)
rm -rf **/**/*.bin
qemu: clean all
$(QEMU) -fda $(IMG) $(QEMU_FLAGS)
.PHONY:
all

179
day16/asmhead.asm Normal file

@ -0,0 +1,179 @@
; haribote-os
VBEMODE EQU 0x105
; 0x100: 640 * 400 * 8bit
; 0x101: 640 * 480 * 8bit
; 0x103: 800 * 600 * 8bit
; 0x105: 1024 * 768 * 8bit
; 0x107: 1280 * 1024 * 8bit
BOTPAK EQU 0x00280000 ; 加载bootpack
DSKCAC EQU 0x00100000 ; 磁盘缓存的位置
DSKCAC0 EQU 0x00008000 ; 实模式磁盘缓存的位置
; 有关BOOT_INFO
CYLS EQU 0x0ff0 ; 设置启动区
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 关于颜色数目的信息,颜色的位数
SCRNX EQU 0x0ff4 ; 分辨率X
SCRNY EQU 0x0ff6 ; 分辨率Y
VRAM EQU 0x0ff8 ; 图像缓冲区的起始位置
; 使用linker script指定起始地址
ORG 0xc200 ; 程序被加载的内存地址
[BITS 16]
entry:
; 设置屏幕模式
; 确定VBE是否存在
MOV AX, 0x9000
MOV ES, AX
MOV DI, 0
MOV AX, 0x4f00
INT 0x10
CMP AX, 0x004f
JNE scrn320
; 检查VBE的版本
MOV AX, [ES:DI+4]
CMP AX, 0x0200
JB scrn320
; 取得画面模式信息
MOV CX, VBEMODE
MOV AX, 0x4f01
INT 0x10
CMP AX, 0x004f
JNE scrn320
; 画面模式的确认
CMP BYTE [ES:DI+0x19], 8
JNE scrn320
CMP BYTE [ES:DI+0x1b], 4
JNE scrn320
MOV AX, [ES:DI+0x00]
AND AX, 0x0080
JZ scrn320
; 画面模式的切换
MOV BX, VBEMODE+0x4000
MOV AX, 0x4f02
INT 0x10
MOV BYTE [VMODE], 8 ; 记下画面模式
MOV AX, [ES:DI+0x12]
MOV [SCRNX], AX
MOV AX, [ES:DI+0x14]
MOV [SCRNY], AX
MOV EAX, [ES:DI+0x28]
MOV [VRAM], EAX
JMP keystatus
scrn320:
MOV AL, 0x13 ; VGA图320*200*8bit彩色
MOV AH, 0x00
INT 0x10
MOV BYTE [VMODE], 8 ; 记下画面模式
MOV WORD [SCRNX], 320
MOV WORD [SCRNY], 200
MOV DWORD [VRAM], 0x000a0000
keystatus:
; 用BIOS取得键盘上各种LED指示灯的状态
MOV AH, 0x02
INT 0x16 ; 键盘BIOS
MOV [LEDS], AL
; 防止PIC接受所有中断
; 根据AT兼容机的规范初始化PIC
; 如果没有在CLI指令前执行可能会挂起
; 并继续初始化PIC
MOV AL, 0xff
OUT 0x21, AL
NOP ; 有些机器不能连续执行NOP指令
OUT 0xa1, AL
CLI
; 设置A20GATE使CPU支持1M以上的内存
CALL waitkbdout
MOV AL, 0xd1
OUT 0x64, AL
CALL waitkbdout
MOV AL, 0xdf ; 开启A20
OUT 0x60, AL
CALL waitkbdout
; 切换到保护模式
LGDT [GDTR0] ; 设置临时GDT
MOV EAX, CR0
AND EAX, 0x7fffffff ; 禁用分页
OR EAX, 0x00000001 ; 开启保护模式
MOV CR0, EAX
JMP pipelineflush
pipelineflush:
MOV AX, 1*8 ; 写32bit段
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX
; bootpack传递
MOV ESI, bootpack ; 源
MOV EDI, BOTPAK ; 目标
MOV ECX, 512*1024/4
CALL memcpy
; 传输磁盘数据
; 从引导区开始
MOV ESI, 0x7c00 ; 源
MOV EDI, DSKCAC ; 目标
MOV ECX, 512/4
CALL memcpy
; 剩余的全部
MOV ESI, DSKCAC0+512 ; 源
MOV EDI, DSKCAC+512 ; 目标
MOV ECX, 0
MOV CL, BYTE [CYLS]
IMUL ECX, 512*18*2/4 ; 除以4得到字节数
SUB ECX, 512/4 ; IPL偏移量
CALL memcpy
skip:
MOV ESP, 0xffff
JMP DWORD 2*8:0x00000000
waitkbdout:
IN AL, 0x64
AND AL, 0x02
JNZ waitkbdout ; AND结果不为0跳转至waitkbdout
RET
memcpy:
MOV EAX, [ESI]
ADD ESI, 4
MOV [EDI], EAX
ADD EDI, 4
SUB ECX, 1
JNZ memcpy ; 结果不为0跳转至memcpy
RET
; memcpy地址前缀大小
ALIGN 16
GDT0:
RESB 8 ; 初始值
DW 0xffff, 0x0000, 0x9200, 0x00cf ; 可写的32位段寄存器
DW 0xffff, 0x0000, 0x9a28, 0x0047 ; 可执行的文件的32位寄存器
DW 0
GDTR0:
DW 8*3-1
DD GDT0
ALIGN 16
bootpack:

243
day16/bootpack.c Normal file

@ -0,0 +1,243 @@
#include <stdio.h>
#include "bootpack.h"
#include "desctbl.h"
#include "fifo.h"
#include "graphic.h"
#include "int.h"
#include "io.h"
#include "keyboard.h"
#include "memory.h"
#include "mouse.h"
#include "sheet.h"
#include "task.h"
#include "timer.h"
#include "window.h"
void task_b_main(struct Sheet *sht_back) {
struct FIFO32 fifo;
int fifobuf[128], count = 0, count0 = 0;
char s[12];
fifo32_init(&fifo, 128, fifobuf);
struct Timer *timer_put = timer_alloc();
timer_init(timer_put, &fifo, 1);
timer_set_timer(timer_put, 1);
struct Timer *timer_1s = timer_alloc();
timer_init(timer_1s, &fifo, 100);
timer_set_timer(timer_1s, 100);
for (;;) {
count++;
io_cli();
if (!fifo32_status(&fifo)) {
io_stihlt();
} else {
int data = fifo32_get(&fifo);
io_sti();
if (data == 1) {
sprintf(s, "%11d", count);
put_fonts8_asc_sht(sht_back, 0, 144, COL8_FFFFFF, COL8_008484, s, 11);
timer_set_timer(timer_put, 1);
} else if (data == 100) {
sprintf(s, "%11d", count - count0);
put_fonts8_asc_sht(sht_back, 0, 128, COL8_FFFFFF, COL8_008484, s, 11);
count0 = count;
timer_set_timer(timer_1s, 100);
}
}
}
}
int main(void) {
struct BootInfo *binfo = (struct BootInfo *)ADR_BOOTINFO;
struct MemMan *memman = (struct MemMan *)MEMMAN_ADDR;
struct MouseDec mdec;
char s[40], mcursor[256];
unsigned int memtotal;
struct Shtctl *shtctl;
struct Sheet *sht_back, *sht_mouse, *sht_win;
unsigned char *buf_back, buf_mouse[256], *buf_win;
struct Timer *timer, *timer2, *timer3;
struct FIFO32 fifo;
int fifobuf[128], data;
init_gdtidt();
init_pic(); // GDT/IDT完成初始化开放CPU中断
io_sti();
fifo32_init(&fifo, 128, fifobuf);
init_keyboard(&fifo, 256);
enable_mouse(&fifo, 512, &mdec);
init_pit();
io_out8(PIC0_IMR, 0xf8); // 开放PIT、PIC1以及键盘中断
io_out8(PIC1_IMR, 0xef); // 开放鼠标中断
timer = timer_alloc();
timer_init(timer, &fifo, 10);
timer_set_timer(timer, 1000);
timer2 = timer_alloc();
timer_init(timer2, &fifo, 3);
timer_set_timer(timer2, 300);
timer3 = timer_alloc();
timer_init(timer3, &fifo, 1);
timer_set_timer(timer3, 50);
memtotal = memtest(0x00400000, 0xbfffffff);
memman_init(memman);
// 书中为0x00001000 ~ 0x0009e000
// 注1: 测试时发现会造成错误原因未知所以改为由0x00010000开始
// 注2: 在640*480模式下free该段内存后会导致屏幕画面错误
// memman_free(memman, 0x00010000, 0x0009e000); // 0x00010000 ~ 0x0009efff
memman_free(memman, 0x00400000, memtotal - 0x00400000);
init_palette();
shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny);
sht_back = sheet_alloc(shtctl);
sht_mouse = sheet_alloc(shtctl);
sht_win = sheet_alloc(shtctl);
buf_back =
(unsigned char *)memman_alloc_4k(memman, binfo->scrnx * binfo->scrny);
buf_win = (unsigned char *)memman_alloc_4k(memman, 160 * 52);
sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny,
-1); // 没有透明色
sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99); // 透明色号99
sheet_setbuf(sht_win, buf_win, 160, 52, -1); // 没有透明色
init_screen8(buf_back, binfo->scrnx, binfo->scrny);
init_mouse_cursor8(buf_mouse, 99); // 背景色号99
make_window8(buf_win, 160, 52, "counter");
make_textbox8(sht_win, 8, 28, 144, 16, COL8_FFFFFF);
int cursor_x = 8;
int cursor_c = COL8_FFFFFF;
sheet_slide(sht_back, 0, 0);
int mx = (binfo->scrnx - 16) / 2; // 按在画面中央来计算坐标
int my = (binfo->scrny - 28 - 16) / 2;
sheet_slide(sht_mouse, mx, my);
sheet_slide(sht_win, 80, 72);
sheet_updown(sht_back, 0);
sheet_updown(sht_win, 1);
sheet_updown(sht_mouse, 2);
sprintf(s, "(%3d, %3d)", mx, my);
put_fonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
sprintf(s, "memory %dMB, free: %dKB", memtotal / (1024 * 1024),
memman_total(memman) / 1024);
put_fonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);
sheet_refresh(sht_back, 0, 0, binfo->scrnx, 48);
task_init(memman);
struct Task *task_b = task_alloc();
task_b->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024 - 8;
task_b->tss.eip = (int)&task_b_main;
task_b->tss.es = 1 * 8;
task_b->tss.cs = 2 * 8;
task_b->tss.ss = 1 * 8;
task_b->tss.ds = 1 * 8;
task_b->tss.fs = 1 * 8;
task_b->tss.gs = 1 * 8;
*((int *)(task_b->tss.esp + 4)) = (int)sht_back;
task_run(task_b);
for (;;) {
io_cli();
if (fifo32_status(&fifo) == 0) {
io_stihlt();
} else {
data = fifo32_get(&fifo);
io_sti();
if (256 <= data && data <= 511) {
// 键盘数据
sprintf(s, "%02X", data - 256);
put_fonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
if (data < 0x54 + 256) {
if (keytable[data - 256] && cursor_x < 144) {
// 一般字符
s[0] = keytable[data - 256];
s[1] = '\0';
put_fonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF,
s, 1);
cursor_x += 8;
}
if (data == 256 + 0x0e && cursor_x > 8) {
// 退格键
// 用空格键把光标消去后,后移一次光标
put_fonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF,
" ", 1);
cursor_x -= 8;
}
box_fill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28,
cursor_x + 7, 43);
sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);
}
} else if (512 <= data && data <= 767) {
// 鼠标数据
if (mouse_decode(&mdec, data - 512)) {
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
if ((mdec.btn & 0x01)) {
s[1] = 'L';
}
if ((mdec.btn & 0x02)) {
s[3] = 'R';
}
if ((mdec.btn & 0x04)) {
s[2] = 'C';
}
put_fonts8_asc_sht(sht_back, 32, 16, COL8_FFFFFF, COL8_008484, s, 15);
// 移动光标
mx += mdec.x;
my += mdec.y;
if (mx < 0) {
mx = 0;
}
if (my < 0) {
my = 0;
}
if (mx > binfo->scrnx - 1) {
mx = binfo->scrnx - 1;
}
if (my > binfo->scrny - 1) {
my = binfo->scrny - 1;
}
sprintf(s, "(%3d, %3d)", mx, my);
put_fonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
sheet_slide(sht_mouse, mx, my);
if (mdec.btn & 0x01) {
// 按下左键移动sht_win
sheet_slide(sht_win, mx - 80, my - 8);
}
}
} else if (data == 10) {
put_fonts8_asc_sht(sht_back, 0, 64, COL8_FFFFFF, COL8_008484, "10[sec]",
7);
} else if (data == 3) {
put_fonts8_asc_sht(sht_back, 0, 80, COL8_FFFFFF, COL8_008484, "3[sec]",
6);
} else if (data <= 1) {
if (data) {
timer_init(timer3, &fifo, 0);
cursor_c = COL8_000000;
} else {
timer_init(timer3, &fifo, 1);
cursor_c = COL8_FFFFFF;
}
timer_set_timer(timer3, 50);
box_fill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28,
cursor_x + 7, 43);
sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);
}
}
}
return 0;
}

49
day16/desctbl.c Normal file

@ -0,0 +1,49 @@
#include "desctbl.h"
#include "int.h"
#include "timer.h"
void init_gdtidt(void) {
struct SegmentDescriptor *gdt = (struct SegmentDescriptor *)ADR_GDT;
struct GateDescriptor *idt = (struct GateDescriptor *)ADR_IDT;
for (int i = 0; i <= LIMIT_GDT / 8; i++) {
set_segmdesc(gdt + i, 0, 0, 0);
}
set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, AR_DATA32_RW);
set_segmdesc(gdt + 2, LIMIT_BOOTPACK, ADR_BOOTPACK, AR_CODE32_ER);
load_gdtr(LIMIT_GDT, ADR_GDT);
for (int i = 0; i <= LIMIT_IDT / 8; i++) {
set_gatedesc(idt + i, 0, 0, 0);
}
load_idtr(LIMIT_IDT, ADR_IDT);
set_gatedesc(idt + 0x20, (int)asm_int_handler20, 2 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x21, (int)asm_int_handler21, 2 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x27, (int)asm_int_handler27, 2 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x2c, (int)asm_int_handler2c, 2 * 8, AR_INTGATE32);
}
void set_segmdesc(struct SegmentDescriptor *sd, unsigned int limit, int base,
int ar) {
if (limit > 0xfffff) {
ar |= 0x8000; // G_bit = 1
limit /= 0x1000;
}
sd->limit_low = limit & 0xffff;
sd->base_low = base & 0xffff;
sd->base_mid = (base >> 16) & 0xff;
sd->access_right = ar & 0xff;
sd->limit_high = ((limit >> 16) & 0x0f) | ((ar >> 8) | 0xf0);
sd->base_high = (base >> 24) & 0xff;
}
void set_gatedesc(struct GateDescriptor *gd, int offset, int selector, int ar) {
gd->offset_low = offset & 0xffff;
gd->selector = selector;
gd->dw_count = (ar >> 8) & 0xff;
gd->access_right = ar & 0xff;
gd->offset_high = (offset >> 16) & 0xffff;
}

81
day16/fifo.c Normal file

@ -0,0 +1,81 @@
#include "fifo.h"
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf) {
fifo->size = size;
fifo->buf = buf;
fifo->free = size;
fifo->flags = 0;
fifo->next_r = 0;
fifo->next_w = 0;
}
int fifo8_put(struct FIFO8 *fifo, unsigned char data) {
if (fifo->free == 0) {
fifo->flags |= FLAGS_OVERRUN;
return -1;
}
fifo->buf[fifo->next_w++] = data;
if (fifo->next_w == fifo->size) {
fifo->next_w = 0;
}
fifo->free--;
return 0;
}
int fifo8_get(struct FIFO8 *fifo) {
if (fifo->free == fifo->size) {
return -1;
}
int data = fifo->buf[fifo->next_r++];
if (fifo->next_r == fifo->size) {
fifo->next_r = 0;
}
fifo->free++;
return data;
}
int fifo8_status(struct FIFO8 *fifo) { return fifo->size - fifo->free; }
void fifo32_init(struct FIFO32 *fifo, int size, int *buf) {
fifo->size = size;
fifo->buf = buf;
fifo->free = size;
fifo->flags = 0;
fifo->next_r = 0;
fifo->next_w = 0;
}
int fifo32_put(struct FIFO32 *fifo, int data) {
if (fifo->free == 0) {
fifo->flags |= FLAGS_OVERRUN;
return -1;
}
fifo->buf[fifo->next_w] = data;
fifo->next_w++;
if (fifo->next_w == fifo->size) {
fifo->next_w = 0;
}
fifo->free--;
return 0;
}
int fifo32_get(struct FIFO32 *fifo) {
if (fifo->free == fifo->size) {
return -1;
}
int data = fifo->buf[fifo->next_r];
fifo->next_r++;
if (fifo->next_r == fifo->size) {
fifo->next_r = 0;
}
fifo->free++;
return data;
}
int fifo32_status(struct FIFO32 *fifo) { return fifo->size - fifo->free; }

168
day16/graphic.c Normal file

@ -0,0 +1,168 @@
#include "graphic.h"
#include "io.h"
#include "sheet.h"
void init_palette(void) {
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00, // 黑色
0xff, 0x00, 0x00, // 亮红色
0x00, 0xff, 0x00, // 亮绿色
0xff, 0xff, 0x00, // 亮黄色
0x00, 0x00, 0xff, // 亮蓝色
0xff, 0x00, 0xff, // 亮紫色
0x00, 0xff, 0xff, // 浅亮蓝色
0xff, 0xff, 0xff, // 白色
0xc6, 0xc6, 0xc6, // 亮灰色
0x84, 0x00, 0x00, // 暗红色
0x00, 0x84, 0x00, // 暗绿色
0x84, 0x84, 0x00, // 暗黄色
0x00, 0x00, 0x84, // 暗蓝色
0x84, 0x00, 0x84, // 暗紫色
0x00, 0x84, 0x84, // 浅暗蓝色
0x84, 0x84, 0x84 // 暗灰色
};
set_palette(0, 15, table_rgb);
}
void set_palette(int start, int end, unsigned char *rgb) {
int eflags = io_load_eflags(); // 记录标志
io_cli(); // 禁止中断
io_out8(0x03c8, start);
for (int i = start; i <= end; i++) {
io_out8(0x03c9, rgb[0] / 4);
io_out8(0x03c9, rgb[1] / 4);
io_out8(0x03c9, rgb[2] / 4);
rgb += 3;
}
io_store_eflags(eflags);
}
void box_fill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0,
int x1, int y1) {
for (int y = y0; y <= y1; y++) {
for (int x = x0; x <= x1; x++) {
vram[y * xsize + x] = c;
}
}
}
void init_screen8(unsigned char *vram, int x, int y) {
box_fill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29);
box_fill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28);
box_fill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27);
box_fill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1);
box_fill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24);
box_fill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4);
box_fill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4);
box_fill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5);
box_fill8(vram, x, COL8_000000, 2, y - 4, 59, y - 3);
box_fill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3);
box_fill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24);
box_fill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4);
box_fill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3);
box_fill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3);
}
void put_font8(unsigned char *vram, int xsize, int x, int y, char c,
char *font) {
unsigned char *p;
char d;
for (int i = 0; i < 16; i++) {
p = vram + (y + i) * xsize + x;
d = font[i];
if ((d & 0x80) != 0) {
p[0] = c;
}
if ((d & 0x40) != 0) {
p[1] = c;
}
if ((d & 0x20) != 0) {
p[2] = c;
}
if ((d & 0x10) != 0) {
p[3] = c;
}
if ((d & 0x08) != 0) {
p[4] = c;
}
if ((d & 0x04) != 0) {
p[5] = c;
}
if ((d & 0x02) != 0) {
p[6] = c;
}
if ((d & 0x01) != 0) {
p[7] = c;
}
}
}
void put_fonts8_asc(unsigned char *vram, int xsize, int x, int y, char c,
char *s) {
extern char hankaku[4096];
for (; *s != '\0'; s++) {
put_font8(vram, xsize, x, y, c, hankaku + *s * 16);
x += 8;
}
}
void init_mouse_cursor8(unsigned char *mouse, char bc) {
static char cursor[16][16] = {
"**************..",
"*OOOOOOOOOOO*...",
"*OOOOOOOOOO*....",
"*OOOOOOOOO*.....",
"*OOOOOOOO*......",
"*OOOOOOO*.......",
"*OOOOOOO*.......",
"*OOOOOOOO*......",
"*OOOO**OOO*.....",
"*OOO*..*OOO*....",
"*OO*....*OOO*...",
"*O*......*OOO*..",
"**........*OOO*.",
"*..........*OOO*",
"............*OO*",
".............***"};
for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) {
if (cursor[y][x] == '*') {
mouse[y * 16 + x] = COL8_000000;
}
if (cursor[y][x] == 'O') {
mouse[y * 16 + x] = COL8_FFFFFF;
}
if (cursor[y][x] == '.') {
mouse[y * 16 + x] = bc;
}
}
}
}
void put_block8_8(unsigned char *vram, int vxsize, int pxsize, int pysize,
int px0, int py0, char *buf, int bxsize) {
for (int y = 0; y < pysize; y++) {
for (int x = 0; x < pxsize; x++) {
vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
}
}
}
void put_fonts8_asc_sht(struct Sheet *sht, int x, int y, int c, int b, char *s,
int l) {
box_fill8(sht->buf, sht->bxsize, b, x, y, x + l * 8 - 1, y + 15);
put_fonts8_asc(sht->buf, sht->bxsize, x, y, c, s);
sheet_refresh(sht, x, y, x + l * 8, y + 16);
}

4611
day16/hankaku.asm Normal file

File diff suppressed because it is too large Load Diff

16
day16/include/bootpack.h Normal file

@ -0,0 +1,16 @@
#ifndef _BOOTPACK_H_
#define _BOOTPACK_H_
#define ADR_BOOTINFO 0x00000ff0
struct BootInfo{
char cyls;
char leds;
char vmode;
char reserve;
short scrnx;
short scrny;
unsigned char *vram;
};
#endif // _BOOTPACK_H_

37
day16/include/desctbl.h Normal file

@ -0,0 +1,37 @@
#ifndef _DESCTBL_H_
#define _DESCTBL_H_
#define ADR_IDT 0x0026f800
#define LIMIT_IDT 0x000007ff
#define ADR_GDT 0x00270000
#define LIMIT_GDT 0x0000ffff
#define ADR_BOOTPACK 0x00280000
#define LIMIT_BOOTPACK 0x0007ffff
#define AR_DATA32_RW 0x4092
#define AR_CODE32_ER 0x409a
#define AR_TSS32 0x0089
#define AR_INTGATE32 0x008e
struct SegmentDescriptor {
short limit_low, base_low;
char base_mid, access_right;
char limit_high, base_high;
};
struct GateDescriptor {
short offset_low, selector;
char dw_count, access_right;
short offset_high;
};
void init_gdtidt(void);
void set_segmdesc(struct SegmentDescriptor *sd, unsigned int limit, int base,
int ar);
void set_gatedesc(struct GateDescriptor *gd, int offset, int selector, int ar);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);
#endif // _DESCTBL_H_

28
day16/include/fifo.h Normal file

@ -0,0 +1,28 @@
#ifndef _FIFO_H_
#define _FIFO_H_
#define FLAGS_OVERRUN 0x0001
struct FIFO8 {
unsigned char *buf;
int size, free, flags;
int next_r, next_w;
};
struct FIFO32 {
int *buf;
int size, free, flags;
int next_r, next_w;
};
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf);
int fifo8_put(struct FIFO8 *fifo, unsigned char data);
int fifo8_get(struct FIFO8 *fifo);
int fifo8_status(struct FIFO8 *fifo);
void fifo32_init(struct FIFO32 *fifo, int size, int *buf);
int fifo32_put(struct FIFO32 *fifo, int data);
int fifo32_get(struct FIFO32 *fifo);
int fifo32_status(struct FIFO32 *fifo);
#endif // _FIFO_H_

38
day16/include/graphic.h Normal file

@ -0,0 +1,38 @@
#include "sheet.h"
#ifndef _GRAPHIC_H_
#define _GRAPHIC_H_
#define COL8_000000 0
#define COL8_FF0000 1
#define COL8_00FF00 2
#define COL8_FFFF00 3
#define COL8_0000FF 4
#define COL8_FF00FF 5
#define COL8_00FFFF 6
#define COL8_FFFFFF 7
#define COL8_C6C6C6 8
#define COL8_840000 9
#define COL8_008400 10
#define COL8_848400 11
#define COL8_000084 12
#define COL8_840084 13
#define COL8_008484 14
#define COL8_848484 15
void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb);
void box_fill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0,
int x1, int y1);
void init_screen8(unsigned char *vram, int x, int y);
void put_font8(unsigned char *vram, int xsize, int x, int y, char c,
char *font);
void put_fonts8_asc(unsigned char *vram, int xsize, int x, int y, char c,
char *s);
void init_mouse_cursor8(unsigned char *mouse, char bc);
void put_block8_8(unsigned char *vram, int vxsize, int pxsize, int pysize,
int px0, int py0, char *buf, int bxsize);
void put_fonts8_asc_sht(struct Sheet *sht, int x, int y, int c, int b, char *s,
int l);
#endif // _GRAPHIC_H_

26
day16/include/int.h Normal file

@ -0,0 +1,26 @@
#ifndef _INT_H_
#define _INT_H_
#define PIC0_ICW1 0x0020
#define PIC0_OCW2 0x0020
#define PIC0_IMR 0x0021
#define PIC0_ICW2 0x0021
#define PIC0_ICW3 0x0021
#define PIC0_ICW4 0x0021
#define PIC1_ICW1 0x00a0
#define PIC1_OCW2 0x00a0
#define PIC1_IMR 0x00a1
#define PIC1_ICW2 0x00a1
#define PIC1_ICW3 0x00a1
#define PIC1_ICW4 0x00a1
void init_pic(void);
void int_handler2c(int *esp);
void asm_int_handler20(void);
void asm_int_handler21(void);
void asm_int_handler27(void);
void asm_int_handler2c(void);
#endif // _INT_H_

26
day16/include/io.h Normal file

@ -0,0 +1,26 @@
#ifndef _IO_H_
#define _IO_H_
#define EFLAGS_AC_BIT 0x00040000
#define CR0_CACHE_DISABLE 0x60000000
void io_hlt(void);
void io_cli(void);
void io_sti(void);
void io_stihlt(void);
int io_in8(int port);
int io_in16(int port);
int io_in32(int port);
void io_out8(int port, int data);
void io_out16(int port, int data);
void io_out32(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);
int io_load_cr0(void);
void io_store_cr0(int cr0);
#endif // _IO_H_

27
day16/include/keyboard.h Normal file

@ -0,0 +1,27 @@
#include "fifo.h"
#ifndef _KEYBOARD_H_
#define _KEYBOARD_H_
#define PORT_KEYDAT 0x0060
#define PORT_KEYSTA 0x0064
#define PORT_KEYCMD 0x0064
#define KEYSTA_SEND_NOTREADY 0x02
#define KEYCMD_WRITE_MODE 0x60
#define KBC_MODE 0x47
static char keytable[0x54] = {
0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
0, 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '[', ']',
0, 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ':', 0,
0, '\\', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/', 0, '*',
0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.'};
void wait_KBC_sendready(void);
void init_keyboard(struct FIFO32 *fifo, int data0);
void int_handler21(int *esp);
#endif // _KEYBOARD_H_

26
day16/include/memory.h Normal file

@ -0,0 +1,26 @@
#ifndef _MEMORY_H_
#define _MEMORY_H_
#define MEMMAN_ADDR 0x003c0000
#define MEMMAN_FREES 4090 // 大约是32kb
struct FreeInfo {
unsigned int addr, size;
};
struct MemMan {
int frees, maxfrees, lostsize, losts;
struct FreeInfo free[MEMMAN_FREES];
};
unsigned int memtest(unsigned int start, unsigned int end);
unsigned int memtest_sub(unsigned int start, unsigned int end);
void memman_init(struct MemMan *man);
unsigned int memman_total(struct MemMan *man);
unsigned int memman_alloc(struct MemMan *man, unsigned int size);
unsigned int memman_alloc_4k(struct MemMan *man, unsigned int size);
int memman_free(struct MemMan *man, unsigned int addr, unsigned int size);
int memman_free_4k(struct MemMan *man, unsigned int addr, unsigned int size);
#endif // _MEMORY_H_

19
day16/include/mouse.h Normal file

@ -0,0 +1,19 @@
#include "fifo.h"
#ifndef _MOUSE_H_
#define _MOUSE_H_
#define KEYCMD_SENDTO_MOUSE 0xd4
#define MOUSECMD_ENABLE 0xf4
struct MouseDec {
unsigned char buf[3], phase;
int x, y, btn;
};
void enable_mouse(struct FIFO32 *fifo, int data0, struct MouseDec *mdec);
int mouse_decode(struct MouseDec *mdec, unsigned char dat);
void int_handler27(int *esp);
#endif // _MOUSE_H_

38
day16/include/sheet.h Normal file

@ -0,0 +1,38 @@
#include "memory.h"
#ifndef _SHEET_H_
#define _SHEET_H_
#define MAX_SHEETS 256
#define SHEET_USE 1
struct Shtctl;
struct Sheet {
unsigned char *buf;
int bxsize, bysize, vx0, vy0, col_inv, height, flags;
struct Shtctl *ctl;
};
struct Shtctl {
unsigned char *vram, *map;
int xsize, ysize, top;
struct Sheet *sheets[MAX_SHEETS];
struct Sheet sheets0[MAX_SHEETS];
};
struct Shtctl *shtctl_init(struct MemMan *memman, unsigned char *vram,
int xsize, int ysize);
struct Sheet *sheet_alloc(struct Shtctl *ctl);
void sheet_setbuf(struct Sheet *sht, unsigned char *buf, int xsize, int ysize,
int col_inv);
void sheet_updown(struct Sheet *sht, int height);
void sheet_refreshmap(struct Shtctl *ctl, int vx0, int vy0, int vx1, int vy1,
int h0);
void sheet_refreshsub(struct Shtctl *ctl, int vx0, int vy0, int vx1, int vy1,
int h0, int h1);
void sheet_refresh(struct Sheet *sht, int bx0, int by0, int bx1, int by1);
void sheet_slide(struct Sheet *sht, int vx0, int vy0);
void sheet_free(struct Sheet *sht);
#endif // _SHEET_H_

44
day16/include/task.h Normal file

@ -0,0 +1,44 @@
#include "memory.h"
#include "timer.h"
#ifndef _TASK_H_
#define _TASK_H_
#define MAX_TASKS 1000 // 最大任务数量
#define TASK_GDT0 3 // 定义从GDT的几号开始分配给TSS
struct TSS32 {
int backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;
int eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
int es, cs, ss, ds, fs, gs;
int ldtr, iomap;
};
struct Task {
int sel, flags; // sel用于存放GDT的编号
struct TSS32 tss;
};
struct TaskCtl {
int running; // 正在运行的任务数量
int now; // 记录正在运行的任务
struct Task *tasks[MAX_TASKS];
struct Task tasks0[MAX_TASKS];
};
extern struct TaskCtl *taskctl;
extern struct Timer *task_timer;
void load_tr(int tr);
void far_jmp(int eip, int cs);
void mt_init(void);
void mt_task_switch(void);
struct Task *task_init(struct MemMan *memman);
struct Task *task_alloc(void);
void task_run(struct Task *task);
void task_switch(void);
#endif // _TASK_H_

38
day16/include/timer.h Normal file

@ -0,0 +1,38 @@
#include "fifo.h"
#ifndef _TIMER_H_
#define _TIMER_H_
#define PIT_CTRL 0x0043
#define PIT_CNT0 0x0040
#define TIMER_FLAGS_ALLOC 1 // 已配置状态
#define TIMER_FLAGS_USING 2 // 定时器运行中
#define MAX_TIMER 500
struct Timer {
struct Timer *next;
unsigned int flags;
unsigned int timeout;
struct FIFO32 *fifo;
int data;
};
struct TimerCtl {
unsigned int count, next;
struct Timer *t0;
struct Timer timers0[MAX_TIMER];
};
extern struct TimerCtl timerctl;
void init_pit(void);
struct Timer *timer_alloc(void);
void timer_free(struct Timer *timer);
void timer_init(struct Timer *timer, struct FIFO32 *fifo, int data);
void timer_set_timer(struct Timer *timer, unsigned int timeout);
void int_handler20(int *esp);
#endif // _TIMER_H_

9
day16/include/window.h Normal file

@ -0,0 +1,9 @@
#include "sheet.h"
#ifndef _WINDOW_H_
#define _WINDOW_H_
void make_window8(unsigned char *buf, int xsize, int ysize, char *title);
void make_textbox8(struct Sheet *sht, int x0, int y0, int sx, int sy, int c);
#endif // _WINDOW_H_

30
day16/int.c Normal file

@ -0,0 +1,30 @@
#include <stdio.h>
#include "bootpack.h"
#include "fifo.h"
#include "graphic.h"
#include "int.h"
#include "io.h"
#include "keyboard.h"
#include "mouse.h"
void init_pic(void) {
// 禁止所有中断
io_out8(PIC0_IMR, 0xff);
io_out8(PIC1_IMR, 0xff);
io_out8(PIC0_ICW1, 0x11); // 边缘触发模式
io_out8(PIC0_ICW2, 0x20); // IRQ0-7由INT20-27接收
io_out8(PIC0_ICW3, 1 << 2); // PIC1由IRQ2连接
io_out8(PIC0_ICW4, 0x01); // 无缓冲区模式
io_out8(PIC1_ICW1, 0x11); // 边缘触发模式
io_out8(PIC1_ICW2, 0x28); // IRQ8-15由INT28-2f接收
io_out8(PIC1_ICW3, 2); // PIC1由IRQ2连接
io_out8(PIC1_ICW4, 0x01); // 无缓冲区模式
io_out8(PIC0_IMR, 0xfb); // PIC1以外中断全部禁止
io_out8(PIC1_IMR, 0xff); // 禁止全部中断
}
void int_handler27(int *esp) { io_out8(PIC0_OCW2, 0x67); }

69
day16/inthandler.asm Normal file

@ -0,0 +1,69 @@
[BITS 32]
GLOBAL asm_int_handler20, asm_int_handler21, asm_int_handler27, asm_int_handler2c
EXTERN int_handler20, int_handler21, int_handler27, int_handler2c
asm_int_handler20:
PUSH ES
PUSH DS
PUSHAD
MOV EAX, ESP
PUSH EAX
MOV AX, SS
MOV DS, AX
MOV ES, AX
CALL int_handler20
POP EAX
POPAD
POP DS
POP ES
IRETD
asm_int_handler21:
PUSH ES
PUSH DS
PUSHAD
MOV EAX, ESP
PUSH EAX
MOV AX, SS
MOV DS, AX
MOV ES, AX
CALL int_handler21
POP EAX
POPAD
POP DS
POP ES
IRETD
asm_int_handler27:
PUSH ES
PUSH DS
PUSHAD
MOV EAX, ESP
PUSH EAX
MOV AX, SS
MOV DS, AX
MOV ES, AX
CALL int_handler27
POP EAX
POPAD
POP DS
POP ES
IRETD
asm_int_handler2c:
PUSH ES
PUSH DS
PUSHAD
MOV EAX, ESP
PUSH EAX
MOV AX, SS
MOV DS, AX
MOV ES, AX
CALL int_handler2c
POP EAX
POPAD
POP DS
POP ES
IRETD

81
day16/io.asm Normal file

@ -0,0 +1,81 @@
[BITS 32]
; 程序中包含函数名
GLOBAL io_hlt, io_cli, io_sti, io_stihlt
GLOBAL io_in8, io_in16, io_in32
GLOBAL io_out8, io_out16, io_out32
GLOBAL io_load_eflags, io_store_eflags
GLOBAL io_load_cr0, io_store_cr0
[SECTION .text]
io_hlt: ; void io_hlt(void);
HLT
RET
io_cli: ; void io_cli(void);
CLI
RET
io_sti: ; void io_sti(void);
STI
RET
io_stihlt: ; void io_stihlt(void);
STI
HLT
RET
io_in8: ; int io_in8(int port);
MOV EDX, [ESP+4] ; port
MOV EAX, 0
IN AL, DX
RET
io_in16: ; int io_in16(int port);
MOV EDX, [ESP+4] ; port
MOV EAX, 0
IN AX, DX
RET
io_in32: ; int io_in32(int port);
MOV EDX, [ESP+4] ; port
IN EAX, DX
RET
io_out8: ; void io_out8(int port, int data);
MOV EDX, [ESP+4] ; port
MOV AL, [ESP+8] ; data
OUT DX, AL
RET
io_out16: ; void io_out16(int port, int data);
MOV EDX, [ESP+4] ; port
MOV AX, [ESP+8] ; data
OUT DX, AX
RET
io_out32: ; void io_out32(int port, int data);
MOV EDX, [ESP+4] ; port
MOV EAX, [ESP+8] ; data
OUT DX, EAX
RET
io_load_eflags: ; int io_load_eflags(void);
PUSHFD
POP EAX
RET
io_store_eflags: ; void io_store_eflags(int eflags);
MOV EAX, [ESP+4] ; eflags
PUSH EAX
POPFD
RET
io_load_cr0: ; int io_load_cr0(void);
MOV EAX, CR0
RET
io_store_cr0: ; void io_store_cr0(int cr0);
MOV EAX, [ESP+4] ; cr0
MOV CR0, EAX
RET

115
day16/ipl.asm Normal file

@ -0,0 +1,115 @@
; hello-os
CYLS EQU 10 ; 读取的柱面数量CYLS = cylinders
ORG 0x7c00 ; 指明程序的装载地址
; 用于标准FAT12格式的软盘
JMP entry ; 跳转指令
NOP ; NOP指令
DB "HARIBOTE" ; OEM标识符8字节
DW 512 ; 每个扇区sector的字节数必须为512字节
DB 1 ; 每个簇cluster的扇区数必须为1个扇区
DW 1 ; FAT的预留扇区数包含boot扇区
DB 2 ; FAT表的数量通常为2
DW 224 ; 根目录文件的最大值一般设为224项
DW 2880 ; 磁盘的扇区总数若为0则代表超过65535个扇区需要使用22行记录
DB 0xf0 ; 磁盘的种类本项目中设为0xf0代表1.44MB的软盘)
DW 9 ; 每个FAT的长度必须为9扇区
DW 18 ; 1个磁道track拥有的扇区数必须是18
DW 2 ; 磁头数必须为2
DD 0 ; 隐藏的扇区数
DD 2880 ; 大容量扇区总数若16行记录的值为0则使用本行记录扇区数
DB 0 ; 中断0x13的设备号
DB 0 ; Windows NT标识符
DB 0x29 ; 扩展引导标识
DD 0xffffffff ; 卷序列号
DB "HARIBOTEOS " ; 卷标11字节
DB "FAT12 " ; 文件系统类型8字节
RESB 18 ; 空18字节
; 程序核心
entry:
MOV AX, 0 ; 初始化寄存器
MOV SS, AX
MOV SP, 0x7c00
MOV DS, AX
; 读取硬盘
MOV AX, 0x0820
MOV ES, AX
MOV CH, 0 ; 柱面0
MOV DH, 0 ; 磁头0
MOV CL, 2 ; 扇区2
readloop:
MOV SI, 0 ; 记录失败次数的寄存器
retry:
MOV AH, 0x02 ; AH=0x02读盘
MOV AL, 1 ; 1个扇区
MOV BX, 0
MOV DL, 0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JNC next ; 没出错跳转到next
ADD SI, 1 ; 失败次数+1
CMP SI, 5 ; 失败次数是否达到5次
JAE error ; 失败次数达到5次跳转到error
MOV AH, 0x00
MOV DL, 0x00 ; A驱动器
INT 0x13 ; 重置驱动器
JMP retry
next:
MOV AX, ES ; 把内存地址后移0x200
ADD AX, 0x0020
MOV ES, AX ; 实现ES += 0x0020的目的
; 扇区范围 118
ADD CL, 1 ; 扇区加1
CMP CL, 18 ; 扇区是否达到18
JBE readloop ; 小于等于18扇区则跳转到readloop
MOV CL, 1 ; 恢复到扇区1
; 磁头范围 01正面0反面1
ADD DH, 1
CMP DH, 2
JB readloop ; 磁头未达到2则跳转到readloop
MOV DH, 0
; 柱面范围 0 79
ADD CH, 1
CMP CH, CYLS
JB readloop ; 读取指定数量的柱面未达到CYLS则跳转readloop
; 读取完毕跳转到haribote.sys执行
MOV [0x0ff0], CH ; 记下IPL读了多远谷歌翻译自IPLがどこまで読んだのかをメモ
JMP 0xc200
fin:
HLT ; CPU停止等待指令
JMP fin ; 无限循环
error:
MOV SI, msg
putloop:
MOV AL, [SI]
ADD SI, 1 ; SI加1
CMP AL, 0
JE fin
MOV AH, 0x0e ; 显示一个文字
MOV BX, 15 ; 指定字符颜色
INT 0x10 ; 调用显卡BIOS
JMP putloop
msg:
DB 0x0a, 0x0a ; 两个换行
DB "load error"
DB 0x0a ; 换行
DB 0
RESB 0x1fe - ($ - $$) ; 填写0x00直到0x001fe
DB 0x55, 0xaa

32
day16/kernel.ld Normal file

@ -0,0 +1,32 @@
ENTRY( main )
MEMORY
{
rom : ORIGIN = 0x000000, LENGTH = 0x280000
ram : ORIGIN = 0x280000, LENGTH = 0x020000
}
SECTIONS
{
. = 0x0000;
.text :
{
*(.text.main);
*(.text);
} > rom AT > ram
.rodata :
{
*(.rodata)
} > ram
.data :
{
*(.data)
} > ram
.bss :
{
*(.bss)
} > ram
}

32
day16/keyboard.c Normal file

@ -0,0 +1,32 @@
#include "keyboard.h"
#include "fifo.h"
#include "int.h"
#include "io.h"
struct FIFO32 *keyfifo;
int keydata0;
void wait_KBC_sendready(void) {
for (;;) {
if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
break;
}
}
}
void init_keyboard(struct FIFO32 *fifo, int data0) {
keyfifo = fifo;
keydata0 = data0;
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
wait_KBC_sendready();
io_out8(PORT_KEYDAT, KBC_MODE);
}
void int_handler21(int *esp) {
io_out8(PIC0_OCW2, 0x61); // 通知PIC IRQ-1的受理已经完成
int data = io_in8(PORT_KEYDAT);
fifo32_put(keyfifo, data + keydata0);
}

@ -0,0 +1,12 @@
#ifndef _STDARG_H
#define _STDARG_H
typedef __builtin_va_list va_list;
#define va_start(ap, last) __builtin_va_start(ap, last)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#define va_end(ap) __builtin_va_end(ap)
#endif // _STDARG_H

@ -0,0 +1,13 @@
#ifndef _STDIO_H
#define _STDIO_H
#include <stdarg.h>
#ifndef NULL
#define NULL ((void *)0)
#endif // NULL
int sprintf(char *s, const char *format, ...);
int vsprintf(char *s, const char *format, va_list args);
#endif // _STDIO_H

161
day16/libc/stdio/stdio.c Normal file

@ -0,0 +1,161 @@
#include <stdarg.h>
#include <stdio.h>
struct SprintBuf {
char *buf;
int count;
};
struct PrintNumAttr {
int base;
int width;
int pad;
int uppercase;
int negative;
};
void printnum(void (*fputch)(char, void *), void *data, unsigned long num,
struct PrintNumAttr attr) {
if (num >= attr.base) {
attr.width -= 1;
printnum(fputch, data, num / attr.base, attr);
} else {
while (--attr.width > attr.negative) {
fputch(attr.pad, data);
}
if (attr.negative) {
fputch('-', data);
}
}
if (attr.uppercase) {
fputch("0123456789ABCDEF"[num % attr.base], data);
} else {
fputch("0123456789abcdef"[num % attr.base], data);
}
}
void vprintfmt(void (*fputch)(char, void *), void *data, const char *fmt,
va_list ap) {
int ch;
unsigned long num;
char *str;
struct PrintNumAttr attr;
while (1) {
while ((ch = *fmt++) != '%') {
fputch(ch, data);
if (ch == '\0') {
return;
}
}
num = 0;
attr.base = 0;
attr.pad = ' ';
attr.width = 0;
attr.negative = 0;
attr.uppercase = 0;
reswitch:
switch (ch = *fmt++) {
case '0':
attr.pad = '0';
goto reswitch;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (attr.width = 0;; ++fmt) {
attr.width = attr.width * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9')
break;
}
goto reswitch;
case 'c':
fputch(va_arg(ap, int), data);
break;
case 'd':
num = va_arg(ap, int);
if ((long)num < 0) {
attr.negative = 1;
num = -(long)num;
}
attr.base = 10;
printnum(fputch, data, num, attr);
break;
case 'p':
fputch('0', data);
fputch('x', data);
num = (unsigned long)va_arg(ap, void *);
attr.base = 16;
printnum(fputch, data, num, attr);
break;
case 's':
str = va_arg(ap, char *);
if (str == NULL) {
str = "<null>";
}
while (*str != '\0') {
fputch(*str, data);
str++;
}
break;
case 'x':
num = va_arg(ap, unsigned int);
attr.base = 16;
printnum(fputch, data, num, attr);
break;
case 'X':
num = va_arg(ap, unsigned int);
attr.base = 16;
attr.uppercase = 1;
printnum(fputch, data, num, attr);
break;
case '%':
fputch('%', data);
break;
default:
break;
}
}
}
void sprint_putch(char c, struct SprintBuf *data) {
*data->buf++ = c;
data->count++;
}
int vsprintf(char *s, const char *format, va_list ap) {
struct SprintBuf buf = {s, 0};
vprintfmt((void *)sprint_putch, &buf, format, ap);
return buf.count;
}
int sprintf(char *s, const char *format, ...) {
va_list ap;
int ret;
va_start(ap, format);
ret = vsprintf(s, format, ap);
va_end(ap);
return ret;
}

191
day16/memory.c Normal file

@ -0,0 +1,191 @@
#include "memory.h"
#include "io.h"
unsigned int memtest(unsigned int start, unsigned int end) {
char flg486 = 0;
unsigned int eflg, cr0;
eflg = io_load_eflags();
eflg |= EFLAGS_AC_BIT; // AC-bit = 1
io_store_eflags(eflg);
eflg = io_load_eflags();
if ((eflg & EFLAGS_AC_BIT)) {
// 如果是i386即使设定AC=1也会自动变回到0
flg486 = 1;
}
eflg &= ~EFLAGS_AC_BIT; // AC-bit = 0
io_store_eflags(eflg);
if (flg486) {
cr0 = io_load_cr0();
cr0 |= CR0_CACHE_DISABLE; // 禁止缓存
io_store_cr0(cr0);
}
unsigned int ret = memtest_sub(start, end);
if (flg486) {
cr0 = io_load_cr0();
cr0 &= ~CR0_CACHE_DISABLE; // 允许缓存
io_store_cr0(cr0);
}
return ret;
}
/**
* 便
*/
unsigned int memtest_sub(unsigned int start, unsigned int end) {
unsigned int i, *p, old, pat0 = 0xaa55aa55, pat1 = 0x55aa55aa;
for (i = start; i <= end; i += 0x1000) {
p = (unsigned int *)(i + 0xffc);
old = *p; // 先记住修改前的值
*p = pat0; // 试写
*p ^= 0xffffffff; // 反转
if (*p != pat1) {
// 检查反转结果
not_memory:
*p = old;
break;
}
*p ^= 0xffffffff; // 再次反转
if (*p != pat0) {
// 检查值是否恢复
goto not_memory;
}
*p = old;
}
return i;
}
void memman_init(struct MemMan *man) {
man->frees = 0; // 可用信息数目
man->maxfrees = 0; // 用于观察可用状况frees的最大值
man->lostsize = 0; // 释放失败的内存的大小总和
man->losts = 0; // 释放失败次数
}
/**
*
*/
unsigned int memman_total(struct MemMan *man) {
unsigned int i, t = 0;
for (i = 0; i < man->frees; i++) {
t += man->free[i].size;
}
return t;
}
/**
*
*/
unsigned int memman_alloc(struct MemMan *man, unsigned int size) {
for (unsigned int i = 0; i < man->frees; i++) {
if (man->free[i].size >= size) {
// 找到了足够大的内存
unsigned int a = man->free[i].addr;
man->free[i].addr += size;
man->free[i].size -= size;
if (man->free[i].size == 0) {
// 如果free[i]变成了0就减掉一条可用信息
man->frees--;
for (; i < man->frees; i++) {
man->free[i] = man->free[i + 1]; // 代入结构体
}
}
return a;
}
}
return 0; // 没有可用空间
}
unsigned int memman_alloc_4k(struct MemMan *man, unsigned int size) {
size = (size + 0xfff) & 0xfffff000;
return memman_alloc(man, size);
}
/**
*
*/
int memman_free(struct MemMan *man, unsigned int addr, unsigned int size) {
int i, j;
for (i = 0; i < man->frees; i++) {
if (man->free[i].addr > addr) {
break;
}
}
// free[i - 1].addr < addr < free[i].addr
if (i > 0) {
// 前面有可用内存
if (man->free[i - 1].addr + man->free[i - 1].size == addr) {
// 可以与前面的可用内存归纳到一起
man->free[i - 1].size += size;
if (i < man->frees) {
// 后面也是
if (addr + size == man->free[i].addr) {
// 也可以与后面的可用内存归纳到一起
man->free[i - 1].size += man->free[i].size;
// man->free[i]删除
// free[i]变成0后归纳到前面去
man->frees--;
for (; i < man->frees; i++) {
man->free[i] = man->free[i + 1]; // 结构体赋值
}
}
}
}
}
// 不能与前面的可用空间归纳到一起
if (i < man->frees) {
// 后面还有
if (addr + size == man->free[i].addr) {
man->free[i].addr = addr;
man->free[i].size += size;
return 0; // 成功完成
}
}
// 既不能与前面归纳到一起,也不能与后面归纳到一起
if (man->frees < MEMMAN_FREES) {
// free[i]之后的,向后移动,腾出一点可用空间
for (j = man->frees; j > i; j--) {
man->free[j] = man->free[j - 1];
}
man->frees++;
if (man->maxfrees < man->frees) {
man->maxfrees = man->frees; // 更新最大值
}
man->free[i].addr = addr;
man->free[i].size = size;
return 0; // 成功完成
}
// 不能往后移动
man->losts++;
man->lostsize += size;
return -1;
}
int memman_free_4k(struct MemMan *man, unsigned int addr, unsigned int size) {
size = (size + 0xfff) & 0xfffff000;
return memman_free(man, addr, size);
}

72
day16/mouse.c Normal file

@ -0,0 +1,72 @@
#include "mouse.h"
#include "fifo.h"
#include "int.h"
#include "io.h"
#include "keyboard.h"
struct FIFO32 *mousefifo;
int mousedata0;
void enable_mouse(struct FIFO32 *fifo, int data0, struct MouseDec *mdec) {
mousefifo = fifo;
mousedata0 = data0;
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
wait_KBC_sendready();
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
mdec->phase = 0;
}
int mouse_decode(struct MouseDec *mdec, unsigned char dat) {
if (mdec->phase == 0) {
// 等待鼠标的0xfa状态
if (dat == 0xfa) {
mdec->phase = 1;
}
return 0;
} else if (mdec->phase == 1) {
// 等待鼠标的第一个字节
if ((dat & 0xc8) == 0x08) {
// 如果第一个字节正确
mdec->buf[0] = dat;
mdec->phase = 2;
}
return 0;
} else if (mdec->phase == 2) {
// 等待鼠标的第二个字节
mdec->buf[1] = dat;
mdec->phase = 3;
return 0;
} else if (mdec->phase == 3) {
// 等待鼠标的第三个字节
mdec->buf[2] = dat;
mdec->phase = 1;
mdec->btn = mdec->buf[0] & 0x07;
mdec->x = mdec->buf[1];
mdec->y = mdec->buf[2];
if ((mdec->buf[0] & 0x10) != 0) {
mdec->x |= 0xffffff00;
}
if ((mdec->buf[0] & 0x20) != 0) {
mdec->y |= 0xffffff00;
}
mdec->y = -mdec->y; // 鼠标的y方向与画面符号相反
return 1;
}
return -1;
}
void int_handler2c(int *esp) {
io_out8(PIC1_OCW2, 0x64); // 通知PIC1 IRQ-12的受理已经完成
io_out8(PIC0_OCW2, 0x62); // 通知PIC0 IRQ-02的受理已经完成
int data = io_in8(PORT_KEYDAT);
fifo32_put(mousefifo, data + mousedata0);
}

81
day16/mtask.c Normal file

@ -0,0 +1,81 @@
#include <stdio.h>
#include "desctbl.h"
#include "memory.h"
#include "task.h"
#include "timer.h"
struct TaskCtl *taskctl;
struct Timer *task_timer;
struct Task *task_init(struct MemMan *memman) {
struct SegmentDescriptor *gdt = (struct SegmentDescriptor *)ADR_GDT;
taskctl = (struct TaskCtl *)memman_alloc_4k(memman, sizeof(struct TaskCtl));
for (int i = 0; i < MAX_TASKS; i++) {
taskctl->tasks0[i].flags = 0;
taskctl->tasks0[i].sel = (TASK_GDT0 + i) * 8;
set_segmdesc(gdt + TASK_GDT0 + i, 103, (int)&taskctl->tasks0[i].tss,
AR_TSS32);
}
struct Task *task = task_alloc();
task->flags = 2; // 活动中标志
taskctl->running = 1;
taskctl->now = 0;
taskctl->tasks[0] = task;
load_tr(task->sel);
task_timer = timer_alloc();
timer_set_timer(task_timer, 2);
return task;
}
struct Task *task_alloc(void) {
struct Task *task;
for (int i = 0; i < MAX_TASKS; i++) {
if (taskctl->tasks0[i].flags == 0) {
task = &taskctl->tasks0[i];
task->flags = 1; // 正在使用标志
task->tss.eflags = 0x00000202; // IF = 1;
task->tss.eax = 0;
task->tss.ecx = 0;
task->tss.edx = 0;
task->tss.ebx = 0;
task->tss.ebp = 0;
task->tss.esi = 0;
task->tss.edi = 0;
task->tss.es = 0;
task->tss.ds = 0;
task->tss.fs = 0;
task->tss.gs = 0;
task->tss.ldtr = 0;
task->tss.iomap = 0x40000000;
return task;
}
}
return NULL;
}
void task_run(struct Task *task) {
task->flags = 2; // 活动中标志
taskctl->tasks[taskctl->running] = task;
taskctl->running++;
}
void task_switch(void) {
timer_set_timer(task_timer, 2);
if (taskctl->running >= 2) {
taskctl->now++;
if (taskctl->now == taskctl->running) {
taskctl->now = 0;
}
far_jmp(0, taskctl->tasks[taskctl->now]->sel);
}
}

16
day16/pm.asm Normal file

@ -0,0 +1,16 @@
[BITS 32]
GLOBAL load_gdtr, load_idtr
[SECTION .text]
load_gdtr: ; void load_gdt(int limit, int addr);
MOV AX, [ESP+4] ; limit
MOV [ESP+6], AX
LGDT [ESP+6]
RET
load_idtr: ; void load_idt(int limit, int addr);
MOV AX, [ESP+4] ; limit
MOV [ESP+6], AX
LIDT [ESP+6]
RET

265
day16/sheet.c Normal file

@ -0,0 +1,265 @@
#include <stdio.h>
#include "memory.h"
#include "sheet.h"
struct Shtctl *shtctl_init(struct MemMan *memman, unsigned char *vram,
int xsize, int ysize) {
struct Shtctl *ctl =
(struct Shtctl *)memman_alloc_4k(memman, sizeof(struct Shtctl));
if (!ctl) {
return NULL;
}
ctl->map = (unsigned char *)memman_alloc_4k(memman, xsize * ysize);
if (!ctl->map) {
memman_free_4k(memman, (int)ctl, sizeof(struct Shtctl));
return NULL;
}
ctl->vram = vram;
ctl->xsize = xsize;
ctl->ysize = ysize;
ctl->top = -1; // 没有Sheet
for (int i = 0; i < MAX_SHEETS; i++) {
ctl->sheets0[i].flags = 0; // 标记为未使用
ctl->sheets0[i].ctl = ctl; // 记录所属
}
return ctl;
}
struct Sheet *sheet_alloc(struct Shtctl *ctl) {
struct Sheet *sht;
for (int i = 0; i < MAX_SHEETS; i++) {
if (ctl->sheets0[i].flags == 0) {
sht = &ctl->sheets0[i];
sht->flags = SHEET_USE; // 标记为正在使用
sht->height = -1; // 隐藏
return sht;
}
}
return NULL;
}
void sheet_setbuf(struct Sheet *sht, unsigned char *buf, int xsize, int ysize,
int col_inv) {
sht->buf = buf;
sht->bxsize = xsize;
sht->bysize = ysize;
sht->col_inv = col_inv;
}
void sheet_updown(struct Sheet *sht, int height) {
struct Shtctl *ctl = sht->ctl;
int h, old = sht->height; // 记录设置前的高度
// 如果指定的高度过高或过低,则进行修正
if (height > ctl->top + 1) {
height = ctl->top + 1;
}
if (height < -1) {
height = -1;
}
sht->height = height; // 设定高度
// 下面主要是进行sheets[]的重新排列
if (old > height) {
// 比以前低
if (height >= 0) {
// 把中间的往上提
for (h = old; h > height; h--) {
ctl->sheets[h] = ctl->sheets[h - 1];
ctl->sheets[h]->height = h;
}
ctl->sheets[height] = sht;
sheet_refreshmap(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize,
sht->vy0 + sht->bysize, height + 1);
sheet_refreshsub(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize,
sht->vy0 + sht->bysize, height + 1, old);
} else {
// 隐藏
if (ctl->top > old) {
// 把上面的降下来
for (h = old; h < ctl->top; h++) {
ctl->sheets[h] = ctl->sheets[h + 1];
ctl->sheets[h]->height = h;
}
}
ctl->top--; // 由于显示中的图层减少了一个,所以最上面的图层高度下降
sheet_refreshmap(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize,
sht->vy0 + sht->bysize, 0);
sheet_refreshsub(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize,
sht->vy0 + sht->bysize, 0, old - 1);
}
} else if (old < height) {
// 比以前高
if (old >= 0) {
// 把中间的拉下去
for (h = old; h < height; h++) {
ctl->sheets[h] = ctl->sheets[h + 1];
ctl->sheets[h]->height = h;
}
ctl->sheets[height] = sht;
} else {
// 由隐藏状态转为显示状态
// 将已在上面的提上来
for (h = ctl->top; h >= height; h--) {
ctl->sheets[h + 1] = ctl->sheets[h];
ctl->sheets[h + 1]->height = h + 1;
}
ctl->sheets[height] = sht;
ctl->top++; // 由于已显示的图层增加了1个所以最上面的图层高度增加
}
sheet_refreshmap(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize,
sht->vy0 + sht->bysize, height);
sheet_refreshsub(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize,
sht->vy0 + sht->bysize, height, height);
}
}
void sheet_refreshmap(struct Shtctl *ctl, int vx0, int vy0, int vx1, int vy1,
int h0) {
unsigned char *map = ctl->map;
if (vx0 < 0) {
vx0 = 0;
}
if (vy0 < 0) {
vy0 = 0;
}
if (vx1 > ctl->xsize) {
vx1 = ctl->xsize;
}
if (vy1 > ctl->ysize) {
vy1 = ctl->ysize;
}
for (int h = h0; h <= ctl->top; h++) {
struct Sheet *sht = ctl->sheets[h];
unsigned char sid = sht - ctl->sheets0;
unsigned char *buf = sht->buf;
int bx0 = vx0 - sht->vx0;
int by0 = vy0 - sht->vy0;
int bx1 = vx1 - sht->vx0;
int by1 = vy1 - sht->vy0;
if (bx0 < 0) {
bx0 = 0;
}
if (by0 < 0) {
by0 = 0;
}
if (bx1 > sht->bxsize) {
bx1 = sht->bxsize;
}
if (by1 > sht->bysize) {
by1 = sht->bysize;
}
for (int by = by0; by < by1; by++) {
int vy = sht->vy0 + by;
for (int bx = bx0; bx < bx1; bx++) {
int vx = sht->vx0 + bx;
if (buf[by * sht->bxsize + bx] != sht->col_inv) {
map[vy * ctl->xsize + vx] = sid;
}
}
}
}
}
void sheet_refreshsub(struct Shtctl *ctl, int vx0, int vy0, int vx1, int vy1,
int h0, int h1) {
unsigned char *buf, *vram = ctl->vram, *map = ctl->map;
struct Sheet *sht;
if (vx0 < 0) {
vx0 = 0;
}
if (vy0 < 0) {
vy0 = 0;
}
if (vx1 > ctl->xsize) {
vx1 = ctl->xsize;
}
if (vy1 > ctl->ysize) {
vy1 = ctl->ysize;
}
for (int h = h0; h <= h1; h++) {
sht = ctl->sheets[h];
buf = sht->buf;
unsigned char sid = sht - ctl->sheets0;
// 使用vx0 ~ vy1对bx0 ~ by1进行倒推
int bx0 = vx0 - sht->vx0;
int by0 = vy0 - sht->vy0;
int bx1 = vx1 - sht->vx0;
int by1 = vy1 - sht->vy0;
if (bx0 < 0) {
bx0 = 0;
}
if (by0 < 0) {
by0 = 0;
}
if (bx1 > sht->bxsize) {
bx1 = sht->bxsize;
}
if (by1 > sht->bysize) {
by1 = sht->bysize;
}
for (int by = by0; by < by1; by++) {
int vy = sht->vy0 + by;
for (int bx = bx0; bx < bx1; bx++) {
int vx = sht->vx0 + bx;
if (map[vy * ctl->xsize + vx] == sid) {
vram[vy * ctl->xsize + vx] = buf[by * sht->bxsize + bx];
}
}
}
}
}
void sheet_refresh(struct Sheet *sht, int bx0, int by0, int bx1, int by1) {
if (sht->height >= 0) {
// 如果正在显示,则按新图层的信息刷新画面
sheet_refreshsub(sht->ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1,
sht->vy0 + by1, sht->height, sht->height);
}
}
void sheet_slide(struct Sheet *sht, int vx0, int vy0) {
struct Shtctl *ctl = sht->ctl;
int old_vx0 = sht->vx0, old_vy0 = sht->vy0;
sht->vx0 = vx0;
sht->vy0 = vy0;
if (sht->height >= 0) {
// 如果正在显示,则按新图层的信息刷新画面
sheet_refreshmap(ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize,
old_vy0 + sht->bysize, 0);
sheet_refreshmap(ctl, vx0, vy0, vx0 + sht->bxsize, vy0 + sht->bysize,
sht->height);
sheet_refreshsub(ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize,
old_vy0 + sht->bysize, 0, sht->height - 1);
sheet_refreshsub(ctl, vx0, vy0, vx0 + sht->bxsize, vy0 + sht->bysize,
sht->height, sht->height);
}
}
void sheet_free(struct Sheet *sht) {
if (sht->height >= 0) {
sheet_updown(sht, -1); // 如果处于显示状态,则先设定为隐藏
}
sht->flags = 0; // 未使用标志
}

12
day16/task.asm Normal file

@ -0,0 +1,12 @@
[BITS 32]
GLOBAL load_tr
GLOBAL far_jmp
load_tr: ; void load_tr(int tr);
LTR [ESP+4] ; tr
RET
far_jmp: ; void far_jmp(int eip, int cs);
JMP FAR [ESP+4]
RET

115
day16/timer.c Normal file

@ -0,0 +1,115 @@
#include <stdio.h>
#include "int.h"
#include "io.h"
#include "task.h"
#include "timer.h"
struct TimerCtl timerctl;
void init_pit(void) {
io_out8(PIT_CTRL, 0x34);
io_out8(PIT_CNT0, 0x9c);
io_out8(PIT_CNT0, 0x2e);
for (int i = 0; i < MAX_TIMER; i++) {
timerctl.timers0[i].flags = 0;
}
struct Timer *t = timer_alloc();
t->timeout = 0xffffffff;
t->flags = TIMER_FLAGS_USING;
t->next = NULL;
timerctl.count = 0;
timerctl.t0 = t;
timerctl.next = 0xffffffff;
}
struct Timer *timer_alloc(void) {
for (int i = 0; i < MAX_TIMER; i++) {
if (timerctl.timers0[i].flags == 0) {
timerctl.timers0[i].flags = TIMER_FLAGS_ALLOC;
return &timerctl.timers0[i];
}
}
return NULL;
}
void timer_free(struct Timer *timer) { timer->flags = 0; }
void timer_init(struct Timer *timer, struct FIFO32 *fifo, int data) {
timer->fifo = fifo;
timer->data = data;
}
void timer_set_timer(struct Timer *timer, unsigned int timeout) {
int eflags;
struct Timer *t, *s;
timer->timeout = timeout + timerctl.count;
timer->flags = TIMER_FLAGS_USING;
eflags = io_load_eflags();
io_cli();
t = timerctl.t0;
if (timer->timeout <= t->timeout) {
timerctl.t0 = timer;
timer->next = t;
timerctl.next = timer->timeout;
io_store_eflags(eflags);
return;
}
// 搜索插入未知
for (;;) {
s = t;
t = t->next;
if (timer->timeout <= t->timeout) {
s->next = timer;
timer->next = t;
io_store_eflags(eflags);
return;
}
}
}
void int_handler20(int *esp) {
char ts = 0;
io_out8(PIC0_OCW2, 0x60); // 接收IRQ-00信号通知PIC
timerctl.count++;
if (timerctl.next > timerctl.count) {
return;
}
struct Timer *timer = timerctl.t0;
for (;;) {
// timers的定时器都处于动作中所以不确认flags
if (timer->timeout > timerctl.count) {
break;
}
// 超时
timer->flags = TIMER_FLAGS_ALLOC;
if (timer != task_timer) {
fifo32_put(timer->fifo, timer->data);
} else {
ts = 1;
}
timer = timer->next;
}
timerctl.t0 = timer;
timerctl.next = timer->timeout;
if (ts) {
task_switch();
}
}

67
day16/window.c Normal file

@ -0,0 +1,67 @@
#include "window.h"
#include "graphic.h"
void make_window8(unsigned char *buf, int xsize, int ysize, char *title) {
static char closebtn[14][16] = {
"OOOOOOOOOOOOOOO@",
"OQQQQQQQQQQQQQ$@",
"OQQQQQQQQQQQQQ$@",
"OQQQ@@QQQQ@@QQ$@",
"OQQQQ@@QQ@@QQQ$@",
"OQQQQQ@@@@QQQQ$@",
"OQQQQQQ@@QQQQQ$@",
"OQQQQQ@@@@QQQQ$@",
"OQQQQ@@QQ@@QQQ$@",
"OQQQ@@QQQQ@@QQ$@",
"OQQQQQQQQQQQQQ$@",
"OQQQQQQQQQQQQQ$@",
"O$$$$$$$$$$$$$$@",
"@@@@@@@@@@@@@@@@"};
box_fill8(buf, xsize, COL8_C6C6C6, 0, 0, xsize - 1, 0);
box_fill8(buf, xsize, COL8_FFFFFF, 1, 1, xsize - 2, 1);
box_fill8(buf, xsize, COL8_C6C6C6, 0, 0, 0, ysize - 1);
box_fill8(buf, xsize, COL8_FFFFFF, 1, 1, 1, ysize - 2);
box_fill8(buf, xsize, COL8_848484, xsize - 2, 1, xsize - 2, ysize - 2);
box_fill8(buf, xsize, COL8_000000, xsize - 1, 0, xsize - 1, ysize - 1);
box_fill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3);
box_fill8(buf, xsize, COL8_000084, 3, 3, xsize - 4, 20);
box_fill8(buf, xsize, COL8_848484, 1, ysize - 2, xsize - 2, ysize - 2);
box_fill8(buf, xsize, COL8_000000, 0, ysize - 1, xsize - 1, ysize - 1);
put_fonts8_asc(buf, xsize, 24, 4, COL8_FFFFFF, title);
for (int y = 0; y < 14; y++) {
for (int x = 0; x < 16; x++) {
char c = closebtn[y][x];
switch (c) {
case '@':
c = COL8_000000;
break;
case '$':
c = COL8_848484;
break;
case 'Q':
c = COL8_C6C6C6;
break;
default:
c = COL8_FFFFFF;
break;
}
buf[(5 + y) * xsize + (xsize - 21 + x)] = c;
}
}
}
void make_textbox8(struct Sheet *sht, int x0, int y0, int sx, int sy, int c) {
int x1 = x0 + sx, y1 = y0 + sy;
box_fill8(sht->buf, sht->bxsize, COL8_848484, x0 - 2, y0 - 3, x1 + 1, y0 - 3);
box_fill8(sht->buf, sht->bxsize, COL8_848484, x0 - 3, y0 - 3, x0 - 3, y1 + 1);
box_fill8(sht->buf, sht->bxsize, COL8_FFFFFF, x0 - 3, y1 + 2, x1 + 1, y1 + 2);
box_fill8(sht->buf, sht->bxsize, COL8_FFFFFF, x1 + 2, y0 - 3, x1 + 2, y1 + 2);
box_fill8(sht->buf, sht->bxsize, COL8_000000, x0 - 1, y0 - 2, x1 + 0, y0 - 2);
box_fill8(sht->buf, sht->bxsize, COL8_000000, x0 - 2, y0 - 2, x0 - 2, y1 + 0);
box_fill8(sht->buf, sht->bxsize, COL8_C6C6C6, x0 - 2, y1 + 1, x1 + 1, y1 + 1);
box_fill8(sht->buf, sht->bxsize, COL8_C6C6C6, x1 + 1, y0 - 2, x1 + 0, y1 + 1);
box_fill8(sht->buf, sht->bxsize, c, x0 - 1, y0 - 1, x1 + 0, y1 + 0);
}