7 March 2004 Experimenting with VBE I decided to see what video resolutions my Soyo laptop offers, so I wrote a boot sector to find out. The boot sector does not access the hard disk; it simply calls the BIOS to retrieve data about the video card and dumps the data to the screen. There are two functions that I use here:
(Online references: The VESA VBE 3.0 Standard (PDF). Here I link to pages in an online version of the VBE 2.0 Standard for convenience.) Note that there are different versions of VBE. The most recent as of this writing is 3.0; the earliest public standard was 1.0. I need at least Version 2.0, because that was when VESA introduced support for linear frame buffers. A linear frame buffer is a single large chunk of memory representing the entire screen display. If the current graphics mode provides a linear frame buffer, any pixel on the screen can be changed at any time. If the current graphics mode does not provide a linear frame buffer, then you could change only some of the pixels on the screen, and if you wanted to change pixels on another part of the screen, you'd have to change the current "bank" first. Using a linear frame buffer is simpler and requires less code. Code and results Here is the boot-sector source code. After setting up the segment registers and stack and clearing the screen, the code calls function 0x4F00 to get the video card information. The buffer into which this data is saved begins right after the boot-sector code, at address 0x7E00. Note that the first four bytes in the buffer must contain the characters "VBE2". This tells the function to return information relevant to VBE 2.0. mov ax, 0x4F00 mov di, 0x7E00 ; 512-byte buffer mov ebx, "VBE2" mov [di], ebx int 0x10 This done, I then dump the first 32 bytes of the data to the screen. mov bx, 0x7E00 call dump_16 call dump_16 This part of the code prints the following two lines on the screen: 0000:7E00: 56 45 53 41 00 02 22 7F 00 00 00 00 00 00 22 7E | VESA ". "~ 0000:7E10: 00 00 10 00 02 01 00 7F 00 00 09 7F 00 00 1D 7F | . . . There are a number of fields here, but I care only about the following:
Next, I want to display a list of the video modes that my laptop supports. I'm hoping to find the mode 0x114 listed. The VBE standard states that this mode usually offers (though apparently is not guaranteed to offer) 800x600 resolution and 65,536 colors. I'd go for a higher resolution or more colors, except that the video card has only one megabyte of memory. If I were to try for 1024x768 resolution, for example, I'd have to settle for a palette of only 256 colors. If I wanted more colors, I'd have to settle for a smaller video resolution. So in this case, 800x600 resolution with 65,536 colors is a decent tradeoff. So I load the VideoModePtr from address 0x7E0E and dump the first 32 bytes pointed to. mov bx, [0x7E0E] call dump_16 call dump_16 The list turns out to contain fifteen video-mode numbers (in hex): 100, 101, 102, 103, 104, 105, 10D, 10E, 110, 111, 112, 113, 114, 120, and 121. (The last value, FFFF, signals the end of the list.) 0000:7E22: 00 01 01 01 02 01 03 01 04 01 05 01 0D 01 0E 01 | 0000:7E32: 10 01 11 01 12 01 13 01 14 01 20 01 21 01 FF FF | ! .. So mode 0x114 is supported. Let's see if this video card's mode 0x114 is indeed 800x600 with 65,536 colors. To do this, I use function 0x4F01. I pass in CX the number of the video mode I want to investigate, and I pass in DI the address to which the data should be saved. mov ax, 0x4F01 mov cx, 0x114 mov di, 0x7F00 ; ModeInfoBlock is 256 bytes long int 0x10 This function returns quite a bit more information that I'm interested in than does 0x4F00, so I dump more bytes to the screen: mov bx, 0x7F00 call dump_16 call dump_16 call dump_16 call dump_16 These are the bytes dumped: 0000:7F00: 9F 00 07 00 40 00 40 00 00 A0 00 00 A5 1F 00 C0 | . @ @ . . . 0000:7F10: 40 06 20 03 58 02 08 10 01 10 01 06 00 00 01 05 | @ X 0000:7F20: 0B 06 05 05 00 00 00 00 00 00 00 E0 00 A8 0E 00 | . . 0000:7F30: 94 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | . There are more fields in this data than I discuss here. The fields I care about are the following:
Modes 0x120 and 0x121? Curiosity led me to investigate the modes 0x120 and 0x121 that my Soyo offers. Neither are improvements over my chosen mode 0x114 for my purposes, for both modes offer only 320x240 resolution. How will I use this information? I suspect that I won't include in Karig the code to do all of this investigating. I'll probably just write code that expects mode 0x114 and a linear frame buffer to be available and complains if they aren't. If my code expects a certain video resolution and color depth, then I don't have to write code to support other video resolutions or color depths. I also don't plan on writing code to support "banking" video modes that can't use a linear frame buffer. Video mode 0x114 is apparently a standard, and the VBE 2.0 standard is now years old, so there is a good chance that Karig will work on most recent computers. I probably will have to write code to get the address of video memory, though. The video memory on my laptop is at physical address 0xE0000000, while Chuck Moore's ColorForth source code lists two other possible physical addresses: 0xF0000000, apparently the video address used in Fujitsu computers; and 0xF2000000, apparently the video address used by the NVIDIA video card inside an eMonster PC. So there doesn't seem to be any standard on exactly where video card manufacturers should make the video card memory "appear" within the main memory space. Update — 2004-03-09 Disappointment! It turns out that, while the Soyo's video card supports 800x600 resolution, the built-in monitor only supports 640x480! How did I find out? Well, as it turns out, the Windows 2000 OS that came with the Soyo was not destroyed by my MBR experiments as I had thought. I booted my Soyo to see if my new MBR-modifying code had worked properly, and lo and behold, Windows starts booting. So I let it finish booting, loaded up Control Panel, and decided to see what the screen looked like in 800x600 resolution. Well, 800x600 resolution looked a lot like 640x480 resolution — except that when you moved the mouse to the edge of the screen, the screen scrolled so that you could see another part of the 800x600 virtual screen show up on the 640x480 real screen. Ugh. This was not a good sign. Sure enough, when I ran some experimental boot code to set graphic mode 0x114 and to cover the 800x600 screen with six color bars (each 100 scanlines high), the screen showed only five bars, and the bar on the bottom looked a little shorter than the others. So that's how I know that my Soyo is stuck with 640x480 resolution. Still, it's not a total loss. I have been working on a font to use in 800x600 resolution, with each character 8 pixels wide and 16 pixels high. If the resolution is 640x480, I can still display 80 characters on a line (the same as in text mode) and 30 lines on the screen (an improvement over text mode's 25 lines). Check the index for other entries. |