SnailOS printf 和屏显函数重写

 

//在打印函数中,字符串常量定义为(强制类型转换)无符号常字符指针似乎是必须的
//但不知道原理为何!
//在变量转化为字符串的函数中,如果/为奇数个就很可能会出现显示乱码的问题。
//看来是个棘手的问题,还是等到将来再解决吧!
//drawfont()如果在指定了行号的情况下,是否能够对全部的东西正常显示,我还
//是没有把握,不过基本正常了,倒是这个程序调试了很长时间。

extern "C" {
	typedef unsigned int _u_i;
	struct Draw{
		static char buf[0x1000];
		static void fillbox(_u_i* fb, _u_i xsize, int color,
		int x0, int y0, int x1, int y1);
		static void drawfontline(int color, int x, int y,
								const unsigned char *str);
		static void drawfont(int color, int x, int y,
								const unsigned char *str);
		static void myprintf(char* buf, const char* s, ...);
//	private:
		static void makeascii(_u_i* fb, _u_i xsize, int color,
								int x, int y, char *font);
		static void makegb2312(_u_i* fb, _u_i xsize, int color,
								int x, int y, short *font);
		static int mydiv(int* n,unsigned int b);
		static void myitoa(char* buf, int n, unsigned int b);
		static int mystrlen(const unsigned char* s);
		static void mystrcpy(char* d, const unsigned char* s, int n);
		static int ascnum(const unsigned char* s);
		static int sign;
		static char mybuf[0x1000];
		static const unsigned int MaxLines;
		static unsigned int Lines;
	};
	int mymain(int eax, int ebx);
}

char Draw::buf[] = {0,};
int Draw::sign = 0;
char Draw::mybuf[] = {0,};
const unsigned int MaxLines = 48;
unsigned int Lines = 0;

void Draw::fillbox(_u_i* fb, _u_i xsize, int color,
			int x0, int y0, int x1, int y1) {
	int x, y;
	for (y = 0; y <= y1 - y0; y++) {
		for (x = 0; x <= x1 - x0; x++) {
			fb[x0 + x + (y0 + y) * xsize] = color;
		}
	}
}

void Draw::makeascii (_u_i* fb, _u_i xsize, int color,
			int x, int y, char *font) {
	char d;
	_u_i* p;
	int i;
	for (i = 0; i < 16; i++){
		p = (_u_i*)fb + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) {p[0] = color;}
		if ((d & 0x40) != 0) {p[1] = color;}
		if ((d & 0x20) != 0) {p[2] = color;}
		if ((d & 0x10) != 0) {p[3] = color;}
		if ((d & 0x08) != 0) {p[4] = color;}
		if ((d & 0x04) != 0) {p[5] = color;}
		if ((d & 0x02) != 0) {p[6] = color;}
		if ((d & 0x01) != 0) {p[7] = color;}
	}
}

void Draw::makegb2312 (_u_i* fb, _u_i xsize, int color,
			int x, int y, short *font) {
	short d;
	_u_i* p;
	int i;
	for (i = 0; i < 16; i++){
		p = (_u_i*)fb + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) {p[0] = color;}
		if ((d & 0x40) != 0) {p[1] = color;}
		if ((d & 0x20) != 0) {p[2] = color;}
		if ((d & 0x10) != 0) {p[3] = color;}
		if ((d & 0x08) != 0) {p[4] = color;}
		if ((d & 0x04) != 0) {p[5] = color;}
		if ((d & 0x02) != 0) {p[6] = color;}
		if ((d & 0x01) != 0) {p[7] = color;}
		if ((d & 0x8000) != 0) {p[8] = color;}
		if ((d & 0x4000) != 0) {p[9] = color;}
		if ((d & 0x2000) != 0) {p[10] = color;}
		if ((d & 0x1000) != 0) {p[11] = color;}
		if ((d & 0x800) != 0) {p[12] = color;}
		if ((d & 0x400) != 0) {p[13] = color;}
		if ((d & 0x200) != 0) {p[14] = color;}
		if ((d & 0x100) != 0) {p[15] = color;}
	}
}

void Draw::drawfontline(int color, int x, int y, const unsigned char *str) {
	extern short font[0x8000];
	extern char myfont[0x1000];
	int i = 0, j = 0;
	unsigned char a, b;
	unsigned int offset;
	while (str[i] != 0) {
		if (str[i] < 0x80) {
			a = str[i];
			Draw::makeascii((_u_i*)0xe0000000, 1024, color, x + j, y, myfont + a * 16);
			if (str[i + 1] == 0)
				break;
			i++;
			j += 8;
		} else {	
			a = str[i] - 0xa0;
			b = str[i + 1] - 0xa0;
			offset = ((a - 1) * 94 + (b - 1)) * 16;
			Draw::makegb2312((_u_i*)0xe0000000, 1024, color, x + j , y, font + offset);
			i += 2;
			j += 16;
		}
	}
}

