728x90
void io_hlt(void);
void io_cli(void);
void io_out8(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);

void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb);
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
void init_screen(char *vram, int x, int y);
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);

#define COL8_000000		0
#define COL8_FF0000		1
#define COL8_00FF00		2
#define COL8_FFFF00		3
#define COL8_0000FF		4
#define COL8_FF00FF		5
#define COL8_00FFFF		6
#define COL8_FFFFFF		7
#define COL8_C6C6C6		8
#define COL8_840000		9
#define COL8_008400		10
#define COL8_848400		11
#define COL8_000084		12
#define COL8_840084		13
#define COL8_008484		14
#define COL8_848484		15

struct BOOTINFO {
	char cyls, leds, vmode, reserve;
	short scrnx, scrny;
	char *vram;
};

void HariMain(void)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
	static char font_A[16] = {
		0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24,
		0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00
	};

	init_palette();
	init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
	putfont8(binfo->vram, binfo->scrnx, 10, 10, COL8_FFFFFF, font_A);

	for (;;) {
		io_hlt();
	}
}

void init_palette(void)
{
	static unsigned char table_rgb[16 * 3] = {
		0x00, 0x00, 0x00,	/*  0:검은색 */
		0xff, 0x00, 0x00,	/*  1:밝은 적색 */
		0x00, 0xff, 0x00,	/*  2:밝은 녹색 */
		0xff, 0xff, 0x00,	/*  3:밝은 노란색 */
		0x00, 0x00, 0xff,	/*  4:밝은 청색 */
		0xff, 0x00, 0xff,	/*  5:밝은 보라색 */
		0x00, 0xff, 0xff,	/*  6:밝은 청색*/
		0xff, 0xff, 0xff,	/*  7:흰색 */
		0xc6, 0xc6, 0xc6,	/*  8:밝은 회색 */
		0x84, 0x00, 0x00,	/*  9:어두운 적색 */
		0x00, 0x84, 0x00,	/* 10:어두운 녹색 */
		0x84, 0x84, 0x00,	/* 11:어두운 노란색 */
		0x00, 0x00, 0x84,	/* 12:군청색 */
		0x84, 0x00, 0x84,	/* 13:어두운 보라색 */
		0x00, 0x84, 0x84,	/* 14:어두운 청색 */
		0x84, 0x84, 0x84	/* 15:어두운 회색 */
	};
	set_palette(0, 15, table_rgb);
	return;

	/* static char 명령은 (주소가 아니라)데이터밖에 쓰지 못하지만, DB명령과 동일함 */
}

void set_palette(int start, int end, unsigned char *rgb)
{
	int i, eflags;
	eflags = io_load_eflags();	/* 인터럽트 허가 플래그 값을 기록 */
	io_cli(); 					/* 허가 플래그를 0으로 하여 인터럽트 금지 */
	io_out8(0x03c8, start);
	for (i = start; i <= end; i++) {
		io_out8(0x03c9, rgb[0] / 4);
		io_out8(0x03c9, rgb[1] / 4);
		io_out8(0x03c9, rgb[2] / 4);
		rgb += 3;
	}
	io_store_eflags(eflags);	/* 인터럽트 허가 플래그를 본래 값으로 되돌린다. */
	return;
}

void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
	int x, y;
	for (y = y0; y <= y1; y++) {
		for (x = x0; x <= x1; x++)
			vram[y * xsize + x] = c;
	}
	return;
}

void init_screen(char *vram, int x, int y)
{
	boxfill8(vram, x, COL8_008484,  0,     0,      x -  1, y - 29);
	boxfill8(vram, x, COL8_C6C6C6,  0,     y - 28, x -  1, y - 28);
	boxfill8(vram, x, COL8_FFFFFF,  0,     y - 27, x -  1, y - 27);
	boxfill8(vram, x, COL8_C6C6C6,  0,     y - 26, x -  1, y -  1);

	boxfill8(vram, x, COL8_FFFFFF,  3,     y - 24, 59,     y - 24);
	boxfill8(vram, x, COL8_FFFFFF,  2,     y - 24,  2,     y -  4);
	boxfill8(vram, x, COL8_848484,  3,     y -  4, 59,     y -  4);
	boxfill8(vram, x, COL8_848484, 59,     y - 23, 59,     y -  5);
	boxfill8(vram, x, COL8_000000,  2,     y -  3, 59,     y -  3);
	boxfill8(vram, x, COL8_000000, 60,     y - 24, 60,     y -  3);

	boxfill8(vram, x, COL8_848484, x - 47, y - 24, x -  4, y - 24);
	boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y -  4);
	boxfill8(vram, x, COL8_FFFFFF, x - 47, y -  3, x -  4, y -  3);
	boxfill8(vram, x, COL8_FFFFFF, x -  3, y - 24, x -  3, y -  3);
	return;
}

