;; ;; vesaModes.s (adapted from Visopsys OS-loader) ;; ;; Copyright (c) 2000, J. Andrew McLaughlin ;; You're free to use this code in any manner you like, as long as this ;; notice is included (and you give credit where it is due), and as long ;; as you understand and accept that it comes with NO WARRANTY OF ANY KIND. ;; Contact me at <andy@visopsys.org> about any bugs or problems. ;; ;; Change this to zero if you don't require Linear Framebuffer ;; abilities in your graphics modes. This could be turned into ;; a function parameter of the routine below, if desired. %define REQUIRELFB 1 BITS 16 findGraphicMode: ;; The VESA 2.0 specification states that they will no longer ;; create standard video mode numbers, and video card vendors are ;; no longer required to support the old numbers. This routine ;; will dynamically find a supported mode number from the VIDEO BIOS, ;; according to the desired resolutions, etc. ;; The function takes parameters that describe the desired graphic ;; mode, (X resolution, Y resolution, and Bits Per Pixel) and returns ; the VESA mode number in EAX, if found. Returns 0 on error. ;; The C prototype for this function would look like the following: ;; int findGraphicMode(short int x_res, short int y_res, ;; short int bpp); ;; (Push bpp, then y_res, then x_res onto the 16-bit stack before ;; calling. Caller pops them off again after the call.) ;; Save space on the stack for the mode number we're returning sub SP, 2 ;; Save regs pusha ;; Save the stack pointer mov BP, SP ;; By default, return the value 0 (failure) mov word [SS:(BP + 16)], 0 ;; Get the VESA info block. Save ES, since this call could ;; destroy it push ES mov DI, VESAINFO mov AX, 4F00h int 10h ;; Restore ES pop ES cmp AX, 004Fh ;; Fail jne .done ;; We need to get a far pointer to a list of graphics mode numbers ;; from the VESA info block we just retrieved. Get the offset now, ;; and the segment inside the loop. mov SI, [VESAINFO + 0Eh] ;; Do a loop through the supported modes .modeLoop: ;; Save ES push ES ;; Now get the segment of the far pointer, as mentioned above mov AX, [VESAINFO + 10h] mov ES, AX ;; ES:SI is now a pointer to the next supported mode. The list ;; terminates with the value FFFFh ;; Get the first/next mode number mov DX, word [ES:SI] ;; Restore ES pop ES ;; Is it the end of the mode number list? cmp DX, 0FFFFh je near .done ;; Increment the pointer for the next loop add SI, 2 ;; We have a mode number. Now we need to do a VBE call to ;; determine whether this mode number suits our needs. ;; This call will put a bunch of info in the buffer pointed to ;; by ES:DI mov CX, DX mov AX, 4F01h mov DI, MODEINFO int 10h ;; Make sure the function call is supported cmp AL, 4Fh ;; Fail jne near .done ;; Is the mode supported by this call? (sometimes, they're not) cmp AH, 00h jne .modeLoop ;; We need to look for a few features to determine whether this ;; is the mode we want. First, it needs to be supported, and it ;; needs to be a graphics mode. Next, it needs to match the ;; requested attributes of resolution and BPP ;; Get the first word of the buffer mov AX, word [MODEINFO] ;; Is the mode supported? bt AX, 0 jnc .modeLoop ;; Is this mode a graphics mode? bt AX, 4 jnc .modeLoop %if REQUIRELFB ;; Does this mode support a linear frame buffer? bt AX, 7 jnc .modeLoop %endif ;; Does the horizontal resolution of this mode match the requested ;; number? mov AX, word [MODEINFO + 12h] cmp AX, word [SS:(BP + 20)] jne near .modeLoop ;; Does the vertical resolution of this mode match the requested ;; number? mov AX, word [MODEINFO + 14h] cmp AX, word [SS:(BP + 22)] jne near .modeLoop ;; Do the Bits Per Pixel of this mode match the requested number? xor AX, AX mov AL, byte [MODEINFO + 19h] cmp AX, word [SS:(BP + 24)] jne near .modeLoop ;; If we fall through to here, this is the mode we want. mov word [SS:(BP + 16)], DX .done: popa ;; Return the mode number xor EAX, EAX pop AX ret ;; ;; The data segment ;; SEGMENT .data ALIGN 4 VESAINFO db 'VBE2' ;; Space for info ret by vid BIOS times 508 db 0 MODEINFO times 256 db 0