음.. broneri homebrew project에는 minios를 두지 않으려 했는데 블로그를 두개로 운영하려니 귀찮네요..; (http://minios.tistory.com 는 천천히 없애야겠네요 )



윈도우 시스템은 역시나 예전에 만들어두었던 minigui를 사용하였습니다. 4년이 넘은 코드에 의존하고 있다니 --;

아래는 mini gui가 최초(?)로 사용된 arm rtos 인 usys os의 화면입니다.
이 땐 LCD컨트롤러만 잡으면 기본적으로 linear한 frame buffer가 잡혔지요. 그리고 터치 드라이버를 작성해서 터치로 설정할 수 있게 했었습니다.

어쨋든 Mini-GUI 소스 헤더에  2004/10/18라는 타임 스탬프는 저를 놀라게 하는군요. -_- 세월은 참 빠르구나.. 드뎌 mini fat과 mini gui가 모두 mini os로 이식되는구낭. ㅠ.ㅠ (혼자 감회가 새로움) ㅋㅋ

다시 x86 mini os로 돌아와서.. 문제는 아직 마우스를 잡지 않아서 아무런 컨트롤도 할 수 없다는 것이었습니다. 뜨헉...
어서 마우스를 먼저 잡아야 할것 같네요.

아래는 svga vesa 114h, 800x600x16bpp 입니다.

아래는 svga vesa 111h, 640x480x16bpp입니다.

부팅 시 리얼 모드에서 아래와 같이 먼저 svga를 vesa bios를 이용하여 설정합니다.
;   mov    bx, 0x114 ; ok, 800x600 5:6:5
   mov    bx, 0x111 ; ok, 640x480 5:6:5
   or     bh, 0x40 ; want linear model, clear screen (LFB linear Frame buffer)
   mov   ax, 0x4F02 ; change mode
   int   0x10 ; go
이 때 LFB (linear frame buffer)의 주소가 어디서부터 시작하는지 알아내야 합니다. (VMWare의 경우 두 svga 모드 모두 0xF0000000 번지였습니다. )

따라서 꽁수(?)를 부려서 0x9000번지에 vbe_mode_info 정보를 담아두도록 했습니다.
   mov ax, 0x900
   mov es, ax ; save ModeInfoBlock to 900:0h = 0x9000
   mov ax, 4f01h ; get vbe_mode_info
  ; mov cx, 0x114 ; vbe mode (800x600 5:6:5)
   mov cx, 0x111 ; vbe mode (640x480 5:6:5)
   mov di, 0x0   
   int 0x10

그리곤 32 bit protected kernel의 시작 엔트리가 호출되면 잽싸게 0x9000번지의 소중한(?) 현재 svga설정 값들을 받아왔습니다.

VBEMode* p = (VBEMode*)0x9000;
lfb_width = p->bytes; // 한 줄 scan line의 바이트 수
lfb = p->lfbaddr; // lfb 시작 주소 (젤중요)
lfb_xres = p->xres;
lfb_yres = p->yres;

그리고 최초 kernel의 virtual memory mapping시 lfb 주소 공간도 매핑하도록 추가하였습니다.
void vmm_map_kernel( unsigned char* phys_page_directory )
{
vmm_maps( "boot", phys_page_directory, (unsigned char*)PHYS_BOOT_START, (unsigned char*)VIRT_BOOT_START, PHYS_BOOT_PAGES );
vmm_maps( "bios", phys_page_directory, (unsigned char*)PHYS_BIOS_START, (unsigned char*)VIRT_BIOS_START, PHYS_BIOS_PAGES );
vmm_maps( "kheap", phys_page_directory, (unsigned char*)PHYS_KHEAP_START, (unsigned char*)VIRT_KHEAP_START, PHYS_KHEAP_PAGES );
vmm_maps( "kernel", phys_page_directory, (unsigned char*)PHYS_KERNEL_START, (unsigned char*)VIRT_KERNEL_START, PHYS_KERNEL_PAGES );
vmm_maps( "vmm", phys_page_directory, (unsigned char*)PHYS_VMM_START, (unsigned char*)VIRT_VMM_START, PHYS_VMM_PAGES );

vmm_maps( "lfb", phys_page_directory, (unsigned char*)PHYS_LFB_START, (unsigned char*)VIRT_LFB_START, PHYS_LFB_PAGES );
}
아주 재미있는 것은 아까 받아온 0xF0000000라는 주소는 언뜻보기엔 가상주소같은데 physical 주소라는 것이지요! 

이제 점을 찍을 수 있습니다. 

void my_draw_setpixel( int x, int y, COLOR cr )
{
char* vmem = (char*)lfb;

*((unsigned short*)(vmem + (lfb_width*y) + x * 2)) = cr;

'프로젝트 > minios OS 개발' 카테고리의 다른 글

minios on ipad  (0) 2011.12.07
minios - real IU !!  (1) 2011.02.11
minios x86 homebrew os project  (0) 2008.12.13
IBM VGA programming  (0) 2008.12.13
minios mouse control  (0) 2008.12.13

+ Recent posts