void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
	int i;
	char *p, d /* data */;
	for (i = 0; i < 16; i++) {
		p = vram + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) { p[0] = c; }
		if ((d & 0x40) != 0) { p[1] = c; }
		if ((d & 0x20) != 0) { p[2] = c; }
		if ((d & 0x10) != 0) { p[3] = c; }
		if ((d & 0x08) != 0) { p[4] = c; }
		if ((d & 0x04) != 0) { p[5] = c; }
		if ((d & 0x02) != 0) { p[6] = c; }
		if ((d & 0x01) != 0) { p[7] = c; }
	}
	return;
}

 

현황

- 22번 글에서는 부트 정보를 편리하게 접근할수 있도록 구조체와 화살표 연산자를 사용했다. 이제 메모리에 대한 내용들은 직접 적을 필요없이 포인터를 사용해서 접근하면 되겠지만, 이제 글자도 좀 써려고 한다.

 

 

바이오스로 문자쓰기?

- 어셈블리어로 바이오스에 입출력 요청해서 문자를 띄우면 될수도 있지만 이제 32비트 모드로 바이오스를 쓸수없음.

 

 

문자 쓰기?

- 8 x 16사각형 화소가 존재하면 문자를 어떻게 쓸가

 * 구글링해도 비슷한 사진도 없고 어떻게 보여줄까 고민 중 사진 찍으려다가 그냥 표로 그렸다. 아래의 상자는 8 x 16 화소로 문자 A를 표기한것

               
      000 000      
      000 000      
      000 000      
      000 000      
    000     000    
    000     000    
    000     000    
    000     000    
  000 000 000 000 000 000  
  000         000
 
  000         000  
  000         000  
  000         000  
000 000 000     000 000 000
               
               

- 위 표를 2진수로 나타내보고 16진수로 정리해보자

0 0 0 0 0 0 0 0   => 0x00

0 0 0 1 1 0 0 0   => 0x18

0 0 0 1 1 0 0 0   => 0x18

0 0 0 1 1 0 0 0   => 0x18

0 0 0 1 1 0 0 0   => 0x18

0 0 1 0 0 1 0 0   => 0x24

0 0 1 0 0 1 0 0   => 0x24

0 0 1 0 0 1 0 0   => 0x24

0 0 1 0 0 1 0 0   => 0x24

0 1 1 1 1 1 1 0   => 0x7e

0 1 0 0 0 0 1 0   => 0x42

0 1 0 0 0 0 1 0   => 0x42

0 1 0 0 0 0 1 0   => 0x42

1 1 1 0 0 1 1 1   => 0xe7

0 0 0 0 0 0 0 0   => 0x00

0 0 0 0 0 0 0 0   => 0x00

 

- 위 16진수 값들의 모음을 폰트 데이터가 된다.

static char font_A[16] = {
  0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24,
  0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00
};

- 8화소 폰트를 그리기 위해서 위 배열을 16번 반복하면 되며, 이를 정리한 결과가 아래의 putfont8 함수가 된다.

void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
	int i;
	char *p, d /* data */;
	for (i = 0; i < 16; i++) {
		p = vram + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) { p[0] = c; }
		if ((d & 0x40) != 0) { p[1] = c; }
		if ((d & 0x20) != 0) { p[2] = c; }
		if ((d & 0x10) != 0) { p[3] = c; }
		if ((d & 0x08) != 0) { p[4] = c; }
		if ((d & 0x04) != 0) { p[5] = c; }
		if ((d & 0x02) != 0) { p[6] = c; }
		if ((d & 0x01) != 0) { p[7] = c; }
	}
	return;
}

 

 

폰트를 출력해보자

