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

📄 vga.c

📁 nucleus_arm.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <support.h>
#include <video/graphic.h>
#include <video/modes.h>
#include <video/fonts.h>
#include <video/palette.h>
#include <drivers/mem/mem.h>
#include <drivers/timer.h>

static unsigned char * font_buf = g_8x8_font;
static unsigned int vga_card = GR_VGA;
static unsigned int cursor_position = 0;
static unsigned int current_mode = 0x03;	// text mode

#define pokeb(A,V)		( *(char*) ( A ) = ( V ) ) 
#define pokew(A,V)		( *(short*) ( A ) = ( V ) )  

static struct Screen
{
	unsigned int x, y;
	unsigned color_fg, color_bg;
} screen = { 1, 1, CL_WHITE, CL_BLACK };

static unsigned get_fb_seg(void)
{
	unsigned seg;

	outportb(GRA_I, 6);
	seg = inportb(GRA_D);
	seg >>= 2;
	seg &= 3;
	switch(seg)
	{
		case 0:
		case 1:	seg = 0xA0000;	break;
		case 2:	seg = 0xB0000;	break;
		case 3:	seg = 0xB8000;	break;
	}
	return seg;
}

#define	_vmemwr(A,S,N)	_dosmemputb(S, N, A)

static void vmemwr(unsigned dst_off, unsigned char *src, unsigned count)
{
	_vmemwr(get_fb_seg() + dst_off, src, count);
}

static void vga_putpixel(unsigned int x, unsigned int y, unsigned color);
static void vga_gotoxy ( unsigned int x, unsigned int y );
static unsigned int vga_wherex ( void );
static unsigned int vga_wherey ( void );
static void vga_scroll(long lines);

static unsigned int getcuraddr ( void )
{
	byte b1, b2 ;	

	outportb ( CRT_I, 14 ) ;
	b1 = inportb ( CRT_D ) ;
	outportb ( CRT_I, 15 ) ;
	b2 = inportb ( CRT_D ) ;
	
	return ( ((unsigned int)b1 << 8) | ((unsigned int)b2) ) ;
}

static void setcuraddr ( unsigned int addr )
{
	outportb ( CRT_I, 14 ) ;
	outportb ( CRT_D, (addr & 0x0FF00) >> 8 ) ;
	outportb ( CRT_I, 15 ) ;
	outportb ( CRT_D, addr & 0x0FF ) ;
	
	cursor_position = addr * 2;
}

static void text_show_cursor(void)
{
	outportb(CRT_I, 0x0A);
	outportb(CRT_D, inportb(CRT_D) | 0x20);
}

static void text_hide_cursor(void)
{
	outportb(CRT_I, 0x0A);
	outportb(CRT_D, inportb(CRT_D) & ~0x20);
}

static void vga_putch(unsigned int xx, unsigned int yy, unsigned char data)
{
	unsigned int x, y, i, j;
	unsigned char ch;
	
	vga_gotoxy(xx, yy);
	x = vga_wherex();
	y = vga_wherey();
	if (bios_modes[current_mode].graphic)
	{
		if (data == '\r')
		{
			vga_gotoxy (1, y);
			return;
		}
		if (data == '\n')
		{
			x = 1;
			y++;
			if (y > bios_modes[current_mode].max_y / bios_modes[current_mode].font_height)
			{
				vga_scroll(1);
				y = bios_modes[current_mode].max_y / bios_modes[current_mode].font_height;
			}
			vga_gotoxy(x, y);
		}
		else
		{
			for (i=0; i < bios_modes[current_mode].font_height; i++)
			{
				ch = font_buf[data * bios_modes[current_mode].font_height + i];

				for (j=0; j < bios_modes[current_mode].font_width; j++)	
				{
					if (ch & 0x80)
						vga_putpixel(screen.x + j, screen.y + i, screen.color_fg);
					else
						vga_putpixel(screen.x + j, screen.y + i, screen.color_bg);
					ch <<= 1;
				}
			}
			x++;
			if (x > bios_modes[current_mode].max_x / bios_modes[current_mode].font_width)
			{				
				x = 1;
				y++;
		
				if (y > bios_modes[current_mode].max_y / bios_modes[current_mode].font_height)
				{
					//vga_scroll(1);
					y = bios_modes[current_mode].max_y / bios_modes[current_mode].font_height;
				}
			}
			vga_gotoxy(x, y);
		}
	}
	else
	{
		if (data == '\r')
		{
			vga_gotoxy (1, y);
			return;
		}

		if (data == '\n')
		{
			x = 1;		y++;
			if (y > bios_modes[current_mode].max_y)
			{
				vga_scroll(1);
				y = bios_modes[current_mode].max_y;
			}
			vga_gotoxy(x, y);
		}
		else
		{				
			bios_modes[current_mode].video_ptr[cursor_position] = data;
			bios_modes[current_mode].video_ptr[cursor_position + 1] = screen.color_fg;
			x++;
			
			if (x > bios_modes[current_mode].max_x)
			{
				x = 1;		y++;			
				if (y > bios_modes[current_mode].max_y)
				{
					vga_scroll(1);
					y = bios_modes[current_mode].max_y;
				}
			}
			vga_gotoxy(x, y);
		}
	}
}

