Esempio n. 1
0
//打开新的console的函数
LAYER *open_console(LAYER_MANAGE *layer_manage, unsigned int memory_total)
{
	MEMMANAGE *memmanage = (MEMMANAGE *)MEMMANAGE_ADDR;
	LAYER *layer_console = layer_alloc(layer_manage);
	unsigned char *buf_console = (unsigned char *)memmanage_alloc_4K(memmanage, 256 * 165);	
	TASK *task_console = task_alloc();
	int *console_fifo = (int *)memmanage_alloc_4K(memmanage, 128 * 4);
	layer_set(layer_console, buf_console, 256, 165, -1);
	create_window(buf_console, 256, 165, "console", INACTIVE);
	create_textbox(layer_console, 8, 28, 240, 128, COL8_000000);
	task_console->console_stack = memmanage_alloc_4K(memmanage, 64 * 1024) + 64 * 1024 - 12;			//由于这里要传入两个参数,所以减去了12
	task_console->tss.esp = task_console->console_stack;
	task_console->tss.eip = (int) &console_task;			//eip指向的是运行console的函数首地址
	task_console->tss.es = 1 * 8;
	task_console->tss.cs = 2 * 8;
	task_console->tss.ss = 1 * 8;
	task_console->tss.ds = 1 * 8;
	task_console->tss.fs = 1 * 8;
	task_console->tss.gs = 1 * 8;
	*((int *) (task_console->tss.esp + 4)) = (int) layer_console;
	*((int *) (task_console->tss.esp + 8)) = memory_total;	
	task_run(task_console, 2, 2); 			/* level=2, priority=2 */
	layer_console->task = task_console;
	layer_console->flags |= 0x20;			//flags的0x20代表当前窗口的光标ON
	init_fifo(&task_console->fifo, 128, console_fifo, task_console);
	return layer_console;
}
Esempio n. 2
0
//打开新的console的函数
LAYER *open_console(LAYER_MANAGE *layer_manage, unsigned int memory_total)
{
	MEMMANAGE *memmanage = (MEMMANAGE *)MEMMANAGE_ADDR;
	LAYER *layer_console = layer_alloc(layer_manage);
	unsigned char *buf_console = (unsigned char *)memmanage_alloc_4K(memmanage, 256 * 165);	
	layer_set(layer_console, buf_console, 256, 165, -1);
	create_window(buf_console, 256, 165, "console", INACTIVE);
	create_textbox(layer_console, 8, 28, 240, 128, COL8_000000);
	layer_console->task = open_console_task(layer_console, memory_total);
	layer_console->flags |= 0x20;			//flags的0x20代表当前窗口的光标ON
	return layer_console;
}
Esempio n. 3
0
void HariMain(void)
{
	/*
	**最初的这部分变量没有通过内存管理来分配,它们本身属于操作系统的一部分,存在于bootpack.hrb所在的那块儿内存空间中
	*/
	BOOTINFO *binfo = (BOOTINFO *) ADR_BOOTINFO;
	MOUSE_DECODE mouse_dec;
	MEMMANAGE *memmanage = (MEMMANAGE *)MEMMANAGE_ADDR;
	LAYER_MANAGE *layer_manage;
	LAYER *layer_bg, *layer_mouse;
	FIFO fifo_mutual;									//缓冲区管理,所有中断公用的
	FIFO keycmd_fifo;									
	TASK *task_a, *task_console[2], *task;				//后面的那个task只是作为一个临时变量来用的
	CONSOLE *console;
	int fifobuf[128], keycmd_buf[32], *console_fifo[2];							//缓冲区
	int mCursorX, mCursorY;				//鼠标光标显示位置的横纵坐标
	int key_shift = 0, key_ctrl = 0, key_leds = (binfo->leds >> 4) & 7, keycmd_wait = -1;			//标志键盘输入到哪个窗口中
	int j, x, y, last_mcursorX = -1, last_mcursorY= -1, tmp_layerX = 0;			//last_mcursorX这两个变量记录的是鼠标移动之前的坐标
	int new_mcursorX = 0, new_mcursorY = 0, new_layerX = 0x7fffffff, new_layerY = 0;
	LAYER *layer = 0, *key_to_window;							//key_to_window这个变量记录当前的键盘输入到哪个窗口中
	unsigned int memory_total, i;
	char buf_cursor[mCursorWidth * mCursorHeight];
	unsigned char *buf_bg, *buf_console[2];		//屏幕的大背景会在init_screen的时候画出来,这里只需要一个指向它的指针即可
	unsigned char strings[40];
	mCursorX = binfo->scrnx / 2;			
	mCursorY = (binfo->scrny - 28)/ 2;		//减去下方任务栏的高度
	
	
	/*内存检查*/
	i = memtest(0x00400000, 0xbfffffff) / (1024 * 1024);	//i的单位是MB
	
	/*内存管理*/
	memmanage_init(memmanage);
	memory_total = i * 1024 * 1024;
	memmanage_free_4K(memmanage, 0x00001000, 0x0009e000);
	memmanage_free_4K(memmanage, 0x00400000, memory_total - 0x00400000);
	
	init_fifo(&keycmd_fifo, 32, keycmd_buf, 0);
	/*初始化接收中断的缓冲区*/
	init_fifo(&fifo_mutual, 128, fifobuf, 0);				//初始化mouseFIFO缓冲区,现在还没任务,先指定为0
	/*初始化GDT和IDT表以及PIC板的数据*/
	init_GDTandIDT();				//初始化GDT和IDT表
	init_pic();						//初始化PIC主从板数据,除了IRQ2禁止了全部中断
	io_sti();						//开始接收中断
	/*初始化PIT中断控制*/
	init_PIT();
		/*若要接收鼠标中断需要两个步骤,首先必须使鼠标控制电路(就是键盘控制电路的一部分)有效,然后要使鼠标本身有效*/
	init_keyboard(&fifo_mutual, 256);						//初始化键盘控制器电路
	enable_mouse(&fifo_mutual, 512, &mouse_dec);			//激活鼠标
	/*开放各种中断*/
	io_out8(PIC0_IMR, 0xf8);			//PIC0开发IRQ(11111000),开放IRQ0、IRQ1和IRQ2,定时器、键盘中断和从PIC板
	io_out8(PIC1_IMR, 0xef); 			//PIC1开放IRQ(11101111), 开放鼠标中断
	/*初始化任务切换管理*/
	task_a = task_init(memmanage);		//这个task_a其实代表的就是这些鼠标键盘等的任务
	fifo_mutual.task = task_a;			//为鼠标键盘等的缓冲区指定唤醒任务为task_a
	task_run(task_a, 1, 2);
	/*初始化调色板,为图形界面做准备*/
	init_palette();						//初始化调色板
	/*初始化图层管理,并且初始化鼠标光标和背景的图层*/
	layer_manage = layer_man_init(memmanage, binfo->vram, binfo->scrnx, binfo->scrny);
	*((int *) 0x0fe4) = (int) layer_manage;
	
	layer_bg = layer_alloc(layer_manage);			//为背景分配图层
	layer_mouse = layer_alloc(layer_manage);		//为鼠标分配图层
	
	buf_bg = (unsigned char *)memmanage_alloc_4K(memmanage, binfo->scrnx * binfo->scrny);		//为背景图形的内容分配内存
	/*为各个图形的图层内容进行设定*/
	layer_set(layer_bg, buf_bg, binfo->scrnx, binfo->scrny, -1);			
	layer_set(layer_mouse, buf_cursor, 16, 16 ,99);
	/*初始化整个桌面背景*/
	init_screen(buf_bg, binfo->scrnx, binfo->scrny);				//这个时候的init_screen不再是直接画出背景,而是在mBg内存地址中填写好背景内容
	layer_slide(layer_bg, 0, 0);									//把背景图层从(0,0)坐标开始画
	/*初始化鼠标图标*/
	init_mouse_cursor(buf_cursor, 99);								//初始化鼠标光标
	layer_slide(layer_mouse, mCursorX, mCursorY);					//现在显示图形不需要再用displayShape函数了,直接用这个图层管理的绘图函数就行

	/*执行两个命令行窗口任务*/
	key_to_window = open_console(layer_manage, memory_total);		//最初的时候由第一个console接收键盘输入
	
	layer_slide(key_to_window, 8, 2);
	/*设置好各个图层的高度*/
	layer_switch(layer_bg, 0);						//把背景图层调为最底层,高度为0
	layer_switch(key_to_window, 1);					//命令行窗口图层调节为第三层,高度为2
	layer_switch(layer_mouse, 2);					//鼠标图层调为最高层,高度为3	
					
	keywindow_on(key_to_window);
	
	//
	fifo_put(&keycmd_fifo, KEYCMD_LED);
	fifo_put(&keycmd_fifo, key_leds);
	
	*((int *) 0x0fec) = (int) &fifo_mutual;			
	for(;;)
	{ 
		if(fifo_status(&keycmd_fifo) > 0 && keycmd_wait < 0)
		{
			keycmd_wait = fifo_get(&keycmd_fifo);
			wait_KBC_sendready();
			io_out8(PORT_KEYDATA, keycmd_wait);
		}
		/*只有在从中断返回的缓冲区中读取数据的时候才需要禁止中断,因为如果这个时候来了中断而没有禁止的话,
		**有可能读脏数据,即把还没有读出的数据的给抹掉或换成别的数据
		*/
		io_cli();		
		if(0 == fifo_status(&fifo_mutual))		//当前没有中断产生
		{
			//利用CPU空闲的时间来执行耗时的绘图工作(这样的话会造成反应很快的表象,但其实,如果中断很多,尤其是鼠标中断很多的时候,
			//会把之前记录下的new_mcursorX覆盖掉,而只绘制最新的图层坐标)
			if(new_mcursorX >= 0)
			{
				io_sti();
				layer_slide(layer_mouse, new_mcursorX, new_mcursorY);
				new_mcursorX = -1;				//绘制完鼠标之后,就把它的坐标设置为负数,反正鼠标不会出去屏幕,为负数的时候就说明不需要重绘鼠标
			}
			//图层的横坐标为0x7fffffff的时候就不需要重绘了,这是作为一个标志的,它为其他值的时候就需要重绘了
			else if(new_layerX != 0x7fffffff)
			{
				io_sti();
				layer_slide(layer, new_layerX, new_layerY);
				new_layerX = 0x7fffffff;
			}
			//如果不需要重绘鼠标和图层的话,就没有什么工作可做了,进入休眠就可以了
			else
			{
				task_sleep(task_a);	//如果没有需要处理的数据,就自己让自己休眠
				/*上面的那个函数直接就跳转到另一个任务中去了,不过,因为每个人物的默认eflags都是开启中断的,
				**所以不用担心,这个任务还是能被唤醒的,耳环醒后的第一个动作就是为了以防万一先开启中断
				*/
				io_sti();		//万一只有自己在运行的话,则无法睡眠,那么就执行hlt指令好了,这样省电嘛	
			}
		}
		else
		{
			i = fifo_get(&fifo_mutual);
			io_sti();
			//窗口被关闭的情况
			if(0 != key_to_window && 0 == key_to_window->flags)
			{
				//如果当前画面上只剩下鼠标和背景的时候
				if(1 == layer_manage->top)
				{
					key_to_window = 0;
				}
				else
				{
					key_to_window = layer_manage->layers_order[layer_manage->top - 1];			//当窗口被关闭的时候,自动切换成最上层的layer接收键盘输入
					keywindow_on(key_to_window);
				}
			}
			//如果是键盘中断的话,需要处理键盘发送来的中断数据
			if((keyboard_offset <= i) && (i <= keyboard_offset + 255))			
			{
				//判断shift键是否按下,然后使用不同的keytable表
				if(i < 0x80 + keyboard_offset)
				{
					if(0 == key_shift)
					{
						strings[0] = key_table[i - keyboard_offset];
					}
					else
					{
						strings[0] = key_table_shift[i - keyboard_offset];
					}
				}
				else
				{
					strings[0] = 0;
				}
				//判断Caps和Shift键的情况以确定输入大写还是小写字母
				if('A' <= strings[0] && strings[0] <= 'Z')
				{
					//小写字母的情况
					if((0 == (key_leds & 4) && 0 == key_shift) || (0 != (key_leds & 4) && 0 != key_shift))
					{
						strings[0] += 0x20;
					}
				}
				//判断按下的字符是否为一般字符,0对应的字符不处理,对退格键和回车键加上了对应字符,他们对应的table表里的元素不再是0
				if(strings[0] != 0 && key_to_window != 0)				
				{
					fifo_put(&key_to_window->task->fifo, strings[0] + 256);
				}
				//如果按下了ctrl+d,就打开一个console
				if(('D' == strings[0] || 'd' == strings[0]) && (0 != key_ctrl))
				{
					if(key_to_window != 0)
					{
						keywindow_off(key_to_window);
					}					
					key_to_window = open_console(layer_manage, memory_total);
					layer_slide(key_to_window, 300, 2);
					layer_switch(key_to_window, layer_manage->top);
					//自动把键盘输入切换到这个新打开的console中
					keywindow_on(key_to_window);
				}
				//如果同时按下了ctrl+x,那么就关闭应用程序
				if(('X' == strings[0] || 'x' == strings[0]) && (0 != key_ctrl) && key_to_window != 0)
				{
					task = key_to_window->task;				//找到当前接收键盘输入的(即最前面的)图层所对应的任务
					if(0 != task && task->tss.ss0 != 0)
					{
						console_putstring_toend(task->console, "\nTerminate program! :\n");
						io_cli();
						//让CPU直接跳转到console中执行,不再管应用程序,也就是所谓的停止应用程序继续运行
						task->tss.eax = (int) &(task->tss.esp0);
						task->tss.eip = (int) asm_end_app;
						io_sti();
					}
					
				}
				/*这些都是那些不能打印的特殊按键,它们对应的都是0*/
				//按下“TAB键”的处理情况,切换输入窗口
				if(i == keyboard_offset + 0x0f && key_to_window != 0)					
				{
					//先让当前的窗口的光标OFF掉
					keywindow_off(key_to_window);
					j = key_to_window->height - 1;
					if(0 == j)
					{
						//如果切换之后的图层是最底层的操作系统的图层,那么就切换成最上层的图层
						j = layer_manage->top - 1;
					}
					key_to_window = layer_manage->layers_order[j];
					//使切换到的窗口的光标ON
					keywindow_on(key_to_window);
				}
				//左或右Ctrl ON
				if(0x1d + keyboard_offset == i)
				{
					key_ctrl = 1;
				}
				//左或右Ctrl OFF
				if(0x9d + keyboard_offset == i)
				{
					key_ctrl = 0;
				}
				//左shift ON
				if(0x2a + keyboard_offset == i)
				{
					key_shift |= 1;
				}
				//右shift ON
				if(0x36 + keyboard_offset == i)
				{
					key_shift |= 2;
				}
				//左shift OFF
				if(0xaa + keyboard_offset == i)
				{
					key_shift &= ~1;
				}
				//左shift OFF
				if(0xb6 + keyboard_offset == i)
				{
					key_shift &= ~2;
				}
				/*对各种锁定键的处理*/
				//CapsLock键
				if(i == keyboard_offset + 0x3a)
				{
					key_leds ^= 4;
					fifo_put(&keycmd_fifo, KEYCMD_LED);
					fifo_put(&keycmd_fifo, key_leds);
				}
				//NumLock键
				if(i == keyboard_offset + 0x45)
				{
					key_leds ^= 2;
					fifo_put(&keycmd_fifo, KEYCMD_LED);
					fifo_put(&keycmd_fifo, key_leds);
				}
				//ScrollLock键
				if(i == keyboard_offset + 0x46)
				{
					key_leds ^= 1;
					fifo_put(&keycmd_fifo, KEYCMD_LED);
					fifo_put(&keycmd_fifo, key_leds);
				}
				//键盘成功接收到数据
				if(i == keyboard_offset + 0xfa)
				{
					keycmd_wait = -1;
				}
				//键盘没有成功接收到数据
				if(i == keyboard_offset + 0xfe)
				{
					wait_KBC_sendready();
					io_out8(PORT_KEYDATA, keycmd_wait);
				}
			}
			//如果是鼠标中断的话,需要处理鼠标发送来的中断数据
			else if((mouse_offset <= i) && (i <= mouse_offset + 255))		
			{
				if(0 != mouse_decode(&mouse_dec, i - mouse_offset))		//只有返回值为1的时候才说明成功接收完成一次鼠标的中断
				{
					
					/*鼠标的移动*/
					//根据mouse_dec里存储的鼠标信息画出新的鼠标图像
					mCursorX += mouse_dec.x;
					mCursorY += mouse_dec.y;
					//不能让鼠标移出画面
					if(mCursorX < 0)
					{
						mCursorX = 0;
					}
					if(mCursorY < 0)
					{
						mCursorY = 0;
					}
					if(mCursorX > binfo->scrnx - 1)
					{
						mCursorX = binfo->scrnx - 1;
					}
					if(mCursorY > binfo->scrny - 1)
					{
						mCursorY = binfo->scrny - 1;
					}
					//记录下鼠标光标的移动到的位置,等待fifo中为空的时候开始绘图
					new_mcursorX = mCursorX;
					new_mcursorY = mCursorY;
					//按下了左键
					if(0 != (mouse_dec.btn & 0x01))
					{
						//如果last_mcursorX小于0,说明当前不是处于窗口移动模式,那么就需要检查现在鼠标按下左键之后有没有落在某个图层的标题栏上
						if(last_mcursorX < 0)
						{
							for(j = layer_manage->top - 1; j > 0; j--)
							{
								layer = layer_manage->layers_order[j];
								//计算一下鼠标的坐标在不在这个图层里面
								x = mCursorX - layer->x;
								y = mCursorY - layer->y;
								if(0 <= x && x < layer->length && 0 <= y && y <= layer->width)
								{
									//鼠标所在区域也不能是涂层的透明区域
									if(layer->buffer[y * layer->length + x] != layer->color_luc)
									{
										layer_switch(layer, layer_manage->top - 1);
										//如果当前的layer不是接收键盘输入的图层(即最前面的图层),那么就需要切换
										if(layer != key_to_window)
										{
											//鼠标左击窗口所做的事情跟按下TAB键的事情差不多
											keywindow_off(key_to_window);
											key_to_window = layer;
											keywindow_on(key_to_window);
										}
										//查看鼠标当前点击的区域是不是窗口的标题栏,并且不能是关闭按钮所在的区域
										if(3 <= x && x < layer->length - 21 && 3 <= y && y <= 21)
										{
											last_mcursorX = mCursorX;
											last_mcursorY = mCursorY;
											tmp_layerX = layer->x;		//这个tmp_layerX只是个要绘制的图层横坐标的过渡部分,真正的坐标还需要处理
											new_layerY = layer->y;
										}
										//这个是鼠标点击到关闭按钮的情况
										if(layer->length - 21 <= x && x <= layer->length - 5 && 5 <= y && y <= 19)
										{	
											//查看该窗口是否为应用程序的窗口,如果是应用程序产生的窗口而不是console的那个黑窗口,那么这个窗口的flags有0x10
											if(0 != (layer->flags & 0x10))
											{
												//这部分处理跟按下ctrl+x的处理基本一样
												task = layer->task;
												console_putstring_toend(task->console, "Break by mouse!\n");
												io_cli();
												task->tss.eax = (int)&(task->tss.esp0);
												task->tss.eip = (int)asm_end_app;
												io_sti();
											}
											//不是应用程序的话就是console命令行窗口产生的layer
											else
											{
												//不能再这里的task_a中直接关闭,因为还有些console自身管理的定时器和fat等东西无法释放了
												task = layer->task;
												io_cli();
												fifo_put(&task->fifo, 4);
												io_sti();
											}
										}
										break;
									}
								}
							}
						}
						//只要last_mcursorX大于0,说明当前处于窗口移动模式,说明当前鼠标正点击着某个图层的标题栏呢
						else
						{
							x = mCursorX - last_mcursorX;
							y = mCursorY - last_mcursorY;
							new_layerX = (tmp_layerX + x + 2) & ~3;
							new_layerY = new_layerY + y;
							last_mcursorY = mCursorY;			//更新到移动后的坐标
						}
					}
					//如果当前没有按下左键,就把last_mcursorX设置为负数,作为当前不处于窗口移动的依据
					else
					{
						last_mcursorX = -1;
						if(0x7fffffff != new_layerX)
						{
							layer_slide(layer, new_layerX, new_layerY);		//一旦鼠标不点击这窗口移动了,就立即最后一次绘制窗口并且停止窗口的移动
							new_layerX = 0x7fffffff; 
						}
					}
					
				}
			}
			//收到这个之间的数据,说明是让关闭console的
			else if(768 <= i && i <= 1023)
			{
				close_console(layer_manage->layers + (i - 768));
			}
		}
	}	
}
Esempio n. 4
0
void HariMain(void)
{
	BOOTINFO *binfo = (BOOTINFO *) ADR_BOOTINFO;
	MOUSE_DECODE mouse_dec;
	MEMMANAGE *memmanage = (MEMMANAGE *)MEMMANAGE_ADDR;
	LAYER_MANAGE *layer_manage;
	LAYER *layer_bg, *layer_mouse;
	char mCursor[mCursorWidth * mCursorHeight];
	unsigned char *mBg;			//屏幕的大背景会在init_screen的时候画出来,这里只需要一个指向它的指针即可
	unsigned char strings[40], keyBuffer[32], mouseBuffer[128],i;
	unsigned int memory_total;
	int j;
	int mCursorX, mCursorY;				//鼠标光标显示位置的横纵坐标
	mCursorX = binfo->scrnx / 2;			
	mCursorY = (binfo->scrny - 28)/ 2;		//减去下方任务栏的高度
	
	
	/*内存检查*/
	i = memtest(0x00400000, 0xbfffffff) / (1024 * 1024);		//i的单位是MB
	
	/*内存管理*/
	memmanage_init(memmanage);
	memory_total = i * 1024 * 1024;
	memmanage_free_4K(memmanage, 0x00001000, 0x0009e000);
	memmanage_free_4K(memmanage, 0x00400000, memory_total - 0x00400000);
	
	/*初始化接收中断的缓冲区*/
	init_fifo(&keyFIFO, 32, keyBuffer);				//初始化keyFIFO缓冲区
	init_fifo(&mouseFIFO, 128, mouseBuffer);		//初始化mouseFIFO缓冲区
	/*初始化GDT和IDT表以及PIC板的数据*/
	init_GDTandIDT();				//初始化GDT和IDT表
	init_pic();						//初始化PIC主从板数据
	io_sti();						//开始接收中断
		/*若要接收鼠标中断需要两个步骤,首先必须使鼠标控制电路(就是键盘控制电路的一部分)有效,然后要使鼠标本身有效*/
	init_keyboard();						//初始化键盘控制器电路
	enable_mouse(&mouse_dec);				//激活鼠标
	/*开放鼠标和键盘中断*/
	io_out8(PIC0_IMR, 0xf9); 						/* PIC0开发IRQ(11111001),开放IRQ1和IRQ2,键盘中断和从PIC板 */
	io_out8(PIC1_IMR, 0xef); 						/* PIC1开放IRQ(11101111), 开放鼠标中断*/
	/*初始化调色板,为图形界面做准备*/
	init_palette();					//初始化调色板
	/*初始化图层管理,并且初始化鼠标光标和背景的图层*/
	layer_manage = layer_man_init(memmanage, binfo->vram, binfo->scrnx, binfo->scrny);
	layer_bg = layer_alloc(layer_manage);			//为背景分配图层
	layer_mouse = layer_alloc(layer_manage);		//为鼠标分配图层
	mBg = (unsigned char *)memmanage_alloc_4K(memmanage, binfo->scrnx * binfo->scrny);		//为背景图形的内容分配内存
	layer_set(layer_bg, mBg, binfo->scrnx, binfo->scrny, -1);
	layer_set(layer_mouse, mCursor, 16, 16 ,99);
	/*初始化整个桌面背景*/
	init_screen(mBg, binfo->scrnx, binfo->scrny);				//这个时候的init_screen不再是直接画出背景,而是在mBg内存地址中填写好背景内容
	layer_slide(layer_manage, layer_bg, 0, 0);					//把背景图层从(0,0)坐标开始画
	/*初始化鼠标图标*/
	init_mouse_cursor(mCursor, 99);								//初始化鼠标光标
	layer_slide(layer_manage, layer_mouse, mCursorX, mCursorY);	//现在显示图形不需要再用displayShape函数了,直接用这个图层管理的绘图函数就行
	
	layer_switch(layer_manage, layer_bg, 0);					//把背景图层调为最底层,高度为0
	layer_switch(layer_manage, layer_mouse, 1);					//鼠标图层调为第二层,高度为1
	//layer_all_refresh(layer_manage);
	
	sprintf(strings, "Memory has %dMB", i);
	displayStrings_CS(mBg, binfo->scrnx, 0, 64, COL8_FFFFFF,strings);
	layer_refresh(layer_manage, layer_bg, 0, 64, binfo->scrnx, 80);
	sprintf(strings, "free memory:%dKB",memmanage_total(memmanage) / 1024);
	displayStrings_CS(mBg, binfo->scrnx, 120, 64, COL8_FFFFFF,strings);			//用字体显示当前内存容量
	layer_refresh(layer_manage, layer_bg, 120, 64, binfo->scrnx, 80);
	
	
	for(;;)
	{
		io_cli();
		if(0 == fifo_status(&keyFIFO) + fifo_status(&mouseFIFO))		//当前没有中断产生
		{
			io_stihlt();			//当CPU执行hlt指令之后只有外部中断等之情况才会再次唤醒CPU继续工作
		}
		else
		{
			if(0 != fifo_status(&keyFIFO))
			{
				i = fifo_get(&keyFIFO);
				io_sti();
				sprintf(strings,"%2X",i);
				drawRectangle(mBg, binfo->scrnx, COL8_008484, 0, 0, 16,16);		//这里的字体不再是卸载vram中,而是写到mBg这个背景内存中,与背景成为一个图层
				displayStrings_CS(mBg, binfo->scrnx, 0, 0, COL8_FFFFFF,strings);
				layer_refresh(layer_manage, layer_bg, 0, 0, 16, 16);								//由于向背景图层中添加了新东西,需要重绘各个图层
			}
			else if(0 != fifo_status(&mouseFIFO))
			{
				i = fifo_get(&mouseFIFO);
				io_sti();
				if(0 != mouse_decode(&mouse_dec, i))		//只有返回值为1的时候才说明成功接收完成一次鼠标的中断
				{
					/*显示鼠标的信息*/
					sprintf(strings,"[lcr %4d %4d]",mouse_dec.x, mouse_dec.y);
					if(0 != (mouse_dec.btn & 0x01))		//按下了左键
					{
						strings[1] = 'L';
					}
					if(0 != (mouse_dec.btn & 0x02))		//按下了右键
					{
						strings[3] = 'R';
					}
					if(0 != (mouse_dec.btn & 0x04))		//按下了中键
					{
						strings[2] = 'C';
					}
					drawRectangle(mBg, binfo->scrnx, COL8_008484, 0, 16, 15 * 8, 16);		//用背景色覆盖上次的坐标
					displayStrings_CS(mBg, binfo->scrnx, 0, 16, COL8_FFFFFF,strings);		//显示新的坐标
					layer_refresh(layer_manage, layer_bg,0, 16, 15 * 8, 32);
					/*鼠标的移动*/
					//根据mouse_dec里存储的鼠标信息画出新的鼠标图像
					mCursorX += mouse_dec.x;
					mCursorY += mouse_dec.y;
					//不能让鼠标移出画面
					if(mCursorX < 0)
					{
						mCursorX = 0;
					}
					if(mCursorY < 0)
					{
						mCursorY = 0;
					}
					if(mCursorX > binfo->scrnx - 16)
					{
						mCursorX = binfo->scrnx - 16;
					}
					if(mCursorY > binfo->scrny - 16)
					{
						mCursorY = binfo->scrny - 16;
					}
					sprintf(strings, "(%4d %4d)", mCursorX, mCursorY);
					drawRectangle(mBg, binfo->scrnx, COL8_008484, 40, 32, 20 * 8,16);		//用背景色覆盖上次的坐标
					displayStrings_CS(mBg, binfo->scrnx, 40, 32, COL8_FFFFFF,strings);		//显示新的坐标
					layer_refresh(layer_manage, layer_bg, 40, 32, 20 * 8,48);
					layer_slide(layer_manage, layer_mouse, mCursorX, mCursorY);
				}
			}
		}
	}	
}
Esempio n. 5
0
void level::LoadLevel( char * xmlfile )
{
  //begining xmlreader implementation
  /*
  pugi::xml_document doc;
  
  pugi::xml_parse_result result = doc.load_file("assets/pallet.tmx");
  
  pugi::xml_node spider = doc.child("map");
  std::cout << spider.attribute("height").value();
  spider = spider.child("tileset");
  std::cout << spider.attribute("name").value() << std::endl;
  spider = spider.next_sibling("tileset");
  std::cout << spider.attribute("name").value() << std::endl;
  std::cout  << spider;
  spider = spider.next_sibling("tileset");
  std::cout << spider.attribute("name").value() << std::endl;
  */
  int height, width;
  
  //open file
  pugi::xml_document doc;
  pugi::xml_parse_result result;
  //pugi::xml_parse_result result = doc.load_file( xmlfile );
  //TODO: assets pallet needs to be based on a lookup table

  try
    {
      result = doc.load_file("assets/pallet.tmx");
    }
  catch( ... )
    {
      exit(1);
    }

  
  if (result)
    {
      std::cout << "Load Result: " << result.description() << std::endl;
    }
  else
    {
      
    }
  
  //get width and hight
  //and make layer maps

  //sets spider on the map tag
  pugi::xml_node spider = doc.child("map");

  //grabs width and height from xml
  height = spider.attribute("height").as_int();
  width  = spider.attribute( "width").as_int();
  
  //std::cout << height << " " << width << std::endl;

  
  create_tilesets( spider );
  
  std::cout << "tilesets created\n";
  //make tile rules

  pugi::xml_node datafinder;
  
  //read in tile layers
  spider = spider.child("layer");
  //std::cout << "\nusing " << spider.attribute("name").value();
  datafinder = spider;
  bottom = layer_set( datafinder, width, height ); 

  spider = spider.next_sibling("layer");
  //std::cout << "\nusing " << spider.attribute("name").value();
  datafinder = spider;
  mid = layer_set( datafinder, width, height ); 

  spider = spider.next_sibling("layer");
  //std::cout << "\nusing " << spider.attribute("name").value();
  datafinder = spider;
  top = layer_set( datafinder, width, height ); 
  
}
Esempio n. 6
0
void HariMain(void)
{
	/*
	**最初的这部分变量没有通过内存管理来分配,它们本身属于操作系统的一部分,存在于bootpack.hrb所在的那块儿内存空间中
	*/
	BOOTINFO *binfo = (BOOTINFO *) ADR_BOOTINFO;
	MOUSE_DECODE mouse_dec;
	MEMMANAGE *memmanage = (MEMMANAGE *)MEMMANAGE_ADDR;
	LAYER_MANAGE *layer_manage;
	LAYER *layer_bg, *layer_mouse, *layer_window;
	TIMER *timer1, *timer2, *timer3;
	FIFO fifo_mutual;									//缓冲区管理,所有中断公用的
	TSS tss_a, tss_b;									//用于切换的两个任务
	int fifobuf[128];									//缓冲区
	int cursor_x = 8, cursor_color = COL8_FFFFFF;		//分别代表输入字符后的那个闪烁光标的横坐标和颜色
	int mCursorX, mCursorY;				//鼠标光标显示位置的横纵坐标
	int task_b_esp;
	unsigned int memory_total, i;
	char buf_cursor[mCursorWidth * mCursorHeight];
	unsigned char *buf_bg, *buf_window;			//屏幕的大背景会在init_screen的时候画出来,这里只需要一个指向它的指针即可
	unsigned char strings[40];
	mCursorX = binfo->scrnx / 2;			
	mCursorY = (binfo->scrny - 28)/ 2;		//减去下方任务栏的高度
	
	
	/*内存检查*/
	i = memtest(0x00400000, 0xbfffffff) / (1024 * 1024);		//i的单位是MB
	
	/*内存管理*/
	memmanage_init(memmanage);
	memory_total = i * 1024 * 1024;
	memmanage_free_4K(memmanage, 0x00001000, 0x0009e000);
	memmanage_free_4K(memmanage, 0x00400000, memory_total - 0x00400000);
	
	/*初始化接收中断的缓冲区*/
	init_fifo(&fifo_mutual, 128, fifobuf);		//初始化mouseFIFO缓冲区
	/*初始化GDT和IDT表以及PIC板的数据*/
	init_GDTandIDT();				//初始化GDT和IDT表
	init_pic();						//初始化PIC主从板数据,除了IRQ2禁止了全部中断
	io_sti();						//开始接收中断
	/*初始化PIT中断控制*/
	init_PIT();
		/*若要接收鼠标中断需要两个步骤,首先必须使鼠标控制电路(就是键盘控制电路的一部分)有效,然后要使鼠标本身有效*/
	init_keyboard(&fifo_mutual, 256);						//初始化键盘控制器电路
	enable_mouse(&fifo_mutual, 512, &mouse_dec);				//激活鼠标
	/*开放各种中断*/
	io_out8(PIC0_IMR, 0xf8);				//PIC0开发IRQ(11111000),开放IRQ0、IRQ1和IRQ2,定时器、键盘中断和从PIC板
	io_out8(PIC1_IMR, 0xef); 				//PIC1开放IRQ(11101111), 开放鼠标中断
	/*初始化调色板,为图形界面做准备*/
	init_palette();					//初始化调色板
	/*初始化图层管理,并且初始化鼠标光标和背景的图层*/
	layer_manage = layer_man_init(memmanage, binfo->vram, binfo->scrnx, binfo->scrny);
	
	layer_bg = layer_alloc(layer_manage);			//为背景分配图层
	layer_mouse = layer_alloc(layer_manage);		//为鼠标分配图层
	layer_window = layer_alloc(layer_manage);		//为窗口分配图层
	
	buf_bg = (unsigned char *)memmanage_alloc_4K(memmanage, binfo->scrnx * binfo->scrny);		//为背景图形的内容分配内存
	buf_window = (unsigned char *)memmanage_alloc_4K(memmanage, 160 * 52);						//为窗口图形的内容分配内存
	/*为各个图形的图层内容进行设定*/
	layer_set(layer_bg, buf_bg, binfo->scrnx, binfo->scrny, -1);			
	layer_set(layer_mouse, buf_cursor, 16, 16 ,99);
	layer_set(layer_window, buf_window, 160, 52, -1);
	/*初始化整个桌面背景*/
	init_screen(buf_bg, binfo->scrnx, binfo->scrny);				//这个时候的init_screen不再是直接画出背景,而是在mBg内存地址中填写好背景内容
	layer_slide(layer_bg, 0, 0);					//把背景图层从(0,0)坐标开始画
	/*初始化鼠标图标*/
	init_mouse_cursor(buf_cursor, 99);								//初始化鼠标光标
	layer_slide(layer_mouse, mCursorX, mCursorY);	//现在显示图形不需要再用displayShape函数了,直接用这个图层管理的绘图函数就行
	/*初始化窗口*/
	create_window(buf_window, 160, 52, "window");					//制作窗口
	layer_slide(layer_window, 80, 72);								//在指定位置显示出窗口
	create_textbox(layer_window, 8, 28, 144, 16, COL8_FFFFFF);		//在这个窗口中创建一个输入框
	/*设置好各个图层的高度*/
	layer_switch(layer_bg, 0);						//把背景图层调为最底层,高度为0
	layer_switch(layer_window, 1);					//窗口图层调节为第二层,高度为1
	layer_switch(layer_mouse, 2);					//鼠标图层调为最高层,高度为2
	/*定时器的初始化及其设置*/
	timer1 = timer_alloc();
	timer_init(timer1, &fifo_mutual, 10);
	timer_set(timer1, 1000);
	
	timer2 = timer_alloc();
	timer_init(timer2, &fifo_mutual, 3);
	timer_set(timer2, 300);
	
	timer3 = timer_alloc();
	timer_init(timer3, &fifo_mutual, 1);
	timer_set(timer3, 50);
	/*在屏幕上显示一些内存、鼠标和键盘等信息*/
	sprintf(strings, "Memory has %dMB", i);
	displayStrings_CS(buf_bg, binfo->scrnx, 0, 48, COL8_FFFFFF,strings);
	layer_refresh(layer_bg, 0, 48, binfo->scrnx, 80);
	sprintf(strings, "free memory:%dKB",memmanage_total(memmanage) / 1024);
	displayStrings_CS(buf_bg, binfo->scrnx, 120, 48, COL8_FFFFFF,strings);			//用字体显示当前内存容量
	layer_refresh(layer_bg, 120, 48, binfo->scrnx, 80);
	
	/*任务切换*/
	SEGMENT_DESCRIPTOR *gdt = (SEGMENT_DESCRIPTOR *)ADR_GDT;
	tss_a.ldtr = 0;
	tss_a.iomap = 0x40000000;
	tss_b.ldtr = 0;
	tss_b.iomap = 0x40000000;
	
	set_segmdesc(gdt + 3, 103, (int) &tss_a, AR_TSS32);			//任务a在第三个段中运行,段限是103字节
	set_segmdesc(gdt + 4, 103, (int) &tss_b, AR_TSS32);
	
	load_tr(3 * 8);				//代表当前在运行第三个段中的程序
	task_b_esp = memmanage_alloc_4K(memmanage, 64 * 1024) + 64 * 1024;
	tss_b.eip = (int) &task_b_main;
	tss_b.eflags = 0x00000202; /* IF = 1; */
	tss_b.eax = 0;
	tss_b.ecx = 0;
	tss_b.edx = 0;
	tss_b.ebx = 0;
	tss_b.esp = task_b_esp;
	tss_b.ebp = 0;
	tss_b.esi = 0;
	tss_b.edi = 0;
	tss_b.es = 1 * 8;
	tss_b.cs = 2 * 8;
	tss_b.ss = 1 * 8;
	tss_b.ds = 1 * 8;
	tss_b.fs = 1 * 8;
	tss_b.gs = 1 * 8;
	
	for(;;)
	{
		/*只有在从中断返回的缓冲区中读取数据的时候才需要禁止中断,因为如果这个时候来了中断而没有禁止的话,
		**有可能读脏数据,即把还没有读出的数据的给抹掉或换成别的数据
		*/
		io_cli();		
		if(0 == fifo_status(&fifo_mutual))		//当前没有中断产生
		{
			io_stihlt();			//当CPU执行hlt指令之后只有外部中断等之情况才会再次唤醒CPU继续工作
		}
		else
		{
			i = fifo_get(&fifo_mutual);
			io_sti();
			if((keyboard_offset <= i) && (i <= keyboard_offset + 255))			//键盘数据
			{
				sprintf(strings, "%2X", i - keyboard_offset);
				displayStrings_atLayer(layer_bg, 0, 0, COL8_FFFFFF, COL8_008484, strings);					//由于向背景图层中添加了新东西,需要重绘各个图层
				if(i < keyboard_offset + 0x54)				//判断按下的字符是否可打印
				{
					if(0 != key_table[i - keyboard_offset] && cursor_x < 144)			//0对应的字符无法打印出来
					{
						strings[0] = key_table[i - keyboard_offset];
						strings[1] = 0;
						displayStrings_atLayer(layer_window, cursor_x, 28, COL8_000000, COL8_FFFFFF, strings);
						cursor_x += 8;			//光标的位置随着每一个字符的输入向后移动一个字符宽度的位置即8像素
					}
					if((keyboard_offset + 0x0e == i) && cursor_x > 8)				//按下了退格键的情况,退格键的号码是0x0e
					{
						cursor_x -= 8;
						/*本来退格键应该只填充一个空格就行的,但是这样的话没办法刷新光标所在的那块儿区域了,
						**会留下光标的黑色痕迹,所以直接填充两个空格,刷新之后就不会有痕迹了
						*/
						displayStrings_atLayer(layer_window, cursor_x, 28, COL8_000000, COL8_FFFFFF, "  ");
					}
					//由于光标坐标后退了,为了及时显示它,需要立即重绘光标
					drawRectangle(layer_window->buffer, layer_window->length, cursor_color, cursor_x, 28, 2, 15);
					layer_refresh(layer_window, cursor_x, 28, cursor_x + 8, 44);
				}
			}
			else if((mouse_offset <= i) && (i <= mouse_offset + 255))		//鼠标数据
			{
				if(0 != mouse_decode(&mouse_dec, i - mouse_offset))		//只有返回值为1的时候才说明成功接收完成一次鼠标的中断
				{
				/*显示鼠标的信息*/
					sprintf(strings,"[lcr %3d,%3d]",mouse_dec.x, mouse_dec.y);
					if(0 != (mouse_dec.btn & 0x01))		//按下了左键
					{
						strings[1] = 'L';
						//layer_slide(layer_window, mCursorX - 80, mCursorY -8);		//这行代码是移动窗口的
					}
					if(0 != (mouse_dec.btn & 0x02))		//按下了右键
					{
						strings[3] = 'R';
					}
					if(0 != (mouse_dec.btn & 0x04))		//按下了中键
					{
						strings[2] = 'C';
					}
					displayStrings_atLayer(layer_bg, 0, 16, COL8_FFFFFF, COL8_008484, strings);	
					/*鼠标的移动*/
					//根据mouse_dec里存储的鼠标信息画出新的鼠标图像
					mCursorX += mouse_dec.x;
					mCursorY += mouse_dec.y;
					//不能让鼠标移出画面
					if(mCursorX < 0)
					{
						mCursorX = 0;
					}
					if(mCursorY < 0)
					{
						mCursorY = 0;
					}
					if(mCursorX > binfo->scrnx - 1)
					{
						mCursorX = binfo->scrnx - 1;
					}
					if(mCursorY > binfo->scrny - 1)
					{
						mCursorY = binfo->scrny - 1;
					}
					sprintf(strings, "(%3d,%3d)", mCursorX, mCursorY);
					displayStrings_atLayer(layer_bg, 40, 32, COL8_FFFFFF, COL8_008484, strings);
					layer_slide(layer_mouse, mCursorX, mCursorY);
				}
			}
			else if(10 == i)						//10秒定时器
			{	
				displayStrings_atLayer(layer_bg, 0, 64, COL8_FFFFFF, COL8_008484, "10[sec]");
				taskswitch4();		//执行任务切换
			}
			else if(3 == i)							//3秒定时器
			{
				displayStrings_atLayer(layer_bg, 0, 80, COL8_FFFFFF, COL8_008484, "3[sec]");
			}
			else if(1 == i || 0 == i)				//光标闪烁定时器
			{
				if(0 != i)				//这个timer的数据为1的时候显示光标
				{
					timer_init(timer3, &fifo_mutual, 0);
					cursor_color = COL8_000000;
				}
				else					//这个timer的数据为0的时候不显示光标
				{
					timer_init(timer3, &fifo_mutual, 1);
					cursor_color = COL8_FFFFFF;
				}
				timer_set(timer3, 50);
				drawRectangle(layer_window->buffer, layer_window->length, cursor_color, cursor_x, 28, 2, 15);
				layer_refresh(layer_window, cursor_x, 28, cursor_x + 8, 44);
			}
		}
	}	
}
Esempio n. 7
0
void HariMain(void)
{
	/*
	**最初的这部分变量没有通过内存管理来分配,它们本身属于操作系统的一部分,存在于bootpack.hrb所在的那块儿内存空间中
	*/
	BOOTINFO *binfo = (BOOTINFO *) ADR_BOOTINFO;
	MOUSE_DECODE mouse_dec;
	MEMMANAGE *memmanage = (MEMMANAGE *)MEMMANAGE_ADDR;
	LAYER_MANAGE *layer_manage;
	LAYER *layer_bg, *layer_mouse, *layer_window, *layer_console;
	TIMER *timer;
	FIFO fifo_mutual;									//缓冲区管理,所有中断公用的
	FIFO keycmd_fifo;									
	TASK *task_a, *task_console;
	int fifobuf[128];									//缓冲区
	int keycmd_buf[32];
	int cursor_x = 8, cursor_color = COL8_FFFFFF;		//分别代表输入字符后的那个闪烁光标的横坐标和颜色
	int mCursorX, mCursorY;				//鼠标光标显示位置的横纵坐标
	int key_to = 0, key_shift = 0, key_leds = (binfo->leds >> 4) & 7, keycmd_wait = -1;			//标志键盘输入到哪个窗口中
	unsigned int memory_total, i;
	char buf_cursor[mCursorWidth * mCursorHeight];
	unsigned char *buf_bg, *buf_window, *buf_console;			//屏幕的大背景会在init_screen的时候画出来,这里只需要一个指向它的指针即可
	unsigned char strings[40];
	mCursorX = binfo->scrnx / 2;			
	mCursorY = (binfo->scrny - 28)/ 2;		//减去下方任务栏的高度
	
	
	/*内存检查*/
	i = memtest(0x00400000, 0xbfffffff) / (1024 * 1024);		//i的单位是MB
	
	/*内存管理*/
	memmanage_init(memmanage);
	memory_total = i * 1024 * 1024;
	memmanage_free_4K(memmanage, 0x00001000, 0x0009e000);
	memmanage_free_4K(memmanage, 0x00400000, memory_total - 0x00400000);
	
	init_fifo(&keycmd_fifo, 32, keycmd_buf, 0);
	/*初始化接收中断的缓冲区*/
	init_fifo(&fifo_mutual, 128, fifobuf, 0);		//初始化mouseFIFO缓冲区,现在还没任务,先指定为0
	/*初始化GDT和IDT表以及PIC板的数据*/
	init_GDTandIDT();				//初始化GDT和IDT表
	init_pic();						//初始化PIC主从板数据,除了IRQ2禁止了全部中断
	io_sti();						//开始接收中断
	/*初始化PIT中断控制*/
	init_PIT();
		/*若要接收鼠标中断需要两个步骤,首先必须使鼠标控制电路(就是键盘控制电路的一部分)有效,然后要使鼠标本身有效*/
	init_keyboard(&fifo_mutual, 256);						//初始化键盘控制器电路
	enable_mouse(&fifo_mutual, 512, &mouse_dec);				//激活鼠标
	/*开放各种中断*/
	io_out8(PIC0_IMR, 0xf8);				//PIC0开发IRQ(11111000),开放IRQ0、IRQ1和IRQ2,定时器、键盘中断和从PIC板
	io_out8(PIC1_IMR, 0xef); 				//PIC1开放IRQ(11101111), 开放鼠标中断
	/*初始化任务切换管理*/
	task_a = task_init(memmanage);		//这个task_a其实代表的就是这些鼠标键盘等的任务
	fifo_mutual.task = task_a;						//为鼠标键盘等的缓冲区指定唤醒任务为task_a
	task_run(task_a, 1, 2);
	/*初始化调色板,为图形界面做准备*/
	init_palette();					//初始化调色板
	/*初始化图层管理,并且初始化鼠标光标和背景的图层*/
	layer_manage = layer_man_init(memmanage, binfo->vram, binfo->scrnx, binfo->scrny);
	
	layer_bg = layer_alloc(layer_manage);			//为背景分配图层
	layer_mouse = layer_alloc(layer_manage);		//为鼠标分配图层
	layer_window = layer_alloc(layer_manage);		//为窗口分配图层
	
	buf_bg = (unsigned char *)memmanage_alloc_4K(memmanage, binfo->scrnx * binfo->scrny);		//为背景图形的内容分配内存
	buf_window = (unsigned char *)memmanage_alloc_4K(memmanage, 160 * 52);						//为窗口图形的内容分配内存
	/*为各个图形的图层内容进行设定*/
	layer_set(layer_bg, buf_bg, binfo->scrnx, binfo->scrny, -1);			
	layer_set(layer_mouse, buf_cursor, 16, 16 ,99);
	layer_set(layer_window, buf_window, 160, 52, -1);
	/*初始化整个桌面背景*/
	init_screen(buf_bg, binfo->scrnx, binfo->scrny);				//这个时候的init_screen不再是直接画出背景,而是在mBg内存地址中填写好背景内容
	layer_slide(layer_bg, 0, 0);					//把背景图层从(0,0)坐标开始画
	/*初始化鼠标图标*/
	init_mouse_cursor(buf_cursor, 99);								//初始化鼠标光标
	layer_slide(layer_mouse, mCursorX, mCursorY);	//现在显示图形不需要再用displayShape函数了,直接用这个图层管理的绘图函数就行
	/*初始化窗口*/
	create_window(buf_window, 160, 52, "task_a", ACTIVE);					//制作窗口
	layer_slide(layer_window, 80, 100);								//在指定位置显示出窗口
	create_textbox(layer_window, 8, 28, 144, 16, COL8_FFFFFF);		//在这个窗口中创建一个输入框
	/*执行一个命令行窗口任务*/
	layer_console = layer_alloc(layer_manage);
	buf_console = (unsigned char *)memmanage_alloc_4K(memmanage, 256 * 165);	
	layer_set(layer_console, buf_console, 256, 165, -1);
	create_window(buf_console, 256, 165, "console", INACTIVE);
	create_textbox(layer_console, 8, 28, 240, 128, COL8_000000);
	task_console = task_alloc();
	task_console->tss.esp = memmanage_alloc_4K(memmanage, 64 * 1024) + 64 * 1024 - 8;
	task_console->tss.eip = (int) &console_task;
	task_console->tss.es = 1 * 8;
	task_console->tss.cs = 2 * 8;
	task_console->tss.ss = 1 * 8;
	task_console->tss.ds = 1 * 8;
	task_console->tss.fs = 1 * 8;
	task_console->tss.gs = 1 * 8;
	*((int *) (task_console->tss.esp + 4)) = (int) layer_console;
	task_run(task_console, 2, 2); /* level=2, priority=2 */
	
	
	layer_slide(layer_console, 32, 60);
	/*设置好各个图层的高度*/
	layer_switch(layer_bg, 0);						//把背景图层调为最底层,高度为0
	layer_switch(layer_console, 1);					//命令行窗口图层调节为第三层,高度为2
	layer_switch(layer_window, 2);					//窗口图层调节为第二层,高度为1
	layer_switch(layer_mouse, 3);					//鼠标图层调为最高层,高度为3
	/*定时器的初始化及其设置*/
	timer = timer_alloc();
	timer_init(timer, &fifo_mutual, 1);
	timer_set(timer, 50);
	/*在屏幕上显示一些内存、鼠标和键盘等信息*/
	sprintf(strings, "Memory has %dMB", i);
	displayStrings_CS(buf_bg, binfo->scrnx, 0, 48, COL8_FFFFFF,strings);
	layer_part_refresh(layer_bg, 0, 48, binfo->scrnx, 80);
	sprintf(strings, "free memory:%dKB",memmanage_total(memmanage) / 1024);
	displayStrings_CS(buf_bg, binfo->scrnx, 120, 48, COL8_FFFFFF,strings);			//用字体显示当前内存容量
	layer_part_refresh(layer_bg, 120, 48, binfo->scrnx, 80);
	
	
	//
	fifo_put(&keycmd_fifo, KEYCMD_LED);
	fifo_put(&keycmd_fifo, key_leds);
	
	for(;;)
	{ 
		if(fifo_status(&keycmd_fifo) > 0 && keycmd_wait < 0)
		{
			keycmd_wait = fifo_get(&keycmd_fifo);
			wait_KBC_sendready();
			io_out8(PORT_KEYDATA, keycmd_wait);
		}
		/*只有在从中断返回的缓冲区中读取数据的时候才需要禁止中断,因为如果这个时候来了中断而没有禁止的话,
		**有可能读脏数据,即把还没有读出的数据的给抹掉或换成别的数据
		*/
		io_cli();		
		if(0 == fifo_status(&fifo_mutual))		//当前没有中断产生
		{
			task_sleep(task_a);	//如果没有需要处理的数据,就自己让自己休眠
			/*上面的那个函数直接就跳转到另一个任务中去了,不过,因为每个人物的默认eflags都是开启中断的,
			**所以不用担心,这个任务还是能被唤醒的,耳环醒后的第一个动作就是为了以防万一先开启中断
			*/
			io_sti();		//万一只有自己在运行的话,则无法睡眠,那么就执行hlt指令好了,这样省电嘛	
		}
		else
		{
			i = fifo_get(&fifo_mutual);
			io_sti();
			//如果是键盘中断的话,需要处理键盘发送来的中断数据
			if((keyboard_offset <= i) && (i <= keyboard_offset + 255))			
			{
				sprintf(strings, "%2X", i - keyboard_offset);
				displayStrings_atLayer(layer_bg, 0, 0, COL8_FFFFFF, COL8_008484, strings);					//由于向背景图层中添加了新东西,需要重绘各个图层
				//判断shift键是否按下
				if(i < 0x80 + keyboard_offset)
				{
					if(0 == key_shift)
					{
						strings[0] = key_table[i - keyboard_offset];
					}
					else
					{
						strings[0] = key_table_shift[i - keyboard_offset];
					}
				}
				else
				{
					strings[0] = 0;
				}
				//判断Caps和Shift键的情况以确定输入大写还是小写字母
				if('A' <= strings[0] && strings[0] <= 'Z')
				{
					//小写字母的情况
					if((0 == (key_leds & 4) && 0 == key_shift) || (0 != (key_leds & 4) && 0 != key_shift))
					{
						strings[0] += 0x20;
					}
				}
				//判断按下的字符是否为一般字符,0对应的字符不处理
				if(strings[0] != 0)				
				{
					//发送给task_a任务的窗口
					if(0 == key_to)
					{
						//所有可打印的字符都需要打印出来
						if(cursor_x < 144)
						{
							strings[1] = 0;
							displayStrings_atLayer(layer_window, cursor_x, 28, COL8_000000, COL8_FFFFFF, strings);
							cursor_x += 8;			//光标的位置随着每一个字符的输入向后移动一个字符宽度的位置即8像素
						}
					}
					//发送给命令行窗口
					else
					{
						fifo_put(&task_console->fifo, strings[0] + 256);
					}
				}
				/*这些都是那些不能打印的特殊按键,它们对应的都是0*/
				//按下了退格键的情况,退格键的号码是0x0e
				if((keyboard_offset + 0x0e == i))				
				{
					if(0 == key_to)
					{
						//只有当前的输入位置上有字符了才能向前删除
						if(cursor_x > 8)
						{
							cursor_x -= 8;
							/*本来退格键应该只填充一个空格就行的,但是这样的话没办法刷新光标所在的那块儿区域了,
							**会留下光标的黑色痕迹,所以直接填充两个空格,刷新之后就不会有痕迹了
							*/
							displayStrings_atLayer(layer_window, cursor_x, 28, COL8_000000, COL8_FFFFFF, "  ");
						}
					}
					else
					{
						fifo_put(&task_console->fifo, 8 + keyboard_offset);
					}
				}
				//按下TAB键的处理情况,切换输入窗口
				if(keyboard_offset + 0x0f == i)					
				{
					if(0 == key_to)			//当前最前面窗口为task_a,则让console窗口成为最前端窗口
					{
						key_to = 1;
						create_titlebar(buf_window, layer_window->length, "task_a", INACTIVE);
						create_titlebar(buf_console, layer_console->length, "console", ACTIVE);
					}
					else					//task_a任务的窗口成为最前端窗口
					{
						key_to = 0;
						create_titlebar(buf_window, layer_window->length, "task_a", ACTIVE);
						create_titlebar(buf_console, layer_console->length, "console", INACTIVE);
					}
					layer_part_refresh(layer_window, 0, 0, layer_window->length, 21);
					layer_part_refresh(layer_console, 0, 0, layer_console->length, 21);
				}
				//左shift ON
				if(0x2a + keyboard_offset == i)
				{
					key_shift |= 1;
				}
				//右shift ON
				if(0x36 + keyboard_offset == i)
				{
					key_shift |= 2;
				}
				//左shift OFF
				if(0xaa + keyboard_offset == i)
				{
					key_shift &= ~1;
				}
				//左shift OFF
				if(0xb6 + keyboard_offset == i)
				{
					key_shift &= ~2;
				}
				//由于光标坐标后退了,为了及时显示它,需要立即重绘光标
				drawRectangle(layer_window->buffer, layer_window->length, cursor_color, cursor_x, 28, 2, 15);
				layer_part_refresh(layer_window, cursor_x, 28, cursor_x + 8, 44);
				/*对各种锁定键的处理*/
				//CapsLock键
				if(i == keyboard_offset + 0x3a)
				{
					key_leds ^= 4;
					fifo_put(&keycmd_fifo, KEYCMD_LED);
					fifo_put(&keycmd_fifo, key_leds);
				}
				//NumLock键
				if(i == keyboard_offset + 0x45)
				{
					key_leds ^= 2;
					fifo_put(&keycmd_fifo, KEYCMD_LED);
					fifo_put(&keycmd_fifo, key_leds);
				}
				//ScrollLock键
				if(i == keyboard_offset + 0x46)
				{
					key_leds ^= 1;
					fifo_put(&keycmd_fifo, KEYCMD_LED);
					fifo_put(&keycmd_fifo, key_leds);
				}
				//键盘成功接收到数据
				if(i == keyboard_offset + 0xfa)
				{
					keycmd_wait = -1;
				}
				//键盘没有成功接收到数据
				if(i == keyboard_offset + 0xfe)
				{
					wait_KBC_sendready();
					io_out8(PORT_KEYDATA, keycmd_wait);
				}
			}
			//如果是鼠标中断的话,需要处理鼠标发送来的中断数据
			else if((mouse_offset <= i) && (i <= mouse_offset + 255))		
			{
				if(0 != mouse_decode(&mouse_dec, i - mouse_offset))		//只有返回值为1的时候才说明成功接收完成一次鼠标的中断
				{
				/*显示鼠标的信息*/
					sprintf(strings,"[lcr %3d,%3d]",mouse_dec.x, mouse_dec.y);
					if(0 != (mouse_dec.btn & 0x01))		//按下了左键
					{
						strings[1] = 'L';
						layer_slide(layer_window, mCursorX - 80, mCursorY -8);		//这行代码是移动窗口的
					}
					if(0 != (mouse_dec.btn & 0x02))		//按下了右键
					{
						strings[3] = 'R';
					}
					if(0 != (mouse_dec.btn & 0x04))		//按下了中键
					{
						strings[2] = 'C';
					}
					displayStrings_atLayer(layer_bg, 0, 16, COL8_FFFFFF, COL8_008484, strings);	
					/*鼠标的移动*/
					//根据mouse_dec里存储的鼠标信息画出新的鼠标图像
					mCursorX += mouse_dec.x;
					mCursorY += mouse_dec.y;
					//不能让鼠标移出画面
					if(mCursorX < 0)
					{
						mCursorX = 0;
					}
					if(mCursorY < 0)
					{
						mCursorY = 0;
					}
					if(mCursorX > binfo->scrnx - 1)
					{
						mCursorX = binfo->scrnx - 1;
					}
					if(mCursorY > binfo->scrny - 1)
					{
						mCursorY = binfo->scrny - 1;
					}
					sprintf(strings, "(%3d,%3d)", mCursorX, mCursorY);
					displayStrings_atLayer(layer_bg, 40, 32, COL8_FFFFFF, COL8_008484, strings);
					layer_slide(layer_mouse, mCursorX, mCursorY);
				}
			}
			//如果是定时器中断的话,需要处理定时器对应的任务
			else if(1 == i || 0 == i)				
			{
				if(0 != i)				//这个timer的数据为1的时候显示光标
				{
					timer_init(timer, &fifo_mutual, 0);
					cursor_color = COL8_000000;
				}
				else					//这个timer的数据为0的时候不显示光标
				{
					timer_init(timer, &fifo_mutual, 1);
					cursor_color = COL8_FFFFFF;
				}
				timer_set(timer, 50);
				drawRectangle(layer_window->buffer, layer_window->length, cursor_color, cursor_x, 28, 2, 15);
				layer_part_refresh(layer_window, cursor_x, 28, cursor_x + 8, 44);
			}
		}
	}	
}
Esempio n. 8
0
void HariMain(void)
{
	/*
	**最初的这部分变量没有通过内存管理来分配,它们本身属于操作系统的一部分,存在于bootpack.hrb所在的那块儿内存空间中
	*/
	BOOTINFO *binfo = (BOOTINFO *) ADR_BOOTINFO;
	MOUSE_DECODE mouse_dec;
	MEMMANAGE *memmanage = (MEMMANAGE *)MEMMANAGE_ADDR;
	LAYER_MANAGE *layer_manage;
	LAYER *layer_bg, *layer_mouse, *layer_window, *layer_windowB[3];
	TIMER *timer;
	FIFO fifo_mutual;									//缓冲区管理,所有中断公用的
	TASK *task_a, *task_b[3];
	int fifobuf[128];									//缓冲区
	int cursor_x = 8, cursor_color = COL8_FFFFFF;		//分别代表输入字符后的那个闪烁光标的横坐标和颜色
	int mCursorX, mCursorY;				//鼠标光标显示位置的横纵坐标
	unsigned int memory_total, i;
	char buf_cursor[mCursorWidth * mCursorHeight];
	unsigned char *buf_bg, *buf_window, *buf_windowB;			//屏幕的大背景会在init_screen的时候画出来,这里只需要一个指向它的指针即可
	unsigned char strings[40];
	mCursorX = binfo->scrnx / 2;			
	mCursorY = (binfo->scrny - 28)/ 2;		//减去下方任务栏的高度
	
	
	/*内存检查*/
	i = memtest(0x00400000, 0xbfffffff) / (1024 * 1024);		//i的单位是MB
	
	/*内存管理*/
	memmanage_init(memmanage);
	memory_total = i * 1024 * 1024;
	memmanage_free_4K(memmanage, 0x00001000, 0x0009e000);
	memmanage_free_4K(memmanage, 0x00400000, memory_total - 0x00400000);
	
	/*初始化接收中断的缓冲区*/
	init_fifo(&fifo_mutual, 128, fifobuf, 0);		//初始化mouseFIFO缓冲区,现在还没任务,先指定为0
	/*初始化GDT和IDT表以及PIC板的数据*/
	init_GDTandIDT();				//初始化GDT和IDT表
	init_pic();						//初始化PIC主从板数据,除了IRQ2禁止了全部中断
	io_sti();						//开始接收中断
	/*初始化PIT中断控制*/
	init_PIT();
		/*若要接收鼠标中断需要两个步骤,首先必须使鼠标控制电路(就是键盘控制电路的一部分)有效,然后要使鼠标本身有效*/
	init_keyboard(&fifo_mutual, 256);						//初始化键盘控制器电路
	enable_mouse(&fifo_mutual, 512, &mouse_dec);				//激活鼠标
	/*开放各种中断*/
	io_out8(PIC0_IMR, 0xf8);				//PIC0开发IRQ(11111000),开放IRQ0、IRQ1和IRQ2,定时器、键盘中断和从PIC板
	io_out8(PIC1_IMR, 0xef); 				//PIC1开放IRQ(11101111), 开放鼠标中断
	/*初始化任务切换管理*/
	task_a = task_init(memmanage);		//这个task_a其实代表的就是这些鼠标键盘等的任务
	fifo_mutual.task = task_a;						//为鼠标键盘等的缓冲区指定唤醒任务为task_a
	task_run(task_a, 1, 2);
	/*初始化调色板,为图形界面做准备*/
	init_palette();					//初始化调色板
	/*初始化图层管理,并且初始化鼠标光标和背景的图层*/
	layer_manage = layer_man_init(memmanage, binfo->vram, binfo->scrnx, binfo->scrny);
	
	layer_bg = layer_alloc(layer_manage);			//为背景分配图层
	layer_mouse = layer_alloc(layer_manage);		//为鼠标分配图层
	layer_window = layer_alloc(layer_manage);		//为窗口分配图层
	
	buf_bg = (unsigned char *)memmanage_alloc_4K(memmanage, binfo->scrnx * binfo->scrny);		//为背景图形的内容分配内存
	buf_window = (unsigned char *)memmanage_alloc_4K(memmanage, 160 * 52);						//为窗口图形的内容分配内存
	/*为各个图形的图层内容进行设定*/
	layer_set(layer_bg, buf_bg, binfo->scrnx, binfo->scrny, -1);			
	layer_set(layer_mouse, buf_cursor, 16, 16 ,99);
	layer_set(layer_window, buf_window, 160, 52, -1);
	/*初始化整个桌面背景*/
	init_screen(buf_bg, binfo->scrnx, binfo->scrny);				//这个时候的init_screen不再是直接画出背景,而是在mBg内存地址中填写好背景内容
	layer_slide(layer_bg, 0, 0);					//把背景图层从(0,0)坐标开始画
	/*初始化鼠标图标*/
	init_mouse_cursor(buf_cursor, 99);								//初始化鼠标光标
	layer_slide(layer_mouse, mCursorX, mCursorY);	//现在显示图形不需要再用displayShape函数了,直接用这个图层管理的绘图函数就行
	/*初始化窗口*/
	create_window(buf_window, 160, 52, "task_a", ACTIVE);					//制作窗口
	layer_slide(layer_window, 80, 72);								//在指定位置显示出窗口
	create_textbox(layer_window, 8, 28, 144, 16, COL8_FFFFFF);		//在这个窗口中创建一个输入框
	/*再画出3个窗口*/
	for (i = 0; i < 3; i++) {
		layer_windowB[i] = layer_alloc(layer_manage);
		buf_windowB = (unsigned char *)memmanage_alloc_4K(memmanage, 144 * 52);
		layer_set(layer_windowB[i], buf_windowB, 144, 52, -1);		//无透明色
		sprintf(strings, "task_b%d", i);
		create_window(buf_windowB, 144, 52, strings, INACTIVE);
		
		task_b[i] = task_alloc();
		task_b[i]->tss.esp = memmanage_alloc_4K(memmanage, 64 * 1024) + 64 * 1024 - 8;
		task_b[i]->tss.eip = (int) &task_b_main;
		task_b[i]->tss.es = 1 * 8;
		task_b[i]->tss.cs = 2 * 8;
		task_b[i]->tss.ss = 1 * 8;
		task_b[i]->tss.ds = 1 * 8;
		task_b[i]->tss.fs = 1 * 8;
		task_b[i]->tss.gs = 1 * 8;
		*((int *) (task_b[i]->tss.esp + 4)) = (int) layer_windowB[i];
		task_run(task_b[i], 2, i + 1); 
	}
	task_run(task_a, 1, 0);
	layer_slide(layer_windowB[0], 240, 72);
	layer_slide(layer_windowB[1], 80, 132);
	layer_slide(layer_windowB[2], 240, 132);
	
	/*设置好各个图层的高度*/
	layer_switch(layer_bg, 0);						//把背景图层调为最底层,高度为0
	layer_switch(layer_windowB[0], 1);					//窗口图层调节为第二层,高度为1
	layer_switch(layer_windowB[1], 2);					//窗口图层调节为第二层,高度为1
	layer_switch(layer_windowB[2], 3);					//窗口图层调节为第二层,高度为1
	layer_switch(layer_window, 4);					//窗口图层调节为第二层,高度为1
	layer_switch(layer_mouse, 5);					//鼠标图层调为最高层,高度为2
	/*定时器的初始化及其设置*/
	timer = timer_alloc();
	timer_init(timer, &fifo_mutual, 1);
	timer_set(timer, 50);
	/*在屏幕上显示一些内存、鼠标和键盘等信息*/
	sprintf(strings, "Memory has %dMB", i);
	displayStrings_CS(buf_bg, binfo->scrnx, 0, 48, COL8_FFFFFF,strings);
	layer_refresh(layer_bg, 0, 48, binfo->scrnx, 80);
	sprintf(strings, "free memory:%dKB",memmanage_total(memmanage) / 1024);
	displayStrings_CS(buf_bg, binfo->scrnx, 120, 48, COL8_FFFFFF,strings);			//用字体显示当前内存容量
	layer_refresh(layer_bg, 120, 48, binfo->scrnx, 80);
	
	
	
	for(;;)
	{
		/*只有在从中断返回的缓冲区中读取数据的时候才需要禁止中断,因为如果这个时候来了中断而没有禁止的话,
		**有可能读脏数据,即把还没有读出的数据的给抹掉或换成别的数据
		*/
		io_cli();		
		if(0 == fifo_status(&fifo_mutual))		//当前没有中断产生
		{
			task_sleep(task_a);	//如果没有需要处理的数据,就自己让自己休眠
			/*上面的那个函数直接就跳转到另一个任务中去了,不过,因为每个人物的默认eflags都是开启中断的,
			**所以不用担心,这个任务还是能被唤醒的,耳环醒后的第一个动作就是为了以防万一先开启中断
			*/
			io_sti();		//万一只有自己在运行的话,则无法睡眠,那么就执行hlt指令好了,这样省电嘛	
		}
		else
		{
			i = fifo_get(&fifo_mutual);
			io_sti();
			if((keyboard_offset <= i) && (i <= keyboard_offset + 255))			//键盘数据
			{
				sprintf(strings, "%2X", i - keyboard_offset);
				displayStrings_atLayer(layer_bg, 0, 0, COL8_FFFFFF, COL8_008484, strings);					//由于向背景图层中添加了新东西,需要重绘各个图层
				if(i < keyboard_offset + 0x54)				//判断按下的字符是否可打印
				{
					if(0 != key_table[i - keyboard_offset] && cursor_x < 144)			//0对应的字符无法打印出来
					{
						strings[0] = key_table[i - keyboard_offset];
						strings[1] = 0;
						displayStrings_atLayer(layer_window, cursor_x, 28, COL8_000000, COL8_FFFFFF, strings);
						cursor_x += 8;			//光标的位置随着每一个字符的输入向后移动一个字符宽度的位置即8像素
					}
					if((keyboard_offset + 0x0e == i) && cursor_x > 8)				//按下了退格键的情况,退格键的号码是0x0e
					{
						cursor_x -= 8;
						/*本来退格键应该只填充一个空格就行的,但是这样的话没办法刷新光标所在的那块儿区域了,
						**会留下光标的黑色痕迹,所以直接填充两个空格,刷新之后就不会有痕迹了
						*/
						displayStrings_atLayer(layer_window, cursor_x, 28, COL8_000000, COL8_FFFFFF, "  ");
					}
					//由于光标坐标后退了,为了及时显示它,需要立即重绘光标
					drawRectangle(layer_window->buffer, layer_window->length, cursor_color, cursor_x, 28, 2, 15);
					layer_refresh(layer_window, cursor_x, 28, cursor_x + 8, 44);
				}
			}
			else if((mouse_offset <= i) && (i <= mouse_offset + 255))		//鼠标数据
			{
				if(0 != mouse_decode(&mouse_dec, i - mouse_offset))		//只有返回值为1的时候才说明成功接收完成一次鼠标的中断
				{
				/*显示鼠标的信息*/
					sprintf(strings,"[lcr %3d,%3d]",mouse_dec.x, mouse_dec.y);
					if(0 != (mouse_dec.btn & 0x01))		//按下了左键
					{
						strings[1] = 'L';
						layer_slide(layer_window, mCursorX - 80, mCursorY -8);		//这行代码是移动窗口的
					}
					if(0 != (mouse_dec.btn & 0x02))		//按下了右键
					{
						strings[3] = 'R';
					}
					if(0 != (mouse_dec.btn & 0x04))		//按下了中键
					{
						strings[2] = 'C';
					}
					displayStrings_atLayer(layer_bg, 0, 16, COL8_FFFFFF, COL8_008484, strings);	
					/*鼠标的移动*/
					//根据mouse_dec里存储的鼠标信息画出新的鼠标图像
					mCursorX += mouse_dec.x;
					mCursorY += mouse_dec.y;
					//不能让鼠标移出画面
					if(mCursorX < 0)
					{
						mCursorX = 0;
					}
					if(mCursorY < 0)
					{
						mCursorY = 0;
					}
					if(mCursorX > binfo->scrnx - 1)
					{
						mCursorX = binfo->scrnx - 1;
					}
					if(mCursorY > binfo->scrny - 1)
					{
						mCursorY = binfo->scrny - 1;
					}
					sprintf(strings, "(%3d,%3d)", mCursorX, mCursorY);
					displayStrings_atLayer(layer_bg, 40, 32, COL8_FFFFFF, COL8_008484, strings);
					layer_slide(layer_mouse, mCursorX, mCursorY);
				}
			}
			else if(1 == i || 0 == i)				//光标闪烁定时器
			{
				if(0 != i)				//这个timer的数据为1的时候显示光标
				{
					timer_init(timer, &fifo_mutual, 0);
					cursor_color = COL8_000000;
				}
				else					//这个timer的数据为0的时候不显示光标
				{
					timer_init(timer, &fifo_mutual, 1);
					cursor_color = COL8_FFFFFF;
				}
				timer_set(timer, 50);
				drawRectangle(layer_window->buffer, layer_window->length, cursor_color, cursor_x, 28, 2, 15);
				layer_refresh(layer_window, cursor_x, 28, cursor_x + 8, 44);
			}
		}
	}	
}