- 메인 함수를 보면 static char font_A[16] 으로 폰트 데이터를 초기화 해주고, putfont8을 보면 FFFFFFF 색상으로 (10,10)위치에 찍으라고 하는것 같다 실행해보면

void HariMain(void)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
	static char font_A[16] = {
		0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24,
		0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00
	};

	init_palette();
	init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
	putfont8(binfo->vram, binfo->scrnx, 10, 10, COL8_FFFFFF, font_A);

	for (;;) {
		io_hlt();
	}
}

 

- 정상적으로 A가 출력됨

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

void io_hlt(void);
void io_cli(void);
void io_out8(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);

void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb);
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
void init_screen(char *vram, int x, int y);
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);

#define COL8_000000		0
#define COL8_FF0000		1
#define COL8_00FF00		2
#define COL8_FFFF00		3
#define COL8_0000FF		4
#define COL8_FF00FF		5
#define COL8_00FFFF		6
#define COL8_FFFFFF		7
#define COL8_C6C6C6		8
#define COL8_840000		9
#define COL8_008400		10
#define COL8_848400		11
#define COL8_000084		12
#define COL8_840084		13
#define COL8_008484		14
#define COL8_848484		15

struct BOOTINFO {
	char cyls, leds, vmode, reserve;
	short scrnx, scrny;
	char *vram;
};

void HariMain(void)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
	extern char hankaku[4096];

	init_palette();
	init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
	putfont8(binfo->vram, binfo->scrnx,  8, 8, COL8_FFFFFF, hankaku + 'E' * 16);
	putfont8(binfo->vram, binfo->scrnx, 16, 8, COL8_FFFFFF, hankaku + '1' * 16);
	putfont8(binfo->vram, binfo->scrnx, 24, 8, COL8_FFFFFF, hankaku + 'D' * 16);
	putfont8(binfo->vram, binfo->scrnx, 32, 8, COL8_FFFFFF, hankaku + 'l' * 16);
	putfont8(binfo->vram, binfo->scrnx, 40, 8, COL8_FFFFFF, hankaku + 'L' * 16);
	putfont8(binfo->vram, binfo->scrnx, 48, 8, COL8_FFFFFF, hankaku + '1' * 16);
	putfont8(binfo->vram, binfo->scrnx, 56, 8, COL8_FFFFFF, hankaku + 'l' * 16);
	putfont8(binfo->vram, binfo->scrnx, 64, 8, COL8_FFFFFF, hankaku + 'E' * 16);
	putfont8(binfo->vram, binfo->scrnx, 72, 8, COL8_FFFFFF, hankaku + '1' * 16);
	putfont8(binfo->vram, binfo->scrnx, 80, 8, COL8_FFFFFF, hankaku + ' ' * 16);
	putfont8(binfo->vram, binfo->scrnx, 88, 8, COL8_FFFFFF, hankaku + 'O' * 16);
	putfont8(binfo->vram, binfo->scrnx, 96, 8, COL8_FFFFFF, hankaku + '1' * 16);
	putfont8(binfo->vram, binfo->scrnx, 104, 8, COL8_FFFFFF, hankaku + 'O' * 16);
	putfont8(binfo->vram, binfo->scrnx, 112, 8, COL8_FFFFFF, hankaku + 'F' * 16);
	putfont8(binfo->vram, binfo->scrnx, 120, 8, COL8_FFFFFF, hankaku + '7' * 16);
	putfont8(binfo->vram, binfo->scrnx, 128, 8, COL8_FFFFFF, hankaku + '1' * 16);

	for (;;) {
		io_hlt();
	}
}


