⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video.c

📁 自己从头开始开发操作系统的几个实例
💻 C
字号:
/*============================================================================
TEXT VIDEO ROUTINES

EXPORTS:
void blink(void);
void select_vc(unsigned which_con);
void putch(unsigned char c);
void init_video(void);
============================================================================*/
#include <string.h> /* memcpy(), memsetw() */
#include <ctype.h> /* isdigit() */
#include <x86.h> /* outportb(), inportb() */
#include "_krnl.h" /* MAX_VC, console_t */

/* IMPORTS
from MAIN.C */
void kprintf(const char *fmt, ...);

#define	VGA_MISC_READ	0x3CC

console_t _vc[MAX_VC];
static	unsigned short _num_vcs;
static	console_t *_curr_vc;

static unsigned short *_vga_fb_adr;
static unsigned _crtc_io_adr, _vc_width, _vc_height;
/*****************************************************************************
*****************************************************************************/
void blink(void)
{
	(*(unsigned char *)_vga_fb_adr)++;
}
/*****************************************************************************
*****************************************************************************/
static void scroll(console_t *con)
{
	unsigned short *fb_adr;
	unsigned blank, temp;

	blank = 0x20 | ((unsigned)con->attrib << 8);
	fb_adr = con->fb_adr;
/* scroll up */
	if(con->csr_y >= _vc_height)
	{
		temp = con->csr_y - _vc_height + 1;
		memcpy(fb_adr, fb_adr + temp * _vc_width,
			(_vc_height - temp) * _vc_width * 2);
/* blank the bottom line of the screen */
		memsetw(fb_adr + (_vc_height - temp) * _vc_width,
			blank, _vc_width);
		con->csr_y = _vc_height - 1;
	}
}
/*****************************************************************************
*****************************************************************************/
static void set_attrib(console_t *con, unsigned att)
{
	static const unsigned ansi_to_vga[] =
	{
		0, 4, 2, 6, 1, 5, 3, 7
	};
/**/
	unsigned new_att;

	new_att = con->attrib;
	if(att == 0)
		new_att &= ~0x08;		/* bold off */
	else if(att == 1)
		new_att |= 0x08;		/* bold on */
	else if(att >= 30 && att <= 37)
	{
		att = ansi_to_vga[att - 30];
		new_att = (new_att & ~0x07) | att;/* fg color */
	}
	else if(att >= 40 && att <= 47)
	{
		att = ansi_to_vga[att - 40] << 4;
		new_att = (new_att & ~0x70) | att;/* bg color */
	}
	con->attrib = new_att;
}
/*****************************************************************************
*****************************************************************************/
static void move_csr(void)
{
	unsigned short temp;

	temp = (_curr_vc->csr_y * _vc_width + _curr_vc->csr_x) +
		(_curr_vc->fb_adr - _vga_fb_adr);
	outportb(_crtc_io_adr + 0, 14);
	outportb(_crtc_io_adr + 1, temp >> 8);
	outportb(_crtc_io_adr + 0, 15);
	outportb(_crtc_io_adr + 1, temp);
}
/*****************************************************************************
*****************************************************************************/
void select_vc(unsigned which_vc)
{
	unsigned i;

	if(which_vc >= _num_vcs)
		return;
	_curr_vc = _vc + which_vc;
	i = _curr_vc->fb_adr - _vga_fb_adr;
	outportb(_crtc_io_adr + 0, 12);
	outportb(_crtc_io_adr + 1, i >> 8);
	outportb(_crtc_io_adr + 0, 13);
	outportb(_crtc_io_adr + 1, i);
/* oops, forgot this: */
	move_csr();
}
/*****************************************************************************
*****************************************************************************/
static void putch_help(console_t *con, unsigned c)
{
	unsigned short *fb_adr;
	unsigned att;

	att = (unsigned)con->attrib << 8;
	fb_adr = con->fb_adr;
/* state machine to handle the escape sequences
ESC */
	if(con->esc == 1)
	{
		if(c == '[')
		{
			con->esc++;
			con->esc1 = 0;
			return;
		}
		/* else fall-through: zero esc and print c */
	}
/* ESC[ */
	else if(con->esc == 2)
	{
		if(isdigit(c))
		{
			con->esc1 = con->esc1 * 10 + c - '0';
			return;
		}
		else if(c == ';')
		{
			con->esc++;
			con->esc2 = 0;
			return;
		}
/* ESC[2J -- clear screen */
		else if(c == 'J')
		{
			if(con->esc1 == 2)
			{
				memsetw(fb_adr, ' ' | att,
					_vc_height * _vc_width);
				con->csr_x = con->csr_y = 0;
			}
		}
/* ESC[num1m -- set attribute num1 */
		else if(c == 'm')
			set_attrib(con, con->esc1);
		con->esc = 0;	/* anything else with one numeric arg */
		return;
	}
/* ESC[num1; */
	else if(con->esc == 3)
	{
		if(isdigit(c))
		{
			con->esc2 = con->esc2 * 10 + c - '0';
			return;
		}
		else if(c == ';')
		{
			con->esc++;	/* ESC[num1;num2; */
			con->esc3 = 0;
			return;
		}
/* ESC[num1;num2H -- move cursor to num1,num2 */
		else if(c == 'H')
		{
			if(con->esc2 < _vc_width)
				con->csr_x = con->esc2;
			if(con->esc1 < _vc_height)
				con->csr_y = con->esc1;
		}
/* ESC[num1;num2m -- set attributes num1,num2 */
		else if(c == 'm')
		{
			set_attrib(con, con->esc1);
			set_attrib(con, con->esc2);
		}
		con->esc = 0;
		return;
	}
/* ESC[num1;num2;num3 */
	else if(con->esc == 4)
	{
		if(isdigit(c))
		{
			con->esc3 = con->esc3 * 10 + c - '0';
			return;
		}
/* ESC[num1;num2;num3m -- set attributes num1,num2,num3 */
		else if(c == 'm')
		{
			set_attrib(con, con->esc1);
			set_attrib(con, con->esc2);
			set_attrib(con, con->esc3);
		}
		con->esc = 0;
		return;
	}
	con->esc = 0;

/* escape character */
	if(c == 0x1B)
	{
		con->esc = 1;
		return;
	}
/* backspace */
	if(c == 0x08)
	{
		if(con->csr_x != 0)
			con->csr_x--;
	}
/* tab */
	else if(c == 0x09)
		con->csr_x = (con->csr_x + 8) & ~(8 - 1);
/* carriage return */
	else if(c == '\r')	/* 0x0D */
		con->csr_x = 0;
/* line feed */
//	else if(c == '\n')	/* 0x0A */
//		con->csr_y++;
/* CR/LF */
	else if(c == '\n')	/* ### - 0x0A again */
	{
		con->csr_x = 0;
		con->csr_y++;
	}
/* printable ASCII */
	else if(c >= ' ')
	{
		unsigned short *where;

		where = fb_adr + (con->csr_y * _vc_width + con->csr_x);
		*where = (c | att);
		con->csr_x++;
	}
	if(con->csr_x >= _vc_width)
	{
		con->csr_x = 0;
		con->csr_y++;
	}
	scroll(con);
/* move cursor only if the VC we're writing is the current VC */
	if(_curr_vc == con)
		move_csr();
}
/*****************************************************************************
*****************************************************************************/
void putch(unsigned c)
{
/* all kernel messages to VC #0 */
//	putch_help(_vc + 0, c);
/* all kernel messages to current VC */
	putch_help(_curr_vc, c);
}
/*****************************************************************************
*****************************************************************************/
void init_video(void)
{
	unsigned i;

/* check for monochrome or color VGA emulation */
	if((inportb(VGA_MISC_READ) & 0x01) != 0)
	{
		_vga_fb_adr = (unsigned short *)0xB8000L;
		_crtc_io_adr = 0x3D4;
	}
	else
	{
		_vga_fb_adr = (unsigned short *)0xB0000L;
		_crtc_io_adr = 0x3B4;
	}
/* read current screen size from BIOS data segment (addresses 400-4FF) */
	_vc_width = *(unsigned short *)0x44A;
	_vc_height = *(unsigned char *)0x484 + 1;
/* figure out how many VCs we can have with 32K of display memory.
Use INTEGER division to round down. */
	_num_vcs = 32768L / (_vc_width * _vc_height * 2);
	if(_num_vcs > MAX_VC)
		_num_vcs = MAX_VC;
/* init VCs, with a different foreground color for each */
	for(i = 0; i < _num_vcs; i++)
	{
		_curr_vc = _vc + i;
		_curr_vc->attrib = i + 1;
		_curr_vc->fb_adr = _vga_fb_adr +
			_vc_width * _vc_height * i;
/* ESC[2J clears the screen */
		kprintf("\x1B[2J  this is VC#%u (of 0-%u)\n",
			i, _num_vcs - 1);
	}
	select_vc(0);
	kprintf("init_video: %s emulation, %u x %u, framebuffer at "
		"0x%lX\n", (_crtc_io_adr == 0x3D4) ? "color" : "mono",
		_vc_width, _vc_height, _vga_fb_adr);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -