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

📄 video.c

📁 一个类linux的dos下开发的操作系统.
💻 C
字号:
/*****************************************************************************
TEXT VIDEO

EXPORTS:
extern console_t _vc[MAX_VC];
extern unsigned short _num_vc;
extern volatile console_t *_curr_vc;

void blink(void);
void putch(console_t *con, unsigned char c);
void select_vc(unsigned which_con);
void init_console(void);
*****************************************************************************/
#include <string.h> /* movedata() */
#include <stdio.h> /* sprintf() */
#include <krnl.h> /* console_t */
#include <x86.h> /* inportb(), outportb(), critb(), crite() */

#define	VGA_MISC_READ	0x3CC
#define	VGA_GC_INDEX	0x3CE
#define	VGA_GC_DATA	0x3CF

console_t _vc[MAX_VC];
unsigned short _num_vc;
volatile console_t *_curr_vc;

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

	blank = 0x20 | ((unsigned short)con->attrib << 8);
/* scroll up */
	if(con->csr_y >= _vc_height)
	{
		temp = con->csr_y - _vc_height + 1;
/* use farptr access to framebuffer so it works with both
paging and segmentation */
		movedata(LINEAR_DATA_SEL, con->fb_adr + temp * _vc_width * 2,
			LINEAR_DATA_SEL, con->fb_adr,
			(_vc_height - temp) * _vc_width * 2);
/* blank the bottom line of the screen */
		fmemsetw(LINEAR_DATA_SEL,
			con->fb_adr + (_vc_height - temp) * _vc_width * 2,
			blank, _vc_width);
		con->csr_y = _vc_height - 1;
	}
}
/*****************************************************************************
*****************************************************************************/
static void set_attrib(unsigned char att, console_t *con)
{
	static const char ansi_to_vga[] =
	{
		0, 4, 2, 6, 1, 5, 3, 7
	};
	unsigned char 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(console_t *con)
{
	unsigned long temp;
	unsigned short off;
	unsigned flags;

	temp = (con->csr_y * _vc_width + con->csr_x) * 2;
	temp = con->fb_adr + temp - _vga_fb_adr;
	off = temp;
	flags = critb();
/* extra shift because even/odd text mode uses word clocking */
	outportb(_crtc_io_adr + 0, 14);
	outportb(_crtc_io_adr + 1, off >> 9);
	outportb(_crtc_io_adr + 0, 15);
	outportb(_crtc_io_adr + 1, off >> 1);
	crite(flags);
}
/*****************************************************************************
*****************************************************************************/
void select_vc(unsigned which_con)
{
	unsigned long temp;
	unsigned short off;
	unsigned flags;

	if(which_con >= _num_vc)
		return;
	_curr_vc = _vc + which_con;
	temp = (unsigned long)_curr_vc->fb_adr - _vga_fb_adr;
	off = temp;
	flags = critb();
/* extra shift because even/odd text mode uses word clocking */
	outportb(_crtc_io_adr + 0, 12);
	outportb(_crtc_io_adr + 1, off >> 9);
	outportb(_crtc_io_adr + 0, 13);
	outportb(_crtc_io_adr + 1, off >> 1);
	move_csr(_curr_vc);
	crite(flags);
}
/*****************************************************************************
*****************************************************************************/
/* don't want to use ctype.h */
#define	ISDIGIT(X)	(((X) >= '0') && ((X) <= '9'))

void putch(console_t *con, unsigned char c)
{
	unsigned short att;

	att = (unsigned short)con->attrib << 8;
/* 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)
			{
				fmemsetw(LINEAR_DATA_SEL, con->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->esc1, con);
		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->esc1, con);
			set_attrib(con->esc2, con);
		}
		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->esc1, con);
			set_attrib(con->esc2, con);
			set_attrib(con->esc3, con);
		}
		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 long where;

		where = con->fb_adr + 2 *
			(con->csr_y * _vc_width + con->csr_x);
		pokew(LINEAR_DATA_SEL, 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(con);
}
/*****************************************************************************
*****************************************************************************/
static void puts(console_t *con, char *str)
{
	while(*str != '\0')
	{
		putch(con, *str);
		str++;
	}
}
/*****************************************************************************
*****************************************************************************/
DISCARDABLE_CODE(void init_console(void))
{
	unsigned temp, v_disp, char_ht;

/* code to detect mono/color emulation
cobbled from info in Finn Thoegersen's VGADOC4
Mono is UNTESTED. */
	if((inportb(VGA_MISC_READ) & 0x01) != 0)
	{
		_crtc_io_adr = 0x3D4;	/* color */
		_vga_fb_adr = 0xB8000;
	}
	else
	{
		_crtc_io_adr = 0x3B4;	/* mono */
		_vga_fb_adr = 0xB0000;
	}
/* figure out width and height of current display:
vertical scan lines displayed */
	outportb(_crtc_io_adr, 0x12);
	v_disp = inportb(_crtc_io_adr + 1);
/* pull in the 9th and 10th bits from the dread overflow register */
	outportb(_crtc_io_adr, 0x07);
	temp = inportb(_crtc_io_adr + 1);
	if((temp & 0x02) != 0)
		v_disp |= 0x100;
	if((temp & 0x40) != 0)
		v_disp |= 0x200;
/* the value in the register is actually vertical displayed - 1, so fix it */
	v_disp++;
/* scan lines/char */
	outportb(_crtc_io_adr, 0x09);
	char_ht = (inportb(_crtc_io_adr + 1) & 0x1F) + 1;
/* vertical resolution in characters is the quotient.
If the monochrome/color detection is faulty, char_ht may be 0,
and the divide-by-zero will cause a triple fault. */
	_vc_height = v_disp / char_ht;
/* horizontal resolution in characters */
	outportb(_crtc_io_adr, 0x01);
	_vc_width = inportb(_crtc_io_adr + 1) + 1;
#if 1
/* move text framebuffer to A000:0000
This does not work with Bochs */
	outportb(VGA_GC_INDEX, 0x06);
	outportb(VGA_GC_DATA, 0x06);
	_vga_fb_adr = 0xA0000;
/* figure out how many VCs we can have with 64K of display memory
Note: integer divides here */
	_num_vc = 65536L / (_vc_width * _vc_height * 2);
#else
/* leave text framebuffer at B800:0000 or B000:0000;
figure out how many VCs we can have with 32K of display memory */
	_num_vc = 32768L / (_vc_width * _vc_height * 2);
#endif
	if(_num_vc > MAX_VC)
		_num_vc = MAX_VC;
/* init VCs (different foreground color for each) */
	for(temp = 0; temp < _num_vc; temp++)
	{char buf[64];

		_curr_vc = _vc + temp;
		_curr_vc->attrib = temp + 1;
		_curr_vc->fb_adr = _vga_fb_adr +
			_vc_width * _vc_height * 2 * temp;
/* ESC[2J is an ANSI-like escape to clear the screen */
sprintf(buf, "\x1B[2J""this is VC#%u (of 0-%u)\n", temp, _num_vc - 1);
puts(_curr_vc, buf); }
//		puts("\x1B[2J"); }

	select_vc(0);
}

⌨️ 快捷键说明

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