static unsigned int vga_wherex ( void )
{
	if (bios_modes[current_mode].graphic)
	{
		return (screen.x / bios_modes[current_mode].font_width) + 1;
	}
	return ( getcuraddr() % bios_modes[current_mode].max_x ) + 1;
}

static unsigned int vga_wherey ( void )
{
	if (bios_modes[current_mode].graphic)
	{
		return (screen.y / bios_modes[current_mode].font_height) + 1;
	}
	return ( getcuraddr() / bios_modes[current_mode].max_x ) + 1;
}

static unsigned int vga_max_x(void)
{
	return bios_modes[current_mode].max_x;
}
	
static unsigned int vga_max_y(void)
{
	return bios_modes[current_mode].max_y;
}

static unsigned long vga_max_col(void)
{
	return bios_modes[current_mode].max_cols;
}

static void vga_gotoxy ( unsigned int x, unsigned int y )
{	
	if (x > 0 && x <= bios_modes[current_mode].max_x && y > 0 && y <= bios_modes[current_mode].max_y)
	{
		x--;	y--;
		if (!bios_modes[current_mode].graphic)
		{
			screen.x = x;
			screen.y = y;
			setcuraddr ((y * bios_modes[current_mode].max_x) + x);
		}
		else
		{
			screen.x = x * bios_modes[current_mode].font_width;
			screen.y = y * bios_modes[current_mode].font_height;
		}
	}
}

// fixed: scroll didn't draw more blank lines if lines > 1
static void vga_scroll(long lines)
{
	unsigned tmp1, tmp2, div;
	
	if (lines > 0)
	{
		if (bios_modes[current_mode].graphic)
		{
			switch(current_mode)
			{
				case 0x04:
				case 0x05:	
				case 0x13:	div = 4; break;
				case 0x06:	
				case 0x0D:
				case 0x0E:
				case 0x0F:
				case 0x10:
				case 0x11:
				case 0x12:	div = 8; break;
				default: div = 8;
			}			
			
			tmp1 = lines * bios_modes[current_mode].max_x * (bios_modes[current_mode].font_height);			
			tmp1 /= div;
			tmp2 = (bios_modes[current_mode].max_x * bios_modes[current_mode].max_y) - tmp1;
			tmp2 /= div;
			
			// Move all the text on the screen up, discard top line(s)
			memmove((char *)bios_modes[current_mode].video_ptr,
				(char *)bios_modes[current_mode].video_ptr + tmp1, tmp2);
				
			tmp2 = (bios_modes[current_mode].max_x * bios_modes[current_mode].max_y) -
				((bios_modes[current_mode].font_height) * lines);
			tmp2 /= div;
			
			// Draw a line of spaces at the bottom			
			memset((char *)bios_modes[current_mode].video_ptr + tmp2, screen.color_bg, tmp1);
			vga_gotoxy(1, bios_modes[current_mode].max_y - bios_modes[current_mode].font_height - 1);
		}
		else
		{
			tmp1 = lines * bios_modes[current_mode].max_x * 2;
			tmp2 = (bios_modes[current_mode].max_x * bios_modes[current_mode].max_y * 2) - tmp1;
			// Move all the text on the screen up, discard top line(s)
			memmove((char *)bios_modes[current_mode].video_ptr,
				(char *)bios_modes[current_mode].video_ptr + tmp1, tmp2);
				
			tmp1 = bios_modes[current_mode].max_x * (bios_modes[current_mode].max_y-1) * 2; 
			// Draw a line of spaces at the bottom
			memsetw((char *)bios_modes[current_mode].video_ptr + tmp1,
				(((screen.color_bg << 4) | screen.color_fg) << 8) | ' ', lines * bios_modes[current_mode].max_x);
			vga_gotoxy(1, bios_modes[current_mode].max_y);
		}
	}
}

static void vga_clrscr(void)
{
	if (!bios_modes[current_mode].graphic)
	{
		memsetw((char *)bios_modes[current_mode].video_ptr, MAKEWORD(' ', screen.color_bg),
			(bios_modes[current_mode].max_x * bios_modes[current_mode].max_y));
		setcuraddr(0);
	}
	else
//	switch(current_mode)
	{
//		case 0x13:
//			{
				outportb(SEQ_I, 2);		// index map register
				outportb(SEQ_D, 0x0F);	// allow write access on all levels
				memset((char *)bios_modes[current_mode].video_ptr, CL_BLACK, 65535);
				screen.x = 1;
				screen.y = 1;
//			} break;
	}
}

// only for vga
// mm = 0	EGA	a0000 -bffff
// mm = 1	EGA	a0000 -affff
// mm = 2	MDA	b0000 -b7fff
// mm = 3	CGA	b8000 -b8fff
void vga_mmap(int mm)
{
	mm &= 3;
	outportb(GRA_I, 6);
	if (vga_card == GR_EGA)
		outportb(GRA_D, (0x0E & 3) | (mm << 3));	// GRA_D not readable
	else
		outportb(GRA_D, (inportb(GRA_D) & 3) | (mm << 2));	// bits 2, 3
}

static void vga_putpixel(unsigned int x, unsigned int y, unsigned color)
{
	unsigned int offset, mask, col_mask[4] = {0x00, 0x55, 0xAA, 0xFF};
	unsigned char tmp;

⌨️ 快捷键说明

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