VESA에서는 BIOS를 통해서 그래픽 모드로 전환할 수 있는 방법을 규정하여 표준으로 만들었다.
(VESA에서 제정한 VESA BIOS Extension 2.0 이상을 따르는 BIOS라면 사용할 수 있다.)
VBE (VESA BIOS Extension)
선형 프레임 버퍼
VBE 2.0 버전 이상을 지원하는 BIOS를 사용하여 비디오 컨트롤러를 제어하는 방법
(MINT OS에서는 BIOS 인터럽트 서비스를 사용한다.)
① BIOS 인터럽트 서비스 0x10을 사용하는 방법 ② 보호 모드 인터페이스 함수의 포인터를 추출하여 직접 호출하는 방법
VBE가 지원하는 기능은 12가지 이지만, MINT OS에서는 선형 프레임 버퍼 모드로 변환하는데 사용하는 0x4F01과 0x4F02 만 사용한다.
VBE 모드 번호
(1) 그래픽 모드 선택과 모드 정보 블록 추출
그래픽 모드로 전환할 때, 가장 먼저 하는 일은 ‘사용할 해상도와 색 수’를 정하는 것이다. ( Mint OS에서는 1024x768 해상도에 16비트(64K) 색을 사용한다. )
모드 정보 블록 구성 요소
// VBE에서 정의한 모드 정보 블록 자료구조, 256바이트
typedef struct VBEInfoBlockStruct{
//====================================================
// 모든 VBE 버전에 공통인 부분
//====================================================
WORD wModeAttribure // 모드의 속성
BYTE bWinAAttribute; // 윈도우 A의 속성
BYTE bWinAAttribute; // 윈도우 B의 속성
WORD wWinGranulity; // 윈도우의 가중치(Granularity)
WORD wWinSize; // 윈도우의 크기
WORD wWinASegment; // 윈도우 A가 시작하는 세그먼트 어드레스
WORD wWInBSegment; // 윈도우 B가 시작하는 세그먼트 어드레스
DWORD dwWinFuncPtr; // 윈도우 관련 함수의 포인터(리얼모드 용)
WORD wBytesPerScanLine; // 화면 스캔 라인당 바이트 수
//====================================================
// VBE 버전 1,2 이상 공통인 부분
//====================================================
WORD wXResolution; // X축 픽셀 수 또는 문자 수
WORD wYResolution; // Y축 픽셀 수 또는 문자 수
BYTE bXCharSize; // 한 문자의 X축 픽셀 수
BYTE bYCharSize; // 한 문자의 Y축 필세 수
BYTE bNumberOfPlane; // 메모리 플레인 수
BYTE bBitsPerPixel; // 한 픽셀을 구성하는 비트 수
BYTE bNumberOfBanks; // 뱅크 수
BYTE bMemoryModel; // 비디오 메모리 구성
BYTE bBankSize; // 뱅크의 크기(KB)
BYTE bNumberOfImagePages; // 이미지 페이지 개수
BYTE bReserved; // 페이지 기능을 위해 예약된 영역
// 다이렉트 컬러(Direct Color)에 관련된 필드
BYTE bRedMaskSize; // 빨간색 필드가 차지하는 크기
BYTE bRedFieldPosition; // 빨간색 필드의 위치
BYTE bGreenMaskSize; // 녹색 필드가 차지하는 크기
BYTE bGreenFieldPosition; // 녹색 필드의 위치
BYTE bBlueMaskSize; // 파란색 필드가 차지하는 크기
BYTE bBlueFieldPosition; // 파란색 필드의 위치
BYTE bReservedMaskSize; // 예약된 필드의 크기
BYTE bReservedFiledPosition; // 예약된 필드의 위치
BYTE bDirectColorModeInfo; // 다이렉트 컬러 모드의 정보
//====================================================
// VBE 버전 2.0 이상 공통인 부분
//====================================================
DWORD dwPhysicalBasePointer; // 선형 프레임 버퍼 메모리의 시작 어드레스
DWORD dwReserved1; // 예약된 필드
DWORD dwReserved2;
//====================================================
// VBE 버전 3.0 이상 공통인 부분
//====================================================
WORD wLinearBytesPerScanLine; // 선형 프레임 버퍼 모드의
// 화면 스캔 라인(Scan Line) 당 바이트 수
BYTE bBankNumberOfImagePages; // 뱅크 모드일 때 이미지 페이지 수
BYTE bLinearNumberOfImagePages; // 선형 프레임 버퍼 모드일 때 이미지 페이지 수
// 선형 프레임 버퍼 모드일 때 다이렉트 컬러(Direct Color)에 관련된 필드
BYTE bLinearRedMaskSize; // 빨간색 필드가 차지하는 크기
BYTE bLinearRedFiledPosition; // 빨간색 필드의 위치
BYTE bLinearGreenMaskSize; // 녹색 필드가 차지하는 크기
BYTE bLinearGreenFiledPosition; // 녹색 필드의 위치
BYTE bLinearBlueMaskSize; // 파란색 필드가 차지하는 크기
BYTE bLinearBlueFiledPosition; // 파란색 필드의 위치
BYTE bLinearReservedMaskSize; // 예약된 필드의 크기
BYTE bLinearReservedFieldPosition; // 예약된 필드의 위치
DWORD dwMaxPixelClock; // 픽셀 클록의 최대 값(Hz)
BYTE vbReserved[ 189 ]; // 나머지 영역
} VBEMODEINFOBLOCK;
선형 프레임 버퍼 모드
① 비디오 메모리 시작 주소
② 화면 해상도
③ 화면에 표시할 수 있는 색 수
④ 모드 정보 블록을 저장할 위치 선정
모드 정보 블록을 얻는 어셈블리어 코드
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; VBE 기능 번호 0x4F01을 호출하여,
; 그래픽 모드에 대한 모드 정보 블록을 구함
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ax, 0x4F01 ; VBE 기능 번호 0x4F01를 AX 레지스터에 저장
mov cx, 0x117 ; 1024x768 해상도에 16비트(R(5):G(6):B(5)) 색 모드 지정
mov bx, 0x07E0 ; BX 레지스터에 0x07E0를 저장
mov es, bx ; ES 세그먼트 레지스터에 BX의 값을 설정하고, DI 레지스텅
mov di, 0x00 ; 0x00을 설정하여 0x07E0:0000(0x7E00) 어드레스에 모드 정보 블록을 저장
int 0x10 ; 인터럽트 서비스 수행
cmp ax, 0x004F ; 에러가 발생했다면 VBERROR로 이동
jne VBEERROR
VBEERROR:
; ``` 예외 처리 ```
그래픽 모드로 전환하는 코드
STARTGRAPHICMODE: db 0x01 ; 그래픽 모드로 시작하는지 여부
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; VBE 기능 번호 0x4F02을 호출하여 그래픽 모드로 전환
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 부트 로더의 그래픽 모드 전환 플랙를 확인하여 1일 때만 그래픽 모드로 전환
cmp byte [ STRATGRAPHICMODE ], 0x00 ; 그래픽 모드 시작하는지 여부를 0x00과 비교
je JUMPTOPROTECTEDMODE ; 0x00과 같다면 바로 보호 모드로 전환
mov ax, 0x4F02 ; VBE 기능 번호 0x4F02를 AX 레지스터에 저장
mov bx, 0x4117 ; 1024x768 해상도에 16비트(R(5):G(6):B(5)) 색을 사용하는
; 선형 프레임 버퍼 모드 지정
; VBE 모드 번호(Bit 0 ~ 8) = 0x117,
; 버퍼 모드(비트 14) = 1(선형 프레임 버퍼 모드)
int 0x10 ; 인터럽트 서비스 수행
cmp ax, 0x004F ; 에러가 발생했다면 VBEERROR로 이동
jne VBERROR
VBEERROR:
; ``` 예외 처리 ```
JUMPTOPROTECTEDMODE:
; 보호 모드로 전환
Y축을 32등분하여 무작위로 색깔을 출력해주는 함수
void kStartGraphicModeTest(){
VBEMODEINFOBLOCK* pstVBEMode;
WORD* pwFrameBufferAddress;
WORD wColor = 0;
int iBandHeight;
int i;
int j;
// VBE 모드 정보 블록을 반환하고 선형 프레임 버퍼의 시작 어드레스를 저장
pstVBEMode = kGetVBEModeInfoBlock();
pwFrameBufferAddress = ( WORD* ) ((QWORD) pstVBEMode->dwPhysicalBasePointer);
// 화면을 세로로 32 등분하여 색을 칠함
iBandHeight = pstVBEMode->wYResolution / 32;
while( 1 ){
for( j = 0 ; j < pstVBEMode->wYResolution ; j++ ){
// X축의 크기만큼 프레임 버퍼에 색을 저장
for( i = 0 ; i < pstVBEMode->wXResolution ; i ++){
// 비디오 메모리 오프셋을 계산하는 부분
// Y축의 현재 위치(j)에 X축의 크기를 곱하면 Y축의 시작 어드레스를
// 계산할 수 있고, 여기에 X축의 오프셋(i)을 더하면 현재 픽셀을 출력할
// 어드레스를 구할 수 있음
pwFrameBufferAddress[ ( j * pstVBEMode->wXResolution ) + i ] = wColor;
}
// Y 위치가 32등분한 단위로 나누어 떨어지면 색을 바꿈
if( (j % iBandHeight ) == 0 ){
wColor = kRandom() & 0xFFFF;
}
}
// 키 입력을 대기
kGetCh();
}
}
VBE 모드 정보 블록 자료구조를 반환하는 함수
// 모드 정보 블록이 저장된 어드레스
#define VBE_MODEINFOBLOCKADDRESS 0x7E00
// VBE 모드 정보 블록 자료구조의 어드레스
static VBEMODEINFOBLOCK* gs_pstVBEModeBlockInfo =
(VBEMODEINFOBLOCK*) VBE_MODEINFOBLOCKADDRESS;
inline VBEMODEINFOBLOCK* kGetVBEModeInfoBlock( void ){
return gs_pstVBEModeBlockInfo;
}