Address of VRAM (Warning - assembly)

Started by
4 comments, last by demonkoryu 13 years, 8 months ago
Greetings,

it has been some time I've written some question here, anyway here is the current state...
I've been working on my own operating system (and also probably gone crazy) throughout the evenings , I won't go into details of kernel, file system and such (it is graphics forum), although it is currently working in 13h vga mode - so I have 320x200 pixels and 256 colors. My question is, how can I directly access vram from ASM code and tell it the resolution and number of colors and optionally send it also buffer to display?
I know it is possible (it must be), please don't tell me use OpenGL or Direct3D - as I don't have any vga drivers there. My idea was to access vram out of assembly on some address (probably described in vga architecture - of course I think it is card/vendor specific - can I get specification that contains this somewhere? Does anyone know, or should I contact AMD/NVidia directly if they released some specs - would that be more successful?)

Thanks for reading and for possible answers and ideas.

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

Advertisement
If you want graphics better than the simlpe VGA modes without knowing proprietary details about your specific graphics card, you can look into VESA modes. You can start reading here.
If you're looking for hardware acceleration (even say simple 2D) you might want to look at some of the linux drivers. The code is available, and I know AMD/ATI (not so sure about NVidia) has a lot of open source documentation on the inner workings of their older cards. You can get it straight from their website:

http://developer.amd.com/documentation/guides/Pages/default.aspx

At the bottom under 'Open GPU Documentation' will have the low level details you're looking for. Your gonna need a working PCI driver though.

Good luck ; )
Use VESA as suggested to set the mode. There are only a limited number of standard VESA modes, and some vendors provide non-standard modes, but you wont be able to use modes outside of what's provided by the VBIOS. If you want to use other arbitrary resolutions you have to program the card directly yourself, which is a fair bit of work.
According to my 1994 edition of "Tricks of the Game Programming Gurus" (LaMothe et al.) the VGA mode 13h video buffer starts at A000:0000 and ends at A000:F9FF and is 64,000 bytes long (320x200 = 64,000). The VGA card is capable of producing 262,144 colors but can only display 256 colors on screen at the same time. Each byte in the buffer operates as an index into the color look-up table. A byte can store values in the range 0-255 (0-0xFF). The color look-up table is 768 bytes (3x256). Each entry in the look-up table is three bytes, one each for red, green, blue. The color registers of the look-up table are not accessible directly. They are accessible only through the I/O ports of the VGA card. All three components of an entry must be changed together and in a certain order. Within an entry, only the first 6 bits of each byte is used for the color. That means 64 shades of each color for a total of 2^18 different colors (ie. 262,144). "If you place a value larger than 6 bits (ie. > 63) in a color register, it won't hurt anything, but it won't change the color."

Here are the I/O ports to use to change the entries in the color look-up table.

#define PALETTE_MASK 0x3C6
#define PALETTE_REGISTER_READ 0x3C7
#define PALETTE_REGISTER_WRITE 0x3C8
#define PALETTE_DATA 0x3C9

The palette mask is used to mask the bits of the requested palette register.

The palette mask is used to mask the bits of the requested palette register.
With a mask of 0x00 in this port you get register 0, no matter the register you request.
With a mask of 0xFF in this port you get any register you request
by way of palette index registers 0x3C7 and 0x3C8

The palette read register is used to select the entry in the table to read
The palette write register is used to select the entry in the table to write
The palette data port is used to read from or write to data from the r,g,b components.
The three bytes are accessed in sequence - red, green, blue.

To write to the register

1. change the mask to 0xFF to ensure register state
2. select register to change
3. perform three writes to the data register

Here is some code from the book. It was written for DOS, so YMMV.

#include <conio.h>#define PALETTE_MASK 0x3C6#define PALETTE_REGISTER_READ 0x3C7#define PALETTE_REGISTER_WRITE 0x3C8#define PALETTE_DATA 0x3C9typedef struct tagRGB_color { unsigned char red; unsigned char green; unsigned char blue;} RGB_color, RGB_color_ptr;void Set_Palette_Register(int index, RGB_color_ptr color){ _outp(PALETTE_MASK,0xFF); _outp(PALETTE_REGISTER_WRITE,index); _outp(PALETTE_DATA, color->red); _outp(PALETTE_DATA, color->green); _outp(PALETTE_DATA, color->blue);}void Get_Palette_Register(int index, RGB_color_ptr color){ _outp(PALETTE_MASK,0xFF); _outp(PALETTE_REGISTER_READ,index); color->red = _inp(PALETTE_DATA); color->green = _inp(PALETTE_DATA); color->blue = _inp(PALETTE_DATA);}void CreateColorPalette(void){ RGB_color color; int index; for(index=0; index < 64; index++) {  // grays  color.red = index;  color.green = index;  color.blue = index;  SetPalette_Register(index, &color);  // reds  color.red = index;  color.green = 0;  color.blue = 0;  SetPalette_Register(index+64, &color);  // greens  color.red = 0;  color.green = index;  color.blue = 0;  SetPalette_Register(index+128, &color);  // blues  color.red = 0;  color.green = 0;  color.blue = index;  SetPalette_Register(index+192, &color); }}unsigned char far *video_buffer = (char far*)0xA0000000L;void Plot_Pixel(int x, int y, unsigned char color){ video_buffer[((y<<8) + (y<<6)) + x] = color;}
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Obligatory PCGPE link.

Also, this looks helpful.

This topic is closed to new replies.

Advertisement