void init_palette(void)
{
	static unsigned char table_rgb[16 * 3] = {
		0x00, 0x00, 0x00,	/*  0:검은색 */
		0xff, 0x00, 0x00,	/*  1:밝은 적색 */
		0x00, 0xff, 0x00,	/*  2:밝은 녹색 */
		0xff, 0xff, 0x00,	/*  3:밝은 노란색 */
		0x00, 0x00, 0xff,	/*  4:밝은 청색 */
		0xff, 0x00, 0xff,	/*  5:밝은 보라색 */
		0x00, 0xff, 0xff,	/*  6:밝은 청색*/
		0xff, 0xff, 0xff,	/*  7:흰색 */
		0xc6, 0xc6, 0xc6,	/*  8:밝은 회색 */
		0x84, 0x00, 0x00,	/*  9:어두운 적색 */
		0x00, 0x84, 0x00,	/* 10:어두운 녹색 */
		0x84, 0x84, 0x00,	/* 11:어두운 노란색 */
		0x00, 0x00, 0x84,	/* 12:군청색 */
		0x84, 0x00, 0x84,	/* 13:어두운 보라색 */
		0x00, 0x84, 0x84,	/* 14:어두운 청색 */
		0x84, 0x84, 0x84	/* 15:어두운 회색 */
	};
	set_palette(0, 15, table_rgb);
	return;

	/* static char 명령은 (주소가 아니라)데이터밖에 쓰지 못하지만, DB명령과 동일함 */
}

void set_palette(int start, int end, unsigned char *rgb)
{
	int i, eflags;
	eflags = io_load_eflags();	/* 인터럽트 허가 플래그 값을 기록 */
	io_cli(); 					/* 허가 플래그를 0으로 하여 인터럽트 금지 */
	io_out8(0x03c8, start);
	for (i = start; i <= end; i++) {
		io_out8(0x03c9, rgb[0] / 4);
		io_out8(0x03c9, rgb[1] / 4);
		io_out8(0x03c9, rgb[2] / 4);
		rgb += 3;
	}
	io_store_eflags(eflags);	/* 인터럽트 허가 플래그를 본래 값으로 되돌린다. */
	return;
}

void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
	int x, y;
	for (y = y0; y <= y1; y++) {
		for (x = x0; x <= x1; x++)
			vram[y * xsize + x] = c;
	}
	return;
}

void init_screen(char *vram, int x, int y)
{
	boxfill8(vram, x, COL8_008484,  0,     0,      x -  1, y - 29);
	boxfill8(vram, x, COL8_C6C6C6,  0,     y - 28, x -  1, y - 28);
	boxfill8(vram, x, COL8_FFFFFF,  0,     y - 27, x -  1, y - 27);
	boxfill8(vram, x, COL8_C6C6C6,  0,     y - 26, x -  1, y -  1);

	boxfill8(vram, x, COL8_FFFFFF,  3,     y - 24, 59,     y - 24);
	boxfill8(vram, x, COL8_FFFFFF,  2,     y - 24,  2,     y -  4);
	boxfill8(vram, x, COL8_848484,  3,     y -  4, 59,     y -  4);
	boxfill8(vram, x, COL8_848484, 59,     y - 23, 59,     y -  5);
	boxfill8(vram, x, COL8_000000,  2,     y -  3, 59,     y -  3);
	boxfill8(vram, x, COL8_000000, 60,     y - 24, 60,     y -  3);

	boxfill8(vram, x, COL8_848484, x - 47, y - 24, x -  4, y - 24);
	boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y -  4);
	boxfill8(vram, x, COL8_FFFFFF, x - 47, y -  3, x -  4, y -  3);
	boxfill8(vram, x, COL8_FFFFFF, x -  3, y - 24, x -  3, y -  3);
	return;
}

void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
	int i;
	char *p, d /* data */;
	for (i = 0; i < 16; i++) {
		p = vram + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) { p[0] = c; }
		if ((d & 0x40) != 0) { p[1] = c; }
		if ((d & 0x20) != 0) { p[2] = c; }
		if ((d & 0x10) != 0) { p[3] = c; }
		if ((d & 0x08) != 0) { p[4] = c; }
		if ((d & 0x04) != 0) { p[5] = c; }
		if ((d & 0x02) != 0) { p[6] = c; }
		if ((d & 0x01) != 0) { p[7] = c; }
	}
	return;
}

여러 문자 출력하기

- A를 띄운건 좋지만 출력하고싶은 문자는 더 다양하다.

 알파벳은 26개의 소, 대문자, 숫자 10개, 기호 30개.. OSASK의 폰트 데이터 사용하자

 

 

OSASK 폰트 파일

- 아래는 OSASK 폰트 데이터 예시 * 어떻게 C언어에서 이걸쓸지는 Make 파일 참고

 

 

 

 

폰트파일 오브젝트 만들기

- 별도의 컴파일러(makefont.exe)로 오브젝트 파일로 만듬

 

 

