User:Johnburger/Demo/Boot/VGA

From OSDev Wiki
Jump to navigation Jump to search

With the vast number of video adapters on the market, all with their proprietary (and often secret!) access methods, video drivers are the biggest problem for PC system developers. There are certain industry-standard modes and conventions, but the really clever stuff needs drivers provided by the video card manufacturers.

Before leaving Real Mode, now would be the perfect time to set the desired Video Mode using the BIOS. All VGAs support 80x50 mode, so that will be the lowest common denominator for this Demonstrator. Some systems support 90x60 too - VMware is a perfect example! That gives me more experimenting room; but I need a way to disable it in the source code. The easiest is to use %define BIOS.VGA.90x60.

Note though that the 90x60 code takes up a fair bit of space. That will probably be the second code against The Wall if I run out of room...

Oh, and set the cursor to invisible too.

Demo/Boot/VGA.inc

;
; Boot/VGA.inc
;

; Use the BIOS to set the desired video mode (80x50 by default: 90x60 if enabled)

VGA.Set80x25    EQU             (BIOS.VGA.SetMode.Fn << 8) | BIOS.VGA.SetMode.80x25
VGA.Ext80x50    EQU             (BIOS.VGA.ExtMode.Fn << 8) | BIOS.VGA.ExtMode.80x50

; Note: DS and ES are 0000h
Boot.VGA:
                MOV             AX,VGA.Set80x25 ; Set 80x25 mode, 8x16 font
                INT             BIOS.VGA.Int

                MOV             AX,VGA.Ext80x50 ; Ext 80x50 mode, 8x8 font
                MOV             BL,0
                INT             BIOS.VGA.Int

%ifndef BIOS.VGA.90x60

VGA.Rows        EQU             50
VGA.Cols        EQU             80

                MOV             AH,BIOS.VGA.Cursor.Fn   ; Set cursor size
                MOV             CX,BIOS.VGA.Cursor.None ; To invisible
                INT             BIOS.VGA.Int

%else ; BIOS.VGA.90x60

VGA.Rows        EQU             60
VGA.Cols        EQU             90

;-------------------------------------------------------------------------------

; I know I said I don't like "magic numbers", but the following is esoteric!
                MOV             AL,0E7h
                MOV             DX,Dev.VGA.Misc.Port
                OUT             DX,AL

                CLD                             ; Work forwards
                MOV             SI,Boot.VGA.Seq

                MOV             CX,.Seq.Num     ; This many Seq registers
                MOV             DX,Dev.VGA.Seq.Base
                CALL            Boot.VGA.Write

                MOV             AL,017h         ; Enable regs 0-7
                MOV             DX,Dev.VGA.CRTC.Base
                OUT             DX,AL
                INC             DX              ; Go to Data port
                IN              AL,DX
                AND             AL,~80h         ; Enable registers
                OUT             DX,AL
                DEC             DX              ; Back to Index port

                MOV             AL,003h         ; Enable vertical retrace
                OUT             DX,AL
                INC             DX              ; Go to Data port
                IN              AL,DX
                OR              AL,80h          ; Enable registers
                OUT             DX,AL
                DEC             DX              ; Back to Index port

                MOV             CX,.CRTC.Num    ; This many CRTC registers
                PUSH            Boot.VGA.End    ; Fake a call from .End
;-------------------------------------------------------------------------------

.Write:
                MOV             AH,0            ; Start with register 0
.Write.Loop:
                CS                              ; Load from Code Segment!
                LODSB
                XCHG            AL,AH           ; Make sure Index is in AL
                OUT             DX,AX           ; 16-bit write
                MOV             AH,AL           ; But need AL for LODSB
                INC             AH              ; Next index
                LOOP            .Write.Loop
                RET

.Seq            DB              003h, 001h, 003h, 000h, 002h ; Sequence registers
.Seq.Num        EQU             $-.Seq
.CRTC           DB              06Bh, 059h, 05Ah, 082h, 060h, 08Dh, 00Bh, 03Eh
                DB              000h, 047h, 020h, 000h, 000h, 000h, 000h, 000h
                DB              0EAh, 00Ch, 0DFh, 02Dh, 008h, 0E8h, 005h, 0A3h
                DB              0FFh                         ; CRTC registers
.CRTC.Num       EQU             $-.CRTC

%endif ; BIOS.VGA.90x60

.End: