Working with VGA graphics registers

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
marcio
Posts: 14
Joined: Fri Oct 20, 2006 10:54 am

Working with VGA graphics registers

Post by marcio »

Hi guys,

I've read some of the FreeVGA Project's documentation on accessing the graphics registers and I can't get it to work :?
This is what I do in kmain (assembly code is attached):

Code: Select all

ia32_io_write_byte(0x3CE, 0x6);
uint32_t data = ia32_io_read_byte(0x3CF);
log_info("%h\n", data);
As you can see, first I select the Miscellaneous Graphics Register (index 6h) on the Address Register (port 3CEh). Then I read the Data Register (port 3CFh) to detect the memory map in use. The problem is that the value returned is always 0, but I know the memory map is B8000h-BFFFFh because that's what I'm currently using to print strings.

Does anyone has had this problem, or knows how can I solve it?
By the way, I'm using Bochs v2.3.

Thanks,
Attachments
input_output.asm
(428 Bytes) Downloaded 31 times
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

You will find usefull info here
http://bos.asmhackers.net/docs/vga_without_bios/
marcio
Posts: 14
Joined: Fri Oct 20, 2006 10:54 am

Post by marcio »

Thanks, but that's a lot of information for something that seems (I hope) simple :)
I'm saying this because I had the same code working using D, but now that I've translated it to C it doesn't work anymore...

Anyway, I'll check that later as soon as I get the time.
Also, did you check the assembly code? It is alright?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

Reading from 3CF#6 returns 0xE as expected, in four different versions of bochs.

I think your error is here:

Code: Select all

	mov dx, [ebp + 8]     ; Argument 1.
	mov al, [ebp + 10]    ; Argument 2.
as each item on the stack is 4 bytes in size independent of whether the function expects 8, 16 or 32 bits.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
marcio
Posts: 14
Joined: Fri Oct 20, 2006 10:54 am

Post by marcio »

That did the trick, thanks Combuster!

I didn't know that each stack item was always 4 bytes in size... :oops:
Is there a particular reason why, or it's just by design?

EDIT:
Ok, I've just read that only words and double-words are saved on the stack and never a single byte (Sivarama P. Dandamudi, "Introduction to Assembly Language Programming: For Pentium and RISC Processors"). Knowing this, how come the assembly code of, for example, ia32_io_write_byte addresses the function arguments as if all of them were double-words?

Code: Select all

; void ia32_io_write_byte(word_t port, byte_t data)
ia32_io_write_byte:
	enter 0, 0
	
	mov edx, [ebp + 8]     ; Argument 1.
	mov eax, [ebp + 12]    ; Argument 2. Why isn't [ebp + 10], since the 1st arg is a word?
	out dx, al
	
	leave
	ret
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

Is there a particular reason why, or it's just by design?
The stack should be aligned for performance reasons. In 32-bits mode, the alignment is yes, 32 bits. Everything smaller will be promoted to a doubleword.
I've just read that only words and double-words are saved on the stack and never a single byte
In 16-bit mode, the stack is word-aligned which leads us to the conclusion that only words (16-bit mode) and dwords(32-bit mode) are stored on the stack :wink:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
marcio
Posts: 14
Joined: Fri Oct 20, 2006 10:54 am

Post by marcio »

Now I get it, thanks! :)
marcio
Posts: 14
Joined: Fri Oct 20, 2006 10:54 am

Post by marcio »

I have one more question. The list of possible memory maps is known: where they start and their length.

But what about which ones are for color or monochrome displays?
And how many rows/columns do they have, in text mode?

For example, I have this struct:

Code: Select all

typedef struct {
	bool is_color;
	byte_t* start;
	size_t length;
	size_t rows;
	size_t columns;
}
Memory_Map;
Which I then use to populate an array with 4 elements (memory maps). To get the current memory map in use, I just index the array using directly the memory map select bits (bits 2 and 3) as read from the Miscellaneous Graphics Register:

Code: Select all

