본문 바로가기
공부,일/c언어

비디오 램 영역을 통한 화면 출력

by fromnothing1 2021. 6. 16.

프로그램에서 화면에 문자를 출력하는 메커니즘은 다음과 같다. 상세한 부분은 필요에 따
라 참고서적을 살펴보기 바란다. 화면에 출력하려는 데이터(문자)는 VGA 카드에 있는 `비
디오 메모리'에 저장되어 있다. 프로그램은 화면에 출력하는 문자를 비디오 메모리에 기록
함으로 VGA에 의해서 화면에 출력된다. VGA 비디오 메모리의 영역은 RAM의 0xa0000000
~ 0xb000ffff까지의 128Kbyte 크기로 할당되어 있으며, 실제 프로그램에서는 VGA 표준
Text 모드에서는 RAM의 0xb8000000 ~ 0xb000ffff까지의 32Kbyte 크기의 영역을 사용
하고 있다. 이 영역들의 데이터들은 디바이스 드라이브(VGA 카드)에 의하여 그대로 VGA
비디오 메모리로 맵핑에 의해 전달된다. 그러므로 우리는 VGA 표준 Text 모드에서 화면
출력을 하고자 할 때, RAM의 0xb8000000 ~ 0xb000ffff까지의 32Kbyte 크기의 영역에
출력하려는 데이터를 적어주기만 하면 된다. 그러면 이 데이터가 VGA 비디오 메모리로 그
대로 전달되고, 그에 따라 모니터의 출력이 자동적으로 이루어진다. 

 

표준 Text 모드가 4K byte로 한 화면의 내용을 저장할 수 있다는 것을 감안할 때,
32Kbyte는 8개의 화면 내용을 저장할 수 있다. 이 과제에서는 8개의 화면 중 첫 번째 화
면만을 사용한다.

 

화면 1 점에 2byte 가 배정 되는데 이것은 글자의 데이터 뿐만 아니라 속성(글자색 배경색 등)에 대한 정보 또한 가지고 있기 때문이다. 

 

비디오 램의 시작 주소는 컬러 VGA 카드의 경우 B8000,0000h 이고 흑백 인 경우 B000,0000h 이다. 

영역 0000,0449h 영역을 조사하면 알 수 있다.  값이 7 이면 컬러 이다. 요즘은 그냥 다 컬러 ;; 

 

아래 코드는 터보C 컴파일러에서 동작함 

글자의 속성을 나타내는 속성표

 

#include<stdio.h>
#define OFF_SET(x,y) (((x)*2)+((y)*160))
#define VRAM_ASCLL(x,y) *(Video_address+OFF_SET(x,y))
#define VARM_ATTR(x,y) *(Video_address+(x)*2+1+(y)*160)

char far* Video_address;

void vcharxy(int x, int y, char ch, int attr)
{
	VRAM_ASCLL(x, y) = ch; // offset  계산
	VARM_ATTR(x, y) = attr; // 글자 특성 입력
}
int main()
{
	unsigned x, y;
	if (peekb(0, 0x449) == 7)
	{
		Video_address = (char far*)0xB0000000L;
		
	}
	else
	{
		Video_address = (char far*)0xB8000000L;
	}

	for (x = 20; x < 30; x++)
	{
		for (y  = 0; y < 10; y++)
		{
			vcharxy(x, y, 'A', 0x70);
		}

	}
	getch();
	return 0;
}

 

심화 예제 

#include<stdio.h>
#include<conio.h>

#define UP		0x48  
#define DOWN    0x50  
#define LEFT    0x4B  		
#define RIGHT   0x4D  

#define OFF_SET(x,y) (((x)*2)+((y)*160))
#define VRAM_ASCLL(x,y) *(Video_address+OFF_SET(x,y))
#define VARM_ATTR(x,y) *(Video_address+(x)*2+1+(y)*160)
char far* Video_address;

typedef struct MENU_FRAME
{
	char* item;
	int x, y;
}MENU;

void vcharxy(int x, int y, char ch, int attr);
void vputs(char* str, int x, int y, int attr);
void display_menu();

MENU menu[4] = {
	{"NEW Game  Alt-N",0,3},
	{"Load Game Alt-L",0,4},
	{"Options   Alt-O",0,5},
	{"Quit      Alt-X",0,6},
};

int main()
{
	int sno = 0;
	char ch;
	char quit = 0;
	if (peekb(0, 0x449) == 7)
	{
		Video_address = (char far*)0xB0000000L;

	}
	else
	{
		Video_address = (char far*)0xB8000000L;
	}
	display_menu();
	while (1)
	{
		if ((ch = getch()) == 0) // 확장키 입력시  0;
		{
			switch (getch())
			{
				case UP:
					vputs(menu[sno].item, menu[sno].x, menu[sno].y, 0x07);
					sno--; //  메뉴 하나 줄임 
					if (sno<0)
					{
						sno = 3; // 메뉴가 0 보다 작으면 마지막 메뉴 보여줌
					}
					vputs(menu[sno].item, menu[sno].x, menu[sno].y, 0x70);
					break;
				case DOWN:
					vputs(menu[sno].item, menu[sno].x, menu[sno].y, 0x07);
					sno++; //  메뉴 하나 줄임 
					if (sno > 3)
					{
						sno = 0; // 메뉴가 3 보다 크면 처음 항목으로 설정
					}
					vputs(menu[sno].item, menu[sno].x, menu[sno].y, 0x70);
					break;
				default:
					break;
			}
		}
		else if (ch == '\r') // 엔터키 입력
		{
			switch (sno)
			{
			case 0: 
				vputs("the first menu is slected ..", 0, 10, 0x07);
				break;
			case 1:
				vputs("the second menu is slected ..", 0, 10, 0x07);
				break;
			case 2:
				vputs("the third menu is slected ..", 0, 10, 0x07);
				break;
			case 3:
				vputs("thank you for useing ..", 0, 10, 0x07);
				quit = 1;
				break;
			default:
				break;
			}
		}
		if (quit)
		{
			break;
		}
	}
	getch();
	return 0;
}



void vcharxy(int x, int y, char ch, int attr) // 비디오 램에 글자 1 자 씩 씀
{
	VRAM_ASCLL(x, y) = ch; // offset  계산
	VARM_ATTR(x, y) = attr; // 글자 특성 입력
}

void vputs(char* str, int x, int y, int attr) // str 안에 있는 글자 다 쓰는 함수
{
	while (*str != 0)
	{
		vcharxy(x++, y, *str++, attr);
	}
}

void display_menu()
{
	clrscr();
	vputs("-------------", 0, 0, 0x07);
	vputs(" MENU SYSTEM ", 0, 1, 0x07);
	vputs("-------------", 0, 2, 0x07);
	vputs(menu[0].item, menu[0].x, menu[0].y, 0x70);
	vputs(menu[1].item, menu[1].x, menu[1].y, 0x07);
	vputs(menu[2].item, menu[2].x, menu[2].y, 0x07);
	vputs(menu[3].item, menu[3].x, menu[3].y, 0x07);
	vputs("-------------", 0, 7, 0x07);
}

'공부,일 > c언어' 카테고리의 다른 글

간단한 메모리 접근  (0) 2021.06.18
간단한 키보드 제어  (0) 2021.06.17
룸 바이오스 데이터 영역 접근  (0) 2021.06.16
터보C 설치 사용  (0) 2021.06.15
Linked List 구현  (0) 2021.06.14

댓글