메인함수

- 폰트 파일을 extern char hankaku[4096]으로 접근해서 사용

void HariMain(void)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
	extern char hankaku[4096];

	init_palette();
	init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
	putfont8(binfo->vram, binfo->scrnx,  8, 8, COL8_FFFFFF, hankaku + 'E' * 16);
	putfont8(binfo->vram, binfo->scrnx, 16, 8, COL8_FFFFFF, hankaku + '1' * 16);
	putfont8(binfo->vram, binfo->scrnx, 24, 8, COL8_FFFFFF, hankaku + 'D' * 16);
	putfont8(binfo->vram, binfo->scrnx, 32, 8, COL8_FFFFFF, hankaku + 'l' * 16);
	putfont8(binfo->vram, binfo->scrnx, 40, 8, COL8_FFFFFF, hankaku + 'L' * 16);
	putfont8(binfo->vram, binfo->scrnx, 48, 8, COL8_FFFFFF, hankaku + '1' * 16);
	putfont8(binfo->vram, binfo->scrnx, 56, 8, COL8_FFFFFF, hankaku + 'l' * 16);
	putfont8(binfo->vram, binfo->scrnx, 64, 8, COL8_FFFFFF, hankaku + 'E' * 16);
	putfont8(binfo->vram, binfo->scrnx, 72, 8, COL8_FFFFFF, hankaku + '1' * 16);
	putfont8(binfo->vram, binfo->scrnx, 80, 8, COL8_FFFFFF, hankaku + ' ' * 16);
	putfont8(binfo->vram, binfo->scrnx, 88, 8, COL8_FFFFFF, hankaku + 'O' * 16);
	putfont8(binfo->vram, binfo->scrnx, 96, 8, COL8_FFFFFF, hankaku + '1' * 16);
	putfont8(binfo->vram, binfo->scrnx, 104, 8, COL8_FFFFFF, hankaku + 'O' * 16);
	putfont8(binfo->vram, binfo->scrnx, 112, 8, COL8_FFFFFF, hankaku + 'F' * 16);
	putfont8(binfo->vram, binfo->scrnx, 120, 8, COL8_FFFFFF, hankaku + '7' * 16);
	putfont8(binfo->vram, binfo->scrnx, 128, 8, COL8_FFFFFF, hankaku + '1' * 16);

	for (;;) {
		io_hlt();
	}
}

 

 

실행 결과

- 글자는 좀 잘못썻지만 잘 나온다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

함수로 문자열 쓰기

- 방금전 예제에선 putfont8로 문자 하나하나 출력하다보니 힘들었다.

- 이를 함수로 구현해서 다뤄보자.

void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
{
	extern char hankaku[4096];
	for (; *s != 0x00; s++) {
		putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
		x += 8;
	}
	return;
}

 

 

메인 함수

- 위에서 정의한 putfont8_asc 함수로 지정한 위치에 차례 차례 작성해준다.

 *(31, 31)과 (30, 30)을 함으로서 폰트상 굵게 효과를 준것 같다.

void HariMain(void)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;

	init_palette();
	init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
	putfonts8_asc(binfo->vram, binfo->scrnx,  8,  8, COL8_FFFFFF, "Hello BABOYA");
	putfonts8_asc(binfo->vram, binfo->scrnx, 31, 31, COL8_000000, "E1DlL1lOlE1 OlOF7l.");
	putfonts8_asc(binfo->vram, binfo->scrnx, 30, 30, COL8_000000, "E1DlL1lOlE1 OlOF7l.");
	putfonts8_asc(binfo->vram, binfo->scrnx, 30, 130, COL8_FFFFFF, "Computer");
	putfonts8_asc(binfo->vram, binfo->scrnx, 60, 150, COL8_FFFFFF, "annyohasseyo?");
	putfonts8_asc(binfo->vram, binfo->scrnx, 50,  70, COL8_FFFFFF, "Hello BABOYA");
	putfonts8_asc(binfo->vram, binfo->scrnx, 90,  75, COL8_FFFFFF, "Hello BABOYA");
	putfonts8_asc(binfo->vram, binfo->scrnx, 55,  60, COL8_FFFFFF, "Hello BABOYA");

	for (;;) {
		io_hlt();
	}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

300x250

+ Recent posts