static const Memory_Map MEMORY_MAPS[] = {
	/* Index 00b. */ {
		false,      // FIXME: Is it?
		(byte_t*) 0xA0000,
		128 * 1024,
		25,         // FIXME: Is it?
		80,         // FIXME: Is it?
	},
	/* Index 01b. */ {
		false,      // FIXME: Is it?
		(byte_t*) 0xA0000,
		64 * 1024,
		25,         // FIXME: Is it?
		80,         // FIXME: Is it?
	},
	/* Index 10b. */ {
		false,
		(byte_t*) 0xB0000,
		32 * 1024,
		25,
		80,
	},
	/* Index 11b. */ {
		true,
		(byte_t*) 0xB8000,
		32 * 1024,
		25,
		80,
	},
};
The last memory map is the one GRUB uses and the previous is the same except it's monochrome, but what about the first 2?

Thanks!
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

Usually, A0000-AFFFF is a vga color mode. A0000-BFFFF is never used.

Technically, you can set the base address to anything and use that for what you want next. the VGA won't care. You can write a 256-color screen through B8000-0xBFFFF, (accessing half the memory available), or text through 0xA0000-AFFFF. The only difference is the base address.

If you want to check for the actual mode, read the alpha/graphics bit and the shift mode bits. based on these you can fairly safely deduce what mode you're in (text, 4-color, 16-color, 256-color).
It works unless you're called combuster and you use abuse the shift modes to make 16 color mode linear rather than planar, in which you need to check the 256-color bit as well :twisted:

determining the resolution from anything but the CRT registers is prone to fail as many different-resolution modes use the same address or even bit depth. 320x240 vs 320x200 in 256 colors, 640x480 vs 640x400 vs 800x600 mode in 16 colors, etc.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
marcio
Posts: 14
Joined: Fri Oct 20, 2006 10:54 am

Post by marcio »

I see, thanks :)
All that you just explained to me, did you read it somewhere or is just by experience?
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

He has it tattood on his right forearm. Left forearm is the ATA spec and usage examples. The multiboot spec isn't used often and so is relegated to his right shin.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

marcio wrote:I see, thanks :)
All that you just explained to me, did you read it somewhere or is just by experience?
Both.
The FreeVGA project documents pretty much everything, but rather poorly. Most of what I said above can be taken from it, although some things are kind of obfuscated so that you can't be sure how it will work exactly.
There's also, older, Michael Abrash' "Graphics Programming Black Book". (which is now freely available off the web). It documents less, but more of the things you are likely to encounter, and does a more thorough job of describing it (it uses one third of a book to document only part of the VGA, while freevga uses far less space to document it all).
Since VGA (emulation) is present on virtually all graphics cards, I decided it would be the first full graphics driver. Consequently I ran tests to see how much current video cards deviate from the behaviour documented in the mentioned sources. While among real cards the differences are minimal, emulators are less compatible with real cards. (virtualpc being the closest to the real thing). After several hours of experimenting, I drew up some conclusions and put them in VGA Hardware, in an attempt to create a more verbose description of the VGA than provided by the FreeVGA project, as well as pointing out things for practical use.

In short, trying things out for yourself makes you pick up things a bit faster :)
JamesM wrote:He has it tattood on his right forearm. Left forearm is the ATA spec and usage examples. The multiboot spec isn't used often and so is relegated to his right shin.
I had the left one removed. Now I know close to nothing about programming harddisks
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Post by jal »

Combuster wrote:It works unless you're called combuster and you use abuse the shift modes to make 16 color mode linear rather than planar, in which you need to check the 256-color bit as well :twisted:
Does this work reliably on all VGA cards? I remember that I tried it once long ago (december 1994, probably, since I only once programmed 16 color mode directly, for the Babytro credits picture sequence) and although it worked on my Trident 8900, it failed on a Tseng. Then again, I think I didn't try to make it work beyond setting the Chain Odd/Even register.


JAL
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

It should work on a VGA, and all decent clones (it works on geforces and radeon cards) However, you should be aware of the fact that the pixel ordering in linear-16 is card dependent (0x12 in video memory might be rendered as color 1, color 2, but also as color 2, color 1) Since I do not have an original IBM VGA I can't tell which version is the original one.

and no, it does not work by just setting the chain-4 registers. instead, you should enter mode 13, then disable the 256-color mode in the attribute controller.

Most emulators hate it though.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply