User:Omarrx024/VESA Tutorial: Difference between revisions
Content deleted Content added
m I've taken the liberty of adding syntax highlighting, as I feel it makes the code snippets more readable. It's a nice article. |
m Bot: Replace deprecated source tag with syntaxhighlight |
||
(4 intermediate revisions by 3 users not shown) | |||
Line 10:
Here are some modes the VESA defined with VBE 1.x:
<pre>MODE RESOLUTION BITS PER PIXEL MAXIMUM COLORS
0x0100
0x0101 640x480 8 256
0x0102 800x600 4 16
Line 51:
Anyway, the above function returns the following structure and stores it in ES:DI as they were on entry. On entry, ES:DI should contain a pointer to the following structure:
<
.signature db "VBE2" ; indicate support for VBE 2.0+
.table_data: resb 512-4 ; reserve space for the table below</
After the BIOS call, if it succeeded (AX is 0x004F), then the same structure above now contains the following:
<
char[4] signature = "VESA"; // must be "VESA" to indicate valid VBE support
char reserved[222]; // reserved for future expansion
char oem_data[256]; // OEM BIOSes store their strings in this area
} __attribute__ ((packed));</
Notice that all segment:offset fields are in little-endian, which means the low word is the offset, and the high word is the segment.
Things that might be of interest to you from the above structure: "signature" will be changed from "VBE2" to "VESA". It must be "VBE2" on entry to indicate software support for VBE 2.0. If it contains "VBE2", the BIOS will return the 512 bytes of data for VBE 2.0+. If it contains "VESA", the BIOS will return 256 bytes of data for VBE 1.x. If it is not "VESA" after the call, you should assume that VESA BIOS Extensions are not available. "version" tells you the version of VBE; 0x100 is 1.0, 0x101 is 1.1, 0x102 is 1.2, 0x200 is 2.0, and 0x300 is 3.0 (the latest version). VBE 1.x returns 256 bytes of data in the above structure, VBE 2.0 and 3.0 return 512 bytes of data if the "signature" field contained "VBE2" on entry. "video_modes" is a segment:offset pointer to the list of supported video modes. Each entry in the array is a 16-bit word, and is terminated by a 0xFFFF. If while searching for your mode, you find a 0xFFFF, then the mode is not supported. "video_memory" contains how much VGA RAM the PC has in 64 KB chunks. So, to have it in KB, multiply the value in "video_memory" by 64.
Line 90:
Here's the structure returned by this function in ES:DI:
<
} __attribute__ ((packed));</
Lots of useless sh*t, I know. The only things that interest us: "attributes" bit 7 (value 0x80) indicates the mode supports a linear frame buffer. "width", "height" are "bpp" are used while searching for the mode we want to use. "framebuffer" is the 32-bit physical pointer to the linear framebuffer. The linear framebuffer must be enabled while setting the VBE mode, which is discussed in the next function. If you are using paging, be sure to map the framebuffer somewhere known in the virtual address space!
Line 143:
So that means, if VBE mode 0x0118 is 1024x768x32bpp, and we wanted to set this mode and ask the BIOS to clear the screen for us, we can do this:
<
mov bx, 0x4118 ; VBE mode number; notice that bits 0-13 contain the mode number and bit 14 (LFB) is set and bit 15 (DM) is clear.
int 0x10 ; call VBE BIOS
Line 150:
after:
; ...</
Anyway, like I mentioned at least a hundred times, you should first get the mode number from the video modes array. Those mode numbers only have the plain mode numbers (0x0118, 0x0103, etc...) and you should set bit 14 when you set the VBE mode.
Line 202:
Anyway, the table returned by ES:DI looks like this:
<
} __attribute__ ((packed));</
That means, to set the bank from protected mode, one should first find the linear address of the set_window function, by doing ES * 0x10 + DI + [ES:DI] and then doing a near CALL, because all protected mode functions end with a near RET. Useless, I know, but perhaps some people want to use bank switching as a fallback when VBE 2.0 is not available, or when the specific mode doesn't support a linear frame buffer.
Line 213:
'''Need code?'''
Here's a function to set a VESA mode directly from a specified width/height/bpp, copied and pasted from my OS code. Notice that it runs in 16-bit real mode with DS = ES = FS = GS = 0.
<
; Sets a VESA mode
; In\ AX = Width
Line 334:
.segment dw 0
.offset dw 0
.mode dw 0</
'''What's next?'''
Well, that's entirely up to you! Just kidding, here's some tips on implementing a graphics library.
Calculating pixel offset:
<
Where "pitch", "bpp" and "framebuffer" are gotten from the structure returned by function 0x4F01. Then, you can plot a pixel by writing a value there.
For 32-bit modes, each pixel value is 0x00RRGGBB in little endian, so to plot a red pixel, we would write 0x00FF0000. In 24-bit mode, each pixel is 0xRRGGBB in little endian. Due to the bad memory alignment, performance is relatively low with 24-bit modes. In 16-bit modes, we have a total of 64K colors, and the color has 5 bits of red, 6 bits of green, and 5 bits of blue. There is more green because according to Wikipedia, the human eye is more sensitive to green than red and blue...
|