Contributor: DAVID MOHORN þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ þþþþþþþþ SyNeRgY DeSiGn presents a production by LORD HELMET þþþþþþþþ þþþþþþþþ MODE X þþþþþþþþ þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ The purpose of this file is to provide the information necessary for using mode x in your programs. Some knowledge of the VGA card and assembly program- ming are required to understand this text, although I'll try to make it as complete and easy as possible. I was working on a textfile about 3D graphics, but this will be delayed for a while since I started experimenting with the VGA card some time ago. This file should be an even greater help for coders so it will surely make up for this delay. What is mode x ? ---------------- Now there's a difficult question and to be honest, I can't really answer it. Ask this question to ten coders and you will get at least five different answers. The problem is : mode x is non-standard. In my opinion it's the ordinary mode 13 hex (320x200x256) with some registers altered adding some pos- sibilities to the normal graphics output. Mode x is a great help for programs that require fast graphics output and it's excellent for scrollers. Before I go on I will explain some things about mode 13h and the VGA card in general. If you know the VGA card well enough you can skip this part, but don't go thinking "hey, I don't need this VGA crap" too easily, because the clues to mode x are included in the following paragraph, so I would surely advise you to read it. The VGA card & mode 13h ----------------------- As you may know by now, the VGA card's memory is mapped into the computer's central memory at segments A000h & B000h. In most modes, these segments aren't both used at the same time, but one's used for color output (segment A000h), whereas the other is used for monochrome output (segment B000h), allowing more than one graphics card to be present in your computer. Segment B000h isn't nor- mally used in mode 13h with color output (there are some VGA cards which do allow the use of the second segment, such as the Trident cards), so forget about that one. Segment A000h is the important one. Now, when normally using this part of memory for graphics output you might think that it is organized as follows : ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ OFFSET 0 ³. <- pixel 0 ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ OFFSET 63999 ³ pixel 63999 ->.³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ What this means is : the VGA memory would be organized as one big chunk of memory, 64000 bytes long. If you still think this is the case, FORGET IT. The VGA memory ISN'T organized like this, but in bitplanes. Those of you who have worked with EGA must surely know what programming with bitplanes means. Let's take a look at how the VGA memory really is organized : Bit plane 3 -> ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ - Bit plane 2 -> ÚÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ | Bit plane 1 -> ÚÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ | each plane Bit Plane 0 -> ÚÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ | is 64000 ³ ³ ³ ³ ³ | bytes long ³ ³ ³ ³ ³ | ³ ³ ³ ³ ³ | ³ ³ ³ ³ ³ | ³ ³ ³ ÃÄÄÙ - ³ ³ ÃÄÄÙ ³ ÃÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ So, as you can see, the VGA memory consists of four bit planes of 64000 bytes each, just like the EGA. All four bit planes are mapped at adress A0000h. The way the bit planes in VGA mode 13h are used differs from the EGA. In EGA modes the bit planes are used to determine the value of the pixels (0-16). They are (in EGA) organized as four 64000 bytes long bit chains (and not byte chains). In VGA mode 13h they are organised as four byte chains. The four bit planes are chained together and the pixels are spread over these bit planes. More specific : the first pixel = pixel 0 (1 byte) is mapped in bit plane 0 at offset 0, pixel 1 is mapped in bit plane 1 at offset 0, pixel 2 in bit plane 2 at offset 0, pixel 3 in bit plane 3 at offset 0, pixel 4 in bit plane 0 at offset 1 and so on. So far for the VGA mode 13h. A first question that pops up is : how come I don't notice the fact that the pixels are chained over the four bit planes when using mode 13h ? Well, because this is done automatically by the VGA card. It looks at the two least signifi- cant bits in the offset address to determine on which plane the pixel should be mapped. The offset within this bit plane is the original offset divi- ded by four. This may sound confusing, so here's an example : Suppose I want to set the pixel value of the pixel at position (50,50) to 150. Therefore I would change the byte value of the byte at address A000:3EB2 (offset = 50*320 + 50 = 16050 = 3EB2 hex) to 150. In assembler it would look about like this : mov ax,0A000h mov es,ax mov di,3EB2h mov al,150 stosb Now, the VGA card will look at the 2 least significant bits in the offset, in this case 3EB2h = 0011111010110010 binary. These bits are 10 binary = 2, so the pixel will be mapped in bit plane 2. The offset within this bit plane is 3EB2h / 4 = 0FACh = 4012. This automatic mapping is also the reason why you can only access one page in mode 13h (a page is a piece of memory on the card large enough to contain an entire screen, so in mode 13h a page is 64000 bytes long) : since the offset range is limited to 65536, it's impossible to reach the other 3 pages (don't try using 386 inctruction code to force 32-bits offsets, it won't work). Those of you who have tried to make smooth animations such as vectors, sprites and scrollers know that it's impossible to achieve this when accessing the VGA memory directly. A first solution here would be to use a 'virtual page' : a 64000 bytes long array in central memory in which the screen output is first built and then copied to the screen. This works but has 2 disadvantages : it takes 64000 bytes and has to be copied (which takes some time). Therefore, a multipage system is the best solution : several pages allowing pageswapping and no time is lost during the swapping. As you already noticed, it's impossi- ble to achieve this in standard mode 13h (except for some cards, which use seg- ment B000h as a second page), although there's enough space for four pages. This is where mode x comes in. Mode x - that's the way to do it -------------------------------- All the previous problems are solved by changing the normal graphics system to mode x. This is achieved by changing the chain four bit in the memory mode register (port 3C4/3C5, index 4) from 1 to 0 (on some cards it's necessary to alter more than one register, but I'll get to this later). What effect does this have ? Simple, it just disables the automatic mapping and allows the user to access the bit planes himself. This involves some changes in the way graphics output should be used. First, after this bit has been altered, you gain control over all of the 256000 bytes video memory (4 pages in 320x200x256) Second, since the automatic mapping is disabled, you have to access the bit planes yourself (the chained bitplanes system remains, so you have to do exact- ly what the VGA card does with automatic mapping). Last but not least, you have to know how to change the current page. We'll get back to this later, first a sample code which shows how to change to mode x (you have to change to mode 13h first) : mov dx,3C4h ; select sequencer registers mov al,4 ; index 4 -> memory mode register out dx,al inc dx in al,dx ; read the original value and al,NOT 8 ; turn off chain 4 (bit 3) or al,4 ; turn off odd/even (bit 2) out dx,al ; write the new value mov dx,3CEh ; select graphics controller registers mov al,5 ; index 5 -> mode register out dx,al inc dx in al,dx ; read original value and al,NOT 16 ; turn off odd/even (bit 4) out dx,al ; write new value dec dx mov al,6 ; index 6 -> miscellanous register out dx,al inc dx in al,dx ; read original value and al,NOT 2 ; turn off chain odd/even (bit 1) out dx,al ; write original value mov dx,3D4h ; select CRCT registers mov al,14h ; index 14h -> Underline location register out dx,al inc dx in al,dx ; read original value and al,NOT 64 ; turn off doubleword (bit 6) out dx,al ; write new value dec dx mov al,17h ; index 17h -> Mode control register out dx,al inc dx in al,dx ; read original value or al,16 ; turn on byte mode bit (bit 6) out dx,al ; write new value As you can see this sample code does nothing exceptional, it just alters cer- tain bits in certain registers. The odd/even bits have to be changed to ensure that the way the video memory is accessed is as I described above. Not changing these bits can screw up the output (I'm not going to explain what these bits do exactly, but take it from me : change them). The doubleword / word-byte bits have to be changed to make sure all of the video memory can be accessed. As I already explained, the chain four bit is the important one, but make sure to change the others too for compatibility (only changing the chain four bit works fine on my card, but I know it doesn't on some other cards). Now that we know how to change to mode x, let's continue with the second step, putting something on the screen (or rather on one of the pages). Let's use the same example as for the standard mode 13h : suppose I want to change the pixel value of the pixel at position (50,50) to 150. In normal mode 13h this would involve changing the value of the byte at address A000:3EB2 to 150. In mode x this means I have to do what the VGA card normally does for me : change the byte value at offset 0FACh in bit plane 2 to 150 (look at the previous example if you don't understand how I found these numbers). This is what it would look like in assembler : mov ax,A000h mov es,ax ; select VGA memory segment mov dx,3C4h ; select sequencer registers mov al,2 ; index 2 -> map mask register inc dx mov al,4 ; change value to 4 : enable plane 2 only out dx,al mov di,0FACh ; set offset to 0FACh mov al,150 ; value to write stosb Nothing special here either. Now suppose I want to access a different page than page 1 (say page 3). Quite simple, just increase the offset by 32000. Here's an overview of the offset ranges for the four pages in mode x : page 1 : OFFSET 0 - 15999 page 2 : OFFSET 16000 - 31999 page 3 : OFFSET 32000 - 47999 page 4 : OFFSET 48000 - 63999 If you try this out you will notice that it's impossible to see the changes on the other pages (the current page selection interrupt routine doesn't work). You have to select the current page through the Start Address. What exactly is this ? Consider the screen as a window through which the contents of the video memory can be viewed. In standard mode 13h this screen is as large as the accessable video memory. In mode x the accessable video memory is four times larger than as the screen size. The Start Address is used to determine which part of the video memory is shown on the screen. Suppose I use the offset ranges as shown above and I want to view page 3. Therefore, I would have to change the Start Address to 32000. To alter the Start Address two registers have to be changed : Start Address High and Start Addres Low. The reason for this is the fact that the start addres is an offset and therefore a 16-bit value, whereas the VGA registers are 8 bits large. Start Address High con- tains the 8 most significant bits of this 16 bit value and start address low the 8 least significant bits. Enough blabla; here's an assembler code which changes the start address value to 32000 (standard value is 0) : mov dx,3D4h ; select CRCT register mov al,Ch ; index 12 -> start address high out dx,al inc dx mov al,125 ; 32000/256 = 125 out dx,al ; write new value dec dx mov al,Dh ; index 13 -> start address low out dx,al inc dx xor al,al ; start address low = 0 (32000 mod 256 = 0) out dx,al ; write new value (not really necessary since ; standard value is 0) That's about all there's to know about the use of mode x. Some things remain to be told though, especially about certain applications for mode x. Mode x - pro's and con's ------------------------ Now that you know how to use mode x, let's take a look at what can be done with it. A first and easy application is, of course, a pageswapping routine. Since more than one page is available pageswapping lies at hand. Only two pages are needed for this purpose, but the two spare pages can come in handy. A great ad- vantage here is the fact that, although being non-standard, mode x works on all VGA cards (as far as I know). This is not the case with the Trident swapping routine I mentioned earlier (Flame here to the coders who still use this tech- nique; I know it's easy, but it only works on a quite small number of PC's). Another great use of mode x is a scrolling routine (both vertically and hori- zontally). By changing the start address by a certain amount continously, you can scroll through the different pages. Try experimenting with this a bit and you'll surely get some nice results. Last but not least, mode x is great for combining with other applications such as split screen and tweak mode (I'll get back to this one in a moment). Again, experiment and you'll be astounished by the numerous advantages of mode x. Now, after all these advantages you may get a bit too optimistic. Sorry to kill the mood like this, but there are also some great disadvantages to mode x. First, suppose you want to display an ordinary 320x200x256 picture in mode x. Since the pages are spread over 4 bit planes, you'll need to access them (the bit planes) every time you put a pixel on the screen. For a picture that is not real-time calculated, there's a simple solution : divide the picture in 4 , one picture for each bit plane. This way you only have to access the map mask register four times. For other real-time applications such as vectors, it isn't all this simple. Suppose I want to put a wireframed vector on the screen. I would have to change the linedrawing routine making it more complex. The most simple solution is to calculate the new offset/bit plane for every pixel in the line. This is the easiest solution, but also the slowest. A second solution is to change the routine so that it draws 4 dotted lines on each bit plane, reducing the number of map mask register accesses to 4. It's a real drag to code, but it's the fastest way. A third possibility is to draw real-time pictu- res on a 'virtual page' and then overlay it on the video pages. This is also easy but slow. As you can see, I haven't figured out a good solution for this problem, so if you have, please do let me know. Mode x, mode y, tweaked mode, etc ... ------------------------------------- As I mentioned before, mode x works on all VGA cards - although being non- standard - but as I also mentioned before, it means something different to some other coders. This bring us to mode y and tweaked mode. I can't really tell what mode y is exactly, but I guess it's similar to tweaked mode (if some- one knows what it is, let me know). Tweaked mode probably sounds more familiar to most of you. It's also a non-standard mode (or rather modes) which also works on all VGA cards and allows resolutions such as 320x400, 360x480 and so on. The problem here is that tweaked mode implies mode x, since it's necessary to access more than 64000 bytes of video memory. This makes it all a bit con- fusing and I guess mode x and tweaked mode are one and the same to a lot of coders. There are lots of sources available for mode x and tweaked mode, but they are (unfortunately) almost always combined. I didn't find any file explai- ning how mode x works with a 320x200 resolution. This is also the reason why I wrote this textfile. I sure hope it helped you out and saved you the time it took me to find out how mode x works. If you want to find out more about tweaked mode, I would advise you to get one of the so many files available on most BBS's (such as The Graphics Engine or VGAkit). Epilogue -------- Yep, this is about it. There isn't anything left to tell about mode x - at least nothing I can think about. If you do have questions or experienced pro- blems with this text, be free to let me know. Try not to ask too simple questions such as "what's a pixel ?" or "hey, I disassembled my mouse but didn't find the VGA card", I won't respond to those. Don't ask me to teach you everything on the VGA card or on assembler either, just things that concern mode x. You can try to contact me concerning coding in general too. Here's where you can reach me : BBS's : ------- ZEUS : +32-(0)9-264.47.51 (refer to THOMAS VIDTS) BUSTER : node 1 : +32-(0)53-77.23.47 (refer to RETARD ED) INTERNET ADDRESS : VIDTS@WET.RUG.AC.BE