I decided that my operating system needs some graphics. I have seen loads of tutorials on drawing pixels, and I have used some. I now want to use 32bit protected mode (before I was using real mode) and I can't find any tutorials or documentation on drawing with VESA without the bios.
Can anyone point me in the right direction? If I can plot a single pixel, without the bios, I will be happy. :)
...Can anyone point me in the right direction? If I can plot a single pixel, without the bios, I will be happy. :)...
Since you're using 32-bit Protected Mode to program VBE (VESA BIOS Extensions), then you can program for LFB (Linear Frame Buffer). With LFB, you can write to video memory without having to worry about Bank Switching.
I learned how to program the VBE LFB from Charles Sandman's vbetest.c. The following link contains Sandman's vbetest.c source, as well as what seems to be an excellent background on the concepts behind VBE 2.0 LFBs, and DJGPP protected mode: http://pages.cpsc.ucalgary.ca/~walpole/325/DJ_GRAPH.txt
Note that turning off protected memory in DJGPP is generally not a good idea since it could cause conflicts with 3rd party libraries.
The first part of the VBE 2.0 LFB demo is ready. Nothing exciting on the surface, but there's a lot going on behind the scenes.
The development environment I used was DOSBOX, which as you may know is a DOS emulator. The following link is to a zip file with all the files necessary to develop the VBE demos. The folder can be mounted in DOSBOX, and run. The files can be copied to a native, or emulated, DOS installation. Note, you'll need to provide an e-mail address, otherwise filehosting.org will make you download a client (which you don't want to do :P)... VBE development environment
DEMO1.C sets VBE graphics mode 640x480 at depths of 8-BPP (256 colors), 15-BPP (32768 colors), 16-BPP (65536 colors), 24-BPP (16.8 million colors), 32-BPP (16.8 million colors with a padding byte).
I didn't have a chance to test the 24-BPP screen clear, but am reasonably confident that it works. The 24-BPP SetPixel should not have any issues though. By the third demo, I'll dig up an old computer and set it up for 24-BPP testing :)
Note that a real mode Seg:Ofs can be converted into a linear address as follows: LinAddr = (Seg * 16) + Ofs. This is valid for 32-bit Flat Protected Mode. Segmented 32-bit Protected Mode may require a couple of extra steps. According to the VBE spec, the extra steps include getting the base address of the program's data selector, then subtracting it by the Linear Mapped Physical Address.
Using VBE in 32-bit Protected Mode depends heavily on DPMI services. Your OS will need to provide equivalent services.
This structure holds the required information needed to draw graphics. VBEDriverInfo_t and VBEModeInfo_t contain a lot of information that is typically only used once.
Of note are fields rshift, gshift, bshift, and ashift. These values are the number of LSBs that need to be shifted for a more correct RGB value. These values are non-zero in 15-BPP and 16-BPP display modes.
The rmask, gmask, bmask, and amask fields store bit masks in the exact position where the component lies in the encoded pixel. These fields are used in 15/16/24/32-BPP display modes. EncodePixel uses component masks to remove bits which overlap with other component bits. DecodePixel uses component masks to isolate specific component bits.
Under DOS the palette DACs interpret RGB component values as 6-bits. By writing 0xFF to port 0x3C6, the palette DACs interpret RGB component values as 8-bits. The catch, apparently, is that not all video cards support changing the palette DAC mask size. What I do instead is shift the LSB of each RGB component by 2.  -> [-][-]
The display mode is set to 640x480x256 colors. As you already may know, RGB values are used indirectly, so each pixel is actually a color index into a palette. Setting two RGB values is the equivalent of encoding two pixels in higher bit depths.
demo1_Run15() and demo1_Run16()
The display mode is set to 640x480x32768 and 640x480x65536, respectively. 15-BPP and 16-BPP modes are run separately, however, both depths use two bytes per pixel. As a result, they can use the same graphics functions.
In the Real World, most people test for specific cases of RGB pixel formats, such as A1_R5_G6_B5, in order to mask by constants and shift by constants -as opposed to referencing a pointer, to retrieve a value, to store the value into a register, to finally manipulate the pixel.
The display mode is set to 640x480x16.8M. If the bit depth is 24, then 24-BPP graphics functions are used. Otherwise, 32-BPP graphics functions are used. For some reason, VESA separated 15-BPP and 16-BPP modes, but not 24-BPP and 32-BPP modes. New display modes exist specifically 32-BPP, but they are graphics card specific since VESA stopped pre-defining video modes.
The basic process to use VBE 2.0+ LFB follows:
1) Get mode information and test a specific ModeAttributes bit to confirm whether or not LFB is supported.
2) Create an LDT selector, set the granularity and access rights to read/write, set the base address to the mapped linear address.
3) Map the physical address into a linear address.
4) Set the LDT selector base address to the LFB linear address.
5) Set display mode to specified LFB mode.
6) Use the LFB pointer like a data pointer.
With VBE 2.0+ LFB (Linear Frame Buffer), you only need the BIOS to set the display mode.
Hopefully, you'll find this information useful so far. I've always wanted to write a tutorial on VBE graphics, so please feel free to ask if you (or anyone reading this) has any questions.
The following links to references I used to write the demo:
Attached to this reply is a more recent vbesrc.zip file.
This release focuses on demo2, which shows driver and mode information. Don't be surprised if you see mode numbers such as 810E. Whatever display modes demo2 shows are valid.
To build, just type
The following have changed since the previous vbesrc.zip upload:
- Added stubs for FillRect, PutImage, and other functions
- Added missing comments to function implementations
- Added demo2.c and demo3.c
- Added image_t type
- Minor changes to cliprect_t structure
- Fixed minor bug in Clear functions (scaled down lfbsize according to rep stosX)
- Converted BMP file to PCX file
- Deleted BMP file and GIF file
- Tested on a PIII computer
Next up is demo3 which will be a graphics demo including filled rectangles (clipped), image blits (clipped), imaged loading (via PCX), simple pixel conversion (for loading images), and a general interface. With demo3, you will see how clipping a pixel differs from clipping a filled rectangle, and how it differs from clipping an image.
Iret i just found this thread searching for information on VBE, and (though im on a mobile device and unable to read the source at this time) it seems awesome. Im in the same boat as the OP, trying to write an OS, and ive been looking for this information. Is there any chance you could do that tutorial you said youve wanted to do? It would be most appreciated by me and the many other people it will help (and im sure it will help many many people if its as detailed as your posts are). Thank you.
I tested the VBE source in a virtual machine (VirtualBox) using FreeDOS. I dug up 2 computers, but they were 32-BPP.
So the 24-BPP clear function doesn't quite work, but I'm close. I converted Seg:Ofs real mode addresses to a linear address. It works under emulation, but doesn't work consistently on two old computers so I'll need to figure out a better way to access the Real Mode data. There may also be a miscalculation with TotalMemory, I multiplied by 64. Once I straighten out the Real Mode pointers, I will be able to verify the TotalMemory calculation.
The VBE code works flawlessly, it's based on tested code from a graphics library that I worked on a while back. The graphics code will work flawlessly. Sorry for the errors so far. I won't post anything else until the code is fully tested.
I've ironed out a couple of bugs, especially the available mode list being corrupted. Now, 2K of low memory is allocated: 1K for VBE Driver Info + 1K for Mode Info. Also, I rearranged the vbe_SetMode code a bit since for some reason 32-BPP modes didn't want to run.
Regarding the TotalMemory calculation:
- TotalMemory x 64 = Video Memory size in KB
- Total Memory x 65536 = Video Memory size in Bytes
I didn't realize until the previous release that 32-BPP modes don't run. I fixed that by setting the video mode first, then doing all the LFB set up after.
So far, 8/15/16/32-BPP modes work flawlessly. 24-BPP needs a minimal amount of work.
I don't really have a choice but to code 24-BPP under emulation. The demos have crashed where I needed them to under VirtualBox, which helps me find any bugs. When the 24-BPP code is stable under VirtualBox, it will be stable on hardware. I'm working on locating a video card that supports VBE 2.0, LFB, and has 24-BPP video modes.
Moderator: Please remove previous attachments in this thread with extensions C, H, and ZIP. They had bugs which could potentially cause confusion to readers of this thread.
Attached is the most recent source release. This release is fully tested, and obsoletes all previous releases I have attached. Kieran, hopefully this release will make up for my previous releases :/
To compile, simply run wmake from the VBE directory
The following have changed since the last release:
- Changed from DOS/4G stub to PMode/W stub in previous release makefile
- Changed from PMode/W to Causeway stub in current release makefile
- demo1 functions without error for 8/15/16/32-BPP VBE modes on real hardware, and under emulation
- demo1 functions without error for 24-BPP VBE modes under emulation, but should work flawlessly on real hardware (I am working on testing this and will follow up to confirm, when I eventually get a 24-BPP hardware set up)
- vbe_Init() now allocates 2K of low memory where 1K is for VBE Driver Info, and 1K is for VBE Mode Info
- demo2 available modes list is no longer corrupt
- Fixed vbe_SetMode() by re-arranging each major section such that the display mode is changed, the VBE selector is set up, and the VBE physical address is set up
- gfx_Clear24() implemented and tested
- gfx_FillRect24() implemented and tested
- Added stubs and partial functionality to draw/load images for next release
- Updated gfx_t structure to include FillRect and PutImage function pointers
I've decided to make two more releases before letting this thread rest:
- next: image loading, drawing and clipping in demo3
- last: generic API interfacing in demo4; self-sufficient demonstration for video mode changing, setting up the LFB, and drawing a pixel in demo5
After the last release, I will work on a tutorial and will follow up with a link.
First, I know that this article has been dead for a while, but I'm not done yet :)
Still been really busy, but I needed a break so I'm on this again. Turns out the PCX bug was partially due to loading an 8-BPP file, when the file itself is 24-BPP. PCX is an obsolete and annoying format, but few others are as simple to decode (and still around).
I'll follow up when the next demo is ready, which will hopefully be within 2 weeks.