Day 16.
This commit is contained in:
parent
c39414d479
commit
6606a5ee63
70
day16/Makefile
Normal file
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
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
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
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
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
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
4611
day16/hankaku.asm
Normal file
File diff suppressed because it is too large
Load Diff
16
day16/include/bootpack.h
Normal file
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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的目的
|
||||
|
||||
; 扇区范围 1~18
|
||||
ADD CL, 1 ; 扇区加1
|
||||
CMP CL, 18 ; 扇区是否达到18
|
||||
JBE readloop ; 小于等于18扇区则跳转到readloop
|
||||
|
||||
MOV CL, 1 ; 恢复到扇区1
|
||||
; 磁头范围 0~1(正面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
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
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);
|
||||
}
|
12
day16/libc/include/stdarg.h
Normal file
12
day16/libc/include/stdarg.h
Normal file
@ -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
|
13
day16/libc/include/stdio.h
Normal file
13
day16/libc/include/stdio.h
Normal file
@ -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
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
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
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
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
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
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
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
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
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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user