mirror of
https://github.com/yourtion/30dayMakeOS.git
synced 2026-02-05 02:53:19 +08:00
Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c512f3e391 | ||
|
|
d046ca64a4 | ||
|
|
b306606282 | ||
|
|
c8a0464c52 | ||
|
|
908570a673 | ||
|
|
d84bab78e1 | ||
|
|
907b8c61ce | ||
|
|
efb6028e00 | ||
|
|
9475d3d828 | ||
|
|
b27c562b98 | ||
|
|
bde8ac972b | ||
|
|
8264071442 | ||
|
|
d77f778b8e | ||
|
|
991da3f569 | ||
|
|
36da3e87a9 | ||
|
|
2281f38f62 | ||
|
|
698022572a | ||
|
|
591fa69b74 | ||
|
|
041e2a4b52 | ||
|
|
8de80dcee7 | ||
|
|
975bb8c8b7 | ||
|
|
76e2a4a389 | ||
|
|
dc29fff86f | ||
|
|
7fca384104 | ||
|
|
f0aa4d853d | ||
|
|
eadcb88a6c | ||
|
|
75a82443c1 | ||
|
|
02980d3422 | ||
|
|
c718be8fd3 | ||
|
|
fc60d80e6c | ||
|
|
3d141c39c8 | ||
|
|
c53ce4a594 | ||
|
|
e846dbd700 | ||
|
|
4241eb28d8 | ||
|
|
154a2c5791 | ||
|
|
0fd3455e42 | ||
|
|
17b146940c | ||
|
|
e1d760124c | ||
|
|
ae675195d4 | ||
|
|
d07ff5dd44 | ||
|
|
b33125f047 | ||
|
|
4d0e2f1af1 | ||
|
|
2fb28adf44 | ||
|
|
ff3319e083 | ||
|
|
984b2886d0 | ||
|
|
a381fbedc3 | ||
|
|
4054ce43ab | ||
|
|
afac998433 | ||
|
|
5f793069ba | ||
|
|
51e4e06648 | ||
|
|
60fce32986 | ||
|
|
2f2d306783 | ||
|
|
021ae344eb | ||
|
|
99f265e6fb | ||
|
|
61e0d9dc90 | ||
|
|
f237d1fe81 | ||
|
|
88f4f449bb | ||
|
|
9bee564a96 | ||
|
|
916b0b2957 | ||
|
|
1fdb7736f7 | ||
|
|
0306107e15 | ||
|
|
e3745ac531 | ||
|
|
b85921ccfd | ||
|
|
216f914b48 | ||
|
|
2b669176d8 | ||
|
|
5c040441cc | ||
|
|
7ab551c54e | ||
|
|
9299bf0a55 | ||
|
|
50572f2dbe | ||
|
|
b9768c4277 | ||
|
|
96ece33092 | ||
|
|
e924b8c36c | ||
|
|
e467f40129 | ||
|
|
70f82648ee | ||
|
|
7bd6635921 | ||
|
|
ec1f016838 | ||
|
|
04c2e4c402 | ||
|
|
44c9f8c227 | ||
|
|
991f1056ad | ||
|
|
dc8c366fc0 | ||
|
|
30c62ffbd0 | ||
|
|
8534999b7b | ||
|
|
de40053c3d | ||
|
|
b331ed91e2 | ||
|
|
760b403ecb | ||
|
|
cf0fb1c9dc | ||
|
|
035c23b075 | ||
|
|
98c3c56a93 | ||
|
|
df34b85242 | ||
|
|
4d15dbaaba | ||
|
|
f78ffbbfb6 | ||
|
|
5ebfdafc68 | ||
|
|
494bcc1785 | ||
|
|
8832513349 | ||
|
|
44e51ca946 | ||
|
|
dab5bd893a | ||
|
|
5204ca9f32 | ||
|
|
36f64a7650 | ||
|
|
90ad25656d | ||
|
|
d17af6a0f3 | ||
|
|
37eb729596 | ||
|
|
6da34e7cbe | ||
|
|
7517c5e770 | ||
|
|
2984048f76 | ||
|
|
0a166bc8c2 | ||
|
|
2982ab2699 | ||
|
|
c4f1c13129 | ||
|
|
a1142b3a5f | ||
|
|
792c8b7082 | ||
|
|
9e1c17b4d1 | ||
|
|
b50c16d8e0 | ||
|
|
3aea776876 | ||
|
|
375f5deda4 | ||
|
|
71b32daf8d | ||
|
|
b55a841397 | ||
|
|
2c7fd6f752 | ||
|
|
39e9bc34ea | ||
|
|
2898207560 | ||
|
|
f9e8f2736c | ||
|
|
cfde17cc0d | ||
|
|
de008d0ec5 | ||
|
|
62313438f8 | ||
|
|
005f8bd0c3 | ||
|
|
819aa38f4e | ||
|
|
4f53925b6f | ||
|
|
0cc548c0c2 | ||
|
|
89043ef7a8 | ||
|
|
feb468177b | ||
|
|
6e72b241d9 | ||
|
|
b221cc77bc | ||
|
|
bf248a9f46 | ||
|
|
e620e5e6ed | ||
|
|
49287c1505 | ||
|
|
1b0cdedaf0 | ||
|
|
f52d4fef0f | ||
|
|
8af696896d |
1
09_day/!cons_9x.bat
Normal file
1
09_day/!cons_9x.bat
Normal file
@@ -0,0 +1 @@
|
||||
command
|
||||
1
09_day/!cons_nt.bat
Normal file
1
09_day/!cons_nt.bat
Normal file
@@ -0,0 +1 @@
|
||||
cmd.exe
|
||||
93
09_day/Makefile
Normal file
93
09_day/Makefile
Normal file
@@ -0,0 +1,93 @@
|
||||
OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \
|
||||
int.obj fifo.obj keyboard.obj mouse.obj
|
||||
|
||||
TOOLPATH = ../z_tools/
|
||||
INCPATH = ../z_tools/haribote/
|
||||
|
||||
MAKE = $(TOOLPATH)make.exe -r
|
||||
NASK = $(TOOLPATH)nask.exe
|
||||
CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
|
||||
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
|
||||
OBJ2BIM = $(TOOLPATH)obj2bim.exe
|
||||
MAKEFONT = $(TOOLPATH)makefont.exe
|
||||
BIN2OBJ = $(TOOLPATH)bin2obj.exe
|
||||
BIM2HRB = $(TOOLPATH)bim2hrb.exe
|
||||
RULEFILE = $(TOOLPATH)haribote/haribote.rul
|
||||
EDIMG = $(TOOLPATH)edimg.exe
|
||||
IMGTOL = $(TOOLPATH)imgtol.com
|
||||
COPY = copy
|
||||
DEL = del
|
||||
|
||||
# 默认动作
|
||||
|
||||
default :
|
||||
$(MAKE) img
|
||||
|
||||
# 镜像文件生成
|
||||
|
||||
ipl10.bin : ipl10.nas Makefile
|
||||
$(NASK) ipl10.nas ipl10.bin ipl10.lst
|
||||
|
||||
asmhead.bin : asmhead.nas Makefile
|
||||
$(NASK) asmhead.nas asmhead.bin asmhead.lst
|
||||
|
||||
hankaku.bin : hankaku.txt Makefile
|
||||
$(MAKEFONT) hankaku.txt hankaku.bin
|
||||
|
||||
hankaku.obj : hankaku.bin Makefile
|
||||
$(BIN2OBJ) hankaku.bin hankaku.obj _hankaku
|
||||
|
||||
bootpack.bim : $(OBJS_BOOTPACK) Makefile
|
||||
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
|
||||
$(OBJS_BOOTPACK)
|
||||
# 3MB+64KB=3136KB
|
||||
|
||||
bootpack.hrb : bootpack.bim Makefile
|
||||
$(BIM2HRB) bootpack.bim bootpack.hrb 0
|
||||
|
||||
haribote.sys : asmhead.bin bootpack.hrb Makefile
|
||||
copy /B asmhead.bin+bootpack.hrb haribote.sys
|
||||
|
||||
haribote.img : ipl10.bin haribote.sys Makefile
|
||||
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
|
||||
wbinimg src:ipl10.bin len:512 from:0 to:0 \
|
||||
copy from:haribote.sys to:@: \
|
||||
imgout:haribote.img
|
||||
|
||||
# 其他指令
|
||||
|
||||
%.gas : %.c bootpack.h Makefile
|
||||
$(CC1) -o $*.gas $*.c
|
||||
|
||||
%.nas : %.gas Makefile
|
||||
$(GAS2NASK) $*.gas $*.nas
|
||||
|
||||
%.obj : %.nas Makefile
|
||||
$(NASK) $*.nas $*.obj $*.lst
|
||||
|
||||
# 运行程序
|
||||
|
||||
img :
|
||||
$(MAKE) haribote.img
|
||||
|
||||
run :
|
||||
$(MAKE) img
|
||||
$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
|
||||
$(MAKE) -C ../z_tools/qemu
|
||||
|
||||
install :
|
||||
$(MAKE) img
|
||||
$(IMGTOL) w a: haribote.img
|
||||
|
||||
clean :
|
||||
-$(DEL) *.bin
|
||||
-$(DEL) *.lst
|
||||
-$(DEL) *.obj
|
||||
-$(DEL) bootpack.map
|
||||
-$(DEL) bootpack.bim
|
||||
-$(DEL) bootpack.hrb
|
||||
-$(DEL) haribote.sys
|
||||
|
||||
src_only :
|
||||
$(MAKE) clean
|
||||
-$(DEL) haribote.img
|
||||
146
09_day/asmhead.nas
Normal file
146
09_day/asmhead.nas
Normal file
@@ -0,0 +1,146 @@
|
||||
; haribote-os boot asm
|
||||
; TAB=4
|
||||
|
||||
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 ; 图像缓冲区的起始地址
|
||||
|
||||
ORG 0xc200 ; 这个的程序要被装载的内存地址
|
||||
|
||||
; 画面设置
|
||||
|
||||
MOV AL,0x13 ; VGA显卡,320x200x8bit
|
||||
MOV AH,0x00
|
||||
INT 0x10
|
||||
MOV BYTE [VMODE],8 ; 屏幕的模式(参考C语言的引用)
|
||||
MOV WORD [SCRNX],320
|
||||
MOV WORD [SCRNY],200
|
||||
MOV DWORD [VRAM],0x000a0000
|
||||
|
||||
; 通过 BIOS 获取指示灯状态
|
||||
|
||||
MOV AH,0x02
|
||||
INT 0x16 ; keyboard BIOS
|
||||
MOV [LEDS],AL
|
||||
|
||||
; PIC关闭一切中断
|
||||
; 根据AT兼容机的规格,如果要初始化PIC,
|
||||
; 必须在CLI之前进行,否则有时会挂起。
|
||||
; 随后进行PIC的初始化。
|
||||
|
||||
MOV AL,0xff
|
||||
OUT 0x21,AL
|
||||
NOP ; 如果连续执行OUT指令,有些机种会无法正常运行
|
||||
OUT 0xa1,AL
|
||||
|
||||
CLI ; 禁止CPU级别的中断
|
||||
|
||||
; 为了让CPU能够访问1MB以上的内存空间,设定A20GATE
|
||||
|
||||
CALL waitkbdout
|
||||
MOV AL,0xd1
|
||||
OUT 0x64,AL
|
||||
CALL waitkbdout
|
||||
MOV AL,0xdf ; enable A20
|
||||
OUT 0x60,AL
|
||||
CALL waitkbdout
|
||||
|
||||
; 切换到保护模式
|
||||
|
||||
[INSTRSET "i486p"] ; 说明使用486指令
|
||||
|
||||
LGDT [GDTR0] ; 设置临时GDT
|
||||
MOV EAX,CR0
|
||||
AND EAX,0x7fffffff ; 设bit31为0(禁用分页)
|
||||
OR EAX,0x00000001 ; bit0到1转换(保护模式过渡)
|
||||
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
|
||||
|
||||
; 必须由asmhead来完成的工作,至此全部完毕
|
||||
; 以后就交由bootpack来完成
|
||||
|
||||
; bootpack启动
|
||||
|
||||
MOV EBX,BOTPAK
|
||||
MOV ECX,[EBX+16]
|
||||
ADD ECX,3 ; ECX += 3;
|
||||
SHR ECX,2 ; ECX /= 4;
|
||||
JZ skip ; 没有要转送的东西时
|
||||
MOV ESI,[EBX+20] ; 转送源
|
||||
ADD ESI,EBX
|
||||
MOV EDI,[EBX+12] ; 转送目标
|
||||
CALL memcpy
|
||||
skip:
|
||||
MOV ESP,[EBX+12] ; 堆栈的初始化
|
||||
JMP DWORD 2*8:0x0000001b
|
||||
|
||||
waitkbdout:
|
||||
IN AL,0x64
|
||||
AND AL,0x02
|
||||
IN AL,0x60 ; 空读(为了清空数据接收缓冲区中的垃圾数据)
|
||||
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地址前缀大小
|
||||
|
||||
ALIGNB 16
|
||||
GDT0:
|
||||
RESB 8 ; 初始值
|
||||
DW 0xffff,0x0000,0x9200,0x00cf ; 可以读写的段(segment)32bit
|
||||
DW 0xffff,0x0000,0x9a28,0x0047 ; 可执行的文件的32bit寄存器(bootpack用)
|
||||
|
||||
DW 0
|
||||
GDTR0:
|
||||
DW 8*3-1
|
||||
DD GDT0
|
||||
|
||||
ALIGNB 16
|
||||
bootpack:
|
||||
256
09_day/bootpack.c
Normal file
256
09_day/bootpack.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/* bootpackのメイン */
|
||||
|
||||
#include "bootpack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#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);
|
||||
void memman_init(struct MEMMAN *man);
|
||||
unsigned int memman_total(struct MEMMAN *man);
|
||||
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
|
||||
#define MEMMAN_ADDR 0x003c0000
|
||||
|
||||
void HariMain(void)
|
||||
{
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
char s[40], mcursor[256], keybuf[32], mousebuf[128];
|
||||
int mx, my, i;
|
||||
struct MOUSE_DEC mdec;
|
||||
|
||||
unsigned int memtotal;
|
||||
struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
|
||||
|
||||
init_gdtidt();
|
||||
init_pic();
|
||||
io_sti(); /* IDT/PIC的初始化已经完成,于是开放CPU的中断 */
|
||||
|
||||
fifo8_init(&keyfifo, 32, keybuf);
|
||||
fifo8_init(&mousefifo, 128, mousebuf);
|
||||
io_out8(PIC0_IMR, 0xf9); /* 开放PIC1和键盘中断(11111001) */
|
||||
io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */
|
||||
|
||||
init_keyboard();
|
||||
enable_mouse(&mdec);
|
||||
memtotal = memtest(0x00400000, 0xbfffffff);
|
||||
memman_init(memman);
|
||||
memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 0x0009efff */
|
||||
memman_free(memman, 0x00400000, memtotal - 0x00400000);
|
||||
|
||||
init_palette();
|
||||
init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
|
||||
mx = (binfo->scrnx - 16) / 2; /* 计算画面中心坐标 */
|
||||
my = (binfo->scrny - 28 - 16) / 2;
|
||||
init_mouse_cursor8(mcursor, COL8_008484);
|
||||
putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);
|
||||
sprintf(s, "(%d, %d)", mx, my);
|
||||
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
|
||||
|
||||
sprintf(s, "memory %dMB free : %dKB", memtotal / (1024 * 1024), memman_total(memman) / 1024);
|
||||
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 32, COL8_FFFFFF, s);
|
||||
|
||||
for (;;) {
|
||||
io_cli();
|
||||
if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
|
||||
io_stihlt();
|
||||
} else {
|
||||
if (fifo8_status(&keyfifo) != 0) {
|
||||
i = fifo8_get(&keyfifo);
|
||||
io_sti();
|
||||
sprintf(s, "%02X", i);
|
||||
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
|
||||
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
|
||||
} else if (fifo8_status(&mousefifo) != 0) {
|
||||
i = fifo8_get(&mousefifo);
|
||||
io_sti();
|
||||
if (mouse_decode(&mdec, i) != 0) {
|
||||
/* 3字节都凑齐了,所以把它们显示出来*/
|
||||
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
|
||||
if ((mdec.btn & 0x01) != 0) {
|
||||
s[1] = 'L';
|
||||
}
|
||||
if ((mdec.btn & 0x02) != 0) {
|
||||
s[3] = 'R';
|
||||
}
|
||||
if ((mdec.btn & 0x04) != 0) {
|
||||
s[2] = 'C';
|
||||
}
|
||||
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
|
||||
putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
|
||||
/* 鼠标指针的移动 */
|
||||
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, mx, my, mx + 15, my + 15); /* 隐藏鼠标 */
|
||||
mx += mdec.x;
|
||||
my += mdec.y;
|
||||
if (mx < 0) {
|
||||
mx = 0;
|
||||
}
|
||||
if (my < 0) {
|
||||
my = 0;
|
||||
}
|
||||
if (mx > binfo->scrnx - 16) {
|
||||
mx = binfo->scrnx - 16;
|
||||
}
|
||||
if (my > binfo->scrny - 16) {
|
||||
my = binfo->scrny - 16;
|
||||
}
|
||||
sprintf(s, "(%3d, %3d)", mx, my);
|
||||
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 0, 79, 15); /* 隐藏坐标 */
|
||||
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); /* 显示坐标 */
|
||||
putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16); /* 描画鼠标 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define EFLAGS_AC_BIT 0x00040000
|
||||
#define CR0_CACHE_DISABLE 0x60000000
|
||||
|
||||
unsigned int memtest(unsigned int start, unsigned int end)
|
||||
{
|
||||
char flg486 = 0;
|
||||
unsigned int eflg, cr0, i;
|
||||
|
||||
/* 确认CPU是386还是486以上的 */
|
||||
eflg = io_load_eflags();
|
||||
eflg |= EFLAGS_AC_BIT; /* AC-bit = 1 */
|
||||
io_store_eflags(eflg);
|
||||
eflg = io_load_eflags();
|
||||
if ((eflg & EFLAGS_AC_BIT) != 0) {
|
||||
/* 如果是386,即使设定AC=1,AC的值还会自动回到0 */
|
||||
flg486 = 1;
|
||||
}
|
||||
|
||||
eflg &= ~EFLAGS_AC_BIT; /* AC-bit = 0 */
|
||||
io_store_eflags(eflg);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 |= CR0_CACHE_DISABLE; /* 禁止缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
i = memtest_sub(start, end);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 &= ~CR0_CACHE_DISABLE; /* 允许缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void memman_init(struct MEMMAN *man){
|
||||
man->frees = 0; /* 可用信息数目 */
|
||||
man->maxfrees = 0; /* 用于观察可用状况:frees的最大值 */
|
||||
man->lostsize = 0; /* 释放失败的内存的大小总和 */
|
||||
man->losts = 0; /* 释放失败次数 */
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
/* 分配 */
|
||||
{
|
||||
unsigned int i, a;
|
||||
for (i = 0; i < man->frees; i++) {
|
||||
if (man->free[i].size >= size) {
|
||||
/* 找到了足够大的内存 */
|
||||
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; /* 没有可用空间 */
|
||||
}
|
||||
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size)
|
||||
/* 释放 */
|
||||
{
|
||||
int i, j;
|
||||
/* 为便于归纳内存,将free[]按照addr的顺序排列 */
|
||||
/* 所以,先决定应该放在哪里 */
|
||||
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]; /* 结构体赋值 */
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0; /* 成功完成 */
|
||||
}
|
||||
}
|
||||
/* 不能与前面的可用空间归纳到一起 */
|
||||
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; /* 失败 */
|
||||
}
|
||||
118
09_day/bootpack.h
Normal file
118
09_day/bootpack.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/* asmhead.nas */
|
||||
struct BOOTINFO { /* 0x0ff0-0x0fff */
|
||||
char cyls; /* 启动区读磁盘读到此为止 */
|
||||
char leds; /* 启动时键盘的LED的状态 */
|
||||
char vmode; /* 显卡模式为多少位彩色 */
|
||||
char reserve;
|
||||
short scrnx, scrny; /* 画面分辨率 */
|
||||
char *vram;
|
||||
};
|
||||
#define ADR_BOOTINFO 0x00000ff0
|
||||
|
||||
/* naskfunc.nas */
|
||||
void io_hlt(void);
|
||||
void io_cli(void);
|
||||
void io_sti(void);
|
||||
void io_out8(int port, int data);
|
||||
int io_load_eflags(void);
|
||||
void io_store_eflags(int eflags);
|
||||
void load_gdtr(int limit, int addr);
|
||||
void load_idtr(int limit, int addr);
|
||||
void asm_inthandler21(void);
|
||||
void asm_inthandler27(void);
|
||||
void asm_inthandler2c(void);
|
||||
|
||||
/* fifo.c */
|
||||
struct FIFO8 {
|
||||
unsigned char *buf;
|
||||
int p, q, size, free, flags;
|
||||
};
|
||||
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);
|
||||
|
||||
/* graphic.c */
|
||||
void init_palette(void);
|
||||
void set_palette(int start, int end, unsigned char *rgb);
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
|
||||
void init_screen8(char *vram, int x, int y);
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
|
||||
void init_mouse_cursor8(char *mouse, char bc);
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize);
|
||||
#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
|
||||
|
||||
/* dsctbl.c */
|
||||
struct SEGMENT_DESCRIPTOR {
|
||||
short limit_low, base_low;
|
||||
char base_mid, access_right;
|
||||
char limit_high, base_high;
|
||||
};
|
||||
struct GATE_DESCRIPTOR {
|
||||
short offset_low, selector;
|
||||
char dw_count, access_right;
|
||||
short offset_high;
|
||||
};
|
||||
void init_gdtidt(void);
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
|
||||
#define ADR_IDT 0x0026f800
|
||||
#define LIMIT_IDT 0x000007ff
|
||||
#define ADR_GDT 0x00270000
|
||||
#define LIMIT_GDT 0x0000ffff
|
||||
#define ADR_BOTPAK 0x00280000
|
||||
#define LIMIT_BOTPAK 0x0007ffff
|
||||
#define AR_DATA32_RW 0x4092
|
||||
#define AR_CODE32_ER 0x409a
|
||||
#define AR_INTGATE32 0x008e
|
||||
|
||||
/* int.c */
|
||||
void init_pic(void);
|
||||
void inthandler27(int *esp);
|
||||
#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
|
||||
|
||||
/* keyboard.c */
|
||||
void inthandler21(int *esp);
|
||||
void wait_KBC_sendready(void);
|
||||
void init_keyboard(void);
|
||||
extern struct FIFO8 keyfifo;
|
||||
#define PORT_KEYDAT 0x0060
|
||||
#define PORT_KEYCMD 0x0064
|
||||
|
||||
/* mouse.c */
|
||||
struct MOUSE_DEC {
|
||||
unsigned char buf[3], phase;
|
||||
int x, y, btn;
|
||||
};
|
||||
void inthandler2c(int *esp);
|
||||
void enable_mouse(struct MOUSE_DEC *mdec);
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);
|
||||
extern struct FIFO8 mousefifo;
|
||||
56
09_day/dsctbl.c
Normal file
56
09_day/dsctbl.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* GDT、IDT、descriptor table 关系处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_gdtidt(void)
|
||||
{
|
||||
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
|
||||
struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) ADR_IDT;
|
||||
int i;
|
||||
|
||||
/* GDT初始化 */
|
||||
for (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_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);
|
||||
load_gdtr(LIMIT_GDT, ADR_GDT);
|
||||
|
||||
/* IDT初始化 */
|
||||
for (i = 0; i <= LIMIT_IDT / 8; i++) {
|
||||
set_gatedesc(idt + i, 0, 0, 0);
|
||||
}
|
||||
load_idtr(LIMIT_IDT, ADR_IDT);
|
||||
|
||||
/* IDT设置*/
|
||||
set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
57
09_day/fifo.c
Normal file
57
09_day/fifo.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* FIFO */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define FLAGS_OVERRUN 0x0001
|
||||
|
||||
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
|
||||
/* 初始化FIFO缓冲区 */
|
||||
{
|
||||
fifo->size = size;
|
||||
fifo->buf = buf;
|
||||
fifo->free = size; /* 缓冲区大小 */
|
||||
fifo->flags = 0;
|
||||
fifo->p = 0; /* 下一个数据写入位置 */
|
||||
fifo->q = 0; /* 下一个数据读出位置 */
|
||||
return;
|
||||
}
|
||||
|
||||
int fifo8_put(struct FIFO8 *fifo, unsigned char data)
|
||||
/* 向FIFO传送数据并保存 */
|
||||
{
|
||||
if (fifo->free == 0) {
|
||||
/* 没有空间了,溢出 */
|
||||
fifo->flags |= FLAGS_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
fifo->buf[fifo->p] = data;
|
||||
fifo->p++;
|
||||
if (fifo->p == fifo->size) {
|
||||
fifo->p = 0;
|
||||
}
|
||||
fifo->free--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fifo8_get(struct FIFO8 *fifo)
|
||||
/* 从FIFO取得一个数据 */
|
||||
{
|
||||
int data;
|
||||
if (fifo->free == fifo->size) {
|
||||
/* 如果缓冲区为空则返回-1 */
|
||||
return -1;
|
||||
}
|
||||
data = fifo->buf[fifo->q];
|
||||
fifo->q++;
|
||||
if (fifo->q == fifo->size) {
|
||||
fifo->q = 0;
|
||||
}
|
||||
fifo->free++;
|
||||
return data;
|
||||
}
|
||||
|
||||
int fifo8_status(struct FIFO8 *fifo)
|
||||
/* 报告一下积攒是数据量 */
|
||||
{
|
||||
return fifo->size - fifo->free;
|
||||
}
|
||||
157
09_day/graphic.c
Normal file
157
09_day/graphic.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/* 关于绘图部分的处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_palette(void)
|
||||
{
|
||||
static unsigned char table_rgb[16 * 3] = {
|
||||
0x00, 0x00, 0x00, /* 0:黑 */
|
||||
0xff, 0x00, 0x00, /* 1:梁红 */
|
||||
0x00, 0xff, 0x00, /* 2:亮绿 */
|
||||
0xff, 0xff, 0x00, /* 3:亮黄 */
|
||||
0x00, 0x00, 0xff, /* 4:亮蓝 */
|
||||
0xff, 0x00, 0xff, /* 5:亮紫 */
|
||||
0x00, 0xff, 0xff, /* 6:浅亮蓝 */
|
||||
0xff, 0xff, 0xff, /* 7:白 */
|
||||
0xc6, 0xc6, 0xc6, /* 8:亮灰 */
|
||||
0x84, 0x00, 0x00, /* 9:暗红 */
|
||||
0x00, 0x84, 0x00, /* 10:暗绿 */
|
||||
0x84, 0x84, 0x00, /* 11:暗黄 */
|
||||
0x00, 0x00, 0x84, /* 12:暗青 */
|
||||
0x84, 0x00, 0x84, /* 13:暗紫 */
|
||||
0x00, 0x84, 0x84, /* 14:浅暗蓝 */
|
||||
0x84, 0x84, 0x84 /* 15:暗灰 */
|
||||
};
|
||||
set_palette(0, 15, table_rgb);
|
||||
return;
|
||||
|
||||
/* C语言中的static char语句只能用于数据,相当于汇编中的DB指令 */
|
||||
}
|
||||
|
||||
void set_palette(int start, int end, unsigned char *rgb)
|
||||
{
|
||||
int i, eflags;
|
||||
eflags = io_load_eflags(); /* 记录中断许可标志的值 */
|
||||
io_cli(); /* 将中断许可标志置为0,禁止中断 */
|
||||
io_out8(0x03c8, start);
|
||||
for (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); /* 复原中断许可标志 */
|
||||
return;
|
||||
}
|
||||
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
|
||||
{
|
||||
int x, y;
|
||||
for (y = y0; y <= y1; y++) {
|
||||
for (x = x0; x <= x1; x++)
|
||||
vram[y * xsize + x] = c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_screen8(char *vram, int x, int y)
|
||||
{
|
||||
boxfill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1);
|
||||
|
||||
boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5);
|
||||
boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3);
|
||||
boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3);
|
||||
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24);
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3);
|
||||
return;
|
||||
}
|
||||
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
|
||||
{
|
||||
int i;
|
||||
char *p, d /* data */;
|
||||
for (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; }
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
|
||||
{
|
||||
extern char hankaku[4096];
|
||||
/* C语言中,字符串都是以0x00结尾 */
|
||||
for (; *s != 0x00; s++) {
|
||||
putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
|
||||
x += 8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_mouse_cursor8(char *mouse, char bc)
|
||||
/* 鼠标的数据准备(16x16) */
|
||||
{
|
||||
static char cursor[16][16] = {
|
||||
"**************..",
|
||||
"*OOOOOOOOOOO*...",
|
||||
"*OOOOOOOOOO*....",
|
||||
"*OOOOOOOOO*.....",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOO**OOO*.....",
|
||||
"*OOO*..*OOO*....",
|
||||
"*OO*....*OOO*...",
|
||||
"*O*......*OOO*..",
|
||||
"**........*OOO*.",
|
||||
"*..........*OOO*",
|
||||
"............*OO*",
|
||||
".............***"
|
||||
};
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < 16; y++) {
|
||||
for (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize)
|
||||
{
|
||||
int x, y;
|
||||
for (y = 0; y < pysize; y++) {
|
||||
for (x = 0; x < pxsize; x++) {
|
||||
vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
4609
09_day/hankaku.txt
Normal file
4609
09_day/hankaku.txt
Normal file
File diff suppressed because it is too large
Load Diff
38
09_day/int.c
Normal file
38
09_day/int.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*初始化关系 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_pic(void)
|
||||
/* PIC初始化 */
|
||||
{
|
||||
io_out8(PIC0_IMR, 0xff ); /* 禁止所有中断 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 禁止所有中断 */
|
||||
|
||||
io_out8(PIC0_ICW1, 0x11 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 11111011 PIC1以外全部禁止 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 11111111 禁止所有中断 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define PORT_KEYDAT 0x0060
|
||||
|
||||
void inthandler27(int *esp)
|
||||
/* PIC0中断的不完整策略 */
|
||||
/* 这个中断在Athlon64X2上通过芯片组提供的便利,只需执行一次 */
|
||||
/* 这个中断只是接收,不执行任何操作 */
|
||||
/* 为什么不处理?
|
||||
→ 因为这个中断可能是电气噪声引发的、只是处理一些重要的情况。*/
|
||||
{
|
||||
io_out8(PIC0_OCW2, 0x67); /* 通知PIC的IRQ-07(参考7-1) */
|
||||
return;
|
||||
}
|
||||
109
09_day/ipl10.nas
Normal file
109
09_day/ipl10.nas
Normal file
@@ -0,0 +1,109 @@
|
||||
; haribote-ipl
|
||||
; TAB=4
|
||||
|
||||
CYLS EQU 10 ; 声明CYLS=10
|
||||
|
||||
ORG 0x7c00 ; 指明程序装载地址
|
||||
|
||||
; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code
|
||||
|
||||
JMP entry
|
||||
DB 0x90
|
||||
DB "HARIBOTE" ; 启动扇区名称(8字节)
|
||||
DW 512 ; 每个扇区(sector)大小(必须512字节)
|
||||
DB 1 ; 簇(cluster)大小(必须为1个扇区)
|
||||
DW 1 ; FAT起始位置(一般为第一个扇区)
|
||||
DB 2 ; FAT个数(必须为2)
|
||||
DW 224 ; 根目录大小(一般为224项)
|
||||
DW 2880 ; 该磁盘大小(必须为2880扇区1440*1024/512)
|
||||
DB 0xf0 ; 磁盘类型(必须为0xf0)
|
||||
DW 9 ; FAT的长度(必??9扇区)
|
||||
DW 18 ; 一个磁道(track)有几个扇区(必须为18)
|
||||
DW 2 ; 磁头数(必??2)
|
||||
DD 0 ; 不使用分区,必须是0
|
||||
DD 2880 ; 重写一次磁盘大小
|
||||
DB 0,0,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 ; 没出错则跳转到fin
|
||||
ADD SI,1 ; 往SI加1
|
||||
CMP SI,5 ; 比较SI与5
|
||||
JAE error ; SI >= 5 跳转到error
|
||||
MOV AH,0x00
|
||||
MOV DL,0x00 ; A驱动器
|
||||
INT 0x13 ; 重置驱动器
|
||||
JMP retry
|
||||
next:
|
||||
MOV AX,ES ; 把内存地址后移0x200(512/16十六进制转换)
|
||||
ADD AX,0x0020
|
||||
MOV ES,AX ; ADD ES,0x020因为没有ADD ES,只能通过AX进行
|
||||
ADD CL,1 ; 往CL里面加1
|
||||
CMP CL,18 ; 比较CL与18
|
||||
JBE readloop ; CL <= 18 跳转到readloop
|
||||
MOV CL,1
|
||||
ADD DH,1
|
||||
CMP DH,2
|
||||
JB readloop ; DH < 2 跳转到readloop
|
||||
MOV DH,0
|
||||
ADD CH,1
|
||||
CMP CH,CYLS
|
||||
JB readloop ; CH < CYLS 跳转到readloop
|
||||
|
||||
; 读取完毕,跳转到haribote.sys执行!
|
||||
MOV [0x0ff0],CH ; IPLがどこまで読んだのかをメモ
|
||||
JMP 0xc200
|
||||
|
||||
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
|
||||
|
||||
fin:
|
||||
HLT ; 让CPU停止,等待指令
|
||||
JMP fin ; 无限循环
|
||||
|
||||
msg:
|
||||
DB 0x0a, 0x0a ; 换行两次
|
||||
DB "load error"
|
||||
DB 0x0a ; 换行
|
||||
DB 0
|
||||
|
||||
RESB 0x7dfe-$ ; 填写0x00直到0x001fe
|
||||
|
||||
DB 0x55, 0xaa
|
||||
39
09_day/keyboard.c
Normal file
39
09_day/keyboard.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* 键盘控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO8 keyfifo;
|
||||
|
||||
void inthandler21(int *esp) {
|
||||
/* 来自PS/2键盘的中断 */
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
unsigned char data, s[4];
|
||||
io_out8(PIC0_OCW2, 0x61); /* 通知PIC IRQ-01 已经受理完毕 */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo8_put(&keyfifo, data);
|
||||
return;
|
||||
}
|
||||
|
||||
#define PORT_KEYSTA 0x0064
|
||||
#define KEYSTA_SEND_NOTREADY 0x02
|
||||
#define KEYCMD_WRITE_MODE 0x60
|
||||
#define KBC_MODE 0x47
|
||||
|
||||
void wait_KBC_sendready(void) {
|
||||
/* 等待键盘控制电路准备完毕 */
|
||||
for (;;) {
|
||||
if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_keyboard(void) {
|
||||
/* 初始化键盘控制电路 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, KBC_MODE);
|
||||
return;
|
||||
}
|
||||
1
09_day/make.bat
Normal file
1
09_day/make.bat
Normal file
@@ -0,0 +1 @@
|
||||
..\z_tools\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
70
09_day/mouse.c
Normal file
70
09_day/mouse.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/* 鼠标控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO8 mousefifo;
|
||||
|
||||
void inthandler2c(int *esp) {
|
||||
/* 来自PS/2鼠标的中断 */
|
||||
unsigned char data;
|
||||
io_out8(PIC1_OCW2, 0x64); /* 通知PIC IRQ-12 已经受理完毕 */
|
||||
io_out8(PIC0_OCW2, 0x62); /* 通知PIC IRQ-02 已经受理完毕 */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo8_put(&mousefifo, data);
|
||||
return;
|
||||
}
|
||||
|
||||
#define KEYCMD_SENDTO_MOUSE 0xd4
|
||||
#define MOUSECMD_ENABLE 0xf4
|
||||
|
||||
void enable_mouse(struct MOUSE_DEC *mdec) {
|
||||
/* 鼠标有效 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
|
||||
/* 顺利的话,ACK(0xfa)会被送过来 */
|
||||
mdec->phase = 0; /* 等待0xfa的阶段 */
|
||||
return;
|
||||
}
|
||||
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat) {
|
||||
if (mdec->phase == 0) {
|
||||
/* 等待鼠标的0xfa的阶段 */
|
||||
if (dat == 0xfa) {
|
||||
mdec->phase = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 1) {
|
||||
/* 等待鼠标第一字节的阶段 */
|
||||
mdec->buf[0] = dat;
|
||||
mdec->phase = 2;
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 2) {
|
||||
/* 等待鼠标第二字节的阶段 */
|
||||
mdec->buf[1] = dat;
|
||||
mdec->phase = 3;
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
/* 鼠标的y方向与画面符号相反 */
|
||||
mdec->y = - mdec->y;
|
||||
return 1;
|
||||
}
|
||||
/* 应该不可能到这里来 */
|
||||
return -1;
|
||||
}
|
||||
184
09_day/naskfunc.nas
Normal file
184
09_day/naskfunc.nas
Normal file
@@ -0,0 +1,184 @@
|
||||
; naskfunc
|
||||
; TAB=4
|
||||
|
||||
[FORMAT "WCOFF"] ; 制作目标文件的模式
|
||||
[INSTRSET "i486p"] ; 使用到486为止的指令
|
||||
[BITS 32] ; 3制作32位模式用的机器语言
|
||||
[FILE "naskfunc.nas"] ; 文件名
|
||||
|
||||
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 _load_gdtr, _load_idtr
|
||||
GLOBAL _load_cr0, _store_cr0
|
||||
GLOBAL _asm_inthandler21, _asm_inthandler27, _asm_inthandler2c
|
||||
GLOBAL _memtest_sub
|
||||
EXTERN _inthandler21, _inthandler27, _inthandler2c
|
||||
|
||||
[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 EAX,[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 ; PUSH EFLAGS
|
||||
POP EAX
|
||||
RET
|
||||
|
||||
_io_store_eflags: ; void io_store_eflags(int eflags);
|
||||
MOV EAX,[ESP+4]
|
||||
PUSH EAX
|
||||
POPFD ; POP EFLAGS
|
||||
RET
|
||||
|
||||
_load_gdtr: ; void load_gdtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LGDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_idtr: ; void load_idtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LIDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_cr0: ; int load_cr0(void);
|
||||
MOV EAX,CR0
|
||||
RET
|
||||
|
||||
_store_cr0: ; void store_cr0(int cr0);
|
||||
MOV EAX,[ESP+4]
|
||||
MOV CR0,EAX
|
||||
RET
|
||||
|
||||
_asm_inthandler21:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler21
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler27:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler27
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler2c:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler2c
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_memtest_sub: ; unsigned int memtest_sub(unsigned int start, unsigned int end)
|
||||
PUSH EDI ; (由于还要使用EBX, ESI, EDI)
|
||||
PUSH ESI
|
||||
PUSH EBX
|
||||
MOV ESI,0xaa55aa55 ; pat0 = 0xaa55aa55;
|
||||
MOV EDI,0x55aa55aa ; pat1 = 0x55aa55aa;
|
||||
MOV EAX,[ESP+12+4] ; i = start;
|
||||
mts_loop:
|
||||
MOV EBX,EAX
|
||||
ADD EBX,0xffc ; p = i + 0xffc;
|
||||
MOV EDX,[EBX] ; old = *p;
|
||||
MOV [EBX],ESI ; *p = pat0;
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP EDI,[EBX] ; if (*p != pat1) goto fin;
|
||||
JNE mts_fin
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP ESI,[EBX] ; if (*p != pat0) goto fin;
|
||||
JNE mts_fin
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
ADD EAX,0x1000 ; i += 0x1000;
|
||||
CMP EAX,[ESP+12+8] ; if (i <= end) goto mts_loop;
|
||||
JBE mts_loop
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
mts_fin:
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
1
10_day/!cons_9x.bat
Normal file
1
10_day/!cons_9x.bat
Normal file
@@ -0,0 +1 @@
|
||||
command
|
||||
1
10_day/!cons_nt.bat
Normal file
1
10_day/!cons_nt.bat
Normal file
@@ -0,0 +1 @@
|
||||
cmd.exe
|
||||
93
10_day/Makefile
Normal file
93
10_day/Makefile
Normal file
@@ -0,0 +1,93 @@
|
||||
OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \
|
||||
int.obj fifo.obj keyboard.obj mouse.obj memory.obj sheet.obj
|
||||
|
||||
TOOLPATH = ../z_tools/
|
||||
INCPATH = ../z_tools/haribote/
|
||||
|
||||
MAKE = $(TOOLPATH)make.exe -r
|
||||
NASK = $(TOOLPATH)nask.exe
|
||||
CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
|
||||
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
|
||||
OBJ2BIM = $(TOOLPATH)obj2bim.exe
|
||||
MAKEFONT = $(TOOLPATH)makefont.exe
|
||||
BIN2OBJ = $(TOOLPATH)bin2obj.exe
|
||||
BIM2HRB = $(TOOLPATH)bim2hrb.exe
|
||||
RULEFILE = $(TOOLPATH)haribote/haribote.rul
|
||||
EDIMG = $(TOOLPATH)edimg.exe
|
||||
IMGTOL = $(TOOLPATH)imgtol.com
|
||||
COPY = copy
|
||||
DEL = del
|
||||
|
||||
# 默认动作
|
||||
|
||||
default :
|
||||
$(MAKE) img
|
||||
|
||||
# 镜像文件生成
|
||||
|
||||
ipl10.bin : ipl10.nas Makefile
|
||||
$(NASK) ipl10.nas ipl10.bin ipl10.lst
|
||||
|
||||
asmhead.bin : asmhead.nas Makefile
|
||||
$(NASK) asmhead.nas asmhead.bin asmhead.lst
|
||||
|
||||
hankaku.bin : hankaku.txt Makefile
|
||||
$(MAKEFONT) hankaku.txt hankaku.bin
|
||||
|
||||
hankaku.obj : hankaku.bin Makefile
|
||||
$(BIN2OBJ) hankaku.bin hankaku.obj _hankaku
|
||||
|
||||
bootpack.bim : $(OBJS_BOOTPACK) Makefile
|
||||
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
|
||||
$(OBJS_BOOTPACK)
|
||||
# 3MB+64KB=3136KB
|
||||
|
||||
bootpack.hrb : bootpack.bim Makefile
|
||||
$(BIM2HRB) bootpack.bim bootpack.hrb 0
|
||||
|
||||
haribote.sys : asmhead.bin bootpack.hrb Makefile
|
||||
copy /B asmhead.bin+bootpack.hrb haribote.sys
|
||||
|
||||
haribote.img : ipl10.bin haribote.sys Makefile
|
||||
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
|
||||
wbinimg src:ipl10.bin len:512 from:0 to:0 \
|
||||
copy from:haribote.sys to:@: \
|
||||
imgout:haribote.img
|
||||
|
||||
# 其他指令
|
||||
|
||||
%.gas : %.c bootpack.h Makefile
|
||||
$(CC1) -o $*.gas $*.c
|
||||
|
||||
%.nas : %.gas Makefile
|
||||
$(GAS2NASK) $*.gas $*.nas
|
||||
|
||||
%.obj : %.nas Makefile
|
||||
$(NASK) $*.nas $*.obj $*.lst
|
||||
|
||||
# 运行程序
|
||||
|
||||
img :
|
||||
$(MAKE) haribote.img
|
||||
|
||||
run :
|
||||
$(MAKE) img
|
||||
$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
|
||||
$(MAKE) -C ../z_tools/qemu
|
||||
|
||||
install :
|
||||
$(MAKE) img
|
||||
$(IMGTOL) w a: haribote.img
|
||||
|
||||
clean :
|
||||
-$(DEL) *.bin
|
||||
-$(DEL) *.lst
|
||||
-$(DEL) *.obj
|
||||
-$(DEL) bootpack.map
|
||||
-$(DEL) bootpack.bim
|
||||
-$(DEL) bootpack.hrb
|
||||
-$(DEL) haribote.sys
|
||||
|
||||
src_only :
|
||||
$(MAKE) clean
|
||||
-$(DEL) haribote.img
|
||||
146
10_day/asmhead.nas
Normal file
146
10_day/asmhead.nas
Normal file
@@ -0,0 +1,146 @@
|
||||
; haribote-os boot asm
|
||||
; TAB=4
|
||||
|
||||
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 ; 图像缓冲区的起始地址
|
||||
|
||||
ORG 0xc200 ; 这个的程序要被装载的内存地址
|
||||
|
||||
; 画面设置
|
||||
|
||||
MOV AL,0x13 ; VGA显卡,320x200x8bit
|
||||
MOV AH,0x00
|
||||
INT 0x10
|
||||
MOV BYTE [VMODE],8 ; 屏幕的模式(参考C语言的引用)
|
||||
MOV WORD [SCRNX],320
|
||||
MOV WORD [SCRNY],200
|
||||
MOV DWORD [VRAM],0x000a0000
|
||||
|
||||
; 通过 BIOS 获取指示灯状态
|
||||
|
||||
MOV AH,0x02
|
||||
INT 0x16 ; keyboard BIOS
|
||||
MOV [LEDS],AL
|
||||
|
||||
; PIC关闭一切中断
|
||||
; 根据AT兼容机的规格,如果要初始化PIC,
|
||||
; 必须在CLI之前进行,否则有时会挂起。
|
||||
; 随后进行PIC的初始化。
|
||||
|
||||
MOV AL,0xff
|
||||
OUT 0x21,AL
|
||||
NOP ; 如果连续执行OUT指令,有些机种会无法正常运行
|
||||
OUT 0xa1,AL
|
||||
|
||||
CLI ; 禁止CPU级别的中断
|
||||
|
||||
; 为了让CPU能够访问1MB以上的内存空间,设定A20GATE
|
||||
|
||||
CALL waitkbdout
|
||||
MOV AL,0xd1
|
||||
OUT 0x64,AL
|
||||
CALL waitkbdout
|
||||
MOV AL,0xdf ; enable A20
|
||||
OUT 0x60,AL
|
||||
CALL waitkbdout
|
||||
|
||||
; 切换到保护模式
|
||||
|
||||
[INSTRSET "i486p"] ; 说明使用486指令
|
||||
|
||||
LGDT [GDTR0] ; 设置临时GDT
|
||||
MOV EAX,CR0
|
||||
AND EAX,0x7fffffff ; 设bit31为0(禁用分页)
|
||||
OR EAX,0x00000001 ; bit0到1转换(保护模式过渡)
|
||||
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
|
||||
|
||||
; 必须由asmhead来完成的工作,至此全部完毕
|
||||
; 以后就交由bootpack来完成
|
||||
|
||||
; bootpack启动
|
||||
|
||||
MOV EBX,BOTPAK
|
||||
MOV ECX,[EBX+16]
|
||||
ADD ECX,3 ; ECX += 3;
|
||||
SHR ECX,2 ; ECX /= 4;
|
||||
JZ skip ; 没有要转送的东西时
|
||||
MOV ESI,[EBX+20] ; 转送源
|
||||
ADD ESI,EBX
|
||||
MOV EDI,[EBX+12] ; 转送目标
|
||||
CALL memcpy
|
||||
skip:
|
||||
MOV ESP,[EBX+12] ; 堆栈的初始化
|
||||
JMP DWORD 2*8:0x0000001b
|
||||
|
||||
waitkbdout:
|
||||
IN AL,0x64
|
||||
AND AL,0x02
|
||||
IN AL,0x60 ; 空读(为了清空数据接收缓冲区中的垃圾数据)
|
||||
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地址前缀大小
|
||||
|
||||
ALIGNB 16
|
||||
GDT0:
|
||||
RESB 8 ; 初始值
|
||||
DW 0xffff,0x0000,0x9200,0x00cf ; 可以读写的段(segment)32bit
|
||||
DW 0xffff,0x0000,0x9a28,0x0047 ; 可执行的文件的32bit寄存器(bootpack用)
|
||||
|
||||
DW 0
|
||||
GDTR0:
|
||||
DW 8*3-1
|
||||
DD GDT0
|
||||
|
||||
ALIGNB 16
|
||||
bootpack:
|
||||
109
10_day/bootpack.c
Normal file
109
10_day/bootpack.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/* bootpackのメイン */
|
||||
|
||||
#include "bootpack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void HariMain(void)
|
||||
{
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
char s[40], keybuf[32], mousebuf[128];
|
||||
int mx, my, i;
|
||||
unsigned int memtotal;
|
||||
struct MOUSE_DEC mdec;
|
||||
struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
|
||||
struct SHTCTL *shtctl;
|
||||
struct SHEET *sht_back, *sht_mouse;
|
||||
unsigned char *buf_back, buf_mouse[256];
|
||||
|
||||
init_gdtidt();
|
||||
init_pic();
|
||||
io_sti(); /* IDT/PIC的初始化已经完成,于是开放CPU的中断 */
|
||||
|
||||
fifo8_init(&keyfifo, 32, keybuf);
|
||||
fifo8_init(&mousefifo, 128, mousebuf);
|
||||
io_out8(PIC0_IMR, 0xf9); /* 开放PIC1和键盘中断(11111001) */
|
||||
io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */
|
||||
|
||||
init_keyboard();
|
||||
enable_mouse(&mdec);
|
||||
memtotal = memtest(0x00400000, 0xbfffffff);
|
||||
memman_init(memman);
|
||||
memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 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);
|
||||
buf_back = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny);
|
||||
sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); /* 没有透明色 */
|
||||
sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99); /* 透明色号99 */
|
||||
init_screen8(buf_back, binfo->scrnx, binfo->scrny);
|
||||
init_mouse_cursor8(buf_mouse, 99); /* 背景色号99 */
|
||||
sheet_slide(shtctl, sht_back, 0, 0);
|
||||
mx = (binfo->scrnx - 16) / 2; /* 按显示在画面中央来计算坐标 */
|
||||
my = (binfo->scrny - 28 - 16) / 2;
|
||||
sheet_slide(shtctl, sht_mouse, mx, my);
|
||||
sheet_updown(shtctl, sht_back, 0);
|
||||
sheet_updown(shtctl, sht_mouse, 1);
|
||||
sprintf(s, "(%3d, %3d)", mx, my);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
|
||||
sprintf(s, "memory %dMB free : %dKB", memtotal / (1024 * 1024), memman_total(memman) / 1024);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);
|
||||
sheet_refresh(shtctl, sht_back, 0, 0, binfo->scrnx, 48); /* 刷新文字 */
|
||||
|
||||
for (;;) {
|
||||
io_cli();
|
||||
if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
|
||||
io_stihlt();
|
||||
} else {
|
||||
if (fifo8_status(&keyfifo) != 0) {
|
||||
i = fifo8_get(&keyfifo);
|
||||
io_sti();
|
||||
sprintf(s, "%02X", i);
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
|
||||
sheet_refresh(shtctl, sht_back, 0, 16, 16, 32); /* 刷新文字 */
|
||||
} else if (fifo8_status(&mousefifo) != 0) {
|
||||
i = fifo8_get(&mousefifo);
|
||||
io_sti();
|
||||
if (mouse_decode(&mdec, i) != 0) {
|
||||
/* 3字节都凑齐了,所以把它们显示出来*/
|
||||
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
|
||||
if ((mdec.btn & 0x01) != 0) {
|
||||
s[1] = 'L';
|
||||
}
|
||||
if ((mdec.btn & 0x02) != 0) {
|
||||
s[3] = 'R';
|
||||
}
|
||||
if ((mdec.btn & 0x04) != 0) {
|
||||
s[2] = 'C';
|
||||
}
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
|
||||
sheet_refresh(shtctl, sht_back, 32, 16, 32 + 15 * 8, 32); /* 刷新文字 */
|
||||
/* 移动光标 */
|
||||
mx += mdec.x;
|
||||
my += mdec.y;
|
||||
if (mx < 0) {
|
||||
mx = 0;
|
||||
}
|
||||
if (my < 0) {
|
||||
my = 0;
|
||||
}
|
||||
if (mx > binfo->scrnx - 16) {
|
||||
mx = binfo->scrnx - 16;
|
||||
}
|
||||
if (my > binfo->scrny - 16) {
|
||||
my = binfo->scrny - 16;
|
||||
}
|
||||
sprintf(s, "(%3d, %3d)", mx, my);
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 0, 0, 79, 15); /* 消坐标 */
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s); /* 写坐标 */
|
||||
sheet_refresh(shtctl, sht_back, 0, 0, 80, 16); /* 刷新文字 */
|
||||
sheet_slide(shtctl, sht_mouse, mx, my); /* 包含sheet_refresh含sheet_refresh */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
167
10_day/bootpack.h
Normal file
167
10_day/bootpack.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/* asmhead.nas */
|
||||
struct BOOTINFO { /* 0x0ff0-0x0fff */
|
||||
char cyls; /* 启动区读磁盘读到此为止 */
|
||||
char leds; /* 启动时键盘的LED的状态 */
|
||||
char vmode; /* 显卡模式为多少位彩色 */
|
||||
char reserve;
|
||||
short scrnx, scrny; /* 画面分辨率 */
|
||||
char *vram;
|
||||
};
|
||||
#define ADR_BOOTINFO 0x00000ff0
|
||||
|
||||
/* naskfunc.nas */
|
||||
void io_hlt(void);
|
||||
void io_cli(void);
|
||||
void io_sti(void);
|
||||
void io_stihlt(void);
|
||||
int io_in8(int port);
|
||||
void io_out8(int port, int data);
|
||||
int io_load_eflags(void);
|
||||
void io_store_eflags(int eflags);
|
||||
void load_gdtr(int limit, int addr);
|
||||
void load_idtr(int limit, int addr);
|
||||
int load_cr0(void);
|
||||
void store_cr0(int cr0);
|
||||
void asm_inthandler21(void);
|
||||
void asm_inthandler27(void);
|
||||
void asm_inthandler2c(void);
|
||||
unsigned int memtest_sub(unsigned int start, unsigned int end);
|
||||
|
||||
/* fifo.c */
|
||||
struct FIFO8 {
|
||||
unsigned char *buf;
|
||||
int p, q, size, free, flags;
|
||||
};
|
||||
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);
|
||||
|
||||
/* graphic.c */
|
||||
void init_palette(void);
|
||||
void set_palette(int start, int end, unsigned char *rgb);
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
|
||||
void init_screen8(char *vram, int x, int y);
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
|
||||
void init_mouse_cursor8(char *mouse, char bc);
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize);
|
||||
#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
|
||||
|
||||
/* dsctbl.c */
|
||||
struct SEGMENT_DESCRIPTOR {
|
||||
short limit_low, base_low;
|
||||
char base_mid, access_right;
|
||||
char limit_high, base_high;
|
||||
};
|
||||
struct GATE_DESCRIPTOR {
|
||||
short offset_low, selector;
|
||||
char dw_count, access_right;
|
||||
short offset_high;
|
||||
};
|
||||
void init_gdtidt(void);
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
|
||||
#define ADR_IDT 0x0026f800
|
||||
#define LIMIT_IDT 0x000007ff
|
||||
#define ADR_GDT 0x00270000
|
||||
#define LIMIT_GDT 0x0000ffff
|
||||
#define ADR_BOTPAK 0x00280000
|
||||
#define LIMIT_BOTPAK 0x0007ffff
|
||||
#define AR_DATA32_RW 0x4092
|
||||
#define AR_CODE32_ER 0x409a
|
||||
#define AR_INTGATE32 0x008e
|
||||
|
||||
/* int.c */
|
||||
void init_pic(void);
|
||||
void inthandler27(int *esp);
|
||||
#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
|
||||
|
||||
/* keyboard.c */
|
||||
void inthandler21(int *esp);
|
||||
void wait_KBC_sendready(void);
|
||||
void init_keyboard(void);
|
||||
extern struct FIFO8 keyfifo;
|
||||
#define PORT_KEYDAT 0x0060
|
||||
#define PORT_KEYCMD 0x0064
|
||||
|
||||
/* mouse.c */
|
||||
struct MOUSE_DEC {
|
||||
unsigned char buf[3], phase;
|
||||
int x, y, btn;
|
||||
};
|
||||
void inthandler2c(int *esp);
|
||||
void enable_mouse(struct MOUSE_DEC *mdec);
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);
|
||||
extern struct FIFO8 mousefifo;
|
||||
|
||||
/* memory.c */
|
||||
#define MEMMAN_FREES 4090 /* 大约是32KB*/
|
||||
#define MEMMAN_ADDR 0x003c0000
|
||||
|
||||
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);
|
||||
void memman_init(struct MEMMAN *man);
|
||||
unsigned int memman_total(struct MEMMAN *man);
|
||||
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
|
||||
/* sheet.c */
|
||||
#define MAX_SHEETS 256
|
||||
#define SHEET_USE 1
|
||||
|
||||
struct SHEET {
|
||||
unsigned char *buf;
|
||||
int bxsize, bysize, vx0, vy0, col_inv, height, flags;
|
||||
};
|
||||
|
||||
struct SHTCTL {
|
||||
unsigned char *vram;
|
||||
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 SHTCTL *ctl, struct SHEET *sht, int height);
|
||||
void sheet_refresh(struct SHTCTL *ctl, struct SHEET *sht, int bx0, int by0, int bx1, int by1);
|
||||
void sheet_slide(struct SHTCTL *ctl, struct SHEET *sht, int vx0, int vy0);
|
||||
void sheet_free(struct SHTCTL *ctl, struct SHEET *sht);
|
||||
56
10_day/dsctbl.c
Normal file
56
10_day/dsctbl.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* GDT、IDT、descriptor table 关系处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_gdtidt(void)
|
||||
{
|
||||
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
|
||||
struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) ADR_IDT;
|
||||
int i;
|
||||
|
||||
/* GDT初始化 */
|
||||
for (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_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);
|
||||
load_gdtr(LIMIT_GDT, ADR_GDT);
|
||||
|
||||
/* IDT初始化 */
|
||||
for (i = 0; i <= LIMIT_IDT / 8; i++) {
|
||||
set_gatedesc(idt + i, 0, 0, 0);
|
||||
}
|
||||
load_idtr(LIMIT_IDT, ADR_IDT);
|
||||
|
||||
/* IDT设置*/
|
||||
set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
57
10_day/fifo.c
Normal file
57
10_day/fifo.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* FIFO */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define FLAGS_OVERRUN 0x0001
|
||||
|
||||
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
|
||||
/* 初始化FIFO缓冲区 */
|
||||
{
|
||||
fifo->size = size;
|
||||
fifo->buf = buf;
|
||||
fifo->free = size; /* 缓冲区大小 */
|
||||
fifo->flags = 0;
|
||||
fifo->p = 0; /* 下一个数据写入位置 */
|
||||
fifo->q = 0; /* 下一个数据读出位置 */
|
||||
return;
|
||||
}
|
||||
|
||||
int fifo8_put(struct FIFO8 *fifo, unsigned char data)
|
||||
/* 向FIFO传送数据并保存 */
|
||||
{
|
||||
if (fifo->free == 0) {
|
||||
/* 没有空间了,溢出 */
|
||||
fifo->flags |= FLAGS_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
fifo->buf[fifo->p] = data;
|
||||
fifo->p++;
|
||||
if (fifo->p == fifo->size) {
|
||||
fifo->p = 0;
|
||||
}
|
||||
fifo->free--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fifo8_get(struct FIFO8 *fifo)
|
||||
/* 从FIFO取得一个数据 */
|
||||
{
|
||||
int data;
|
||||
if (fifo->free == fifo->size) {
|
||||
/* 如果缓冲区为空则返回-1 */
|
||||
return -1;
|
||||
}
|
||||
data = fifo->buf[fifo->q];
|
||||
fifo->q++;
|
||||
if (fifo->q == fifo->size) {
|
||||
fifo->q = 0;
|
||||
}
|
||||
fifo->free++;
|
||||
return data;
|
||||
}
|
||||
|
||||
int fifo8_status(struct FIFO8 *fifo)
|
||||
/* 报告一下积攒是数据量 */
|
||||
{
|
||||
return fifo->size - fifo->free;
|
||||
}
|
||||
157
10_day/graphic.c
Normal file
157
10_day/graphic.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/* 关于绘图部分的处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_palette(void)
|
||||
{
|
||||
static unsigned char table_rgb[16 * 3] = {
|
||||
0x00, 0x00, 0x00, /* 0:黑 */
|
||||
0xff, 0x00, 0x00, /* 1:梁红 */
|
||||
0x00, 0xff, 0x00, /* 2:亮绿 */
|
||||
0xff, 0xff, 0x00, /* 3:亮黄 */
|
||||
0x00, 0x00, 0xff, /* 4:亮蓝 */
|
||||
0xff, 0x00, 0xff, /* 5:亮紫 */
|
||||
0x00, 0xff, 0xff, /* 6:浅亮蓝 */
|
||||
0xff, 0xff, 0xff, /* 7:白 */
|
||||
0xc6, 0xc6, 0xc6, /* 8:亮灰 */
|
||||
0x84, 0x00, 0x00, /* 9:暗红 */
|
||||
0x00, 0x84, 0x00, /* 10:暗绿 */
|
||||
0x84, 0x84, 0x00, /* 11:暗黄 */
|
||||
0x00, 0x00, 0x84, /* 12:暗青 */
|
||||
0x84, 0x00, 0x84, /* 13:暗紫 */
|
||||
0x00, 0x84, 0x84, /* 14:浅暗蓝 */
|
||||
0x84, 0x84, 0x84 /* 15:暗灰 */
|
||||
};
|
||||
set_palette(0, 15, table_rgb);
|
||||
return;
|
||||
|
||||
/* C语言中的static char语句只能用于数据,相当于汇编中的DB指令 */
|
||||
}
|
||||
|
||||
void set_palette(int start, int end, unsigned char *rgb)
|
||||
{
|
||||
int i, eflags;
|
||||
eflags = io_load_eflags(); /* 记录中断许可标志的值 */
|
||||
io_cli(); /* 将中断许可标志置为0,禁止中断 */
|
||||
io_out8(0x03c8, start);
|
||||
for (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); /* 复原中断许可标志 */
|
||||
return;
|
||||
}
|
||||
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
|
||||
{
|
||||
int x, y;
|
||||
for (y = y0; y <= y1; y++) {
|
||||
for (x = x0; x <= x1; x++)
|
||||
vram[y * xsize + x] = c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_screen8(char *vram, int x, int y)
|
||||
{
|
||||
boxfill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1);
|
||||
|
||||
boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5);
|
||||
boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3);
|
||||
boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3);
|
||||
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24);
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3);
|
||||
return;
|
||||
}
|
||||
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
|
||||
{
|
||||
int i;
|
||||
char *p, d /* data */;
|
||||
for (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; }
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
|
||||
{
|
||||
extern char hankaku[4096];
|
||||
/* C语言中,字符串都是以0x00结尾 */
|
||||
for (; *s != 0x00; s++) {
|
||||
putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
|
||||
x += 8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_mouse_cursor8(char *mouse, char bc)
|
||||
/* 鼠标的数据准备(16x16) */
|
||||
{
|
||||
static char cursor[16][16] = {
|
||||
"**************..",
|
||||
"*OOOOOOOOOOO*...",
|
||||
"*OOOOOOOOOO*....",
|
||||
"*OOOOOOOOO*.....",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOO**OOO*.....",
|
||||
"*OOO*..*OOO*....",
|
||||
"*OO*....*OOO*...",
|
||||
"*O*......*OOO*..",
|
||||
"**........*OOO*.",
|
||||
"*..........*OOO*",
|
||||
"............*OO*",
|
||||
".............***"
|
||||
};
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < 16; y++) {
|
||||
for (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize)
|
||||
{
|
||||
int x, y;
|
||||
for (y = 0; y < pysize; y++) {
|
||||
for (x = 0; x < pxsize; x++) {
|
||||
vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
4609
10_day/hankaku.txt
Normal file
4609
10_day/hankaku.txt
Normal file
File diff suppressed because it is too large
Load Diff
38
10_day/int.c
Normal file
38
10_day/int.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*初始化关系 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_pic(void)
|
||||
/* PIC初始化 */
|
||||
{
|
||||
io_out8(PIC0_IMR, 0xff ); /* 禁止所有中断 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 禁止所有中断 */
|
||||
|
||||
io_out8(PIC0_ICW1, 0x11 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 11111011 PIC1以外全部禁止 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 11111111 禁止所有中断 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define PORT_KEYDAT 0x0060
|
||||
|
||||
void inthandler27(int *esp)
|
||||
/* PIC0中断的不完整策略 */
|
||||
/* 这个中断在Athlon64X2上通过芯片组提供的便利,只需执行一次 */
|
||||
/* 这个中断只是接收,不执行任何操作 */
|
||||
/* 为什么不处理?
|
||||
→ 因为这个中断可能是电气噪声引发的、只是处理一些重要的情况。*/
|
||||
{
|
||||
io_out8(PIC0_OCW2, 0x67); /* 通知PIC的IRQ-07(参考7-1) */
|
||||
return;
|
||||
}
|
||||
109
10_day/ipl10.nas
Normal file
109
10_day/ipl10.nas
Normal file
@@ -0,0 +1,109 @@
|
||||
; haribote-ipl
|
||||
; TAB=4
|
||||
|
||||
CYLS EQU 10 ; 声明CYLS=10
|
||||
|
||||
ORG 0x7c00 ; 指明程序装载地址
|
||||
|
||||
; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code
|
||||
|
||||
JMP entry
|
||||
DB 0x90
|
||||
DB "HARIBOTE" ; 启动扇区名称(8字节)
|
||||
DW 512 ; 每个扇区(sector)大小(必须512字节)
|
||||
DB 1 ; 簇(cluster)大小(必须为1个扇区)
|
||||
DW 1 ; FAT起始位置(一般为第一个扇区)
|
||||
DB 2 ; FAT个数(必须为2)
|
||||
DW 224 ; 根目录大小(一般为224项)
|
||||
DW 2880 ; 该磁盘大小(必须为2880扇区1440*1024/512)
|
||||
DB 0xf0 ; 磁盘类型(必须为0xf0)
|
||||
DW 9 ; FAT的长度(必??9扇区)
|
||||
DW 18 ; 一个磁道(track)有几个扇区(必须为18)
|
||||
DW 2 ; 磁头数(必??2)
|
||||
DD 0 ; 不使用分区,必须是0
|
||||
DD 2880 ; 重写一次磁盘大小
|
||||
DB 0,0,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 ; 没出错则跳转到fin
|
||||
ADD SI,1 ; 往SI加1
|
||||
CMP SI,5 ; 比较SI与5
|
||||
JAE error ; SI >= 5 跳转到error
|
||||
MOV AH,0x00
|
||||
MOV DL,0x00 ; A驱动器
|
||||
INT 0x13 ; 重置驱动器
|
||||
JMP retry
|
||||
next:
|
||||
MOV AX,ES ; 把内存地址后移0x200(512/16十六进制转换)
|
||||
ADD AX,0x0020
|
||||
MOV ES,AX ; ADD ES,0x020因为没有ADD ES,只能通过AX进行
|
||||
ADD CL,1 ; 往CL里面加1
|
||||
CMP CL,18 ; 比较CL与18
|
||||
JBE readloop ; CL <= 18 跳转到readloop
|
||||
MOV CL,1
|
||||
ADD DH,1
|
||||
CMP DH,2
|
||||
JB readloop ; DH < 2 跳转到readloop
|
||||
MOV DH,0
|
||||
ADD CH,1
|
||||
CMP CH,CYLS
|
||||
JB readloop ; CH < CYLS 跳转到readloop
|
||||
|
||||
; 读取完毕,跳转到haribote.sys执行!
|
||||
MOV [0x0ff0],CH ; IPLがどこまで読んだのかをメモ
|
||||
JMP 0xc200
|
||||
|
||||
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
|
||||
|
||||
fin:
|
||||
HLT ; 让CPU停止,等待指令
|
||||
JMP fin ; 无限循环
|
||||
|
||||
msg:
|
||||
DB 0x0a, 0x0a ; 换行两次
|
||||
DB "load error"
|
||||
DB 0x0a ; 换行
|
||||
DB 0
|
||||
|
||||
RESB 0x7dfe-$ ; 填写0x00直到0x001fe
|
||||
|
||||
DB 0x55, 0xaa
|
||||
39
10_day/keyboard.c
Normal file
39
10_day/keyboard.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* 键盘控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO8 keyfifo;
|
||||
|
||||
void inthandler21(int *esp) {
|
||||
/* 来自PS/2键盘的中断 */
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
unsigned char data, s[4];
|
||||
io_out8(PIC0_OCW2, 0x61); /* 通知PIC IRQ-01 已经受理完毕 */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo8_put(&keyfifo, data);
|
||||
return;
|
||||
}
|
||||
|
||||
#define PORT_KEYSTA 0x0064
|
||||
#define KEYSTA_SEND_NOTREADY 0x02
|
||||
#define KEYCMD_WRITE_MODE 0x60
|
||||
#define KBC_MODE 0x47
|
||||
|
||||
void wait_KBC_sendready(void) {
|
||||
/* 等待键盘控制电路准备完毕 */
|
||||
for (;;) {
|
||||
if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_keyboard(void) {
|
||||
/* 初始化键盘控制电路 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, KBC_MODE);
|
||||
return;
|
||||
}
|
||||
1
10_day/make.bat
Normal file
1
10_day/make.bat
Normal file
@@ -0,0 +1 @@
|
||||
..\z_tools\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
161
10_day/memory.c
Normal file
161
10_day/memory.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/* 内存管理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define EFLAGS_AC_BIT 0x00040000
|
||||
#define CR0_CACHE_DISABLE 0x60000000
|
||||
|
||||
unsigned int memtest(unsigned int start, unsigned int end)
|
||||
{
|
||||
char flg486 = 0;
|
||||
unsigned int eflg, cr0, i;
|
||||
|
||||
/* 确认CPU是386还是486以上的 */
|
||||
eflg = io_load_eflags();
|
||||
eflg |= EFLAGS_AC_BIT; /* AC-bit = 1 */
|
||||
io_store_eflags(eflg);
|
||||
eflg = io_load_eflags();
|
||||
if ((eflg & EFLAGS_AC_BIT) != 0) {
|
||||
/* 如果是386,即使设定AC=1,AC的值还会自动回到0 */
|
||||
flg486 = 1;
|
||||
}
|
||||
|
||||
eflg &= ~EFLAGS_AC_BIT; /* AC-bit = 0 */
|
||||
io_store_eflags(eflg);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 |= CR0_CACHE_DISABLE; /* 禁止缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
i = memtest_sub(start, end);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 &= ~CR0_CACHE_DISABLE; /* 允许缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void memman_init(struct MEMMAN *man){
|
||||
man->frees = 0; /* 可用信息数目 */
|
||||
man->maxfrees = 0; /* 用于观察可用状况:frees的最大值 */
|
||||
man->lostsize = 0; /* 释放失败的内存的大小总和 */
|
||||
man->losts = 0; /* 释放失败次数 */
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
/* 分配 */
|
||||
{
|
||||
unsigned int i, a;
|
||||
for (i = 0; i < man->frees; i++) {
|
||||
if (man->free[i].size >= size) {
|
||||
/* 找到了足够大的内存 */
|
||||
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; /* 没有可用空间 */
|
||||
}
|
||||
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size)
|
||||
/* 释放 */
|
||||
{
|
||||
int i, j;
|
||||
/* 为便于归纳内存,将free[]按照addr的顺序排列 */
|
||||
/* 所以,先决定应该放在哪里 */
|
||||
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]; /* 结构体赋值 */
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0; /* 成功完成 */
|
||||
}
|
||||
}
|
||||
/* 不能与前面的可用空间归纳到一起 */
|
||||
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; /* 失败 */
|
||||
}
|
||||
|
||||
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size)
|
||||
{
|
||||
unsigned int a;
|
||||
size = (size + 0xfff) & 0xfffff000;
|
||||
a = memman_alloc(man, size);
|
||||
return a;
|
||||
}
|
||||
|
||||
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size)
|
||||
{
|
||||
int i;
|
||||
size = (size + 0xfff) & 0xfffff000;
|
||||
i = memman_free(man, addr, size);
|
||||
return i;
|
||||
}
|
||||
70
10_day/mouse.c
Normal file
70
10_day/mouse.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/* 鼠标控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO8 mousefifo;
|
||||
|
||||
void inthandler2c(int *esp) {
|
||||
/* 来自PS/2鼠标的中断 */
|
||||
unsigned char data;
|
||||
io_out8(PIC1_OCW2, 0x64); /* 通知PIC IRQ-12 已经受理完毕 */
|
||||
io_out8(PIC0_OCW2, 0x62); /* 通知PIC IRQ-02 已经受理完毕 */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo8_put(&mousefifo, data);
|
||||
return;
|
||||
}
|
||||
|
||||
#define KEYCMD_SENDTO_MOUSE 0xd4
|
||||
#define MOUSECMD_ENABLE 0xf4
|
||||
|
||||
void enable_mouse(struct MOUSE_DEC *mdec) {
|
||||
/* 鼠标有效 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
|
||||
/* 顺利的话,ACK(0xfa)会被送过来 */
|
||||
mdec->phase = 0; /* 等待0xfa的阶段 */
|
||||
return;
|
||||
}
|
||||
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat) {
|
||||
if (mdec->phase == 0) {
|
||||
/* 等待鼠标的0xfa的阶段 */
|
||||
if (dat == 0xfa) {
|
||||
mdec->phase = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 1) {
|
||||
/* 等待鼠标第一字节的阶段 */
|
||||
mdec->buf[0] = dat;
|
||||
mdec->phase = 2;
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 2) {
|
||||
/* 等待鼠标第二字节的阶段 */
|
||||
mdec->buf[1] = dat;
|
||||
mdec->phase = 3;
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
/* 鼠标的y方向与画面符号相反 */
|
||||
mdec->y = - mdec->y;
|
||||
return 1;
|
||||
}
|
||||
/* 应该不可能到这里来 */
|
||||
return -1;
|
||||
}
|
||||
184
10_day/naskfunc.nas
Normal file
184
10_day/naskfunc.nas
Normal file
@@ -0,0 +1,184 @@
|
||||
; naskfunc
|
||||
; TAB=4
|
||||
|
||||
[FORMAT "WCOFF"] ; 制作目标文件的模式
|
||||
[INSTRSET "i486p"] ; 使用到486为止的指令
|
||||
[BITS 32] ; 3制作32位模式用的机器语言
|
||||
[FILE "naskfunc.nas"] ; 文件名
|
||||
|
||||
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 _load_gdtr, _load_idtr
|
||||
GLOBAL _load_cr0, _store_cr0
|
||||
GLOBAL _asm_inthandler21, _asm_inthandler27, _asm_inthandler2c
|
||||
GLOBAL _memtest_sub
|
||||
EXTERN _inthandler21, _inthandler27, _inthandler2c
|
||||
|
||||
[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 EAX,[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 ; PUSH EFLAGS
|
||||
POP EAX
|
||||
RET
|
||||
|
||||
_io_store_eflags: ; void io_store_eflags(int eflags);
|
||||
MOV EAX,[ESP+4]
|
||||
PUSH EAX
|
||||
POPFD ; POP EFLAGS
|
||||
RET
|
||||
|
||||
_load_gdtr: ; void load_gdtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LGDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_idtr: ; void load_idtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LIDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_cr0: ; int load_cr0(void);
|
||||
MOV EAX,CR0
|
||||
RET
|
||||
|
||||
_store_cr0: ; void store_cr0(int cr0);
|
||||
MOV EAX,[ESP+4]
|
||||
MOV CR0,EAX
|
||||
RET
|
||||
|
||||
_asm_inthandler21:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler21
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler27:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler27
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler2c:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler2c
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_memtest_sub: ; unsigned int memtest_sub(unsigned int start, unsigned int end)
|
||||
PUSH EDI ; (由于还要使用EBX, ESI, EDI)
|
||||
PUSH ESI
|
||||
PUSH EBX
|
||||
MOV ESI,0xaa55aa55 ; pat0 = 0xaa55aa55;
|
||||
MOV EDI,0x55aa55aa ; pat1 = 0x55aa55aa;
|
||||
MOV EAX,[ESP+12+4] ; i = start;
|
||||
mts_loop:
|
||||
MOV EBX,EAX
|
||||
ADD EBX,0xffc ; p = i + 0xffc;
|
||||
MOV EDX,[EBX] ; old = *p;
|
||||
MOV [EBX],ESI ; *p = pat0;
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP EDI,[EBX] ; if (*p != pat1) goto fin;
|
||||
JNE mts_fin
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP ESI,[EBX] ; if (*p != pat0) goto fin;
|
||||
JNE mts_fin
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
ADD EAX,0x1000 ; i += 0x1000;
|
||||
CMP EAX,[ESP+12+8] ; if (i <= end) goto mts_loop;
|
||||
JBE mts_loop
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
mts_fin:
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
163
10_day/sheet.c
Normal file
163
10_day/sheet.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/* sheet */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define SHEET_USE 1
|
||||
|
||||
struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize)
|
||||
{
|
||||
struct SHTCTL *ctl;
|
||||
int i;
|
||||
ctl = (struct SHTCTL *) memman_alloc_4k(memman, sizeof (struct SHTCTL));
|
||||
if (ctl == 0) {
|
||||
goto err;
|
||||
}
|
||||
ctl->vram = vram;
|
||||
ctl->xsize = xsize;
|
||||
ctl->ysize = ysize;
|
||||
ctl->top = -1; /* 没有一张SHEET */
|
||||
for (i = 0; i < MAX_SHEETS; i++) {
|
||||
ctl->sheets0[i].flags = 0; /* 标记为未使用 */
|
||||
}
|
||||
err:
|
||||
return ctl;
|
||||
}
|
||||
|
||||
struct SHEET *sheet_alloc(struct SHTCTL *ctl)
|
||||
{
|
||||
struct SHEET *sht;
|
||||
int i;
|
||||
for (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 0; /* 所有的SHEET都处于正在使用状态*/
|
||||
}
|
||||
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_updown(struct SHTCTL *ctl, struct SHEET *sht, int height)
|
||||
{
|
||||
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;
|
||||
} 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_refreshsub(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize, sht->vy0 + sht->bysize); /* 按新图层的信息重新绘制画面 */
|
||||
} 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_refreshsub(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize, sht->vy0 + sht->bysize); /* 按新图层信息重新绘制画面 */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_refresh(struct SHTCTL *ctl, struct SHEET *sht, int bx0, int by0, int bx1, int by1)
|
||||
{
|
||||
if (sht->height >= 0) { /* 如果正在显示,则按新图层的信息刷新画面*/
|
||||
sheet_refreshsub(ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1, sht->vy0 + by1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1)
|
||||
{
|
||||
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
|
||||
unsigned char *buf, c, *vram = ctl->vram;
|
||||
struct SHEET *sht;
|
||||
for (h = 0; h <= ctl->top; h++) {
|
||||
sht = ctl->sheets[h];
|
||||
buf = sht->buf;
|
||||
/* 使用vx0~vy1,对bx0~by1进行倒推 */
|
||||
bx0 = vx0 - sht->vx0;
|
||||
by0 = vy0 - sht->vy0;
|
||||
bx1 = vx1 - sht->vx0;
|
||||
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 (by = by0; by < by1; by++) {
|
||||
vy = sht->vy0 + by;
|
||||
for (bx = bx0; bx < bx1; bx++) {
|
||||
vx = sht->vx0 + bx;
|
||||
c = buf[by * sht->bxsize + bx];
|
||||
if (c != sht->col_inv) {
|
||||
vram[vy * ctl->xsize + vx] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void sheet_slide(struct SHTCTL *ctl, struct SHEET *sht, int vx0, int vy0)
|
||||
{
|
||||
int old_vx0 = sht->vx0, old_vy0 = sht->vy0;
|
||||
sht->vx0 = vx0;
|
||||
sht->vy0 = vy0;
|
||||
if (sht->height >= 0) { /* 如果正在显示,则按新图层的信息刷新画面 */
|
||||
sheet_refreshsub(ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize, old_vy0 + sht->bysize);
|
||||
sheet_refreshsub(ctl, vx0, vy0, vx0 + sht->bxsize, vy0 + sht->bysize);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_free(struct SHTCTL *ctl, struct SHEET *sht)
|
||||
{
|
||||
if (sht->height >= 0) {
|
||||
sheet_updown(ctl, sht, -1); /* 如果处于显示状态,则先设定为隐藏 */
|
||||
}
|
||||
sht->flags = 0; /* "未使用"标志 */
|
||||
return;
|
||||
}
|
||||
1
11_day/!cons_9x.bat
Normal file
1
11_day/!cons_9x.bat
Normal file
@@ -0,0 +1 @@
|
||||
command
|
||||
1
11_day/!cons_nt.bat
Normal file
1
11_day/!cons_nt.bat
Normal file
@@ -0,0 +1 @@
|
||||
cmd.exe
|
||||
93
11_day/Makefile
Normal file
93
11_day/Makefile
Normal file
@@ -0,0 +1,93 @@
|
||||
OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \
|
||||
int.obj fifo.obj keyboard.obj mouse.obj memory.obj sheet.obj
|
||||
|
||||
TOOLPATH = ../z_tools/
|
||||
INCPATH = ../z_tools/haribote/
|
||||
|
||||
MAKE = $(TOOLPATH)make.exe -r
|
||||
NASK = $(TOOLPATH)nask.exe
|
||||
CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
|
||||
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
|
||||
OBJ2BIM = $(TOOLPATH)obj2bim.exe
|
||||
MAKEFONT = $(TOOLPATH)makefont.exe
|
||||
BIN2OBJ = $(TOOLPATH)bin2obj.exe
|
||||
BIM2HRB = $(TOOLPATH)bim2hrb.exe
|
||||
RULEFILE = $(TOOLPATH)haribote/haribote.rul
|
||||
EDIMG = $(TOOLPATH)edimg.exe
|
||||
IMGTOL = $(TOOLPATH)imgtol.com
|
||||
COPY = copy
|
||||
DEL = del
|
||||
|
||||
# 默认动作
|
||||
|
||||
default :
|
||||
$(MAKE) img
|
||||
|
||||
# 镜像文件生成
|
||||
|
||||
ipl10.bin : ipl10.nas Makefile
|
||||
$(NASK) ipl10.nas ipl10.bin ipl10.lst
|
||||
|
||||
asmhead.bin : asmhead.nas Makefile
|
||||
$(NASK) asmhead.nas asmhead.bin asmhead.lst
|
||||
|
||||
hankaku.bin : hankaku.txt Makefile
|
||||
$(MAKEFONT) hankaku.txt hankaku.bin
|
||||
|
||||
hankaku.obj : hankaku.bin Makefile
|
||||
$(BIN2OBJ) hankaku.bin hankaku.obj _hankaku
|
||||
|
||||
bootpack.bim : $(OBJS_BOOTPACK) Makefile
|
||||
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
|
||||
$(OBJS_BOOTPACK)
|
||||
# 3MB+64KB=3136KB
|
||||
|
||||
bootpack.hrb : bootpack.bim Makefile
|
||||
$(BIM2HRB) bootpack.bim bootpack.hrb 0
|
||||
|
||||
haribote.sys : asmhead.bin bootpack.hrb Makefile
|
||||
copy /B asmhead.bin+bootpack.hrb haribote.sys
|
||||
|
||||
haribote.img : ipl10.bin haribote.sys Makefile
|
||||
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
|
||||
wbinimg src:ipl10.bin len:512 from:0 to:0 \
|
||||
copy from:haribote.sys to:@: \
|
||||
imgout:haribote.img
|
||||
|
||||
# 其他指令
|
||||
|
||||
%.gas : %.c bootpack.h Makefile
|
||||
$(CC1) -o $*.gas $*.c
|
||||
|
||||
%.nas : %.gas Makefile
|
||||
$(GAS2NASK) $*.gas $*.nas
|
||||
|
||||
%.obj : %.nas Makefile
|
||||
$(NASK) $*.nas $*.obj $*.lst
|
||||
|
||||
# 运行程序
|
||||
|
||||
img :
|
||||
$(MAKE) haribote.img
|
||||
|
||||
run :
|
||||
$(MAKE) img
|
||||
$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
|
||||
$(MAKE) -C ../z_tools/qemu
|
||||
|
||||
install :
|
||||
$(MAKE) img
|
||||
$(IMGTOL) w a: haribote.img
|
||||
|
||||
clean :
|
||||
-$(DEL) *.bin
|
||||
-$(DEL) *.lst
|
||||
-$(DEL) *.obj
|
||||
-$(DEL) bootpack.map
|
||||
-$(DEL) bootpack.bim
|
||||
-$(DEL) bootpack.hrb
|
||||
-$(DEL) haribote.sys
|
||||
|
||||
src_only :
|
||||
$(MAKE) clean
|
||||
-$(DEL) haribote.img
|
||||
146
11_day/asmhead.nas
Normal file
146
11_day/asmhead.nas
Normal file
@@ -0,0 +1,146 @@
|
||||
; haribote-os boot asm
|
||||
; TAB=4
|
||||
|
||||
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 ; 图像缓冲区的起始地址
|
||||
|
||||
ORG 0xc200 ; 这个的程序要被装载的内存地址
|
||||
|
||||
; 画面设置
|
||||
|
||||
MOV AL,0x13 ; VGA显卡,320x200x8bit
|
||||
MOV AH,0x00
|
||||
INT 0x10
|
||||
MOV BYTE [VMODE],8 ; 屏幕的模式(参考C语言的引用)
|
||||
MOV WORD [SCRNX],320
|
||||
MOV WORD [SCRNY],200
|
||||
MOV DWORD [VRAM],0x000a0000
|
||||
|
||||
; 通过 BIOS 获取指示灯状态
|
||||
|
||||
MOV AH,0x02
|
||||
INT 0x16 ; keyboard BIOS
|
||||
MOV [LEDS],AL
|
||||
|
||||
; PIC关闭一切中断
|
||||
; 根据AT兼容机的规格,如果要初始化PIC,
|
||||
; 必须在CLI之前进行,否则有时会挂起。
|
||||
; 随后进行PIC的初始化。
|
||||
|
||||
MOV AL,0xff
|
||||
OUT 0x21,AL
|
||||
NOP ; 如果连续执行OUT指令,有些机种会无法正常运行
|
||||
OUT 0xa1,AL
|
||||
|
||||
CLI ; 禁止CPU级别的中断
|
||||
|
||||
; 为了让CPU能够访问1MB以上的内存空间,设定A20GATE
|
||||
|
||||
CALL waitkbdout
|
||||
MOV AL,0xd1
|
||||
OUT 0x64,AL
|
||||
CALL waitkbdout
|
||||
MOV AL,0xdf ; enable A20
|
||||
OUT 0x60,AL
|
||||
CALL waitkbdout
|
||||
|
||||
; 切换到保护模式
|
||||
|
||||
[INSTRSET "i486p"] ; 说明使用486指令
|
||||
|
||||
LGDT [GDTR0] ; 设置临时GDT
|
||||
MOV EAX,CR0
|
||||
AND EAX,0x7fffffff ; 设bit31为0(禁用分页)
|
||||
OR EAX,0x00000001 ; bit0到1转换(保护模式过渡)
|
||||
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
|
||||
|
||||
; 必须由asmhead来完成的工作,至此全部完毕
|
||||
; 以后就交由bootpack来完成
|
||||
|
||||
; bootpack启动
|
||||
|
||||
MOV EBX,BOTPAK
|
||||
MOV ECX,[EBX+16]
|
||||
ADD ECX,3 ; ECX += 3;
|
||||
SHR ECX,2 ; ECX /= 4;
|
||||
JZ skip ; 没有要转送的东西时
|
||||
MOV ESI,[EBX+20] ; 转送源
|
||||
ADD ESI,EBX
|
||||
MOV EDI,[EBX+12] ; 转送目标
|
||||
CALL memcpy
|
||||
skip:
|
||||
MOV ESP,[EBX+12] ; 堆栈的初始化
|
||||
JMP DWORD 2*8:0x0000001b
|
||||
|
||||
waitkbdout:
|
||||
IN AL,0x64
|
||||
AND AL,0x02
|
||||
IN AL,0x60 ; 空读(为了清空数据接收缓冲区中的垃圾数据)
|
||||
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地址前缀大小
|
||||
|
||||
ALIGNB 16
|
||||
GDT0:
|
||||
RESB 8 ; 初始值
|
||||
DW 0xffff,0x0000,0x9200,0x00cf ; 可以读写的段(segment)32bit
|
||||
DW 0xffff,0x0000,0x9a28,0x0047 ; 可执行的文件的32bit寄存器(bootpack用)
|
||||
|
||||
DW 0
|
||||
GDTR0:
|
||||
DW 8*3-1
|
||||
DD GDT0
|
||||
|
||||
ALIGNB 16
|
||||
bootpack:
|
||||
172
11_day/bootpack.c
Normal file
172
11_day/bootpack.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/* bootpackのメイン */
|
||||
|
||||
#include "bootpack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void HariMain(void)
|
||||
{
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
char s[40], keybuf[32], mousebuf[128];
|
||||
int mx, my, i;
|
||||
unsigned int memtotal, count = 0;
|
||||
struct MOUSE_DEC mdec;
|
||||
struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
|
||||
struct SHTCTL *shtctl;
|
||||
struct SHEET *sht_back, *sht_mouse, *sht_win;
|
||||
unsigned char *buf_back, buf_mouse[256], *buf_win;
|
||||
|
||||
init_gdtidt();
|
||||
init_pic();
|
||||
io_sti(); /* IDT/PIC的初始化已经完成,于是开放CPU的中断 */
|
||||
|
||||
fifo8_init(&keyfifo, 32, keybuf);
|
||||
fifo8_init(&mousefifo, 128, mousebuf);
|
||||
io_out8(PIC0_IMR, 0xf9); /* 开放PIC1和键盘中断(11111001) */
|
||||
io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */
|
||||
|
||||
init_keyboard();
|
||||
enable_mouse(&mdec);
|
||||
memtotal = memtest(0x00400000, 0xbfffffff);
|
||||
memman_init(memman);
|
||||
memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 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");
|
||||
sheet_slide(sht_back, 0, 0);
|
||||
mx = (binfo->scrnx - 16) / 2; /* 按显示在画面中央来计算坐标 */
|
||||
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);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
|
||||
sprintf(s, "memory %dMB free : %dKB", memtotal / (1024 * 1024), memman_total(memman) / 1024);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);
|
||||
sheet_refresh(sht_back, 0, 0, binfo->scrnx, 48); /* 刷新文字 */
|
||||
|
||||
for (;;) {
|
||||
count++; /* 从这里开始 */
|
||||
sprintf(s, "%010d", count);
|
||||
boxfill8(buf_win, 160, COL8_C6C6C6, 40, 28, 119, 43);
|
||||
putfonts8_asc(buf_win, 160, 40, 28, COL8_000000, s);
|
||||
sheet_refresh(sht_win, 40, 28, 120, 44); /* 到这里结束 */
|
||||
|
||||
io_cli();
|
||||
if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
|
||||
io_sti(); /* 不做HLT */
|
||||
} else {
|
||||
if (fifo8_status(&keyfifo) != 0) {
|
||||
i = fifo8_get(&keyfifo);
|
||||
io_sti();
|
||||
sprintf(s, "%02X", i);
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
|
||||
sheet_refresh(sht_back, 0, 16, 16, 32); /* 刷新文字 */
|
||||
} else if (fifo8_status(&mousefifo) != 0) {
|
||||
i = fifo8_get(&mousefifo);
|
||||
io_sti();
|
||||
if (mouse_decode(&mdec, i) != 0) {
|
||||
/* 3字节都凑齐了,所以把它们显示出来*/
|
||||
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
|
||||
if ((mdec.btn & 0x01) != 0) {
|
||||
s[1] = 'L';
|
||||
}
|
||||
if ((mdec.btn & 0x02) != 0) {
|
||||
s[3] = 'R';
|
||||
}
|
||||
if ((mdec.btn & 0x04) != 0) {
|
||||
s[2] = 'C';
|
||||
}
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
|
||||
sheet_refresh(sht_back, 32, 16, 32 + 15 * 8, 32); /* 刷新文字 */
|
||||
/* 移动光标 */
|
||||
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);
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 0, 0, 79, 15); /* 消坐标 */
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s); /* 写坐标 */
|
||||
sheet_refresh(sht_back, 0, 0, 80, 16); /* 刷新文字 */
|
||||
sheet_slide(sht_mouse, mx, my); /* 包含sheet_refresh含sheet_refresh */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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$$$$$$$$$$$$$$@",
|
||||
"@@@@@@@@@@@@@@@@"
|
||||
};
|
||||
|
||||
int x, y;
|
||||
char c;
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, xsize - 1, 0 );
|
||||
boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, xsize - 2, 1 );
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, 0, ysize - 1);
|
||||
boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, 1, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_848484, xsize - 2, 1, xsize - 2, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_000000, xsize - 1, 0, xsize - 1, ysize - 1);
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3);
|
||||
boxfill8(buf, xsize, COL8_000084, 3, 3, xsize - 4, 20 );
|
||||
boxfill8(buf, xsize, COL8_848484, 1, ysize - 2, xsize - 2, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_000000, 0, ysize - 1, xsize - 1, ysize - 1);
|
||||
putfonts8_asc(buf, xsize, 24, 4, COL8_FFFFFF, title);
|
||||
|
||||
for (y = 0; y < 14; y++) {
|
||||
for (x = 0; x < 16; x++) {
|
||||
c = closebtn[y][x];
|
||||
if (c == '@') {
|
||||
c = COL8_000000;
|
||||
} else if (c == '$') {
|
||||
c = COL8_848484;
|
||||
} else if (c == 'Q') {
|
||||
c = COL8_C6C6C6;
|
||||
} else {
|
||||
c = COL8_FFFFFF;
|
||||
}
|
||||
buf[(5 + y) * xsize + (xsize - 21 + x)] = c;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
168
11_day/bootpack.h
Normal file
168
11_day/bootpack.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/* asmhead.nas */
|
||||
struct BOOTINFO { /* 0x0ff0-0x0fff */
|
||||
char cyls; /* 启动区读磁盘读到此为止 */
|
||||
char leds; /* 启动时键盘的LED的状态 */
|
||||
char vmode; /* 显卡模式为多少位彩色 */
|
||||
char reserve;
|
||||
short scrnx, scrny; /* 画面分辨率 */
|
||||
char *vram;
|
||||
};
|
||||
#define ADR_BOOTINFO 0x00000ff0
|
||||
|
||||
/* naskfunc.nas */
|
||||
void io_hlt(void);
|
||||
void io_cli(void);
|
||||
void io_sti(void);
|
||||
void io_stihlt(void);
|
||||
int io_in8(int port);
|
||||
void io_out8(int port, int data);
|
||||
int io_load_eflags(void);
|
||||
void io_store_eflags(int eflags);
|
||||
void load_gdtr(int limit, int addr);
|
||||
void load_idtr(int limit, int addr);
|
||||
int load_cr0(void);
|
||||
void store_cr0(int cr0);
|
||||
void asm_inthandler21(void);
|
||||
void asm_inthandler27(void);
|
||||
void asm_inthandler2c(void);
|
||||
unsigned int memtest_sub(unsigned int start, unsigned int end);
|
||||
|
||||
/* fifo.c */
|
||||
struct FIFO8 {
|
||||
unsigned char *buf;
|
||||
int p, q, size, free, flags;
|
||||
};
|
||||
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);
|
||||
|
||||
/* graphic.c */
|
||||
void init_palette(void);
|
||||
void set_palette(int start, int end, unsigned char *rgb);
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
|
||||
void init_screen8(char *vram, int x, int y);
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
|
||||
void init_mouse_cursor8(char *mouse, char bc);
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize);
|
||||
#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
|
||||
|
||||
/* dsctbl.c */
|
||||
struct SEGMENT_DESCRIPTOR {
|
||||
short limit_low, base_low;
|
||||
char base_mid, access_right;
|
||||
char limit_high, base_high;
|
||||
};
|
||||
struct GATE_DESCRIPTOR {
|
||||
short offset_low, selector;
|
||||
char dw_count, access_right;
|
||||
short offset_high;
|
||||
};
|
||||
void init_gdtidt(void);
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
|
||||
#define ADR_IDT 0x0026f800
|
||||
#define LIMIT_IDT 0x000007ff
|
||||
#define ADR_GDT 0x00270000
|
||||
#define LIMIT_GDT 0x0000ffff
|
||||
#define ADR_BOTPAK 0x00280000
|
||||
#define LIMIT_BOTPAK 0x0007ffff
|
||||
#define AR_DATA32_RW 0x4092
|
||||
#define AR_CODE32_ER 0x409a
|
||||
#define AR_INTGATE32 0x008e
|
||||
|
||||
/* int.c */
|
||||
void init_pic(void);
|
||||
void inthandler27(int *esp);
|
||||
#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
|
||||
|
||||
/* keyboard.c */
|
||||
void inthandler21(int *esp);
|
||||
void wait_KBC_sendready(void);
|
||||
void init_keyboard(void);
|
||||
extern struct FIFO8 keyfifo;
|
||||
#define PORT_KEYDAT 0x0060
|
||||
#define PORT_KEYCMD 0x0064
|
||||
|
||||
/* mouse.c */
|
||||
struct MOUSE_DEC {
|
||||
unsigned char buf[3], phase;
|
||||
int x, y, btn;
|
||||
};
|
||||
void inthandler2c(int *esp);
|
||||
void enable_mouse(struct MOUSE_DEC *mdec);
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);
|
||||
extern struct FIFO8 mousefifo;
|
||||
|
||||
/* memory.c */
|
||||
#define MEMMAN_FREES 4090 /* 大约是32KB*/
|
||||
#define MEMMAN_ADDR 0x003c0000
|
||||
|
||||
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);
|
||||
void memman_init(struct MEMMAN *man);
|
||||
unsigned int memman_total(struct MEMMAN *man);
|
||||
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
|
||||
/* sheet.c */
|
||||
#define MAX_SHEETS 256
|
||||
#define SHEET_USE 1
|
||||
|
||||
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_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);
|
||||
56
11_day/dsctbl.c
Normal file
56
11_day/dsctbl.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* GDT、IDT、descriptor table 关系处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_gdtidt(void)
|
||||
{
|
||||
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
|
||||
struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) ADR_IDT;
|
||||
int i;
|
||||
|
||||
/* GDT初始化 */
|
||||
for (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_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);
|
||||
load_gdtr(LIMIT_GDT, ADR_GDT);
|
||||
|
||||
/* IDT初始化 */
|
||||
for (i = 0; i <= LIMIT_IDT / 8; i++) {
|
||||
set_gatedesc(idt + i, 0, 0, 0);
|
||||
}
|
||||
load_idtr(LIMIT_IDT, ADR_IDT);
|
||||
|
||||
/* IDT设置*/
|
||||
set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
57
11_day/fifo.c
Normal file
57
11_day/fifo.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* FIFO */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define FLAGS_OVERRUN 0x0001
|
||||
|
||||
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
|
||||
/* 初始化FIFO缓冲区 */
|
||||
{
|
||||
fifo->size = size;
|
||||
fifo->buf = buf;
|
||||
fifo->free = size; /* 缓冲区大小 */
|
||||
fifo->flags = 0;
|
||||
fifo->p = 0; /* 下一个数据写入位置 */
|
||||
fifo->q = 0; /* 下一个数据读出位置 */
|
||||
return;
|
||||
}
|
||||
|
||||
int fifo8_put(struct FIFO8 *fifo, unsigned char data)
|
||||
/* 向FIFO传送数据并保存 */
|
||||
{
|
||||
if (fifo->free == 0) {
|
||||
/* 没有空间了,溢出 */
|
||||
fifo->flags |= FLAGS_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
fifo->buf[fifo->p] = data;
|
||||
fifo->p++;
|
||||
if (fifo->p == fifo->size) {
|
||||
fifo->p = 0;
|
||||
}
|
||||
fifo->free--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fifo8_get(struct FIFO8 *fifo)
|
||||
/* 从FIFO取得一个数据 */
|
||||
{
|
||||
int data;
|
||||
if (fifo->free == fifo->size) {
|
||||
/* 如果缓冲区为空则返回-1 */
|
||||
return -1;
|
||||
}
|
||||
data = fifo->buf[fifo->q];
|
||||
fifo->q++;
|
||||
if (fifo->q == fifo->size) {
|
||||
fifo->q = 0;
|
||||
}
|
||||
fifo->free++;
|
||||
return data;
|
||||
}
|
||||
|
||||
int fifo8_status(struct FIFO8 *fifo)
|
||||
/* 报告一下积攒是数据量 */
|
||||
{
|
||||
return fifo->size - fifo->free;
|
||||
}
|
||||
157
11_day/graphic.c
Normal file
157
11_day/graphic.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/* 关于绘图部分的处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_palette(void)
|
||||
{
|
||||
static unsigned char table_rgb[16 * 3] = {
|
||||
0x00, 0x00, 0x00, /* 0:黑 */
|
||||
0xff, 0x00, 0x00, /* 1:梁红 */
|
||||
0x00, 0xff, 0x00, /* 2:亮绿 */
|
||||
0xff, 0xff, 0x00, /* 3:亮黄 */
|
||||
0x00, 0x00, 0xff, /* 4:亮蓝 */
|
||||
0xff, 0x00, 0xff, /* 5:亮紫 */
|
||||
0x00, 0xff, 0xff, /* 6:浅亮蓝 */
|
||||
0xff, 0xff, 0xff, /* 7:白 */
|
||||
0xc6, 0xc6, 0xc6, /* 8:亮灰 */
|
||||
0x84, 0x00, 0x00, /* 9:暗红 */
|
||||
0x00, 0x84, 0x00, /* 10:暗绿 */
|
||||
0x84, 0x84, 0x00, /* 11:暗黄 */
|
||||
0x00, 0x00, 0x84, /* 12:暗青 */
|
||||
0x84, 0x00, 0x84, /* 13:暗紫 */
|
||||
0x00, 0x84, 0x84, /* 14:浅暗蓝 */
|
||||
0x84, 0x84, 0x84 /* 15:暗灰 */
|
||||
};
|
||||
set_palette(0, 15, table_rgb);
|
||||
return;
|
||||
|
||||
/* C语言中的static char语句只能用于数据,相当于汇编中的DB指令 */
|
||||
}
|
||||
|
||||
void set_palette(int start, int end, unsigned char *rgb)
|
||||
{
|
||||
int i, eflags;
|
||||
eflags = io_load_eflags(); /* 记录中断许可标志的值 */
|
||||
io_cli(); /* 将中断许可标志置为0,禁止中断 */
|
||||
io_out8(0x03c8, start);
|
||||
for (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); /* 复原中断许可标志 */
|
||||
return;
|
||||
}
|
||||
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
|
||||
{
|
||||
int x, y;
|
||||
for (y = y0; y <= y1; y++) {
|
||||
for (x = x0; x <= x1; x++)
|
||||
vram[y * xsize + x] = c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_screen8(char *vram, int x, int y)
|
||||
{
|
||||
boxfill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1);
|
||||
|
||||
boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5);
|
||||
boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3);
|
||||
boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3);
|
||||
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24);
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3);
|
||||
return;
|
||||
}
|
||||
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
|
||||
{
|
||||
int i;
|
||||
char *p, d /* data */;
|
||||
for (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; }
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
|
||||
{
|
||||
extern char hankaku[4096];
|
||||
/* C语言中,字符串都是以0x00结尾 */
|
||||
for (; *s != 0x00; s++) {
|
||||
putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
|
||||
x += 8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_mouse_cursor8(char *mouse, char bc)
|
||||
/* 鼠标的数据准备(16x16) */
|
||||
{
|
||||
static char cursor[16][16] = {
|
||||
"**************..",
|
||||
"*OOOOOOOOOOO*...",
|
||||
"*OOOOOOOOOO*....",
|
||||
"*OOOOOOOOO*.....",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOO**OOO*.....",
|
||||
"*OOO*..*OOO*....",
|
||||
"*OO*....*OOO*...",
|
||||
"*O*......*OOO*..",
|
||||
"**........*OOO*.",
|
||||
"*..........*OOO*",
|
||||
"............*OO*",
|
||||
".............***"
|
||||
};
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < 16; y++) {
|
||||
for (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize)
|
||||
{
|
||||
int x, y;
|
||||
for (y = 0; y < pysize; y++) {
|
||||
for (x = 0; x < pxsize; x++) {
|
||||
vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
4609
11_day/hankaku.txt
Normal file
4609
11_day/hankaku.txt
Normal file
File diff suppressed because it is too large
Load Diff
38
11_day/int.c
Normal file
38
11_day/int.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*初始化关系 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_pic(void)
|
||||
/* PIC初始化 */
|
||||
{
|
||||
io_out8(PIC0_IMR, 0xff ); /* 禁止所有中断 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 禁止所有中断 */
|
||||
|
||||
io_out8(PIC0_ICW1, 0x11 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 11111011 PIC1以外全部禁止 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 11111111 禁止所有中断 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define PORT_KEYDAT 0x0060
|
||||
|
||||
void inthandler27(int *esp)
|
||||
/* PIC0中断的不完整策略 */
|
||||
/* 这个中断在Athlon64X2上通过芯片组提供的便利,只需执行一次 */
|
||||
/* 这个中断只是接收,不执行任何操作 */
|
||||
/* 为什么不处理?
|
||||
→ 因为这个中断可能是电气噪声引发的、只是处理一些重要的情况。*/
|
||||
{
|
||||
io_out8(PIC0_OCW2, 0x67); /* 通知PIC的IRQ-07(参考7-1) */
|
||||
return;
|
||||
}
|
||||
109
11_day/ipl10.nas
Normal file
109
11_day/ipl10.nas
Normal file
@@ -0,0 +1,109 @@
|
||||
; haribote-ipl
|
||||
; TAB=4
|
||||
|
||||
CYLS EQU 10 ; 声明CYLS=10
|
||||
|
||||
ORG 0x7c00 ; 指明程序装载地址
|
||||
|
||||
; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code
|
||||
|
||||
JMP entry
|
||||
DB 0x90
|
||||
DB "HARIBOTE" ; 启动扇区名称(8字节)
|
||||
DW 512 ; 每个扇区(sector)大小(必须512字节)
|
||||
DB 1 ; 簇(cluster)大小(必须为1个扇区)
|
||||
DW 1 ; FAT起始位置(一般为第一个扇区)
|
||||
DB 2 ; FAT个数(必须为2)
|
||||
DW 224 ; 根目录大小(一般为224项)
|
||||
DW 2880 ; 该磁盘大小(必须为2880扇区1440*1024/512)
|
||||
DB 0xf0 ; 磁盘类型(必须为0xf0)
|
||||
DW 9 ; FAT的长度(必??9扇区)
|
||||
DW 18 ; 一个磁道(track)有几个扇区(必须为18)
|
||||
DW 2 ; 磁头数(必??2)
|
||||
DD 0 ; 不使用分区,必须是0
|
||||
DD 2880 ; 重写一次磁盘大小
|
||||
DB 0,0,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 ; 没出错则跳转到fin
|
||||
ADD SI,1 ; 往SI加1
|
||||
CMP SI,5 ; 比较SI与5
|
||||
JAE error ; SI >= 5 跳转到error
|
||||
MOV AH,0x00
|
||||
MOV DL,0x00 ; A驱动器
|
||||
INT 0x13 ; 重置驱动器
|
||||
JMP retry
|
||||
next:
|
||||
MOV AX,ES ; 把内存地址后移0x200(512/16十六进制转换)
|
||||
ADD AX,0x0020
|
||||
MOV ES,AX ; ADD ES,0x020因为没有ADD ES,只能通过AX进行
|
||||
ADD CL,1 ; 往CL里面加1
|
||||
CMP CL,18 ; 比较CL与18
|
||||
JBE readloop ; CL <= 18 跳转到readloop
|
||||
MOV CL,1
|
||||
ADD DH,1
|
||||
CMP DH,2
|
||||
JB readloop ; DH < 2 跳转到readloop
|
||||
MOV DH,0
|
||||
ADD CH,1
|
||||
CMP CH,CYLS
|
||||
JB readloop ; CH < CYLS 跳转到readloop
|
||||
|
||||
; 读取完毕,跳转到haribote.sys执行!
|
||||
MOV [0x0ff0],CH ; IPLがどこまで読んだのかをメモ
|
||||
JMP 0xc200
|
||||
|
||||
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
|
||||
|
||||
fin:
|
||||
HLT ; 让CPU停止,等待指令
|
||||
JMP fin ; 无限循环
|
||||
|
||||
msg:
|
||||
DB 0x0a, 0x0a ; 换行两次
|
||||
DB "load error"
|
||||
DB 0x0a ; 换行
|
||||
DB 0
|
||||
|
||||
RESB 0x7dfe-$ ; 填写0x00直到0x001fe
|
||||
|
||||
DB 0x55, 0xaa
|
||||
39
11_day/keyboard.c
Normal file
39
11_day/keyboard.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* 键盘控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO8 keyfifo;
|
||||
|
||||
void inthandler21(int *esp) {
|
||||
/* 来自PS/2键盘的中断 */
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
unsigned char data, s[4];
|
||||
io_out8(PIC0_OCW2, 0x61); /* 通知PIC IRQ-01 已经受理完毕 */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo8_put(&keyfifo, data);
|
||||
return;
|
||||
}
|
||||
|
||||
#define PORT_KEYSTA 0x0064
|
||||
#define KEYSTA_SEND_NOTREADY 0x02
|
||||
#define KEYCMD_WRITE_MODE 0x60
|
||||
#define KBC_MODE 0x47
|
||||
|
||||
void wait_KBC_sendready(void) {
|
||||
/* 等待键盘控制电路准备完毕 */
|
||||
for (;;) {
|
||||
if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_keyboard(void) {
|
||||
/* 初始化键盘控制电路 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, KBC_MODE);
|
||||
return;
|
||||
}
|
||||
1
11_day/make.bat
Normal file
1
11_day/make.bat
Normal file
@@ -0,0 +1 @@
|
||||
..\z_tools\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
161
11_day/memory.c
Normal file
161
11_day/memory.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/* 内存管理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define EFLAGS_AC_BIT 0x00040000
|
||||
#define CR0_CACHE_DISABLE 0x60000000
|
||||
|
||||
unsigned int memtest(unsigned int start, unsigned int end)
|
||||
{
|
||||
char flg486 = 0;
|
||||
unsigned int eflg, cr0, i;
|
||||
|
||||
/* 确认CPU是386还是486以上的 */
|
||||
eflg = io_load_eflags();
|
||||
eflg |= EFLAGS_AC_BIT; /* AC-bit = 1 */
|
||||
io_store_eflags(eflg);
|
||||
eflg = io_load_eflags();
|
||||
if ((eflg & EFLAGS_AC_BIT) != 0) {
|
||||
/* 如果是386,即使设定AC=1,AC的值还会自动回到0 */
|
||||
flg486 = 1;
|
||||
}
|
||||
|
||||
eflg &= ~EFLAGS_AC_BIT; /* AC-bit = 0 */
|
||||
io_store_eflags(eflg);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 |= CR0_CACHE_DISABLE; /* 禁止缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
i = memtest_sub(start, end);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 &= ~CR0_CACHE_DISABLE; /* 允许缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void memman_init(struct MEMMAN *man){
|
||||
man->frees = 0; /* 可用信息数目 */
|
||||
man->maxfrees = 0; /* 用于观察可用状况:frees的最大值 */
|
||||
man->lostsize = 0; /* 释放失败的内存的大小总和 */
|
||||
man->losts = 0; /* 释放失败次数 */
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
/* 分配 */
|
||||
{
|
||||
unsigned int i, a;
|
||||
for (i = 0; i < man->frees; i++) {
|
||||
if (man->free[i].size >= size) {
|
||||
/* 找到了足够大的内存 */
|
||||
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; /* 没有可用空间 */
|
||||
}
|
||||
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size)
|
||||
/* 释放 */
|
||||
{
|
||||
int i, j;
|
||||
/* 为便于归纳内存,将free[]按照addr的顺序排列 */
|
||||
/* 所以,先决定应该放在哪里 */
|
||||
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]; /* 结构体赋值 */
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0; /* 成功完成 */
|
||||
}
|
||||
}
|
||||
/* 不能与前面的可用空间归纳到一起 */
|
||||
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; /* 失败 */
|
||||
}
|
||||
|
||||
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size)
|
||||
{
|
||||
unsigned int a;
|
||||
size = (size + 0xfff) & 0xfffff000;
|
||||
a = memman_alloc(man, size);
|
||||
return a;
|
||||
}
|
||||
|
||||
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size)
|
||||
{
|
||||
int i;
|
||||
size = (size + 0xfff) & 0xfffff000;
|
||||
i = memman_free(man, addr, size);
|
||||
return i;
|
||||
}
|
||||
70
11_day/mouse.c
Normal file
70
11_day/mouse.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/* 鼠标控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO8 mousefifo;
|
||||
|
||||
void inthandler2c(int *esp) {
|
||||
/* 来自PS/2鼠标的中断 */
|
||||
unsigned char data;
|
||||
io_out8(PIC1_OCW2, 0x64); /* 通知PIC IRQ-12 已经受理完毕 */
|
||||
io_out8(PIC0_OCW2, 0x62); /* 通知PIC IRQ-02 已经受理完毕 */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo8_put(&mousefifo, data);
|
||||
return;
|
||||
}
|
||||
|
||||
#define KEYCMD_SENDTO_MOUSE 0xd4
|
||||
#define MOUSECMD_ENABLE 0xf4
|
||||
|
||||
void enable_mouse(struct MOUSE_DEC *mdec) {
|
||||
/* 鼠标有效 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
|
||||
/* 顺利的话,ACK(0xfa)会被送过来 */
|
||||
mdec->phase = 0; /* 等待0xfa的阶段 */
|
||||
return;
|
||||
}
|
||||
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat) {
|
||||
if (mdec->phase == 0) {
|
||||
/* 等待鼠标的0xfa的阶段 */
|
||||
if (dat == 0xfa) {
|
||||
mdec->phase = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 1) {
|
||||
/* 等待鼠标第一字节的阶段 */
|
||||
mdec->buf[0] = dat;
|
||||
mdec->phase = 2;
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 2) {
|
||||
/* 等待鼠标第二字节的阶段 */
|
||||
mdec->buf[1] = dat;
|
||||
mdec->phase = 3;
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
/* 鼠标的y方向与画面符号相反 */
|
||||
mdec->y = - mdec->y;
|
||||
return 1;
|
||||
}
|
||||
/* 应该不可能到这里来 */
|
||||
return -1;
|
||||
}
|
||||
184
11_day/naskfunc.nas
Normal file
184
11_day/naskfunc.nas
Normal file
@@ -0,0 +1,184 @@
|
||||
; naskfunc
|
||||
; TAB=4
|
||||
|
||||
[FORMAT "WCOFF"] ; 制作目标文件的模式
|
||||
[INSTRSET "i486p"] ; 使用到486为止的指令
|
||||
[BITS 32] ; 3制作32位模式用的机器语言
|
||||
[FILE "naskfunc.nas"] ; 文件名
|
||||
|
||||
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 _load_gdtr, _load_idtr
|
||||
GLOBAL _load_cr0, _store_cr0
|
||||
GLOBAL _asm_inthandler21, _asm_inthandler27, _asm_inthandler2c
|
||||
GLOBAL _memtest_sub
|
||||
EXTERN _inthandler21, _inthandler27, _inthandler2c
|
||||
|
||||
[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 EAX,[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 ; PUSH EFLAGS
|
||||
POP EAX
|
||||
RET
|
||||
|
||||
_io_store_eflags: ; void io_store_eflags(int eflags);
|
||||
MOV EAX,[ESP+4]
|
||||
PUSH EAX
|
||||
POPFD ; POP EFLAGS
|
||||
RET
|
||||
|
||||
_load_gdtr: ; void load_gdtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LGDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_idtr: ; void load_idtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LIDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_cr0: ; int load_cr0(void);
|
||||
MOV EAX,CR0
|
||||
RET
|
||||
|
||||
_store_cr0: ; void store_cr0(int cr0);
|
||||
MOV EAX,[ESP+4]
|
||||
MOV CR0,EAX
|
||||
RET
|
||||
|
||||
_asm_inthandler21:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler21
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler27:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler27
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler2c:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler2c
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_memtest_sub: ; unsigned int memtest_sub(unsigned int start, unsigned int end)
|
||||
PUSH EDI ; (由于还要使用EBX, ESI, EDI)
|
||||
PUSH ESI
|
||||
PUSH EBX
|
||||
MOV ESI,0xaa55aa55 ; pat0 = 0xaa55aa55;
|
||||
MOV EDI,0x55aa55aa ; pat1 = 0x55aa55aa;
|
||||
MOV EAX,[ESP+12+4] ; i = start;
|
||||
mts_loop:
|
||||
MOV EBX,EAX
|
||||
ADD EBX,0xffc ; p = i + 0xffc;
|
||||
MOV EDX,[EBX] ; old = *p;
|
||||
MOV [EBX],ESI ; *p = pat0;
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP EDI,[EBX] ; if (*p != pat1) goto fin;
|
||||
JNE mts_fin
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP ESI,[EBX] ; if (*p != pat0) goto fin;
|
||||
JNE mts_fin
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
ADD EAX,0x1000 ; i += 0x1000;
|
||||
CMP EAX,[ESP+12+8] ; if (i <= end) goto mts_loop;
|
||||
JBE mts_loop
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
mts_fin:
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
221
11_day/sheet.c
Normal file
221
11_day/sheet.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/* sheet */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define SHEET_USE 1
|
||||
|
||||
struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize)
|
||||
{
|
||||
struct SHTCTL *ctl;
|
||||
int i;
|
||||
ctl = (struct SHTCTL *) memman_alloc_4k(memman, sizeof (struct SHTCTL));
|
||||
if (ctl == 0) {
|
||||
goto err;
|
||||
}
|
||||
ctl->map = (unsigned char *) memman_alloc_4k(memman, xsize * ysize);
|
||||
if (ctl->map == 0) {
|
||||
memman_free_4k(memman, (int) ctl, sizeof (struct SHTCTL));
|
||||
goto err;
|
||||
}
|
||||
ctl->vram = vram;
|
||||
ctl->xsize = xsize;
|
||||
ctl->ysize = ysize;
|
||||
ctl->top = -1; /* 没有一张SHEET */
|
||||
for (i = 0; i < MAX_SHEETS; i++) {
|
||||
ctl->sheets0[i].flags = 0; /* 标记为未使用 */
|
||||
ctl->sheets0[i].ctl = ctl; /* 记录所属*/
|
||||
}
|
||||
err:
|
||||
return ctl;
|
||||
}
|
||||
|
||||
struct SHEET *sheet_alloc(struct SHTCTL *ctl)
|
||||
{
|
||||
struct SHEET *sht;
|
||||
int i;
|
||||
for (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 0; /* 所有的SHEET都处于正在使用状态*/
|
||||
}
|
||||
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
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); /* 按新图层信息重新绘制画面 */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0, int h1)
|
||||
{
|
||||
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
|
||||
unsigned char *buf, *vram = ctl->vram, *map = ctl->map, sid;
|
||||
struct SHEET *sht;
|
||||
|
||||
/* 如果refresh的范围超出了画面则修正 */
|
||||
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 (h = h0; h <= ctl->top; h++) {
|
||||
sht = ctl->sheets[h];
|
||||
buf = sht->buf;
|
||||
sid = sht -ctl->sheets0;
|
||||
|
||||
/* 使用vx0~vy1,对bx0~by1进行倒推 */
|
||||
bx0 = vx0 - sht->vx0;
|
||||
by0 = vy0 - sht->vy0;
|
||||
bx1 = vx1 - sht->vx0;
|
||||
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 (by = by0; by < by1; by++) {
|
||||
vy = sht->vy0 + by;
|
||||
for (bx = bx0; bx < bx1; bx++) {
|
||||
vx = sht->vx0 + bx;
|
||||
if (map[vy * ctl->xsize + vx] == sid) {
|
||||
vram[vy * ctl->xsize + vx] = buf[by * sht->bxsize + bx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_refreshmap(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0)
|
||||
{
|
||||
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
|
||||
unsigned char *buf, sid, *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 (h = h0; h <= ctl->top; h++) {
|
||||
sht = ctl->sheets[h];
|
||||
sid = sht - ctl->sheets0; /* 将进行了减法计算的地址作为图层号码使用 */
|
||||
buf = sht->buf;
|
||||
bx0 = vx0 - sht->vx0;
|
||||
by0 = vy0 - sht->vy0;
|
||||
bx1 = vx1 - sht->vx0;
|
||||
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 (by = by0; by < by1; by++) {
|
||||
vy = sht->vy0 + by;
|
||||
for (bx = bx0; bx < bx1; bx++) {
|
||||
vx = sht->vx0 + bx;
|
||||
if (buf[by * sht->bxsize + bx] != sht->col_inv) {
|
||||
map[vy * ctl->xsize + vx] = sid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_free(struct SHEET *sht)
|
||||
{
|
||||
if (sht->height >= 0) {
|
||||
sheet_updown(sht, -1); /* 如果处于显示状态,则先设定为隐藏 */
|
||||
}
|
||||
sht->flags = 0; /* "未使用"标志 */
|
||||
return;
|
||||
}
|
||||
1
12_day/!cons_9x.bat
Normal file
1
12_day/!cons_9x.bat
Normal file
@@ -0,0 +1 @@
|
||||
command
|
||||
1
12_day/!cons_nt.bat
Normal file
1
12_day/!cons_nt.bat
Normal file
@@ -0,0 +1 @@
|
||||
cmd.exe
|
||||
93
12_day/Makefile
Normal file
93
12_day/Makefile
Normal file
@@ -0,0 +1,93 @@
|
||||
OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \
|
||||
int.obj fifo.obj keyboard.obj mouse.obj memory.obj sheet.obj timer.obj
|
||||
|
||||
TOOLPATH = ../z_tools/
|
||||
INCPATH = ../z_tools/haribote/
|
||||
|
||||
MAKE = $(TOOLPATH)make.exe -r
|
||||
NASK = $(TOOLPATH)nask.exe
|
||||
CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
|
||||
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
|
||||
OBJ2BIM = $(TOOLPATH)obj2bim.exe
|
||||
MAKEFONT = $(TOOLPATH)makefont.exe
|
||||
BIN2OBJ = $(TOOLPATH)bin2obj.exe
|
||||
BIM2HRB = $(TOOLPATH)bim2hrb.exe
|
||||
RULEFILE = $(TOOLPATH)haribote/haribote.rul
|
||||
EDIMG = $(TOOLPATH)edimg.exe
|
||||
IMGTOL = $(TOOLPATH)imgtol.com
|
||||
COPY = copy
|
||||
DEL = del
|
||||
|
||||
# 默认动作
|
||||
|
||||
default :
|
||||
$(MAKE) img
|
||||
|
||||
# 镜像文件生成
|
||||
|
||||
ipl10.bin : ipl10.nas Makefile
|
||||
$(NASK) ipl10.nas ipl10.bin ipl10.lst
|
||||
|
||||
asmhead.bin : asmhead.nas Makefile
|
||||
$(NASK) asmhead.nas asmhead.bin asmhead.lst
|
||||
|
||||
hankaku.bin : hankaku.txt Makefile
|
||||
$(MAKEFONT) hankaku.txt hankaku.bin
|
||||
|
||||
hankaku.obj : hankaku.bin Makefile
|
||||
$(BIN2OBJ) hankaku.bin hankaku.obj _hankaku
|
||||
|
||||
bootpack.bim : $(OBJS_BOOTPACK) Makefile
|
||||
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
|
||||
$(OBJS_BOOTPACK)
|
||||
# 3MB+64KB=3136KB
|
||||
|
||||
bootpack.hrb : bootpack.bim Makefile
|
||||
$(BIM2HRB) bootpack.bim bootpack.hrb 0
|
||||
|
||||
haribote.sys : asmhead.bin bootpack.hrb Makefile
|
||||
copy /B asmhead.bin+bootpack.hrb haribote.sys
|
||||
|
||||
haribote.img : ipl10.bin haribote.sys Makefile
|
||||
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
|
||||
wbinimg src:ipl10.bin len:512 from:0 to:0 \
|
||||
copy from:haribote.sys to:@: \
|
||||
imgout:haribote.img
|
||||
|
||||
# 其他指令
|
||||
|
||||
%.gas : %.c bootpack.h Makefile
|
||||
$(CC1) -o $*.gas $*.c
|
||||
|
||||
%.nas : %.gas Makefile
|
||||
$(GAS2NASK) $*.gas $*.nas
|
||||
|
||||
%.obj : %.nas Makefile
|
||||
$(NASK) $*.nas $*.obj $*.lst
|
||||
|
||||
# 运行程序
|
||||
|
||||
img :
|
||||
$(MAKE) haribote.img
|
||||
|
||||
run :
|
||||
$(MAKE) img
|
||||
$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
|
||||
$(MAKE) -C ../z_tools/qemu
|
||||
|
||||
install :
|
||||
$(MAKE) img
|
||||
$(IMGTOL) w a: haribote.img
|
||||
|
||||
clean :
|
||||
-$(DEL) *.bin
|
||||
-$(DEL) *.lst
|
||||
-$(DEL) *.obj
|
||||
-$(DEL) bootpack.map
|
||||
-$(DEL) bootpack.bim
|
||||
-$(DEL) bootpack.hrb
|
||||
-$(DEL) haribote.sys
|
||||
|
||||
src_only :
|
||||
$(MAKE) clean
|
||||
-$(DEL) haribote.img
|
||||
146
12_day/asmhead.nas
Normal file
146
12_day/asmhead.nas
Normal file
@@ -0,0 +1,146 @@
|
||||
; haribote-os boot asm
|
||||
; TAB=4
|
||||
|
||||
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 ; 图像缓冲区的起始地址
|
||||
|
||||
ORG 0xc200 ; 这个的程序要被装载的内存地址
|
||||
|
||||
; 画面设置
|
||||
|
||||
MOV AL,0x13 ; VGA显卡,320x200x8bit
|
||||
MOV AH,0x00
|
||||
INT 0x10
|
||||
MOV BYTE [VMODE],8 ; 屏幕的模式(参考C语言的引用)
|
||||
MOV WORD [SCRNX],320
|
||||
MOV WORD [SCRNY],200
|
||||
MOV DWORD [VRAM],0x000a0000
|
||||
|
||||
; 通过 BIOS 获取指示灯状态
|
||||
|
||||
MOV AH,0x02
|
||||
INT 0x16 ; keyboard BIOS
|
||||
MOV [LEDS],AL
|
||||
|
||||
; PIC关闭一切中断
|
||||
; 根据AT兼容机的规格,如果要初始化PIC,
|
||||
; 必须在CLI之前进行,否则有时会挂起。
|
||||
; 随后进行PIC的初始化。
|
||||
|
||||
MOV AL,0xff
|
||||
OUT 0x21,AL
|
||||
NOP ; 如果连续执行OUT指令,有些机种会无法正常运行
|
||||
OUT 0xa1,AL
|
||||
|
||||
CLI ; 禁止CPU级别的中断
|
||||
|
||||
; 为了让CPU能够访问1MB以上的内存空间,设定A20GATE
|
||||
|
||||
CALL waitkbdout
|
||||
MOV AL,0xd1
|
||||
OUT 0x64,AL
|
||||
CALL waitkbdout
|
||||
MOV AL,0xdf ; enable A20
|
||||
OUT 0x60,AL
|
||||
CALL waitkbdout
|
||||
|
||||
; 切换到保护模式
|
||||
|
||||
[INSTRSET "i486p"] ; 说明使用486指令
|
||||
|
||||
LGDT [GDTR0] ; 设置临时GDT
|
||||
MOV EAX,CR0
|
||||
AND EAX,0x7fffffff ; 设bit31为0(禁用分页)
|
||||
OR EAX,0x00000001 ; bit0到1转换(保护模式过渡)
|
||||
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
|
||||
|
||||
; 必须由asmhead来完成的工作,至此全部完毕
|
||||
; 以后就交由bootpack来完成
|
||||
|
||||
; bootpack启动
|
||||
|
||||
MOV EBX,BOTPAK
|
||||
MOV ECX,[EBX+16]
|
||||
ADD ECX,3 ; ECX += 3;
|
||||
SHR ECX,2 ; ECX /= 4;
|
||||
JZ skip ; 没有要转送的东西时
|
||||
MOV ESI,[EBX+20] ; 转送源
|
||||
ADD ESI,EBX
|
||||
MOV EDI,[EBX+12] ; 转送目标
|
||||
CALL memcpy
|
||||
skip:
|
||||
MOV ESP,[EBX+12] ; 堆栈的初始化
|
||||
JMP DWORD 2*8:0x0000001b
|
||||
|
||||
waitkbdout:
|
||||
IN AL,0x64
|
||||
AND AL,0x02
|
||||
IN AL,0x60 ; 空读(为了清空数据接收缓冲区中的垃圾数据)
|
||||
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地址前缀大小
|
||||
|
||||
ALIGNB 16
|
||||
GDT0:
|
||||
RESB 8 ; 初始值
|
||||
DW 0xffff,0x0000,0x9200,0x00cf ; 可以读写的段(segment)32bit
|
||||
DW 0xffff,0x0000,0x9a28,0x0047 ; 可执行的文件的32bit寄存器(bootpack用)
|
||||
|
||||
DW 0
|
||||
GDTR0:
|
||||
DW 8*3-1
|
||||
DD GDT0
|
||||
|
||||
ALIGNB 16
|
||||
bootpack:
|
||||
210
12_day/bootpack.c
Normal file
210
12_day/bootpack.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/* bootpack*/
|
||||
|
||||
#include "bootpack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void make_window8(unsigned char *buf, int xsize, int ysize, char *title);
|
||||
|
||||
void HariMain(void)
|
||||
{
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
struct FIFO8 timerfifo, timerfifo2, timerfifo3;
|
||||
char s[40], keybuf[32], mousebuf[128], timerbuf[8], timerbuf2[8], timerbuf3[8];
|
||||
struct TIMER *timer, *timer2, *timer3;
|
||||
int mx, my, i;
|
||||
unsigned int memtotal;
|
||||
struct MOUSE_DEC mdec;
|
||||
struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
|
||||
struct SHTCTL *shtctl;
|
||||
struct SHEET *sht_back, *sht_mouse, *sht_win;
|
||||
unsigned char *buf_back, buf_mouse[256], *buf_win;
|
||||
|
||||
init_gdtidt();
|
||||
init_pic();
|
||||
io_sti(); /* IDT/PIC的初始化已经完成,于是开放CPU的中断 */
|
||||
fifo8_init(&keyfifo, 32, keybuf);
|
||||
fifo8_init(&mousefifo, 128, mousebuf);
|
||||
init_pit();
|
||||
io_out8(PIC0_IMR, 0xf8); /* PIT和PIC1和键盘设置为许可(11111000) */
|
||||
io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */
|
||||
|
||||
fifo8_init(&timerfifo, 8, timerbuf);
|
||||
timer = timer_alloc();
|
||||
timer_init(timer, &timerfifo, 1);
|
||||
timer_settime(timer, 1000);
|
||||
fifo8_init(&timerfifo2, 8, timerbuf2);
|
||||
timer2 = timer_alloc();
|
||||
timer_init(timer2, &timerfifo2, 1);
|
||||
timer_settime(timer2, 300);
|
||||
fifo8_init(&timerfifo3, 8, timerbuf3);
|
||||
timer3 = timer_alloc();
|
||||
timer_init(timer3, &timerfifo3, 1);
|
||||
timer_settime(timer3, 50);
|
||||
|
||||
init_keyboard();
|
||||
enable_mouse(&mdec);
|
||||
memtotal = memtest(0x00400000, 0xbfffffff);
|
||||
memman_init(memman);
|
||||
memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 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");
|
||||
sheet_slide(sht_back, 0, 0);
|
||||
mx = (binfo->scrnx - 16) / 2; /* 按显示在画面中央来计算坐标 */
|
||||
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);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
|
||||
sprintf(s, "memory %dMB free : %dKB",
|
||||
memtotal / (1024 * 1024), memman_total(memman) / 1024);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);
|
||||
sheet_refresh(sht_back, 0, 0, binfo->scrnx, 48); /* 刷新文字 */
|
||||
|
||||
for (;;) {
|
||||
sprintf(s, "%010d", timerctl.count);
|
||||
boxfill8(buf_win, 160, COL8_C6C6C6, 40, 28, 119, 43);
|
||||
putfonts8_asc(buf_win, 160, 40, 28, COL8_000000, s);
|
||||
sheet_refresh(sht_win, 40, 28, 120, 44); /* 到这里结束 */
|
||||
|
||||
io_cli();
|
||||
if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) + fifo8_status(&timerfifo)
|
||||
+ fifo8_status(&timerfifo2) + fifo8_status(&timerfifo3) == 0) {
|
||||
io_sti(); /* 不做HLT */
|
||||
} else {
|
||||
if (fifo8_status(&keyfifo) != 0) {
|
||||
i = fifo8_get(&keyfifo);
|
||||
io_sti();
|
||||
sprintf(s, "%02X", i);
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
|
||||
sheet_refresh(sht_back, 0, 16, 16, 32); /* 刷新文字 */
|
||||
} else if (fifo8_status(&mousefifo) != 0) {
|
||||
i = fifo8_get(&mousefifo);
|
||||
io_sti();
|
||||
if (mouse_decode(&mdec, i) != 0) {
|
||||
/* 3字节都凑齐了,所以把它们显示出来*/
|
||||
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
|
||||
if ((mdec.btn & 0x01) != 0) {
|
||||
s[1] = 'L';
|
||||
}
|
||||
if ((mdec.btn & 0x02) != 0) {
|
||||
s[3] = 'R';
|
||||
}
|
||||
if ((mdec.btn & 0x04) != 0) {
|
||||
s[2] = 'C';
|
||||
}
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
|
||||
sheet_refresh(sht_back, 32, 16, 32 + 15 * 8, 32); /* 刷新文字 */
|
||||
/* 移动光标 */
|
||||
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);
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 0, 0, 79, 15); /* 消坐标 */
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s); /* 写坐标 */
|
||||
sheet_refresh(sht_back, 0, 0, 80, 16); /* 刷新文字 */
|
||||
sheet_slide(sht_mouse, mx, my); /* 包含sheet_refresh含sheet_refresh */
|
||||
}
|
||||
} else if (fifo8_status(&timerfifo) != 0) {
|
||||
i = fifo8_get(&timerfifo); /* 首先读入(为了设定起始点) */
|
||||
io_sti();
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 64, COL8_FFFFFF, "10[sec]");
|
||||
sheet_refresh(sht_back, 0, 64, 56, 80);
|
||||
} else if (fifo8_status(&timerfifo2) != 0) {
|
||||
i = fifo8_get(&timerfifo2); /* 首先读入(为了设定起始点) */
|
||||
io_sti();
|
||||
putfonts8_asc(buf_back, binfo->scrnx, 0, 80, COL8_FFFFFF, "3[sec]");
|
||||
sheet_refresh(sht_back, 0, 80, 48, 96);
|
||||
} else if (fifo8_status(&timerfifo3) != 0) {
|
||||
i = fifo8_get(&timerfifo3); /* 首先读入(为了设定起始点) */
|
||||
io_sti();
|
||||
if (i != 0) {
|
||||
timer_init(timer3, &timerfifo3, 0); /* 然后设置0 */
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_FFFFFF, 8, 96, 15, 111);
|
||||
} else {
|
||||
timer_init(timer3, &timerfifo3, 1); /* 然后设置1 */
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 8, 96, 15, 111);
|
||||
}
|
||||
timer_settime(timer3, 50);
|
||||
sheet_refresh(sht_back, 8, 96, 16, 112);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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$$$$$$$$$$$$$$@",
|
||||
"@@@@@@@@@@@@@@@@"
|
||||
};
|
||||
int x, y;
|
||||
char c;
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, xsize - 1, 0 );
|
||||
boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, xsize - 2, 1 );
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, 0, ysize - 1);
|
||||
boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, 1, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_848484, xsize - 2, 1, xsize - 2, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_000000, xsize - 1, 0, xsize - 1, ysize - 1);
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3);
|
||||
boxfill8(buf, xsize, COL8_000084, 3, 3, xsize - 4, 20 );
|
||||
boxfill8(buf, xsize, COL8_848484, 1, ysize - 2, xsize - 2, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_000000, 0, ysize - 1, xsize - 1, ysize - 1);
|
||||
putfonts8_asc(buf, xsize, 24, 4, COL8_FFFFFF, title);
|
||||
for (y = 0; y < 14; y++) {
|
||||
for (x = 0; x < 16; x++) {
|
||||
c = closebtn[y][x];
|
||||
if (c == '@') {
|
||||
c = COL8_000000;
|
||||
} else if (c == '$') {
|
||||
c = COL8_848484;
|
||||
} else if (c == 'Q') {
|
||||
c = COL8_C6C6C6;
|
||||
} else {
|
||||
c = COL8_FFFFFF;
|
||||
}
|
||||
buf[(5 + y) * xsize + (xsize - 21 + x)] = c;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
191
12_day/bootpack.h
Normal file
191
12_day/bootpack.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/* asmhead.nas */
|
||||
struct BOOTINFO { /* 0x0ff0-0x0fff */
|
||||
char cyls; /* 启动区读磁盘读到此为止 */
|
||||
char leds; /* 启动时键盘的LED的状态 */
|
||||
char vmode; /* 显卡模式为多少位彩色 */
|
||||
char reserve;
|
||||
short scrnx, scrny; /* 画面分辨率 */
|
||||
char *vram;
|
||||
};
|
||||
#define ADR_BOOTINFO 0x00000ff0
|
||||
|
||||
/* naskfunc.nas */
|
||||
void io_hlt(void);
|
||||
void io_cli(void);
|
||||
void io_sti(void);
|
||||
void io_stihlt(void);
|
||||
int io_in8(int port);
|
||||
void io_out8(int port, int data);
|
||||
int io_load_eflags(void);
|
||||
void io_store_eflags(int eflags);
|
||||
void load_gdtr(int limit, int addr);
|
||||
void load_idtr(int limit, int addr);
|
||||
int load_cr0(void);
|
||||
void store_cr0(int cr0);
|
||||
void asm_inthandler20(void);
|
||||
void asm_inthandler21(void);
|
||||
void asm_inthandler27(void);
|
||||
void asm_inthandler2c(void);
|
||||
unsigned int memtest_sub(unsigned int start, unsigned int end);
|
||||
|
||||
/* fifo.c */
|
||||
struct FIFO8 {
|
||||
unsigned char *buf;
|
||||
int p, q, size, free, flags;
|
||||
};
|
||||
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);
|
||||
|
||||
/* graphic.c */
|
||||
void init_palette(void);
|
||||
void set_palette(int start, int end, unsigned char *rgb);
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
|
||||
void init_screen8(char *vram, int x, int y);
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
|
||||
void init_mouse_cursor8(char *mouse, char bc);
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize);
|
||||
#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
|
||||
|
||||
/* dsctbl.c */
|
||||
struct SEGMENT_DESCRIPTOR {
|
||||
short limit_low, base_low;
|
||||
char base_mid, access_right;
|
||||
char limit_high, base_high;
|
||||
};
|
||||
struct GATE_DESCRIPTOR {
|
||||
short offset_low, selector;
|
||||
char dw_count, access_right;
|
||||
short offset_high;
|
||||
};
|
||||
void init_gdtidt(void);
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
|
||||
#define ADR_IDT 0x0026f800
|
||||
#define LIMIT_IDT 0x000007ff
|
||||
#define ADR_GDT 0x00270000
|
||||
#define LIMIT_GDT 0x0000ffff
|
||||
#define ADR_BOTPAK 0x00280000
|
||||
#define LIMIT_BOTPAK 0x0007ffff
|
||||
#define AR_DATA32_RW 0x4092
|
||||
#define AR_CODE32_ER 0x409a
|
||||
#define AR_INTGATE32 0x008e
|
||||
|
||||
/* int.c */
|
||||
void init_pic(void);
|
||||
void inthandler27(int *esp);
|
||||
#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
|
||||
|
||||
/* keyboard.c */
|
||||
void inthandler21(int *esp);
|
||||
void wait_KBC_sendready(void);
|
||||
void init_keyboard(void);
|
||||
extern struct FIFO8 keyfifo;
|
||||
#define PORT_KEYDAT 0x0060
|
||||
#define PORT_KEYCMD 0x0064
|
||||
|
||||
/* mouse.c */
|
||||
struct MOUSE_DEC {
|
||||
unsigned char buf[3], phase;
|
||||
int x, y, btn;
|
||||
};
|
||||
void inthandler2c(int *esp);
|
||||
void enable_mouse(struct MOUSE_DEC *mdec);
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);
|
||||
extern struct FIFO8 mousefifo;
|
||||
|
||||
/* memory.c */
|
||||
#define MEMMAN_FREES 4090 /* 大约是32KB*/
|
||||
#define MEMMAN_ADDR 0x003c0000
|
||||
|
||||
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);
|
||||
void memman_init(struct MEMMAN *man);
|
||||
unsigned int memman_total(struct MEMMAN *man);
|
||||
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
|
||||
/* sheet.c */
|
||||
#define MAX_SHEETS 256
|
||||
#define SHEET_USE 1
|
||||
|
||||
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_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);
|
||||
|
||||
/* timer.c */
|
||||
#define MAX_TIMER 500
|
||||
struct TIMER {
|
||||
unsigned int timeout, flags;
|
||||
struct FIFO8 *fifo;
|
||||
unsigned char data;
|
||||
};
|
||||
struct TIMERCTL {
|
||||
unsigned int count, next, using;
|
||||
struct TIMER *timers[MAX_TIMER];
|
||||
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 FIFO8 *fifo, unsigned char data);
|
||||
void timer_settime(struct TIMER *timer, unsigned int timeout);
|
||||
void inthandler20(int *esp);
|
||||
|
||||
57
12_day/dsctbl.c
Normal file
57
12_day/dsctbl.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* GDT、IDT、descriptor table 关系处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_gdtidt(void)
|
||||
{
|
||||
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
|
||||
struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) ADR_IDT;
|
||||
int i;
|
||||
|
||||
/* GDT初始化 */
|
||||
for (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_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);
|
||||
load_gdtr(LIMIT_GDT, ADR_GDT);
|
||||
|
||||
/* IDT初始化 */
|
||||
for (i = 0; i <= LIMIT_IDT / 8; i++) {
|
||||
set_gatedesc(idt + i, 0, 0, 0);
|
||||
}
|
||||
load_idtr(LIMIT_IDT, ADR_IDT);
|
||||
|
||||
/* IDT设置*/
|
||||
set_gatedesc(idt + 0x20, (int) asm_inthandler20, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
57
12_day/fifo.c
Normal file
57
12_day/fifo.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* FIFO */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define FLAGS_OVERRUN 0x0001
|
||||
|
||||
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
|
||||
/* 初始化FIFO缓冲区 */
|
||||
{
|
||||
fifo->size = size;
|
||||
fifo->buf = buf;
|
||||
fifo->free = size; /* 缓冲区大小 */
|
||||
fifo->flags = 0;
|
||||
fifo->p = 0; /* 下一个数据写入位置 */
|
||||
fifo->q = 0; /* 下一个数据读出位置 */
|
||||
return;
|
||||
}
|
||||
|
||||
int fifo8_put(struct FIFO8 *fifo, unsigned char data)
|
||||
/* 向FIFO传送数据并保存 */
|
||||
{
|
||||
if (fifo->free == 0) {
|
||||
/* 没有空间了,溢出 */
|
||||
fifo->flags |= FLAGS_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
fifo->buf[fifo->p] = data;
|
||||
fifo->p++;
|
||||
if (fifo->p == fifo->size) {
|
||||
fifo->p = 0;
|
||||
}
|
||||
fifo->free--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fifo8_get(struct FIFO8 *fifo)
|
||||
/* 从FIFO取得一个数据 */
|
||||
{
|
||||
int data;
|
||||
if (fifo->free == fifo->size) {
|
||||
/* 如果缓冲区为空则返回-1 */
|
||||
return -1;
|
||||
}
|
||||
data = fifo->buf[fifo->q];
|
||||
fifo->q++;
|
||||
if (fifo->q == fifo->size) {
|
||||
fifo->q = 0;
|
||||
}
|
||||
fifo->free++;
|
||||
return data;
|
||||
}
|
||||
|
||||
int fifo8_status(struct FIFO8 *fifo)
|
||||
/* 报告一下积攒是数据量 */
|
||||
{
|
||||
return fifo->size - fifo->free;
|
||||
}
|
||||
157
12_day/graphic.c
Normal file
157
12_day/graphic.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/* 关于绘图部分的处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_palette(void)
|
||||
{
|
||||
static unsigned char table_rgb[16 * 3] = {
|
||||
0x00, 0x00, 0x00, /* 0:黑 */
|
||||
0xff, 0x00, 0x00, /* 1:梁红 */
|
||||
0x00, 0xff, 0x00, /* 2:亮绿 */
|
||||
0xff, 0xff, 0x00, /* 3:亮黄 */
|
||||
0x00, 0x00, 0xff, /* 4:亮蓝 */
|
||||
0xff, 0x00, 0xff, /* 5:亮紫 */
|
||||
0x00, 0xff, 0xff, /* 6:浅亮蓝 */
|
||||
0xff, 0xff, 0xff, /* 7:白 */
|
||||
0xc6, 0xc6, 0xc6, /* 8:亮灰 */
|
||||
0x84, 0x00, 0x00, /* 9:暗红 */
|
||||
0x00, 0x84, 0x00, /* 10:暗绿 */
|
||||
0x84, 0x84, 0x00, /* 11:暗黄 */
|
||||
0x00, 0x00, 0x84, /* 12:暗青 */
|
||||
0x84, 0x00, 0x84, /* 13:暗紫 */
|
||||
0x00, 0x84, 0x84, /* 14:浅暗蓝 */
|
||||
0x84, 0x84, 0x84 /* 15:暗灰 */
|
||||
};
|
||||
set_palette(0, 15, table_rgb);
|
||||
return;
|
||||
|
||||
/* C语言中的static char语句只能用于数据,相当于汇编中的DB指令 */
|
||||
}
|
||||
|
||||
void set_palette(int start, int end, unsigned char *rgb)
|
||||
{
|
||||
int i, eflags;
|
||||
eflags = io_load_eflags(); /* 记录中断许可标志的值 */
|
||||
io_cli(); /* 将中断许可标志置为0,禁止中断 */
|
||||
io_out8(0x03c8, start);
|
||||
for (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); /* 复原中断许可标志 */
|
||||
return;
|
||||
}
|
||||
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
|
||||
{
|
||||
int x, y;
|
||||
for (y = y0; y <= y1; y++) {
|
||||
for (x = x0; x <= x1; x++)
|
||||
vram[y * xsize + x] = c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_screen8(char *vram, int x, int y)
|
||||
{
|
||||
boxfill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1);
|
||||
|
||||
boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5);
|
||||
boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3);
|
||||
boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3);
|
||||
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24);
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3);
|
||||
return;
|
||||
}
|
||||
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
|
||||
{
|
||||
int i;
|
||||
char *p, d /* data */;
|
||||
for (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; }
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
|
||||
{
|
||||
extern char hankaku[4096];
|
||||
/* C语言中,字符串都是以0x00结尾 */
|
||||
for (; *s != 0x00; s++) {
|
||||
putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
|
||||
x += 8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_mouse_cursor8(char *mouse, char bc)
|
||||
/* 鼠标的数据准备(16x16) */
|
||||
{
|
||||
static char cursor[16][16] = {
|
||||
"**************..",
|
||||
"*OOOOOOOOOOO*...",
|
||||
"*OOOOOOOOOO*....",
|
||||
"*OOOOOOOOO*.....",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOO**OOO*.....",
|
||||
"*OOO*..*OOO*....",
|
||||
"*OO*....*OOO*...",
|
||||
"*O*......*OOO*..",
|
||||
"**........*OOO*.",
|
||||
"*..........*OOO*",
|
||||
"............*OO*",
|
||||
".............***"
|
||||
};
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < 16; y++) {
|
||||
for (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize)
|
||||
{
|
||||
int x, y;
|
||||
for (y = 0; y < pysize; y++) {
|
||||
for (x = 0; x < pxsize; x++) {
|
||||
vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
4609
12_day/hankaku.txt
Normal file
4609
12_day/hankaku.txt
Normal file
File diff suppressed because it is too large
Load Diff
37
12_day/int.c
Normal file
37
12_day/int.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*初始化关系 */
|
||||
|
||||
#include "bootpack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void init_pic(void)
|
||||
/* PIC初始化 */
|
||||
{
|
||||
io_out8(PIC0_IMR, 0xff ); /* 禁止所有中断 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 禁止所有中断 */
|
||||
|
||||
io_out8(PIC0_ICW1, 0x11 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 11111011 PIC1以外全部禁止 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 11111111 禁止所有中断 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void inthandler27(int *esp)
|
||||
/* PIC0中断的不完整策略 */
|
||||
/* 这个中断在Athlon64X2上通过芯片组提供的便利,只需执行一次 */
|
||||
/* 这个中断只是接收,不执行任何操作 */
|
||||
/* 为什么不处理?
|
||||
→ 因为这个中断可能是电气噪声引发的、只是处理一些重要的情况。*/
|
||||
{
|
||||
io_out8(PIC0_OCW2, 0x67); /* 通知PIC的IRQ-07(参考7-1) */
|
||||
return;
|
||||
}
|
||||
109
12_day/ipl10.nas
Normal file
109
12_day/ipl10.nas
Normal file
@@ -0,0 +1,109 @@
|
||||
; haribote-ipl
|
||||
; TAB=4
|
||||
|
||||
CYLS EQU 10 ; 声明CYLS=10
|
||||
|
||||
ORG 0x7c00 ; 指明程序装载地址
|
||||
|
||||
; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code
|
||||
|
||||
JMP entry
|
||||
DB 0x90
|
||||
DB "HARIBOTE" ; 启动扇区名称(8字节)
|
||||
DW 512 ; 每个扇区(sector)大小(必须512字节)
|
||||
DB 1 ; 簇(cluster)大小(必须为1个扇区)
|
||||
DW 1 ; FAT起始位置(一般为第一个扇区)
|
||||
DB 2 ; FAT个数(必须为2)
|
||||
DW 224 ; 根目录大小(一般为224项)
|
||||
DW 2880 ; 该磁盘大小(必须为2880扇区1440*1024/512)
|
||||
DB 0xf0 ; 磁盘类型(必须为0xf0)
|
||||
DW 9 ; FAT的长度(必??9扇区)
|
||||
DW 18 ; 一个磁道(track)有几个扇区(必须为18)
|
||||
DW 2 ; 磁头数(必??2)
|
||||
DD 0 ; 不使用分区,必须是0
|
||||
DD 2880 ; 重写一次磁盘大小
|
||||
DB 0,0,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 ; 没出错则跳转到fin
|
||||
ADD SI,1 ; 往SI加1
|
||||
CMP SI,5 ; 比较SI与5
|
||||
JAE error ; SI >= 5 跳转到error
|
||||
MOV AH,0x00
|
||||
MOV DL,0x00 ; A驱动器
|
||||
INT 0x13 ; 重置驱动器
|
||||
JMP retry
|
||||
next:
|
||||
MOV AX,ES ; 把内存地址后移0x200(512/16十六进制转换)
|
||||
ADD AX,0x0020
|
||||
MOV ES,AX ; ADD ES,0x020因为没有ADD ES,只能通过AX进行
|
||||
ADD CL,1 ; 往CL里面加1
|
||||
CMP CL,18 ; 比较CL与18
|
||||
JBE readloop ; CL <= 18 跳转到readloop
|
||||
MOV CL,1
|
||||
ADD DH,1
|
||||
CMP DH,2
|
||||
JB readloop ; DH < 2 跳转到readloop
|
||||
MOV DH,0
|
||||
ADD CH,1
|
||||
CMP CH,CYLS
|
||||
JB readloop ; CH < CYLS 跳转到readloop
|
||||
|
||||
; 读取完毕,跳转到haribote.sys执行!
|
||||
MOV [0x0ff0],CH ; IPLがどこまで読んだのかをメモ
|
||||
JMP 0xc200
|
||||
|
||||
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
|
||||
|
||||
fin:
|
||||
HLT ; 让CPU停止,等待指令
|
||||
JMP fin ; 无限循环
|
||||
|
||||
msg:
|
||||
DB 0x0a, 0x0a ; 换行两次
|
||||
DB "load error"
|
||||
DB 0x0a ; 换行
|
||||
DB 0
|
||||
|
||||
RESB 0x7dfe-$ ; 填写0x00直到0x001fe
|
||||
|
||||
DB 0x55, 0xaa
|
||||
39
12_day/keyboard.c
Normal file
39
12_day/keyboard.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* 键盘控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO8 keyfifo;
|
||||
|
||||
void inthandler21(int *esp) {
|
||||
/* 来自PS/2键盘的中断 */
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
unsigned char data, s[4];
|
||||
io_out8(PIC0_OCW2, 0x61); /* 通知PIC IRQ-01 已经受理完毕 */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo8_put(&keyfifo, data);
|
||||
return;
|
||||
}
|
||||
|
||||
#define PORT_KEYSTA 0x0064
|
||||
#define KEYSTA_SEND_NOTREADY 0x02
|
||||
#define KEYCMD_WRITE_MODE 0x60
|
||||
#define KBC_MODE 0x47
|
||||
|
||||
void wait_KBC_sendready(void) {
|
||||
/* 等待键盘控制电路准备完毕 */
|
||||
for (;;) {
|
||||
if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_keyboard(void) {
|
||||
/* 初始化键盘控制电路 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, KBC_MODE);
|
||||
return;
|
||||
}
|
||||
1
12_day/make.bat
Normal file
1
12_day/make.bat
Normal file
@@ -0,0 +1 @@
|
||||
..\z_tools\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
162
12_day/memory.c
Normal file
162
12_day/memory.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>W */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define EFLAGS_AC_BIT 0x00040000
|
||||
#define CR0_CACHE_DISABLE 0x60000000
|
||||
|
||||
unsigned int memtest(unsigned int start, unsigned int end)
|
||||
{
|
||||
char flg486 = 0;
|
||||
unsigned int eflg, cr0, i;
|
||||
|
||||
/* 确认CPU是386还是486以上的 */
|
||||
eflg = io_load_eflags();
|
||||
eflg |= EFLAGS_AC_BIT; /* AC-bit = 1 */
|
||||
io_store_eflags(eflg);
|
||||
eflg = io_load_eflags();
|
||||
if ((eflg & EFLAGS_AC_BIT) != 0) {
|
||||
/* 如果是386,即使设定AC=1,AC的值还会自动回到0 */
|
||||
flg486 = 1;
|
||||
}
|
||||
|
||||
eflg &= ~EFLAGS_AC_BIT; /* AC-bit = 0 */
|
||||
io_store_eflags(eflg);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 |= CR0_CACHE_DISABLE; /* 禁止缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
i = memtest_sub(start, end);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 &= ~CR0_CACHE_DISABLE; /* 允许缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void memman_init(struct MEMMAN *man)
|
||||
{
|
||||
man->frees = 0; /* 可用信息数目 */
|
||||
man->maxfrees = 0; /* 用于观察可用状况:frees的最大值 */
|
||||
man->lostsize = 0; /* 释放失败的内存的大小总和 */
|
||||
man->losts = 0; /* 释放失败次数 */
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
/* 分配 */
|
||||
{
|
||||
unsigned int i, a;
|
||||
for (i = 0; i < man->frees; i++) {
|
||||
if (man->free[i].size >= size) {
|
||||
/* 找到了足够大的内存 */
|
||||
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; /* 没有可用空间 */
|
||||
}
|
||||
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size)
|
||||
/* 释放 */
|
||||
{
|
||||
int i, j;
|
||||
/* 为便于归纳内存,将free[]按照addr的顺序排列 */
|
||||
/* 所以,先决定应该放在哪里 */
|
||||
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]; /* 结构体赋值 */
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0; /* 成功完成 */
|
||||
}
|
||||
}
|
||||
/* 不能与前面的可用空间归纳到一起 */
|
||||
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; /* 失败 */
|
||||
}
|
||||
|
||||
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size)
|
||||
{
|
||||
unsigned int a;
|
||||
size = (size + 0xfff) & 0xfffff000;
|
||||
a = memman_alloc(man, size);
|
||||
return a;
|
||||
}
|
||||
|
||||
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size)
|
||||
{
|
||||
int i;
|
||||
size = (size + 0xfff) & 0xfffff000;
|
||||
i = memman_free(man, addr, size);
|
||||
return i;
|
||||
}
|
||||
73
12_day/mouse.c
Normal file
73
12_day/mouse.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/* 鼠标控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO8 mousefifo;
|
||||
|
||||
void inthandler2c(int *esp)
|
||||
{
|
||||
/* 来自PS/2鼠标的中断 */
|
||||
unsigned char data;
|
||||
io_out8(PIC1_OCW2, 0x64); /* 通知PIC IRQ-12 已经受理完毕 */
|
||||
io_out8(PIC0_OCW2, 0x62); /* 通知PIC IRQ-02 已经受理完毕 */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo8_put(&mousefifo, data);
|
||||
return;
|
||||
}
|
||||
|
||||
#define KEYCMD_SENDTO_MOUSE 0xd4
|
||||
#define MOUSECMD_ENABLE 0xf4
|
||||
|
||||
void enable_mouse(struct MOUSE_DEC *mdec)
|
||||
{
|
||||
/* 鼠标有效 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
|
||||
/* 顺利的话,ACK(0xfa)会被送过来 */
|
||||
mdec->phase = 0; /* 等待0xfa的阶段 */
|
||||
return;
|
||||
}
|
||||
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
|
||||
{
|
||||
if (mdec->phase == 0) {
|
||||
/* 等待鼠标的0xfa的阶段 */
|
||||
if (dat == 0xfa) {
|
||||
mdec->phase = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 1) {
|
||||
/* 等待鼠标第一字节的阶段 */
|
||||
mdec->buf[0] = dat;
|
||||
mdec->phase = 2;
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 2) {
|
||||
/* 等待鼠标第二字节的阶段 */
|
||||
mdec->buf[1] = dat;
|
||||
mdec->phase = 3;
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
/* 鼠标的y方向与画面符号相反 */
|
||||
mdec->y = - mdec->y;
|
||||
return 1;
|
||||
}
|
||||
/* 应该不可能到这里来 */
|
||||
return -1;
|
||||
}
|
||||
202
12_day/naskfunc.nas
Normal file
202
12_day/naskfunc.nas
Normal file
@@ -0,0 +1,202 @@
|
||||
; naskfunc
|
||||
; TAB=4
|
||||
|
||||
[FORMAT "WCOFF"] ; 制作目标文件的模式
|
||||
[INSTRSET "i486p"] ; 使用到486为止的指令
|
||||
[BITS 32] ; 3制作32位模式用的机器语言
|
||||
[FILE "naskfunc.nas"] ; 文件名
|
||||
|
||||
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 _load_gdtr, _load_idtr
|
||||
GLOBAL _load_cr0, _store_cr0
|
||||
GLOBAL _asm_inthandler20, _asm_inthandler21
|
||||
GLOBAL _asm_inthandler27, _asm_inthandler2c
|
||||
GLOBAL _memtest_sub
|
||||
EXTERN _inthandler20, _inthandler21
|
||||
EXTERN _inthandler27, _inthandler2c
|
||||
|
||||
[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 EAX,[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 ; PUSH EFLAGS
|
||||
POP EAX
|
||||
RET
|
||||
|
||||
_io_store_eflags: ; void io_store_eflags(int eflags);
|
||||
MOV EAX,[ESP+4]
|
||||
PUSH EAX
|
||||
POPFD ; POP EFLAGS
|
||||
RET
|
||||
|
||||
_load_gdtr: ; void load_gdtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LGDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_idtr: ; void load_idtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LIDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_cr0: ; int load_cr0(void);
|
||||
MOV EAX,CR0
|
||||
RET
|
||||
|
||||
_store_cr0: ; void store_cr0(int cr0);
|
||||
MOV EAX,[ESP+4]
|
||||
MOV CR0,EAX
|
||||
RET
|
||||
|
||||
_asm_inthandler20:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler20
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler21:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler21
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler27:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler27
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler2c:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler2c
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_memtest_sub: ; unsigned int memtest_sub(unsigned int start, unsigned int end)
|
||||
PUSH EDI ; (由于还要使用EBX, ESI, EDI)
|
||||
PUSH ESI
|
||||
PUSH EBX
|
||||
MOV ESI,0xaa55aa55 ; pat0 = 0xaa55aa55;
|
||||
MOV EDI,0x55aa55aa ; pat1 = 0x55aa55aa;
|
||||
MOV EAX,[ESP+12+4] ; i = start;
|
||||
mts_loop:
|
||||
MOV EBX,EAX
|
||||
ADD EBX,0xffc ; p = i + 0xffc;
|
||||
MOV EDX,[EBX] ; old = *p;
|
||||
MOV [EBX],ESI ; *p = pat0;
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP EDI,[EBX] ; if (*p != pat1) goto fin;
|
||||
JNE mts_fin
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP ESI,[EBX] ; if (*p != pat0) goto fin;
|
||||
JNE mts_fin
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
ADD EAX,0x1000 ; i += 0x1000;
|
||||
CMP EAX,[ESP+12+8] ; if (i <= end) goto mts_loop;
|
||||
JBE mts_loop
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
mts_fin:
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
216
12_day/sheet.c
Normal file
216
12_day/sheet.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/* sheet */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define SHEET_USE 1
|
||||
|
||||
struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize)
|
||||
{
|
||||
struct SHTCTL *ctl;
|
||||
int i;
|
||||
ctl = (struct SHTCTL *) memman_alloc_4k(memman, sizeof (struct SHTCTL));
|
||||
if (ctl == 0) {
|
||||
goto err;
|
||||
}
|
||||
ctl->map = (unsigned char *) memman_alloc_4k(memman, xsize * ysize);
|
||||
if (ctl->map == 0) {
|
||||
memman_free_4k(memman, (int) ctl, sizeof (struct SHTCTL));
|
||||
goto err;
|
||||
}
|
||||
ctl->vram = vram;
|
||||
ctl->xsize = xsize;
|
||||
ctl->ysize = ysize;
|
||||
ctl->top = -1; /* 没有一张SHEET */
|
||||
for (i = 0; i < MAX_SHEETS; i++) {
|
||||
ctl->sheets0[i].flags = 0; /* 标记为未使用 */
|
||||
ctl->sheets0[i].ctl = ctl; /* 记录所属*/
|
||||
}
|
||||
err:
|
||||
return ctl;
|
||||
}
|
||||
|
||||
struct SHEET *sheet_alloc(struct SHTCTL *ctl)
|
||||
{
|
||||
struct SHEET *sht;
|
||||
int i;
|
||||
for (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 0; /* 所有的SHEET都处于正在使用状态*/
|
||||
}
|
||||
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_refreshmap(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0)
|
||||
{
|
||||
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
|
||||
unsigned char *buf, sid, *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 (h = h0; h <= ctl->top; h++) {
|
||||
sht = ctl->sheets[h];
|
||||
sid = sht - ctl->sheets0; /* 将进行了减法计算的地址作为图层号码使用 */
|
||||
buf = sht->buf;
|
||||
bx0 = vx0 - sht->vx0;
|
||||
by0 = vy0 - sht->vy0;
|
||||
bx1 = vx1 - sht->vx0;
|
||||
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 (by = by0; by < by1; by++) {
|
||||
vy = sht->vy0 + by;
|
||||
for (bx = bx0; bx < bx1; bx++) {
|
||||
vx = sht->vx0 + bx;
|
||||
if (buf[by * sht->bxsize + bx] != sht->col_inv) {
|
||||
map[vy * ctl->xsize + vx] = sid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0, int h1)
|
||||
{
|
||||
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
|
||||
unsigned char *buf, *vram = ctl->vram, *map = ctl->map, sid;
|
||||
struct SHEET *sht;
|
||||
|
||||
/* 如果refresh的范围超出了画面则修正 */
|
||||
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 (h = h0; h <= h1; h++) {
|
||||
sht = ctl->sheets[h];
|
||||
buf = sht->buf;
|
||||
sid = sht - ctl->sheets0;
|
||||
|
||||
/* 使用vx0~vy1,对bx0~by1进行倒推 */
|
||||
bx0 = vx0 - sht->vx0;
|
||||
by0 = vy0 - sht->vy0;
|
||||
bx1 = vx1 - sht->vx0;
|
||||
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 (by = by0; by < by1; by++) {
|
||||
vy = sht->vy0 + by;
|
||||
for (bx = bx0; bx < bx1; bx++) {
|
||||
vx = sht->vx0 + bx;
|
||||
if (map[vy * ctl->xsize + vx] == sid) {
|
||||
vram[vy * ctl->xsize + vx] = buf[by * sht->bxsize + bx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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); /* 按新图层信息重新绘制画面 */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_free(struct SHEET *sht)
|
||||
{
|
||||
if (sht->height >= 0) {
|
||||
sheet_updown(sht, -1); /* 如果处于显示状态,则先设定为隐藏 */
|
||||
}
|
||||
sht->flags = 0; /* "未使用"标志 */
|
||||
return;
|
||||
}
|
||||
107
12_day/timer.c
Normal file
107
12_day/timer.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/* 定时器 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define PIT_CTRL 0x0043
|
||||
#define PIT_CNT0 0x0040
|
||||
|
||||
struct TIMERCTL timerctl;
|
||||
|
||||
#define TIMER_FLAGS_ALLOC 1 /* 已配置状态 */
|
||||
#define TIMER_FLAGS_USING 2 /* 定时器运行中 */
|
||||
|
||||
void init_pit(void)
|
||||
{
|
||||
int i;
|
||||
io_out8(PIT_CTRL, 0x34);
|
||||
io_out8(PIT_CNT0, 0x9c);
|
||||
io_out8(PIT_CNT0, 0x2e);
|
||||
timerctl.count = 0;
|
||||
timerctl.next = 0xffffffff; /* 因为最初没有正在运行的定时器 */
|
||||
timerctl.using = 0;
|
||||
for (i = 0; i < MAX_TIMER; i++) {
|
||||
timerctl.timers0[i].flags = 0; /* 未使用 */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
struct TIMER *timer_alloc(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_TIMER; i++) {
|
||||
if (timerctl.timers0[i].flags == 0) {
|
||||
timerctl.timers0[i].flags = TIMER_FLAGS_ALLOC;
|
||||
return &timerctl.timers0[i];
|
||||
}
|
||||
}
|
||||
return 0; /* 没找到 */
|
||||
}
|
||||
|
||||
void timer_free(struct TIMER *timer)
|
||||
{
|
||||
timer->flags = 0; /* 未使用 */
|
||||
return;
|
||||
}
|
||||
|
||||
void timer_init(struct TIMER *timer, struct FIFO8 *fifo, unsigned char data)
|
||||
{
|
||||
timer->fifo = fifo;
|
||||
timer->data = data;
|
||||
return;
|
||||
}
|
||||
|
||||
void timer_settime(struct TIMER *timer, unsigned int timeout)
|
||||
{
|
||||
int e, i, j;
|
||||
timer->timeout = timeout + timerctl.count;
|
||||
timer->flags = TIMER_FLAGS_USING;
|
||||
e = io_load_eflags();
|
||||
io_cli();
|
||||
/* 搜索注册位置 */
|
||||
for (i = 0; i < timerctl.using; i++) {
|
||||
if (timerctl.timers[i]->timeout >= timer->timeout) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* i号之后全部后移一位 */
|
||||
for (j = timerctl.using; j > i; j--) {
|
||||
timerctl.timers[j] = timerctl.timers[j - 1];
|
||||
}
|
||||
timerctl.using++;
|
||||
/* 插入到空位上 */
|
||||
timerctl.timers[i] = timer;
|
||||
timerctl.next = timerctl.timers[0]->timeout;
|
||||
io_store_eflags(e);
|
||||
return;
|
||||
}
|
||||
|
||||
void inthandler20(int *esp)
|
||||
{
|
||||
int i, j;
|
||||
io_out8(PIC0_OCW2, 0x60); /* 把IRQ-00信号接收完了的信息通知给PIC */
|
||||
timerctl.count++;
|
||||
if (timerctl.next > timerctl.count) {
|
||||
return; /* 还不到下一个时刻,所以结束*/
|
||||
}
|
||||
timerctl.next = 0xffffffff;
|
||||
for (i = 0; i < timerctl.using; i++) {
|
||||
/* timers的定时器都处于动作中,所以不确认flags */
|
||||
if (timerctl.timers[i]->timeout > timerctl.count) {
|
||||
break;
|
||||
}
|
||||
/* 超时*/
|
||||
timerctl.timers[i]->flags = TIMER_FLAGS_ALLOC;
|
||||
fifo8_put(timerctl.timers[i]->fifo, timerctl.timers[i]->data);
|
||||
}
|
||||
/* 正好有i个定时器超时了。其余的进行移位。 */
|
||||
timerctl.using -= i;
|
||||
for (j = 0; j < timerctl.using; j++) {
|
||||
timerctl.timers[j] = timerctl.timers[i + j];
|
||||
}
|
||||
if (timerctl.using > 0) {
|
||||
timerctl.next = timerctl.timers[0]->timeout;
|
||||
} else {
|
||||
timerctl.next = 0xffffffff;
|
||||
}
|
||||
return;
|
||||
}
|
||||
1
13_day/!cons_9x.bat
Normal file
1
13_day/!cons_9x.bat
Normal file
@@ -0,0 +1 @@
|
||||
command
|
||||
1
13_day/!cons_nt.bat
Normal file
1
13_day/!cons_nt.bat
Normal file
@@ -0,0 +1 @@
|
||||
cmd.exe
|
||||
93
13_day/Makefile
Normal file
93
13_day/Makefile
Normal file
@@ -0,0 +1,93 @@
|
||||
OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \
|
||||
int.obj fifo.obj keyboard.obj mouse.obj memory.obj sheet.obj timer.obj
|
||||
|
||||
TOOLPATH = ../z_tools/
|
||||
INCPATH = ../z_tools/haribote/
|
||||
|
||||
MAKE = $(TOOLPATH)make.exe -r
|
||||
NASK = $(TOOLPATH)nask.exe
|
||||
CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
|
||||
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
|
||||
OBJ2BIM = $(TOOLPATH)obj2bim.exe
|
||||
MAKEFONT = $(TOOLPATH)makefont.exe
|
||||
BIN2OBJ = $(TOOLPATH)bin2obj.exe
|
||||
BIM2HRB = $(TOOLPATH)bim2hrb.exe
|
||||
RULEFILE = $(TOOLPATH)haribote/haribote.rul
|
||||
EDIMG = $(TOOLPATH)edimg.exe
|
||||
IMGTOL = $(TOOLPATH)imgtol.com
|
||||
COPY = copy
|
||||
DEL = del
|
||||
|
||||
# 默认动作
|
||||
|
||||
default :
|
||||
$(MAKE) img
|
||||
|
||||
# 镜像文件生成
|
||||
|
||||
ipl10.bin : ipl10.nas Makefile
|
||||
$(NASK) ipl10.nas ipl10.bin ipl10.lst
|
||||
|
||||
asmhead.bin : asmhead.nas Makefile
|
||||
$(NASK) asmhead.nas asmhead.bin asmhead.lst
|
||||
|
||||
hankaku.bin : hankaku.txt Makefile
|
||||
$(MAKEFONT) hankaku.txt hankaku.bin
|
||||
|
||||
hankaku.obj : hankaku.bin Makefile
|
||||
$(BIN2OBJ) hankaku.bin hankaku.obj _hankaku
|
||||
|
||||
bootpack.bim : $(OBJS_BOOTPACK) Makefile
|
||||
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
|
||||
$(OBJS_BOOTPACK)
|
||||
# 3MB+64KB=3136KB
|
||||
|
||||
bootpack.hrb : bootpack.bim Makefile
|
||||
$(BIM2HRB) bootpack.bim bootpack.hrb 0
|
||||
|
||||
haribote.sys : asmhead.bin bootpack.hrb Makefile
|
||||
copy /B asmhead.bin+bootpack.hrb haribote.sys
|
||||
|
||||
haribote.img : ipl10.bin haribote.sys Makefile
|
||||
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
|
||||
wbinimg src:ipl10.bin len:512 from:0 to:0 \
|
||||
copy from:haribote.sys to:@: \
|
||||
imgout:haribote.img
|
||||
|
||||
# 其他指令
|
||||
|
||||
%.gas : %.c bootpack.h Makefile
|
||||
$(CC1) -o $*.gas $*.c
|
||||
|
||||
%.nas : %.gas Makefile
|
||||
$(GAS2NASK) $*.gas $*.nas
|
||||
|
||||
%.obj : %.nas Makefile
|
||||
$(NASK) $*.nas $*.obj $*.lst
|
||||
|
||||
# 运行程序
|
||||
|
||||
img :
|
||||
$(MAKE) haribote.img
|
||||
|
||||
run :
|
||||
$(MAKE) img
|
||||
$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
|
||||
$(MAKE) -C ../z_tools/qemu
|
||||
|
||||
install :
|
||||
$(MAKE) img
|
||||
$(IMGTOL) w a: haribote.img
|
||||
|
||||
clean :
|
||||
-$(DEL) *.bin
|
||||
-$(DEL) *.lst
|
||||
-$(DEL) *.obj
|
||||
-$(DEL) bootpack.map
|
||||
-$(DEL) bootpack.bim
|
||||
-$(DEL) bootpack.hrb
|
||||
-$(DEL) haribote.sys
|
||||
|
||||
src_only :
|
||||
$(MAKE) clean
|
||||
-$(DEL) haribote.img
|
||||
146
13_day/asmhead.nas
Normal file
146
13_day/asmhead.nas
Normal file
@@ -0,0 +1,146 @@
|
||||
; haribote-os boot asm
|
||||
; TAB=4
|
||||
|
||||
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 ; 图像缓冲区的起始地址
|
||||
|
||||
ORG 0xc200 ; 这个的程序要被装载的内存地址
|
||||
|
||||
; 画面设置
|
||||
|
||||
MOV AL,0x13 ; VGA显卡,320x200x8bit
|
||||
MOV AH,0x00
|
||||
INT 0x10
|
||||
MOV BYTE [VMODE],8 ; 屏幕的模式(参考C语言的引用)
|
||||
MOV WORD [SCRNX],320
|
||||
MOV WORD [SCRNY],200
|
||||
MOV DWORD [VRAM],0x000a0000
|
||||
|
||||
; 通过 BIOS 获取指示灯状态
|
||||
|
||||
MOV AH,0x02
|
||||
INT 0x16 ; keyboard BIOS
|
||||
MOV [LEDS],AL
|
||||
|
||||
; PIC关闭一切中断
|
||||
; 根据AT兼容机的规格,如果要初始化PIC,
|
||||
; 必须在CLI之前进行,否则有时会挂起。
|
||||
; 随后进行PIC的初始化。
|
||||
|
||||
MOV AL,0xff
|
||||
OUT 0x21,AL
|
||||
NOP ; 如果连续执行OUT指令,有些机种会无法正常运行
|
||||
OUT 0xa1,AL
|
||||
|
||||
CLI ; 禁止CPU级别的中断
|
||||
|
||||
; 为了让CPU能够访问1MB以上的内存空间,设定A20GATE
|
||||
|
||||
CALL waitkbdout
|
||||
MOV AL,0xd1
|
||||
OUT 0x64,AL
|
||||
CALL waitkbdout
|
||||
MOV AL,0xdf ; enable A20
|
||||
OUT 0x60,AL
|
||||
CALL waitkbdout
|
||||
|
||||
; 切换到保护模式
|
||||
|
||||
[INSTRSET "i486p"] ; 说明使用486指令
|
||||
|
||||
LGDT [GDTR0] ; 设置临时GDT
|
||||
MOV EAX,CR0
|
||||
AND EAX,0x7fffffff ; 设bit31为0(禁用分页)
|
||||
OR EAX,0x00000001 ; bit0到1转换(保护模式过渡)
|
||||
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
|
||||
|
||||
; 必须由asmhead来完成的工作,至此全部完毕
|
||||
; 以后就交由bootpack来完成
|
||||
|
||||
; bootpack启动
|
||||
|
||||
MOV EBX,BOTPAK
|
||||
MOV ECX,[EBX+16]
|
||||
ADD ECX,3 ; ECX += 3;
|
||||
SHR ECX,2 ; ECX /= 4;
|
||||
JZ skip ; 没有要转送的东西时
|
||||
MOV ESI,[EBX+20] ; 转送源
|
||||
ADD ESI,EBX
|
||||
MOV EDI,[EBX+12] ; 转送目标
|
||||
CALL memcpy
|
||||
skip:
|
||||
MOV ESP,[EBX+12] ; 堆栈的初始化
|
||||
JMP DWORD 2*8:0x0000001b
|
||||
|
||||
waitkbdout:
|
||||
IN AL,0x64
|
||||
AND AL,0x02
|
||||
IN AL,0x60 ; 空读(为了清空数据接收缓冲区中的垃圾数据)
|
||||
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地址前缀大小
|
||||
|
||||
ALIGNB 16
|
||||
GDT0:
|
||||
RESB 8 ; 初始值
|
||||
DW 0xffff,0x0000,0x9200,0x00cf ; 可以读写的段(segment)32bit
|
||||
DW 0xffff,0x0000,0x9a28,0x0047 ; 可执行的文件的32bit寄存器(bootpack用)
|
||||
|
||||
DW 0
|
||||
GDTR0:
|
||||
DW 8*3-1
|
||||
DD GDT0
|
||||
|
||||
ALIGNB 16
|
||||
bootpack:
|
||||
197
13_day/bootpack.c
Normal file
197
13_day/bootpack.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/* bootpack*/
|
||||
|
||||
#include "bootpack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void make_window8(unsigned char *buf, int xsize, int ysize, char *title);
|
||||
void putfonts8_asc_sht(struct SHEET *sht, int x, int y, int c, int b, char *s, int l);
|
||||
|
||||
void HariMain(void)
|
||||
{
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
struct FIFO32 fifo;
|
||||
char s[40];
|
||||
int fifobuf[128];
|
||||
struct TIMER *timer, *timer2, *timer3;
|
||||
int mx, my, i, count = 0;
|
||||
unsigned int memtotal;
|
||||
struct MOUSE_DEC mdec;
|
||||
struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
|
||||
struct SHTCTL *shtctl;
|
||||
struct SHEET *sht_back, *sht_mouse, *sht_win;
|
||||
unsigned char *buf_back, buf_mouse[256], *buf_win;
|
||||
|
||||
init_gdtidt();
|
||||
init_pic();
|
||||
io_sti(); /* IDT/PIC的初始化已经完成,于是开放CPU的中断 */
|
||||
fifo32_init(&fifo, 128, fifobuf);
|
||||
init_pit();
|
||||
init_keyboard(&fifo, 256);
|
||||
enable_mouse(&fifo, 512, &mdec);
|
||||
io_out8(PIC0_IMR, 0xf8); /* 设定PIT和PIC1以及键盘为许可(11111000) */
|
||||
io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */
|
||||
|
||||
timer = timer_alloc();
|
||||
timer_init(timer, &fifo, 10);
|
||||
timer_settime(timer, 1000);
|
||||
timer2 = timer_alloc();
|
||||
timer_init(timer2, &fifo, 3);
|
||||
timer_settime(timer2, 300);
|
||||
timer3 = timer_alloc();
|
||||
timer_init(timer3, &fifo, 1);
|
||||
timer_settime(timer3, 50);
|
||||
|
||||
memtotal = memtest(0x00400000, 0xbfffffff);
|
||||
memman_init(memman);
|
||||
memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 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");
|
||||
sheet_slide(sht_back, 0, 0);
|
||||
mx = (binfo->scrnx - 16) / 2; /* 按显示在画面中央来计算坐标 */
|
||||
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);
|
||||
putfonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
|
||||
sprintf(s, "memory %dMB free : %dKB",
|
||||
memtotal / (1024 * 1024), memman_total(memman) / 1024);
|
||||
putfonts8_asc_sht(sht_back, 0, 32, COL8_FFFFFF, COL8_008484, s, 40);
|
||||
|
||||
for (;;) {
|
||||
count++;
|
||||
io_cli();
|
||||
if (fifo32_status(&fifo) == 0) {
|
||||
io_sti();
|
||||
} else {
|
||||
i = fifo32_get(&fifo);
|
||||
io_sti();
|
||||
if (256 <= i && i <= 511) { /* 键盘数据*/
|
||||
sprintf(s, "%02X", i - 256);
|
||||
putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
|
||||
} else if (512 <= i && i <= 767) { /* 鼠标数据*/
|
||||
if (mouse_decode(&mdec, i - 512) != 0) {
|
||||
/* 已经收集了3字节的数据,所以显示出来 */
|
||||
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
|
||||
if ((mdec.btn & 0x01) != 0) {
|
||||
s[1] = 'L';
|
||||
}
|
||||
if ((mdec.btn & 0x02) != 0) {
|
||||
s[3] = 'R';
|
||||
}
|
||||
if ((mdec.btn & 0x04) != 0) {
|
||||
s[2] = 'C';
|
||||
}
|
||||
putfonts8_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);
|
||||
putfonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
|
||||
sheet_slide(sht_mouse, mx, my);/* 包含sheet_refresh含sheet_refresh */
|
||||
}
|
||||
} else if (i == 10) { /* 10秒定时器 */
|
||||
putfonts8_asc_sht(sht_back, 0, 64, COL8_FFFFFF, COL8_008484, "10[sec]", 7);
|
||||
sprintf(s, "%010d", count);
|
||||
putfonts8_asc_sht(sht_win, 40, 28, COL8_000000, COL8_C6C6C6, s, 10);
|
||||
} else if (i == 3) { /* 3秒定时器 */
|
||||
putfonts8_asc_sht(sht_back, 0, 80, COL8_FFFFFF, COL8_008484, "3[sec]", 6);
|
||||
count = 0; /* 开始测试 */
|
||||
} else if (i == 1) { /* 光标用定时器*/
|
||||
timer_init(timer3, &fifo, 0); /* 下面是设定0 */
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_FFFFFF, 8, 96, 15, 111);
|
||||
timer_settime(timer3, 50);
|
||||
sheet_refresh(sht_back, 8, 96, 16, 112);
|
||||
} else if (i == 0) { /* 光标用定时器 */
|
||||
timer_init(timer3, &fifo, 1); /* 下面是设定1 */
|
||||
boxfill8(buf_back, binfo->scrnx, COL8_008484, 8, 96, 15, 111);
|
||||
timer_settime(timer3, 50);
|
||||
sheet_refresh(sht_back, 8, 96, 16, 112);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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$$$$$$$$$$$$$$@",
|
||||
"@@@@@@@@@@@@@@@@"
|
||||
};
|
||||
int x, y;
|
||||
char c;
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, xsize - 1, 0 );
|
||||
boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, xsize - 2, 1 );
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, 0, ysize - 1);
|
||||
boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, 1, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_848484, xsize - 2, 1, xsize - 2, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_000000, xsize - 1, 0, xsize - 1, ysize - 1);
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3);
|
||||
boxfill8(buf, xsize, COL8_000084, 3, 3, xsize - 4, 20 );
|
||||
boxfill8(buf, xsize, COL8_848484, 1, ysize - 2, xsize - 2, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_000000, 0, ysize - 1, xsize - 1, ysize - 1);
|
||||
putfonts8_asc(buf, xsize, 24, 4, COL8_FFFFFF, title);
|
||||
for (y = 0; y < 14; y++) {
|
||||
for (x = 0; x < 16; x++) {
|
||||
c = closebtn[y][x];
|
||||
if (c == '@') {
|
||||
c = COL8_000000;
|
||||
} else if (c == '$') {
|
||||
c = COL8_848484;
|
||||
} else if (c == 'Q') {
|
||||
c = COL8_C6C6C6;
|
||||
} else {
|
||||
c = COL8_FFFFFF;
|
||||
}
|
||||
buf[(5 + y) * xsize + (xsize - 21 + x)] = c;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putfonts8_asc_sht(struct SHEET *sht, int x, int y, int c, int b, char *s, int l)
|
||||
{
|
||||
boxfill8(sht->buf, sht->bxsize, b, x, y, x + l * 8 - 1, y + 15);
|
||||
putfonts8_asc(sht->buf, sht->bxsize, x, y, c, s);
|
||||
sheet_refresh(sht, x, y, x + l * 8, y + 16);
|
||||
return;
|
||||
}
|
||||
190
13_day/bootpack.h
Normal file
190
13_day/bootpack.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/* asmhead.nas */
|
||||
struct BOOTINFO { /* 0x0ff0-0x0fff */
|
||||
char cyls; /* 启动区读磁盘读到此为止 */
|
||||
char leds; /* 启动时键盘的LED的状态 */
|
||||
char vmode; /* 显卡模式为多少位彩色 */
|
||||
char reserve;
|
||||
short scrnx, scrny; /* 画面分辨率 */
|
||||
char *vram;
|
||||
};
|
||||
#define ADR_BOOTINFO 0x00000ff0
|
||||
|
||||
/* naskfunc.nas */
|
||||
void io_hlt(void);
|
||||
void io_cli(void);
|
||||
void io_sti(void);
|
||||
void io_stihlt(void);
|
||||
int io_in8(int port);
|
||||
void io_out8(int port, int data);
|
||||
int io_load_eflags(void);
|
||||
void io_store_eflags(int eflags);
|
||||
void load_gdtr(int limit, int addr);
|
||||
void load_idtr(int limit, int addr);
|
||||
int load_cr0(void);
|
||||
void store_cr0(int cr0);
|
||||
void asm_inthandler20(void);
|
||||
void asm_inthandler21(void);
|
||||
void asm_inthandler27(void);
|
||||
void asm_inthandler2c(void);
|
||||
unsigned int memtest_sub(unsigned int start, unsigned int end);
|
||||
|
||||
/* fifo.c */
|
||||
struct FIFO32 {
|
||||
int *buf;
|
||||
int p, q, size, free, flags;
|
||||
};
|
||||
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);
|
||||
|
||||
/* graphic.c */
|
||||
void init_palette(void);
|
||||
void set_palette(int start, int end, unsigned char *rgb);
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
|
||||
void init_screen8(char *vram, int x, int y);
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
|
||||
void init_mouse_cursor8(char *mouse, char bc);
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize);
|
||||
#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
|
||||
|
||||
/* dsctbl.c */
|
||||
struct SEGMENT_DESCRIPTOR {
|
||||
short limit_low, base_low;
|
||||
char base_mid, access_right;
|
||||
char limit_high, base_high;
|
||||
};
|
||||
struct GATE_DESCRIPTOR {
|
||||
short offset_low, selector;
|
||||
char dw_count, access_right;
|
||||
short offset_high;
|
||||
};
|
||||
void init_gdtidt(void);
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
|
||||
#define ADR_IDT 0x0026f800
|
||||
#define LIMIT_IDT 0x000007ff
|
||||
#define ADR_GDT 0x00270000
|
||||
#define LIMIT_GDT 0x0000ffff
|
||||
#define ADR_BOTPAK 0x00280000
|
||||
#define LIMIT_BOTPAK 0x0007ffff
|
||||
#define AR_DATA32_RW 0x4092
|
||||
#define AR_CODE32_ER 0x409a
|
||||
#define AR_INTGATE32 0x008e
|
||||
|
||||
/* int.c */
|
||||
void init_pic(void);
|
||||
void inthandler27(int *esp);
|
||||
#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
|
||||
|
||||
/* keyboard.c */
|
||||
void inthandler21(int *esp);
|
||||
void wait_KBC_sendready(void);
|
||||
void init_keyboard(struct FIFO32 *fifo, int data0);
|
||||
#define PORT_KEYDAT 0x0060
|
||||
#define PORT_KEYCMD 0x0064
|
||||
|
||||
/* mouse.c */
|
||||
struct MOUSE_DEC {
|
||||
unsigned char buf[3], phase;
|
||||
int x, y, btn;
|
||||
};
|
||||
void inthandler2c(int *esp);
|
||||
void enable_mouse(struct FIFO32 *fifo, int data0, struct MOUSE_DEC *mdec);
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);
|
||||
|
||||
/* memory.c */
|
||||
#define MEMMAN_FREES 4090 /* 大约是32KB*/
|
||||
#define MEMMAN_ADDR 0x003c0000
|
||||
|
||||
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);
|
||||
void memman_init(struct MEMMAN *man);
|
||||
unsigned int memman_total(struct MEMMAN *man);
|
||||
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
|
||||
/* sheet.c */
|
||||
#define MAX_SHEETS 256
|
||||
#define SHEET_USE 1
|
||||
|
||||
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_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);
|
||||
|
||||
/* timer.c */
|
||||
#define MAX_TIMER 500
|
||||
struct TIMER {
|
||||
struct TIMER *next;
|
||||
unsigned int timeout, flags;
|
||||
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_settime(struct TIMER *timer, unsigned int timeout);
|
||||
void inthandler20(int *esp);
|
||||
|
||||
57
13_day/dsctbl.c
Normal file
57
13_day/dsctbl.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* GDT、IDT、descriptor table 关系处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_gdtidt(void)
|
||||
{
|
||||
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
|
||||
struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) ADR_IDT;
|
||||
int i;
|
||||
|
||||
/* GDT初始化 */
|
||||
for (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_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);
|
||||
load_gdtr(LIMIT_GDT, ADR_GDT);
|
||||
|
||||
/* IDT初始化 */
|
||||
for (i = 0; i <= LIMIT_IDT / 8; i++) {
|
||||
set_gatedesc(idt + i, 0, 0, 0);
|
||||
}
|
||||
load_idtr(LIMIT_IDT, ADR_IDT);
|
||||
|
||||
/* IDT设置*/
|
||||
set_gatedesc(idt + 0x20, (int) asm_inthandler20, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
57
13_day/fifo.c
Normal file
57
13_day/fifo.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* FIFO */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define FLAGS_OVERRUN 0x0001
|
||||
|
||||
void fifo32_init(struct FIFO32 *fifo, int size, int *buf)
|
||||
/* FIFO缓冲区的初始化*/
|
||||
{
|
||||
fifo->size = size;
|
||||
fifo->buf = buf;
|
||||
fifo->free = size; /*空*/
|
||||
fifo->flags = 0;
|
||||
fifo->p = 0; /*写入位置*/
|
||||
fifo->q = 0; /*读取位置*/
|
||||
return;
|
||||
}
|
||||
|
||||
int fifo32_put(struct FIFO32 *fifo, int data)
|
||||
/*给FIFO发送数据并储存在FIFO中*/
|
||||
{
|
||||
if (fifo->free == 0) {
|
||||
/*没有空余空间,溢出*/
|
||||
fifo->flags |= FLAGS_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
fifo->buf[fifo->p] = data;
|
||||
fifo->p++;
|
||||
if (fifo->p == fifo->size) {
|
||||
fifo->p = 0;
|
||||
}
|
||||
fifo->free--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fifo32_get(struct FIFO32 *fifo)
|
||||
/*从FIFO取得一个数据*/
|
||||
{
|
||||
int data;
|
||||
if (fifo->free == fifo->size) {
|
||||
/*当缓冲区为空的情况下返回-1*/
|
||||
return -1;
|
||||
}
|
||||
data = fifo->buf[fifo->q];
|
||||
fifo->q++;
|
||||
if (fifo->q == fifo->size) {
|
||||
fifo->q = 0;
|
||||
}
|
||||
fifo->free++;
|
||||
return data;
|
||||
}
|
||||
|
||||
int fifo32_status(struct FIFO32 *fifo)
|
||||
/*报告已经存储了多少数据*/
|
||||
{
|
||||
return fifo->size - fifo->free;
|
||||
}
|
||||
157
13_day/graphic.c
Normal file
157
13_day/graphic.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/* 关于绘图部分的处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_palette(void)
|
||||
{
|
||||
static unsigned char table_rgb[16 * 3] = {
|
||||
0x00, 0x00, 0x00, /* 0:黑 */
|
||||
0xff, 0x00, 0x00, /* 1:梁红 */
|
||||
0x00, 0xff, 0x00, /* 2:亮绿 */
|
||||
0xff, 0xff, 0x00, /* 3:亮黄 */
|
||||
0x00, 0x00, 0xff, /* 4:亮蓝 */
|
||||
0xff, 0x00, 0xff, /* 5:亮紫 */
|
||||
0x00, 0xff, 0xff, /* 6:浅亮蓝 */
|
||||
0xff, 0xff, 0xff, /* 7:白 */
|
||||
0xc6, 0xc6, 0xc6, /* 8:亮灰 */
|
||||
0x84, 0x00, 0x00, /* 9:暗红 */
|
||||
0x00, 0x84, 0x00, /* 10:暗绿 */
|
||||
0x84, 0x84, 0x00, /* 11:暗黄 */
|
||||
0x00, 0x00, 0x84, /* 12:暗青 */
|
||||
0x84, 0x00, 0x84, /* 13:暗紫 */
|
||||
0x00, 0x84, 0x84, /* 14:浅暗蓝 */
|
||||
0x84, 0x84, 0x84 /* 15:暗灰 */
|
||||
};
|
||||
set_palette(0, 15, table_rgb);
|
||||
return;
|
||||
|
||||
/* C语言中的static char语句只能用于数据,相当于汇编中的DB指令 */
|
||||
}
|
||||
|
||||
void set_palette(int start, int end, unsigned char *rgb)
|
||||
{
|
||||
int i, eflags;
|
||||
eflags = io_load_eflags(); /* 记录中断许可标志的值 */
|
||||
io_cli(); /* 将中断许可标志置为0,禁止中断 */
|
||||
io_out8(0x03c8, start);
|
||||
for (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); /* 复原中断许可标志 */
|
||||
return;
|
||||
}
|
||||
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
|
||||
{
|
||||
int x, y;
|
||||
for (y = y0; y <= y1; y++) {
|
||||
for (x = x0; x <= x1; x++)
|
||||
vram[y * xsize + x] = c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_screen8(char *vram, int x, int y)
|
||||
{
|
||||
boxfill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1);
|
||||
|
||||
boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5);
|
||||
boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3);
|
||||
boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3);
|
||||
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24);
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3);
|
||||
return;
|
||||
}
|
||||
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
|
||||
{
|
||||
int i;
|
||||
char *p, d /* data */;
|
||||
for (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; }
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
|
||||
{
|
||||
extern char hankaku[4096];
|
||||
/* C语言中,字符串都是以0x00结尾 */
|
||||
for (; *s != 0x00; s++) {
|
||||
putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
|
||||
x += 8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_mouse_cursor8(char *mouse, char bc)
|
||||
/* 鼠标的数据准备(16x16) */
|
||||
{
|
||||
static char cursor[16][16] = {
|
||||
"**************..",
|
||||
"*OOOOOOOOOOO*...",
|
||||
"*OOOOOOOOOO*....",
|
||||
"*OOOOOOOOO*.....",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOO**OOO*.....",
|
||||
"*OOO*..*OOO*....",
|
||||
"*OO*....*OOO*...",
|
||||
"*O*......*OOO*..",
|
||||
"**........*OOO*.",
|
||||
"*..........*OOO*",
|
||||
"............*OO*",
|
||||
".............***"
|
||||
};
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < 16; y++) {
|
||||
for (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize)
|
||||
{
|
||||
int x, y;
|
||||
for (y = 0; y < pysize; y++) {
|
||||
for (x = 0; x < pxsize; x++) {
|
||||
vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
4609
13_day/hankaku.txt
Normal file
4609
13_day/hankaku.txt
Normal file
File diff suppressed because it is too large
Load Diff
37
13_day/int.c
Normal file
37
13_day/int.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*初始化关系 */
|
||||
|
||||
#include "bootpack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void init_pic(void)
|
||||
/* PIC初始化 */
|
||||
{
|
||||
io_out8(PIC0_IMR, 0xff ); /* 禁止所有中断 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 禁止所有中断 */
|
||||
|
||||
io_out8(PIC0_ICW1, 0x11 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 边缘触发模式(edge trigger mode) */
|
||||
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 ); /* 11111011 PIC1以外全部禁止 */
|
||||
io_out8(PIC1_IMR, 0xff ); /* 11111111 禁止所有中断 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void inthandler27(int *esp)
|
||||
/* PIC0中断的不完整策略 */
|
||||
/* 这个中断在Athlon64X2上通过芯片组提供的便利,只需执行一次 */
|
||||
/* 这个中断只是接收,不执行任何操作 */
|
||||
/* 为什么不处理?
|
||||
→ 因为这个中断可能是电气噪声引发的、只是处理一些重要的情况。*/
|
||||
{
|
||||
io_out8(PIC0_OCW2, 0x67); /* 通知PIC的IRQ-07(参考7-1) */
|
||||
return;
|
||||
}
|
||||
109
13_day/ipl10.nas
Normal file
109
13_day/ipl10.nas
Normal file
@@ -0,0 +1,109 @@
|
||||
; haribote-ipl
|
||||
; TAB=4
|
||||
|
||||
CYLS EQU 10 ; 声明CYLS=10
|
||||
|
||||
ORG 0x7c00 ; 指明程序装载地址
|
||||
|
||||
; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code
|
||||
|
||||
JMP entry
|
||||
DB 0x90
|
||||
DB "HARIBOTE" ; 启动扇区名称(8字节)
|
||||
DW 512 ; 每个扇区(sector)大小(必须512字节)
|
||||
DB 1 ; 簇(cluster)大小(必须为1个扇区)
|
||||
DW 1 ; FAT起始位置(一般为第一个扇区)
|
||||
DB 2 ; FAT个数(必须为2)
|
||||
DW 224 ; 根目录大小(一般为224项)
|
||||
DW 2880 ; 该磁盘大小(必须为2880扇区1440*1024/512)
|
||||
DB 0xf0 ; 磁盘类型(必须为0xf0)
|
||||
DW 9 ; FAT的长度(必??9扇区)
|
||||
DW 18 ; 一个磁道(track)有几个扇区(必须为18)
|
||||
DW 2 ; 磁头数(必??2)
|
||||
DD 0 ; 不使用分区,必须是0
|
||||
DD 2880 ; 重写一次磁盘大小
|
||||
DB 0,0,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 ; 没出错则跳转到fin
|
||||
ADD SI,1 ; 往SI加1
|
||||
CMP SI,5 ; 比较SI与5
|
||||
JAE error ; SI >= 5 跳转到error
|
||||
MOV AH,0x00
|
||||
MOV DL,0x00 ; A驱动器
|
||||
INT 0x13 ; 重置驱动器
|
||||
JMP retry
|
||||
next:
|
||||
MOV AX,ES ; 把内存地址后移0x200(512/16十六进制转换)
|
||||
ADD AX,0x0020
|
||||
MOV ES,AX ; ADD ES,0x020因为没有ADD ES,只能通过AX进行
|
||||
ADD CL,1 ; 往CL里面加1
|
||||
CMP CL,18 ; 比较CL与18
|
||||
JBE readloop ; CL <= 18 跳转到readloop
|
||||
MOV CL,1
|
||||
ADD DH,1
|
||||
CMP DH,2
|
||||
JB readloop ; DH < 2 跳转到readloop
|
||||
MOV DH,0
|
||||
ADD CH,1
|
||||
CMP CH,CYLS
|
||||
JB readloop ; CH < CYLS 跳转到readloop
|
||||
|
||||
; 读取完毕,跳转到haribote.sys执行!
|
||||
MOV [0x0ff0],CH ; IPLがどこまで読んだのかをメモ
|
||||
JMP 0xc200
|
||||
|
||||
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
|
||||
|
||||
fin:
|
||||
HLT ; 让CPU停止,等待指令
|
||||
JMP fin ; 无限循环
|
||||
|
||||
msg:
|
||||
DB 0x0a, 0x0a ; 换行两次
|
||||
DB "load error"
|
||||
DB 0x0a ; 换行
|
||||
DB 0
|
||||
|
||||
RESB 0x7dfe-$ ; 填写0x00直到0x001fe
|
||||
|
||||
DB 0x55, 0xaa
|
||||
44
13_day/keyboard.c
Normal file
44
13_day/keyboard.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 键盘控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO32 *keyfifo;
|
||||
int keydata0;
|
||||
|
||||
void inthandler21(int *esp)
|
||||
{
|
||||
int data;
|
||||
io_out8(PIC0_OCW2, 0x61); /* 把IRQ-01接收信号结束的信息通知给PIC */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo32_put(keyfifo, data + keydata0);
|
||||
return;
|
||||
}
|
||||
|
||||
#define PORT_KEYSTA 0x0064
|
||||
#define KEYSTA_SEND_NOTREADY 0x02
|
||||
#define KEYCMD_WRITE_MODE 0x60
|
||||
#define KBC_MODE 0x47
|
||||
|
||||
void wait_KBC_sendready(void)
|
||||
{
|
||||
/* 等待键盘控制电路准备完毕 */
|
||||
for (;;) {
|
||||
if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_keyboard(struct FIFO32 *fifo, int data0)
|
||||
{
|
||||
/* 将FIFO缓冲区的信息保存到全局变量里 */
|
||||
keyfifo = fifo;
|
||||
keydata0 = data0;
|
||||
/* 键盘控制器的初始化 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, KBC_MODE);
|
||||
return;
|
||||
}
|
||||
1
13_day/make.bat
Normal file
1
13_day/make.bat
Normal file
@@ -0,0 +1 @@
|
||||
..\z_tools\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
162
13_day/memory.c
Normal file
162
13_day/memory.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>W */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define EFLAGS_AC_BIT 0x00040000
|
||||
#define CR0_CACHE_DISABLE 0x60000000
|
||||
|
||||
unsigned int memtest(unsigned int start, unsigned int end)
|
||||
{
|
||||
char flg486 = 0;
|
||||
unsigned int eflg, cr0, i;
|
||||
|
||||
/* 确认CPU是386还是486以上的 */
|
||||
eflg = io_load_eflags();
|
||||
eflg |= EFLAGS_AC_BIT; /* AC-bit = 1 */
|
||||
io_store_eflags(eflg);
|
||||
eflg = io_load_eflags();
|
||||
if ((eflg & EFLAGS_AC_BIT) != 0) {
|
||||
/* 如果是386,即使设定AC=1,AC的值还会自动回到0 */
|
||||
flg486 = 1;
|
||||
}
|
||||
|
||||
eflg &= ~EFLAGS_AC_BIT; /* AC-bit = 0 */
|
||||
io_store_eflags(eflg);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 |= CR0_CACHE_DISABLE; /* 禁止缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
i = memtest_sub(start, end);
|
||||
|
||||
if (flg486 != 0) {
|
||||
cr0 = load_cr0();
|
||||
cr0 &= ~CR0_CACHE_DISABLE; /* 允许缓存 */
|
||||
store_cr0(cr0);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void memman_init(struct MEMMAN *man)
|
||||
{
|
||||
man->frees = 0; /* 可用信息数目 */
|
||||
man->maxfrees = 0; /* 用于观察可用状况:frees的最大值 */
|
||||
man->lostsize = 0; /* 释放失败的内存的大小总和 */
|
||||
man->losts = 0; /* 释放失败次数 */
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
/* 分配 */
|
||||
{
|
||||
unsigned int i, a;
|
||||
for (i = 0; i < man->frees; i++) {
|
||||
if (man->free[i].size >= size) {
|
||||
/* 找到了足够大的内存 */
|
||||
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; /* 没有可用空间 */
|
||||
}
|
||||
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size)
|
||||
/* 释放 */
|
||||
{
|
||||
int i, j;
|
||||
/* 为便于归纳内存,将free[]按照addr的顺序排列 */
|
||||
/* 所以,先决定应该放在哪里 */
|
||||
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]; /* 结构体赋值 */
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0; /* 成功完成 */
|
||||
}
|
||||
}
|
||||
/* 不能与前面的可用空间归纳到一起 */
|
||||
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; /* 失败 */
|
||||
}
|
||||
|
||||
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size)
|
||||
{
|
||||
unsigned int a;
|
||||
size = (size + 0xfff) & 0xfffff000;
|
||||
a = memman_alloc(man, size);
|
||||
return a;
|
||||
}
|
||||
|
||||
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size)
|
||||
{
|
||||
int i;
|
||||
size = (size + 0xfff) & 0xfffff000;
|
||||
i = memman_free(man, addr, size);
|
||||
return i;
|
||||
}
|
||||
76
13_day/mouse.c
Normal file
76
13_day/mouse.c
Normal file
@@ -0,0 +1,76 @@
|
||||
/* 鼠标控制代码 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
struct FIFO32 *mousefifo;
|
||||
int mousedata0;
|
||||
|
||||
void inthandler2c(int *esp)
|
||||
/* 来自PS/2鼠标的中断 */
|
||||
{
|
||||
int data;
|
||||
io_out8(PIC1_OCW2, 0x64); /* 把IRQ-12接收信号结束的信息通知给PIC1 */
|
||||
io_out8(PIC0_OCW2, 0x62); /* 把IRQ-02接收信号结束的信息通知给PIC0 */
|
||||
data = io_in8(PORT_KEYDAT);
|
||||
fifo32_put(mousefifo, data + mousedata0);
|
||||
return;
|
||||
}
|
||||
|
||||
#define KEYCMD_SENDTO_MOUSE 0xd4
|
||||
#define MOUSECMD_ENABLE 0xf4
|
||||
|
||||
void enable_mouse(struct FIFO32 *fifo, int data0, struct MOUSE_DEC *mdec)
|
||||
{
|
||||
/* 将FIFO缓冲区的信息保存到全局变量里 */
|
||||
mousefifo = fifo;
|
||||
mousedata0 = data0;
|
||||
/* 鼠标有效 */
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
|
||||
wait_KBC_sendready();
|
||||
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
|
||||
/* 顺利的话,ACK(0xfa)会被发送*/
|
||||
mdec->phase = 0; /* 等待鼠标的0xfa的阶段*/
|
||||
return;
|
||||
}
|
||||
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
|
||||
{
|
||||
if (mdec->phase == 0) {
|
||||
/* 等待鼠标的0xfa的阶段 */
|
||||
if (dat == 0xfa) {
|
||||
mdec->phase = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 1) {
|
||||
/* 等待鼠标第一字节的阶段 */
|
||||
mdec->buf[0] = dat;
|
||||
mdec->phase = 2;
|
||||
return 0;
|
||||
}
|
||||
if (mdec->phase == 2) {
|
||||
/* 等待鼠标第二字节的阶段 */
|
||||
mdec->buf[1] = dat;
|
||||
mdec->phase = 3;
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
202
13_day/naskfunc.nas
Normal file
202
13_day/naskfunc.nas
Normal file
@@ -0,0 +1,202 @@
|
||||
; naskfunc
|
||||
; TAB=4
|
||||
|
||||
[FORMAT "WCOFF"] ; 制作目标文件的模式
|
||||
[INSTRSET "i486p"] ; 使用到486为止的指令
|
||||
[BITS 32] ; 3制作32位模式用的机器语言
|
||||
[FILE "naskfunc.nas"] ; 文件名
|
||||
|
||||
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 _load_gdtr, _load_idtr
|
||||
GLOBAL _load_cr0, _store_cr0
|
||||
GLOBAL _asm_inthandler20, _asm_inthandler21
|
||||
GLOBAL _asm_inthandler27, _asm_inthandler2c
|
||||
GLOBAL _memtest_sub
|
||||
EXTERN _inthandler20, _inthandler21
|
||||
EXTERN _inthandler27, _inthandler2c
|
||||
|
||||
[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 EAX,[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 ; PUSH EFLAGS
|
||||
POP EAX
|
||||
RET
|
||||
|
||||
_io_store_eflags: ; void io_store_eflags(int eflags);
|
||||
MOV EAX,[ESP+4]
|
||||
PUSH EAX
|
||||
POPFD ; POP EFLAGS
|
||||
RET
|
||||
|
||||
_load_gdtr: ; void load_gdtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LGDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_idtr: ; void load_idtr(int limit, int addr);
|
||||
MOV AX,[ESP+4] ; limit
|
||||
MOV [ESP+6],AX
|
||||
LIDT [ESP+6]
|
||||
RET
|
||||
|
||||
_load_cr0: ; int load_cr0(void);
|
||||
MOV EAX,CR0
|
||||
RET
|
||||
|
||||
_store_cr0: ; void store_cr0(int cr0);
|
||||
MOV EAX,[ESP+4]
|
||||
MOV CR0,EAX
|
||||
RET
|
||||
|
||||
_asm_inthandler20:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler20
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler21:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler21
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler27:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler27
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_asm_inthandler2c:
|
||||
PUSH ES
|
||||
PUSH DS
|
||||
PUSHAD
|
||||
MOV EAX,ESP
|
||||
PUSH EAX
|
||||
MOV AX,SS
|
||||
MOV DS,AX
|
||||
MOV ES,AX
|
||||
CALL _inthandler2c
|
||||
POP EAX
|
||||
POPAD
|
||||
POP DS
|
||||
POP ES
|
||||
IRETD
|
||||
|
||||
_memtest_sub: ; unsigned int memtest_sub(unsigned int start, unsigned int end)
|
||||
PUSH EDI ; (由于还要使用EBX, ESI, EDI)
|
||||
PUSH ESI
|
||||
PUSH EBX
|
||||
MOV ESI,0xaa55aa55 ; pat0 = 0xaa55aa55;
|
||||
MOV EDI,0x55aa55aa ; pat1 = 0x55aa55aa;
|
||||
MOV EAX,[ESP+12+4] ; i = start;
|
||||
mts_loop:
|
||||
MOV EBX,EAX
|
||||
ADD EBX,0xffc ; p = i + 0xffc;
|
||||
MOV EDX,[EBX] ; old = *p;
|
||||
MOV [EBX],ESI ; *p = pat0;
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP EDI,[EBX] ; if (*p != pat1) goto fin;
|
||||
JNE mts_fin
|
||||
XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
|
||||
CMP ESI,[EBX] ; if (*p != pat0) goto fin;
|
||||
JNE mts_fin
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
ADD EAX,0x1000 ; i += 0x1000;
|
||||
CMP EAX,[ESP+12+8] ; if (i <= end) goto mts_loop;
|
||||
JBE mts_loop
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
mts_fin:
|
||||
MOV [EBX],EDX ; *p = old;
|
||||
POP EBX
|
||||
POP ESI
|
||||
POP EDI
|
||||
RET
|
||||
216
13_day/sheet.c
Normal file
216
13_day/sheet.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/* sheet */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define SHEET_USE 1
|
||||
|
||||
struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize)
|
||||
{
|
||||
struct SHTCTL *ctl;
|
||||
int i;
|
||||
ctl = (struct SHTCTL *) memman_alloc_4k(memman, sizeof (struct SHTCTL));
|
||||
if (ctl == 0) {
|
||||
goto err;
|
||||
}
|
||||
ctl->map = (unsigned char *) memman_alloc_4k(memman, xsize * ysize);
|
||||
if (ctl->map == 0) {
|
||||
memman_free_4k(memman, (int) ctl, sizeof (struct SHTCTL));
|
||||
goto err;
|
||||
}
|
||||
ctl->vram = vram;
|
||||
ctl->xsize = xsize;
|
||||
ctl->ysize = ysize;
|
||||
ctl->top = -1; /* 没有一张SHEET */
|
||||
for (i = 0; i < MAX_SHEETS; i++) {
|
||||
ctl->sheets0[i].flags = 0; /* 标记为未使用 */
|
||||
ctl->sheets0[i].ctl = ctl; /* 记录所属*/
|
||||
}
|
||||
err:
|
||||
return ctl;
|
||||
}
|
||||
|
||||
struct SHEET *sheet_alloc(struct SHTCTL *ctl)
|
||||
{
|
||||
struct SHEET *sht;
|
||||
int i;
|
||||
for (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 0; /* 所有的SHEET都处于正在使用状态*/
|
||||
}
|
||||
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_refreshmap(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0)
|
||||
{
|
||||
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
|
||||
unsigned char *buf, sid, *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 (h = h0; h <= ctl->top; h++) {
|
||||
sht = ctl->sheets[h];
|
||||
sid = sht - ctl->sheets0; /* 将进行了减法计算的地址作为图层号码使用 */
|
||||
buf = sht->buf;
|
||||
bx0 = vx0 - sht->vx0;
|
||||
by0 = vy0 - sht->vy0;
|
||||
bx1 = vx1 - sht->vx0;
|
||||
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 (by = by0; by < by1; by++) {
|
||||
vy = sht->vy0 + by;
|
||||
for (bx = bx0; bx < bx1; bx++) {
|
||||
vx = sht->vx0 + bx;
|
||||
if (buf[by * sht->bxsize + bx] != sht->col_inv) {
|
||||
map[vy * ctl->xsize + vx] = sid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0, int h1)
|
||||
{
|
||||
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
|
||||
unsigned char *buf, *vram = ctl->vram, *map = ctl->map, sid;
|
||||
struct SHEET *sht;
|
||||
|
||||
/* 如果refresh的范围超出了画面则修正 */
|
||||
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 (h = h0; h <= h1; h++) {
|
||||
sht = ctl->sheets[h];
|
||||
buf = sht->buf;
|
||||
sid = sht - ctl->sheets0;
|
||||
|
||||
/* 使用vx0~vy1,对bx0~by1进行倒推 */
|
||||
bx0 = vx0 - sht->vx0;
|
||||
by0 = vy0 - sht->vy0;
|
||||
bx1 = vx1 - sht->vx0;
|
||||
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 (by = by0; by < by1; by++) {
|
||||
vy = sht->vy0 + by;
|
||||
for (bx = bx0; bx < bx1; bx++) {
|
||||
vx = sht->vx0 + bx;
|
||||
if (map[vy * ctl->xsize + vx] == sid) {
|
||||
vram[vy * ctl->xsize + vx] = buf[by * sht->bxsize + bx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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); /* 按新图层信息重新绘制画面 */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void sheet_free(struct SHEET *sht)
|
||||
{
|
||||
if (sht->height >= 0) {
|
||||
sheet_updown(sht, -1); /* 如果处于显示状态,则先设定为隐藏 */
|
||||
}
|
||||
sht->flags = 0; /* "未使用"标志 */
|
||||
return;
|
||||
}
|
||||
110
13_day/timer.c
Normal file
110
13_day/timer.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 定时器 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define PIT_CTRL 0x0043
|
||||
#define PIT_CNT0 0x0040
|
||||
|
||||
struct TIMERCTL timerctl;
|
||||
|
||||
#define TIMER_FLAGS_ALLOC 1 /* 已配置状态 */
|
||||
#define TIMER_FLAGS_USING 2 /* 定时器运行中 */
|
||||
|
||||
void init_pit(void)
|
||||
{
|
||||
int i;
|
||||
struct TIMER *t;
|
||||
io_out8(PIT_CTRL, 0x34);
|
||||
io_out8(PIT_CNT0, 0x9c);
|
||||
io_out8(PIT_CNT0, 0x2e);
|
||||
timerctl.count = 0;
|
||||
for (i = 0; i < MAX_TIMER; i++) {
|
||||
timerctl.timers0[i].flags = 0; /* 没有使用 */
|
||||
}
|
||||
t = timer_alloc(); /* 取得一个 */
|
||||
t->timeout = 0xffffffff;
|
||||
t->flags = TIMER_FLAGS_USING;
|
||||
t->next = 0; /* 末尾 */
|
||||
timerctl.t0 = t; /* 因为现在只有哨兵,所以他就在最前面*/
|
||||
timerctl.next = 0xffffffff; /* 因为只有哨兵,所以下一个超时时刻就是哨兵的时刻 */
|
||||
return;
|
||||
}
|
||||
|
||||
struct TIMER *timer_alloc(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_TIMER; i++) {
|
||||
if (timerctl.timers0[i].flags == 0) {
|
||||
timerctl.timers0[i].flags = TIMER_FLAGS_ALLOC;
|
||||
return &timerctl.timers0[i];
|
||||
}
|
||||
}
|
||||
return 0; /* 没找到 */
|
||||
}
|
||||
|
||||
void timer_free(struct TIMER *timer)
|
||||
{
|
||||
timer->flags = 0; /* 未使用 */
|
||||
return;
|
||||
}
|
||||
|
||||
void timer_init(struct TIMER *timer, struct FIFO32 *fifo, int data)
|
||||
{
|
||||
timer->fifo = fifo;
|
||||
timer->data = data;
|
||||
return;
|
||||
}
|
||||
|
||||
void timer_settime(struct TIMER *timer, unsigned int timeout)
|
||||
{
|
||||
int e;
|
||||
struct TIMER *t, *s;
|
||||
timer->timeout = timeout + timerctl.count;
|
||||
timer->flags = TIMER_FLAGS_USING;
|
||||
e = io_load_eflags();
|
||||
io_cli();
|
||||
t = timerctl.t0;
|
||||
if (timer->timeout <= t->timeout) {
|
||||
/* 插入最前面的情况 */
|
||||
timerctl.t0 = timer;
|
||||
timer->next = t; /* 下面是设定t */
|
||||
timerctl.next = timer->timeout;
|
||||
io_store_eflags(e);
|
||||
return;
|
||||
}
|
||||
for (;;) {
|
||||
s = t;
|
||||
t = t->next;
|
||||
if (timer->timeout <= t->timeout) {
|
||||
/* 插入s和t之间的情况 */
|
||||
s->next = timer; /* s下一个是timer */
|
||||
timer->next = t; /* timer的下一个是t */
|
||||
io_store_eflags(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void inthandler20(int *esp)
|
||||
{
|
||||
struct TIMER *timer;
|
||||
io_out8(PIC0_OCW2, 0x60); /* 把IRQ-00接收信号结束的信息通知给PIC */
|
||||
timerctl.count++;
|
||||
if (timerctl.next > timerctl.count) {
|
||||
return;
|
||||
}
|
||||
timer = timerctl.t0; /* 首先把最前面的地址赋给timer */
|
||||
for (;;) {
|
||||
/* 因为timers的定时器都处于运行状态,所以不确认flags */
|
||||
if (timer->timeout > timerctl.count) {
|
||||
break;
|
||||
}
|
||||
/* 超时 */
|
||||
timer->flags = TIMER_FLAGS_ALLOC;
|
||||
fifo32_put(timer->fifo, timer->data);
|
||||
timer = timer->next; /* 将下一个定时器的地址赋给timer*/
|
||||
}
|
||||
timerctl.t0 = timer;
|
||||
timerctl.next = timer->timeout;
|
||||
return;
|
||||
}
|
||||
1
14_day/!cons_9x.bat
Normal file
1
14_day/!cons_9x.bat
Normal file
@@ -0,0 +1 @@
|
||||
command
|
||||
1
14_day/!cons_nt.bat
Normal file
1
14_day/!cons_nt.bat
Normal file
@@ -0,0 +1 @@
|
||||
cmd.exe
|
||||
93
14_day/Makefile
Normal file
93
14_day/Makefile
Normal file
@@ -0,0 +1,93 @@
|
||||
OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \
|
||||
int.obj fifo.obj keyboard.obj mouse.obj memory.obj sheet.obj timer.obj
|
||||
|
||||
TOOLPATH = ../z_tools/
|
||||
INCPATH = ../z_tools/haribote/
|
||||
|
||||
MAKE = $(TOOLPATH)make.exe -r
|
||||
NASK = $(TOOLPATH)nask.exe
|
||||
CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
|
||||
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
|
||||
OBJ2BIM = $(TOOLPATH)obj2bim.exe
|
||||
MAKEFONT = $(TOOLPATH)makefont.exe
|
||||
BIN2OBJ = $(TOOLPATH)bin2obj.exe
|
||||
BIM2HRB = $(TOOLPATH)bim2hrb.exe
|
||||
RULEFILE = $(TOOLPATH)haribote/haribote.rul
|
||||
EDIMG = $(TOOLPATH)edimg.exe
|
||||
IMGTOL = $(TOOLPATH)imgtol.com
|
||||
COPY = copy
|
||||
DEL = del
|
||||
|
||||
# 默认动作
|
||||
|
||||
default :
|
||||
$(MAKE) img
|
||||
|
||||
# 镜像文件生成
|
||||
|
||||
ipl10.bin : ipl10.nas Makefile
|
||||
$(NASK) ipl10.nas ipl10.bin ipl10.lst
|
||||
|
||||
asmhead.bin : asmhead.nas Makefile
|
||||
$(NASK) asmhead.nas asmhead.bin asmhead.lst
|
||||
|
||||
hankaku.bin : hankaku.txt Makefile
|
||||
$(MAKEFONT) hankaku.txt hankaku.bin
|
||||
|
||||
hankaku.obj : hankaku.bin Makefile
|
||||
$(BIN2OBJ) hankaku.bin hankaku.obj _hankaku
|
||||
|
||||
bootpack.bim : $(OBJS_BOOTPACK) Makefile
|
||||
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
|
||||
$(OBJS_BOOTPACK)
|
||||
# 3MB+64KB=3136KB
|
||||
|
||||
bootpack.hrb : bootpack.bim Makefile
|
||||
$(BIM2HRB) bootpack.bim bootpack.hrb 0
|
||||
|
||||
haribote.sys : asmhead.bin bootpack.hrb Makefile
|
||||
copy /B asmhead.bin+bootpack.hrb haribote.sys
|
||||
|
||||
haribote.img : ipl10.bin haribote.sys Makefile
|
||||
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
|
||||
wbinimg src:ipl10.bin len:512 from:0 to:0 \
|
||||
copy from:haribote.sys to:@: \
|
||||
imgout:haribote.img
|
||||
|
||||
# 其他指令
|
||||
|
||||
%.gas : %.c bootpack.h Makefile
|
||||
$(CC1) -o $*.gas $*.c
|
||||
|
||||
%.nas : %.gas Makefile
|
||||
$(GAS2NASK) $*.gas $*.nas
|
||||
|
||||
%.obj : %.nas Makefile
|
||||
$(NASK) $*.nas $*.obj $*.lst
|
||||
|
||||
# 运行程序
|
||||
|
||||
img :
|
||||
$(MAKE) haribote.img
|
||||
|
||||
run :
|
||||
$(MAKE) img
|
||||
$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
|
||||
$(MAKE) -C ../z_tools/qemu
|
||||
|
||||
install :
|
||||
$(MAKE) img
|
||||
$(IMGTOL) w a: haribote.img
|
||||
|
||||
clean :
|
||||
-$(DEL) *.bin
|
||||
-$(DEL) *.lst
|
||||
-$(DEL) *.obj
|
||||
-$(DEL) bootpack.map
|
||||
-$(DEL) bootpack.bim
|
||||
-$(DEL) bootpack.hrb
|
||||
-$(DEL) haribote.sys
|
||||
|
||||
src_only :
|
||||
$(MAKE) clean
|
||||
-$(DEL) haribote.img
|
||||
202
14_day/asmhead.nas
Normal file
202
14_day/asmhead.nas
Normal file
@@ -0,0 +1,202 @@
|
||||
; haribote-os boot asm
|
||||
; TAB=4
|
||||
|
||||
[INSTRSET "i486p"]
|
||||
|
||||
VBEMODE EQU 0x105 ; 1024 x 768 x 8bit 彩色
|
||||
; 显示模式
|
||||
; 0x100 : 640 x 400 x 8bit 彩色
|
||||
; 0x101 : 640 x 480 x 8bit 彩色
|
||||
; 0x103 : 800 x 600 x 8bit 彩色
|
||||
; 0x105 : 1024 x 768 x 8bit 彩色
|
||||
; 0x107 : 1280 x 1024 x 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 ; 图像缓冲区的起始地址
|
||||
|
||||
ORG 0xc200 ; 这个的程序要被装载的内存地址
|
||||
|
||||
; 确认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 ; if (AX < 0x0200) goto scrn320
|
||||
|
||||
; 取得画面模式信息
|
||||
|
||||
MOV CX,VBEMODE
|
||||
MOV AX,0x4f01
|
||||
INT 0x10
|
||||
CMP AX,0x004f
|
||||
JNE scrn320
|
||||
|
||||
; 画面模式信息的确认
|
||||
CMP BYTE [ES:DI+0x19],8 ;颜色数必须为8
|
||||
JNE scrn320
|
||||
CMP BYTE [ES:DI+0x1b],4 ;颜色的指定方法必须为4(4是调色板模式)
|
||||
JNE scrn320
|
||||
MOV AX,[ES:DI+0x00] ;模式属性bit7不是1就不能加上0x4000
|
||||
AND AX,0x0080
|
||||
JZ scrn320 ; 模式属性的bit7是0,所以放弃
|
||||
|
||||
; 画面设置
|
||||
|
||||
MOV BX,VBEMODE+0x4000
|
||||
MOV AX,0x4f02
|
||||
INT 0x10
|
||||
MOV BYTE [VMODE],8 ; 屏幕的模式(参考C语言的引用)
|
||||
MOV AX,[ES:DI+0x12]
|
||||
MOV [SCRNX],AX
|
||||
MOV AX,[ES:DI+0x14]
|
||||
MOV [SCRNY],AX
|
||||
MOV EAX,[ES:DI+0x28] ;VRAM的地址
|
||||
MOV [VRAM],EAX
|
||||
JMP keystatus
|
||||
|
||||
scrn320:
|
||||
MOV AL,0x13 ; VGA图、320x200x8bit彩色
|
||||
MOV AH,0x00
|
||||
INT 0x10
|
||||
MOV BYTE [VMODE],8 ; 记下画面模式(参考C语言)
|
||||
MOV WORD [SCRNX],320
|
||||
MOV WORD [SCRNY],200
|
||||
MOV DWORD [VRAM],0x000a0000
|
||||
|
||||
; 通过 BIOS 获取指示灯状态
|
||||
|
||||
keystatus:
|
||||
MOV AH,0x02
|
||||
INT 0x16 ; keyboard BIOS
|
||||
MOV [LEDS],AL
|
||||
|
||||
; PIC关闭一切中断
|
||||
; 根据AT兼容机的规格,如果要初始化PIC,
|
||||
; 必须在CLI之前进行,否则有时会挂起。
|
||||
; 随后进行PIC的初始化。
|
||||
|
||||
MOV AL,0xff
|
||||
OUT 0x21,AL
|
||||
NOP ; 如果连续执行OUT指令,有些机种会无法正常运行
|
||||
OUT 0xa1,AL
|
||||
|
||||
CLI ; 禁止CPU级别的中断
|
||||
|
||||
; 为了让CPU能够访问1MB以上的内存空间,设定A20GATE
|
||||
|
||||
CALL waitkbdout
|
||||
MOV AL,0xd1
|
||||
OUT 0x64,AL
|
||||
CALL waitkbdout
|
||||
MOV AL,0xdf ; enable A20
|
||||
OUT 0x60,AL
|
||||
CALL waitkbdout
|
||||
|
||||
; 切换到保护模式
|
||||
|
||||
[INSTRSET "i486p"] ; 说明使用486指令
|
||||
|
||||
LGDT [GDTR0] ; 设置临时GDT
|
||||
MOV EAX,CR0
|
||||
AND EAX,0x7fffffff ; 设bit31为0(禁用分页)
|
||||
OR EAX,0x00000001 ; bit0到1转换(保护模式过渡)
|
||||
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
|
||||
|
||||
; 必须由asmhead来完成的工作,至此全部完毕
|
||||
; 以后就交由bootpack来完成
|
||||
|
||||
; bootpack启动
|
||||
|
||||
MOV EBX,BOTPAK
|
||||
MOV ECX,[EBX+16]
|
||||
ADD ECX,3 ; ECX += 3;
|
||||
SHR ECX,2 ; ECX /= 4;
|
||||
JZ skip ; 没有要转送的东西时
|
||||
MOV ESI,[EBX+20] ; 转送源
|
||||
ADD ESI,EBX
|
||||
MOV EDI,[EBX+12] ; 转送目标
|
||||
CALL memcpy
|
||||
skip:
|
||||
MOV ESP,[EBX+12] ; 堆栈的初始化
|
||||
JMP DWORD 2*8:0x0000001b
|
||||
|
||||
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地址前缀大小
|
||||
|
||||
ALIGNB 16
|
||||
GDT0:
|
||||
RESB 8 ; 初始值
|
||||
DW 0xffff,0x0000,0x9200,0x00cf ; 可以读写的段(segment)32bit
|
||||
DW 0xffff,0x0000,0x9a28,0x0047 ; 可执行的文件的32bit寄存器(bootpack用)
|
||||
|
||||
DW 0
|
||||
GDTR0:
|
||||
DW 8*3-1
|
||||
DD GDT0
|
||||
|
||||
ALIGNB 16
|
||||
bootpack:
|
||||
240
14_day/bootpack.c
Normal file
240
14_day/bootpack.c
Normal file
@@ -0,0 +1,240 @@
|
||||
/* bootpack*/
|
||||
|
||||
#include "bootpack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void make_window8(unsigned char *buf, int xsize, int ysize, char *title);
|
||||
void putfonts8_asc_sht(struct SHEET *sht, int x, int y, int c, int b, char *s, int l);
|
||||
void make_textbox8(struct SHEET *sht, int x0, int y0, int sx, int sy, int c);
|
||||
|
||||
void HariMain(void)
|
||||
{
|
||||
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
|
||||
struct FIFO32 fifo;
|
||||
char s[40];
|
||||
int fifobuf[128];
|
||||
struct TIMER *timer, *timer2, *timer3;
|
||||
int mx, my, i, cursor_x, cursor_c;
|
||||
unsigned int memtotal;
|
||||
struct MOUSE_DEC mdec;
|
||||
struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
|
||||
struct SHTCTL *shtctl;
|
||||
struct SHEET *sht_back, *sht_mouse, *sht_win;
|
||||
unsigned char *buf_back, buf_mouse[256], *buf_win;
|
||||
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', '.'
|
||||
};
|
||||
|
||||
init_gdtidt();
|
||||
init_pic();
|
||||
io_sti(); /* IDT/PIC的初始化已经完成,于是开放CPU的中断 */
|
||||
fifo32_init(&fifo, 128, fifobuf);
|
||||
init_pit();
|
||||
init_keyboard(&fifo, 256);
|
||||
enable_mouse(&fifo, 512, &mdec);
|
||||
io_out8(PIC0_IMR, 0xf8); /* 设定PIT和PIC1以及键盘为许可(11111000) */
|
||||
io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */
|
||||
|
||||
timer = timer_alloc();
|
||||
timer_init(timer, &fifo, 10);
|
||||
timer_settime(timer, 1000);
|
||||
timer2 = timer_alloc();
|
||||
timer_init(timer2, &fifo, 3);
|
||||
timer_settime(timer2, 300);
|
||||
timer3 = timer_alloc();
|
||||
timer_init(timer3, &fifo, 1);
|
||||
timer_settime(timer3, 50);
|
||||
|
||||
memtotal = memtest(0x00400000, 0xbfffffff);
|
||||
memman_init(memman);
|
||||
memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 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, "window");
|
||||
make_textbox8(sht_win, 8, 28, 144, 16, COL8_FFFFFF);
|
||||
cursor_x = 8;
|
||||
cursor_c = COL8_FFFFFF;
|
||||
sheet_slide(sht_back, 0, 0);
|
||||
mx = (binfo->scrnx - 16) / 2; /* 按显示在画面中央来计算坐标 */
|
||||
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);
|
||||
putfonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
|
||||
sprintf(s, "memory %dMB free : %dKB",
|
||||
memtotal / (1024 * 1024), memman_total(memman) / 1024);
|
||||
putfonts8_asc_sht(sht_back, 0, 32, COL8_FFFFFF, COL8_008484, s, 40);
|
||||
|
||||
for (;;) {
|
||||
io_cli();
|
||||
if (fifo32_status(&fifo) == 0) {
|
||||
io_stihlt();
|
||||
} else {
|
||||
i = fifo32_get(&fifo);
|
||||
io_sti();
|
||||
if (256 <= i && i <= 511) { /* 键盘数据*/
|
||||
sprintf(s, "%02X", i - 256);
|
||||
putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
|
||||
if (i < 0x54 + 256) {
|
||||
if (keytable[i - 256] != 0 && cursor_x < 144) {
|
||||
s[0] = keytable[i - 256];
|
||||
s[1] = 0;
|
||||
putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, s, 1);
|
||||
cursor_x += 8;
|
||||
}
|
||||
}
|
||||
if (i == 256 + 0x0e && cursor_x > 8) { /* 退格键 */
|
||||
/* 用空格键把光标消去后,后移1次光标 */
|
||||
putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, " ", 1);
|
||||
cursor_x -= 8;
|
||||
}
|
||||
/* 光标再显示 */
|
||||
boxfill8(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 <= i && i <= 767) { /* 鼠标数据*/
|
||||
if (mouse_decode(&mdec, i - 512) != 0) {
|
||||
/* 已经收集了3字节的数据,所以显示出来 */
|
||||
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
|
||||
if ((mdec.btn & 0x01) != 0) {
|
||||
s[1] = 'L';
|
||||
}
|
||||
if ((mdec.btn & 0x02) != 0) {
|
||||
s[3] = 'R';
|
||||
}
|
||||
if ((mdec.btn & 0x04) != 0) {
|
||||
s[2] = 'C';
|
||||
}
|
||||
putfonts8_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);
|
||||
putfonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
|
||||
sheet_slide(sht_mouse, mx, my);/* 包含sheet_refresh含sheet_refresh */
|
||||
if ((mdec.btn & 0x01) != 0) { /* 按下左键、移动sht_win */
|
||||
sheet_slide(sht_win, mx - 80, my - 8);
|
||||
}
|
||||
}
|
||||
} else if (i == 10) { /* 10秒定时器 */
|
||||
putfonts8_asc_sht(sht_back, 0, 64, COL8_FFFFFF, COL8_008484, "10[sec]", 7);
|
||||
} else if (i == 3) { /* 3秒定时器 */
|
||||
putfonts8_asc_sht(sht_back, 0, 80, COL8_FFFFFF, COL8_008484, "3[sec]", 6);
|
||||
} else if (i <= 1) { /* 光标用定时器*/
|
||||
if (i != 0) {
|
||||
timer_init(timer3, &fifo, 0); /* 下面设定0 */
|
||||
cursor_c = COL8_000000;
|
||||
} else {
|
||||
timer_init(timer3, &fifo, 1); /* 下面设定1 */
|
||||
cursor_c = COL8_FFFFFF;
|
||||
}
|
||||
timer_settime(timer3, 50);
|
||||
boxfill8(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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$$$$$$$$$$$$$$@",
|
||||
"@@@@@@@@@@@@@@@@"
|
||||
};
|
||||
int x, y;
|
||||
char c;
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, xsize - 1, 0 );
|
||||
boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, xsize - 2, 1 );
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, 0, ysize - 1);
|
||||
boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, 1, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_848484, xsize - 2, 1, xsize - 2, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_000000, xsize - 1, 0, xsize - 1, ysize - 1);
|
||||
boxfill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3);
|
||||
boxfill8(buf, xsize, COL8_000084, 3, 3, xsize - 4, 20 );
|
||||
boxfill8(buf, xsize, COL8_848484, 1, ysize - 2, xsize - 2, ysize - 2);
|
||||
boxfill8(buf, xsize, COL8_000000, 0, ysize - 1, xsize - 1, ysize - 1);
|
||||
putfonts8_asc(buf, xsize, 24, 4, COL8_FFFFFF, title);
|
||||
for (y = 0; y < 14; y++) {
|
||||
for (x = 0; x < 16; x++) {
|
||||
c = closebtn[y][x];
|
||||
if (c == '@') {
|
||||
c = COL8_000000;
|
||||
} else if (c == '$') {
|
||||
c = COL8_848484;
|
||||
} else if (c == 'Q') {
|
||||
c = COL8_C6C6C6;
|
||||
} else {
|
||||
c = COL8_FFFFFF;
|
||||
}
|
||||
buf[(5 + y) * xsize + (xsize - 21 + x)] = c;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putfonts8_asc_sht(struct SHEET *sht, int x, int y, int c, int b, char *s, int l)
|
||||
{
|
||||
boxfill8(sht->buf, sht->bxsize, b, x, y, x + l * 8 - 1, y + 15);
|
||||
putfonts8_asc(sht->buf, sht->bxsize, x, y, c, s);
|
||||
sheet_refresh(sht, x, y, x + l * 8, y + 16);
|
||||
return;
|
||||
}
|
||||
|
||||
void make_textbox8(struct SHEET *sht, int x0, int y0, int sx, int sy, int c)
|
||||
{
|
||||
int x1 = x0 + sx, y1 = y0 + sy;
|
||||
boxfill8(sht->buf, sht->bxsize, COL8_848484, x0 - 2, y0 - 3, x1 + 1, y0 - 3);
|
||||
boxfill8(sht->buf, sht->bxsize, COL8_848484, x0 - 3, y0 - 3, x0 - 3, y1 + 1);
|
||||
boxfill8(sht->buf, sht->bxsize, COL8_FFFFFF, x0 - 3, y1 + 2, x1 + 1, y1 + 2);
|
||||
boxfill8(sht->buf, sht->bxsize, COL8_FFFFFF, x1 + 2, y0 - 3, x1 + 2, y1 + 2);
|
||||
boxfill8(sht->buf, sht->bxsize, COL8_000000, x0 - 1, y0 - 2, x1 + 0, y0 - 2);
|
||||
boxfill8(sht->buf, sht->bxsize, COL8_000000, x0 - 2, y0 - 2, x0 - 2, y1 + 0);
|
||||
boxfill8(sht->buf, sht->bxsize, COL8_C6C6C6, x0 - 2, y1 + 1, x1 + 0, y1 + 1);
|
||||
boxfill8(sht->buf, sht->bxsize, COL8_C6C6C6, x1 + 1, y0 - 2, x1 + 1, y1 + 1);
|
||||
boxfill8(sht->buf, sht->bxsize, c, x0 - 1, y0 - 1, x1 + 0, y1 + 0);
|
||||
return;
|
||||
}
|
||||
190
14_day/bootpack.h
Normal file
190
14_day/bootpack.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/* asmhead.nas */
|
||||
struct BOOTINFO { /* 0x0ff0-0x0fff */
|
||||
char cyls; /* 启动区读磁盘读到此为止 */
|
||||
char leds; /* 启动时键盘的LED的状态 */
|
||||
char vmode; /* 显卡模式为多少位彩色 */
|
||||
char reserve;
|
||||
short scrnx, scrny; /* 画面分辨率 */
|
||||
char *vram;
|
||||
};
|
||||
#define ADR_BOOTINFO 0x00000ff0
|
||||
|
||||
/* naskfunc.nas */
|
||||
void io_hlt(void);
|
||||
void io_cli(void);
|
||||
void io_sti(void);
|
||||
void io_stihlt(void);
|
||||
int io_in8(int port);
|
||||
void io_out8(int port, int data);
|
||||
int io_load_eflags(void);
|
||||
void io_store_eflags(int eflags);
|
||||
void load_gdtr(int limit, int addr);
|
||||
void load_idtr(int limit, int addr);
|
||||
int load_cr0(void);
|
||||
void store_cr0(int cr0);
|
||||
void asm_inthandler20(void);
|
||||
void asm_inthandler21(void);
|
||||
void asm_inthandler27(void);
|
||||
void asm_inthandler2c(void);
|
||||
unsigned int memtest_sub(unsigned int start, unsigned int end);
|
||||
|
||||
/* fifo.c */
|
||||
struct FIFO32 {
|
||||
int *buf;
|
||||
int p, q, size, free, flags;
|
||||
};
|
||||
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);
|
||||
|
||||
/* graphic.c */
|
||||
void init_palette(void);
|
||||
void set_palette(int start, int end, unsigned char *rgb);
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
|
||||
void init_screen8(char *vram, int x, int y);
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
|
||||
void init_mouse_cursor8(char *mouse, char bc);
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize);
|
||||
#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
|
||||
|
||||
/* dsctbl.c */
|
||||
struct SEGMENT_DESCRIPTOR {
|
||||
short limit_low, base_low;
|
||||
char base_mid, access_right;
|
||||
char limit_high, base_high;
|
||||
};
|
||||
struct GATE_DESCRIPTOR {
|
||||
short offset_low, selector;
|
||||
char dw_count, access_right;
|
||||
short offset_high;
|
||||
};
|
||||
void init_gdtidt(void);
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
|
||||
#define ADR_IDT 0x0026f800
|
||||
#define LIMIT_IDT 0x000007ff
|
||||
#define ADR_GDT 0x00270000
|
||||
#define LIMIT_GDT 0x0000ffff
|
||||
#define ADR_BOTPAK 0x00280000
|
||||
#define LIMIT_BOTPAK 0x0007ffff
|
||||
#define AR_DATA32_RW 0x4092
|
||||
#define AR_CODE32_ER 0x409a
|
||||
#define AR_INTGATE32 0x008e
|
||||
|
||||
/* int.c */
|
||||
void init_pic(void);
|
||||
void inthandler27(int *esp);
|
||||
#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
|
||||
|
||||
/* keyboard.c */
|
||||
void inthandler21(int *esp);
|
||||
void wait_KBC_sendready(void);
|
||||
void init_keyboard(struct FIFO32 *fifo, int data0);
|
||||
#define PORT_KEYDAT 0x0060
|
||||
#define PORT_KEYCMD 0x0064
|
||||
|
||||
/* mouse.c */
|
||||
struct MOUSE_DEC {
|
||||
unsigned char buf[3], phase;
|
||||
int x, y, btn;
|
||||
};
|
||||
void inthandler2c(int *esp);
|
||||
void enable_mouse(struct FIFO32 *fifo, int data0, struct MOUSE_DEC *mdec);
|
||||
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);
|
||||
|
||||
/* memory.c */
|
||||
#define MEMMAN_FREES 4090 /* 大约是32KB*/
|
||||
#define MEMMAN_ADDR 0x003c0000
|
||||
|
||||
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);
|
||||
void memman_init(struct MEMMAN *man);
|
||||
unsigned int memman_total(struct MEMMAN *man);
|
||||
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
|
||||
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);
|
||||
|
||||
/* sheet.c */
|
||||
#define MAX_SHEETS 256
|
||||
#define SHEET_USE 1
|
||||
|
||||
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_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);
|
||||
|
||||
/* timer.c */
|
||||
#define MAX_TIMER 500
|
||||
struct TIMER {
|
||||
struct TIMER *next;
|
||||
unsigned int timeout, flags;
|
||||
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_settime(struct TIMER *timer, unsigned int timeout);
|
||||
void inthandler20(int *esp);
|
||||
|
||||
57
14_day/dsctbl.c
Normal file
57
14_day/dsctbl.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* GDT、IDT、descriptor table 关系处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_gdtidt(void)
|
||||
{
|
||||
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
|
||||
struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) ADR_IDT;
|
||||
int i;
|
||||
|
||||
/* GDT初始化 */
|
||||
for (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_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);
|
||||
load_gdtr(LIMIT_GDT, ADR_GDT);
|
||||
|
||||
/* IDT初始化 */
|
||||
for (i = 0; i <= LIMIT_IDT / 8; i++) {
|
||||
set_gatedesc(idt + i, 0, 0, 0);
|
||||
}
|
||||
load_idtr(LIMIT_IDT, ADR_IDT);
|
||||
|
||||
/* IDT设置*/
|
||||
set_gatedesc(idt + 0x20, (int) asm_inthandler20, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
|
||||
set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void set_segmdesc(struct SEGMENT_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
|
||||
void set_gatedesc(struct GATE_DESCRIPTOR *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;
|
||||
return;
|
||||
}
|
||||
57
14_day/fifo.c
Normal file
57
14_day/fifo.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* FIFO */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
#define FLAGS_OVERRUN 0x0001
|
||||
|
||||
void fifo32_init(struct FIFO32 *fifo, int size, int *buf)
|
||||
/* FIFO缓冲区的初始化*/
|
||||
{
|
||||
fifo->size = size;
|
||||
fifo->buf = buf;
|
||||
fifo->free = size; /*空*/
|
||||
fifo->flags = 0;
|
||||
fifo->p = 0; /*写入位置*/
|
||||
fifo->q = 0; /*读取位置*/
|
||||
return;
|
||||
}
|
||||
|
||||
int fifo32_put(struct FIFO32 *fifo, int data)
|
||||
/*给FIFO发送数据并储存在FIFO中*/
|
||||
{
|
||||
if (fifo->free == 0) {
|
||||
/*没有空余空间,溢出*/
|
||||
fifo->flags |= FLAGS_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
fifo->buf[fifo->p] = data;
|
||||
fifo->p++;
|
||||
if (fifo->p == fifo->size) {
|
||||
fifo->p = 0;
|
||||
}
|
||||
fifo->free--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fifo32_get(struct FIFO32 *fifo)
|
||||
/*从FIFO取得一个数据*/
|
||||
{
|
||||
int data;
|
||||
if (fifo->free == fifo->size) {
|
||||
/*当缓冲区为空的情况下返回-1*/
|
||||
return -1;
|
||||
}
|
||||
data = fifo->buf[fifo->q];
|
||||
fifo->q++;
|
||||
if (fifo->q == fifo->size) {
|
||||
fifo->q = 0;
|
||||
}
|
||||
fifo->free++;
|
||||
return data;
|
||||
}
|
||||
|
||||
int fifo32_status(struct FIFO32 *fifo)
|
||||
/*报告已经存储了多少数据*/
|
||||
{
|
||||
return fifo->size - fifo->free;
|
||||
}
|
||||
157
14_day/graphic.c
Normal file
157
14_day/graphic.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/* 关于绘图部分的处理 */
|
||||
|
||||
#include "bootpack.h"
|
||||
|
||||
void init_palette(void)
|
||||
{
|
||||
static unsigned char table_rgb[16 * 3] = {
|
||||
0x00, 0x00, 0x00, /* 0:黑 */
|
||||
0xff, 0x00, 0x00, /* 1:梁红 */
|
||||
0x00, 0xff, 0x00, /* 2:亮绿 */
|
||||
0xff, 0xff, 0x00, /* 3:亮黄 */
|
||||
0x00, 0x00, 0xff, /* 4:亮蓝 */
|
||||
0xff, 0x00, 0xff, /* 5:亮紫 */
|
||||
0x00, 0xff, 0xff, /* 6:浅亮蓝 */
|
||||
0xff, 0xff, 0xff, /* 7:白 */
|
||||
0xc6, 0xc6, 0xc6, /* 8:亮灰 */
|
||||
0x84, 0x00, 0x00, /* 9:暗红 */
|
||||
0x00, 0x84, 0x00, /* 10:暗绿 */
|
||||
0x84, 0x84, 0x00, /* 11:暗黄 */
|
||||
0x00, 0x00, 0x84, /* 12:暗青 */
|
||||
0x84, 0x00, 0x84, /* 13:暗紫 */
|
||||
0x00, 0x84, 0x84, /* 14:浅暗蓝 */
|
||||
0x84, 0x84, 0x84 /* 15:暗灰 */
|
||||
};
|
||||
set_palette(0, 15, table_rgb);
|
||||
return;
|
||||
|
||||
/* C语言中的static char语句只能用于数据,相当于汇编中的DB指令 */
|
||||
}
|
||||
|
||||
void set_palette(int start, int end, unsigned char *rgb)
|
||||
{
|
||||
int i, eflags;
|
||||
eflags = io_load_eflags(); /* 记录中断许可标志的值 */
|
||||
io_cli(); /* 将中断许可标志置为0,禁止中断 */
|
||||
io_out8(0x03c8, start);
|
||||
for (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); /* 复原中断许可标志 */
|
||||
return;
|
||||
}
|
||||
|
||||
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
|
||||
{
|
||||
int x, y;
|
||||
for (y = y0; y <= y1; y++) {
|
||||
for (x = x0; x <= x1; x++)
|
||||
vram[y * xsize + x] = c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_screen8(char *vram, int x, int y)
|
||||
{
|
||||
boxfill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27);
|
||||
boxfill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1);
|
||||
|
||||
boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24);
|
||||
boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4);
|
||||
boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5);
|
||||
boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3);
|
||||
boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3);
|
||||
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24);
|
||||
boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3);
|
||||
boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3);
|
||||
return;
|
||||
}
|
||||
|
||||
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
|
||||
{
|
||||
int i;
|
||||
char *p, d /* data */;
|
||||
for (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; }
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
|
||||
{
|
||||
extern char hankaku[4096];
|
||||
/* C语言中,字符串都是以0x00结尾 */
|
||||
for (; *s != 0x00; s++) {
|
||||
putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
|
||||
x += 8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void init_mouse_cursor8(char *mouse, char bc)
|
||||
/* 鼠标的数据准备(16x16) */
|
||||
{
|
||||
static char cursor[16][16] = {
|
||||
"**************..",
|
||||
"*OOOOOOOOOOO*...",
|
||||
"*OOOOOOOOOO*....",
|
||||
"*OOOOOOOOO*.....",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOO*.......",
|
||||
"*OOOOOOOO*......",
|
||||
"*OOOO**OOO*.....",
|
||||
"*OOO*..*OOO*....",
|
||||
"*OO*....*OOO*...",
|
||||
"*O*......*OOO*..",
|
||||
"**........*OOO*.",
|
||||
"*..........*OOO*",
|
||||
"............*OO*",
|
||||
".............***"
|
||||
};
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < 16; y++) {
|
||||
for (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void putblock8_8(char *vram, int vxsize, int pxsize,
|
||||
int pysize, int px0, int py0, char *buf, int bxsize)
|
||||
{
|
||||
int x, y;
|
||||
for (y = 0; y < pysize; y++) {
|
||||
for (x = 0; x < pxsize; x++) {
|
||||
vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
4609
14_day/hankaku.txt
Normal file
4609
14_day/hankaku.txt
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user