void Draw::drawfont(int color, int x, int y, const unsigned char *str){
	char tmp[130];
	const unsigned char* tmp0;
	int i = 0;
	while(1){
		tmp0 = str;
		mystrcpy(tmp, tmp0, 126);
		if(mystrlen((const unsigned char*)tmp) < 126){
			drawfontline(0x0, x, y + i, (const unsigned char*)tmp);
			break;	
		}
		str += 126;
		*(tmp + 126) = '\0';
		if(!((*str - 1) < 0x80 || *str < 0x80)){
			if(ascnum((const unsigned char*)tmp) % 2 != 0){
				str--;
				*(tmp + 125) = '\0';
			}
		}
		drawfontline(0x0, x, y + i, (const unsigned char*)tmp);
		i += 16;
	}
}

int Draw::mystrlen(const unsigned char* s){
	int len = 0;
	while(*s++){
		len++;
	}
	return len;
}

int Draw::ascnum(const unsigned char* s){
	int num = 0;
	while(*s){
		if(*s++ < 0x80)
			num++;
	}
	return num;
}


void Draw::mystrcpy(char* d, const unsigned char* s, int n){
	for(int i = 0; i < n; i++){
		*d++ = *s++;
	}
}

int Draw::mydiv(int* n, unsigned int b){
	int res;
	res = *n % b;
	*n /= b;
	return res;
}

void Draw::myitoa(char* buf, int n, unsigned int b){
	char s[] = "0123456789abcdef";
	char tmpbuf[0xff];
	char* tmp = tmpbuf;
	if(n < 0){
		sign = -1;
		n = -n;
	}
	while(n){
		*tmp++ = s[Draw::mydiv(&n, b)];
	}
	*tmp = '\0';
	for(int i = mystrlen((const unsigned char*)tmpbuf) - 1; i >= 0 ; i--) {
		*buf++ = tmpbuf[i];
	}
	*buf = '\0';
}

void Draw::myprintf(char* buf, const char* s, ...){
	void** varg = (void**)&s;
	varg++;
	char* tmp;
	int n;
	while(*s){
		if('%' != *s){
			if('\\' != *s){
				*buf++ = *s++;
			} else{
				s++;
				switch(*s){
				case '\\':
					*buf++ = '\\';
					break;
				case 'n':
				case 't':
				case 'b':
					s++;
					break;
				}
			}		
		} else {
			s++;
			switch(*s){
			case '%':
				s++;
				*buf++ = '%';
				break;
			case 's':
				s++;
				tmp = (char*)*varg++;
				while(*tmp){
					*buf++ = *tmp++;
				}
				break;
			case 'c':
				s++;
				tmp = (char*)varg++;
				*buf++ = *tmp;
				break;
			case 'd':
			case 'i':
				s++;
				n = (int)*varg++;
				myitoa(Draw::mybuf, n, 10);
				tmp = Draw::mybuf;
				if(-1 == sign)
					*buf++ = '-';
				while(*tmp){
					*buf++ = *tmp++;
				}
				break;
			case 'x':
			case 'X':
				s++;
				n = (int)*varg++;
				myitoa(Draw::mybuf, n, 16);
				tmp = Draw::mybuf;
				*buf++ = '0';
				*buf++ = 'x';
				while(*tmp){
					*buf++ = *tmp++;
				}
				break;
			case 'b':
			case 'B':
				s++;
				n = (int)*varg++;
				myitoa(Draw::mybuf, n, 2);
				tmp = Draw::mybuf;
				while(*tmp){
					*buf++ = *tmp++;
				}
				*buf++ = 'b';
				break;
			default:
				break;
			}
		}
	}
	*buf = '\0';
	return;
}

int mymain(int eax, int ebx) {
	Draw::fillbox((_u_i*)0xe0000000, 1024, 0x1e90ff, 0, 0, 1024 - 1, 768 - 1);
//	Draw::drawfontline(0xffffffff, 0, 0, (const unsigned char*)"我爱你!SnailOS!");
//	Draw::drawfontline(0x00ff0000, 160, 319, (const unsigned char*)"庆幸的是我们的开发环境很好,能够让我们即是看到效果,开心^_^");
//	int i = 253;
	char str[] = "Welcome to SnailOS! 测试变量。";
	char str0[] = "这 一 次    需要 测试一下如果一行文本超过了行的长度,我们的显示程序会是什么样的\\\\情况,这样我们就能在全屏幕上上显示我们想要的";
	char str1[] = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567";
//	Draw::drawfontline(0x0000ff00, 0, 15, (const unsigned char*)Draw::buf);
//	Draw::myprintf(Draw::buf, "%s", str1);
//	Draw::drawfontline(0x00000000, 0, 31, (const unsigned char*)Draw::buf);
//	Draw::myprintf(Draw::buf, "%d\\n", 1024 / 16);
//	Draw::drawfontline(0x00000000, 0, 47, (const unsigned char*)Draw::buf);
//	Draw::myprintf(Draw::buf, "%d\\n", 13 * 10 - 2);
//	Draw::drawfontline(0x00000000, 0, 59, (const unsigned char*)Draw::buf);
	
	Draw::myprintf(Draw::buf, "二进制数:%b%s %s%d %s%s%%%s",0xff, str, str0, 0x32, str0, str1, str0);
	Draw::drawfont(0x00000000, 0, 0, (const unsigned char*)Draw::buf);

	while(1) {
		asm("hlt"::);
	}
}
发布了159 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_39410618/article/details/89890243