 Ex-planed (;))                   
                                              
                                      
                                          
                                         
                                        
                                      
                                            
                          
                         
                           
                           
                           
                                
                                
                    
 The Bitripper 

Ok guys, for the re-bound. Here's The Bitripper bringing you, coders all over,
_*THE*_ invitation to the so-called tweaked modi. Well, actually this is only
describing the 320x400x256 mode, but there are enough trainers to cover the lack
of this one. BTW, this one is only meant to correct some mistakes which I found
through many trainers, it's not a complete guide on the VGA programming subject.
If you want a complete guide, buy a good book (a thing with papers stuck inside
a hard cover). E.g. Programmers Guide to the EGA/VGA, Richard E. Ferraro,
PC Intern 4, or use some all-round hypertexts, e.g. HelpPC, Tech!Help.

Assumptions: knowledge of ASM, color VGA card in possession, 16-bit programming,
             little knowledge of VGA registers and ports programming

Enclosed in this package should be the following files:

UNCHAIN.TXT  - This textfile
XMODE.ASM    - Example code, changing to XMODE and displaying a 256 color
               picture two times
PALETTE.INC  - Palette for picture shown by XMODE.ASM (is included and must be
               in the same directory)
PICTURE.INC  - Picture shown by XMODE.ASM (is included and must be in the same
               directory)
DESCRIPT.ION - 4DOS Description file
MAKEFILE.    - MakeFile for Borland's MAKE utility
XMODE.EXE    - Compiled and packed version of XMODE.ASM
FILE_ID.DIZ  - File ID for BBS's, please do not remove


Ŀ
 INTRODUCTION ۲


Let me introduce you into my experience with learning about the so-called
tweaked modi (hereafter: xmode).

When I first started to have a look at the xmode, it was basically coz' many of
other productions were using the xmode mainly due to it's higher resolutions.
Everybody was using the xmode, so there had to be something very special about
it, and I got very interested in learning every aspect of the xmode.

I got myself a book (borrowed from a friend of mine). A very good book actually,
the Programmers Guide to the EGA/VGA second edition of Richard E. Ferraro.
In it, there was a total, bug-free description of each VGA register and the way
each part of yar VGA card works. I used it as a reference while I was examining
the xmode code of other programmers and while reading the trainers about the
subject.

I encountered some slight problems while implementing the ideas I got from all
the different trainers. For example, I got myself running into the double-word
modus over and over again because I was anxious to know every bit (literally!)
of the code changing the normal BIOS mode 13h into xmode before I would use it
(as I do with all the rest of the effects etc.).

So, when my friend needed his book back, and I still hadn't found out what the
double-word modus was about, there was some kind of disappointment.

That was until I bought myself PC Intern 4, and started to read in it.
Although, there are quite a few mistakes, even faults and don't mention errors
in the book. With the help of some hypertexts and the PC Game Programmers
Encyclopedia I finally found out what _*EXACTLY*_ this double-word modus
was about.

But hey, enough of this crap. Let's get ya all back to business with the xmode
explanation.

Press cursor down key when ready... ;)


Ŀ
 BIOS MODE 13h vs. XMODE ۲


The xmode has (obviously) advantages above the BIOS mode. Unfortunately, it also
has some disadvantages which must be taken into account when choosing which mode
is going to be used. XMode is not all of the time recommended. I'll show you:

Advantages for BIOS mode 13h:
- Can address all pixels in one segment.
- No need for handling the read/write plane coz' it's automatically selected for
  you (plane number is taken from the offset).
- No need for more code to initialize, only one call to standard BIOS
  video interrupt.

Disadvantages for BIOS mode 13h:
- Only one page for displaying graphics, so no page-flipping can be performed in
  the VGA memory itself.
- Low resolution, 320x200 (although it's actually 320x400, as you'll see l8ron).
- 192 kB of VGA memory is wasted due to the easy accessibility.


Advantages for XMODE:
- Page flipping can be performed using the VGA memory.
- Up to 4 pages can be used.
- Any resolution can be set by programming the VGA registers directly.
- Scrolling of large pictures is easier.

Disadvantages for XMODE:
- Every pixel read/write must be directed to one or more planes.
- Extra code to initialize xmode.


Ŀ
 VGA HARDWARE ۲


The VGA memory consists of four 64 kB planes (see them as large arrays).
In normal BIOS - or 'chained' - mode, these planes are chained together
so that an easy addressing is possible, eliminating the need of specifying each
plane before writing to or reading from it. Planes are numbered from 0 to 3.

For each offset you write to or read from, the two lowest bits of the offset
are used to determine the plane to write to or read from. If, for example, you
write a byte with value 0fh to offset 5h, what plane would it end up ?
Well, take a look at the example:

Offset 0005h = 0000 0000 0000 0101b
                                ^^
The lowest two bits of the offset address are 01b, which equals 1.

Then, the offset is shifted two bits to the right to loose the plane bits.

Offset 0001h = 0000 0000 0000 0001b

To determine the offset within the given plane, the offset is shifted two bits
to the left:

Offset 0004h = 0000 0000 0000 0100b

Thus, writing 0fh to offset 5h in the video memory area results in writing 0fh
to plane 1 at offset 4h within that plane.

When the BIOS mode is initialized, the memory looks like this (where the numbers
in the different planes corresponds to the numbers in the video memory area):

0                                                                         319
Ŀ  0
01234567                                                                   
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           
199
Video memory area as 'seen' by the coder (this is actually also the VGA memory)


         Plane 3 01234567Ŀ
           (11b) 37                                                     
                                                                              
                                                                               
      Plane 2 01234567Ŀ  
        (10b) 26                                                       
                                                                             
                                                                              
   Plane 1 01234567Ŀ    
     (01b) 15                                                         
                                                                            
                                                                           
Plane 0 01234567Ŀ    
  (00b) 04                                                         
                                                                         
                                                                       
                                                                       
                                                                       
                                                                     
                                                                     
                                                                     
Real plane dividing in the memory of the VGA (chained mode, double-word mode)

The '' denotes an empty, unused byte. You see, for each four bytes in a plane,
3 bytes are not used. As each plane contains 320*200 bytes and there are four
planes, there are 320*200*4 bytes = 256000 bytes total of which  is used.

So, actually,  of a plane is used, which equals  16 kB. The bytes are all over
a plane, with gaps of three bytes between them. As the planes and offsets
within planes are automatically selected, we can't use the gaps for any other
data. Thus, in order to get more than one display page, we must get rid of the
gaps between the data (or, make them smaller) !


 Chain4, Odd/Even, Linear 

When the standard BIOS mode is invoked, the chain4 mode is used. Chain4
mode is explained above. There is the odd/even mode too, where there's also a
sort of automatic selection of the plane and the offset within the plane. In
odd/even mode, the lowest bit (LSB) of the offset address together with the page
bit in the miscellaneous register of the graphics controller is used to
determine the plane and offset in a kind of similar way as chain4 does that.
Odd/even mode is not interesting enough to describe here in detail.

As we want to address all of the 256 kB memory of the VGA card, we are not going
to use the chain4 mode, nor the odd/even mode. We are going to set the VGA card
to use a sort of linear mode, so we can address every single byte in a plane.
That will give us access to 256 kB memory. While we are able to address all
memory, we can then use four different display pages (at a resolution of
320x200).


 Double-word, word, byte 

In BIOS mode, double-word mode is set. This means, for each information byte,
there are four bytes to be read (two bytes is a word, four bytes is a
double-word). The VGA card has the opportunity to use one of its three modes:
Double-word mode, word mode and byte mode. In odd/even mode, word mode should be
used. For our purposes (four display pages), byte mode should be used, as the
bytes in the planes will succeed each other, with no gaps.

In short: if double-word mode is set, there are four bytes to read each time one
information byte is wanted. In word mode, there's need to read two bytes of
which one is containing real information. In byte mode, one byte needs to be
read as each separate byte contains information.

As a nasty result (sometimes handy), we will have to tell the VGA to which plane
we will write, because the offset no longer gets shifted to determine the plane
and offset within the plane to write to.

Sometimes this comes in handy, because you can specify more than one plane to
write to. You can, at utmost, set four pixels at the same time to the same
color, by selecting all planes for writing and writing a byte to an offset.
Think about this when you're starting to write code to quickly fill areas on
your screen, for example polygons. With a simple stosb, you can set 4 pixels at
one time, with a simple stosw you then can set 8 pixels to the same color at
once. Or better: on a 386 or higher, you can use stosd. With stosd, you can set
16 pixels at once. Now, isn't that fast ?

To give you more grip on this, I'll exercise the extended ASCII charset again:

         Plane 3 01234567Ŀ
           (11b) 37                                                           
                                                                              
                                                                               
      Plane 2 01234567Ŀ  
        (10b) 26                                                             
                                                                             
                                                                              
   Plane 1 01234567Ŀ    
     (01b) 15                                                               
                                                                            
                                                                           
Plane 0 01234567Ŀ    
  (00b) 04                                                               
                                                                         
                                                                       
                                                                       
                                                                       
                                                                     
                                                                     
                                                                     
Real plane dividing in the memory of the VGA (unchained mode, byte mode)

As you see, one offset now denotes four pixels. As mentioned before, you'll have
to select which planes to write to before setting a pixel.


 Four different pages 

Now, we have room for four different pages, we can also select them, but how to
display each page ?

There are two registers, which together hold the offset in the video area to
begin displaying at. As each screen is 320x200 big, it needs 64 kB.
64 kB is divided over four planes per screen, so a page needs 64000 / 4 = 16000
offsets for being set-up. The first page starts at offset 0000h, the second at
4000h, the third at 8000h and the fourth at 0c000h.

To accommodate this for your set pixel routine, you can add the offset value
divided by 10h to your segment address, so you don't have to bother about the
starting offset anymore. You simply set your segment to 0a000h for page 0,
to 0a400h for page 1, to 0a800h for page 2 and 0ac00h for page three.
Then, offsets for a page are valid from 0000h to 3e80h.


 Writing to or reading from one of the pages 

Writing to a plane is done by first selecting the plane(s) to which to write,
and then writing a byte to a chosen offset. You can select the plane by using
the map mask register of the sequencer controller. It is build as follows:

  7   6   5   4   3   2   1   0
Ŀ
                           

                         
  Ĵ             0: No access to plane 0
                              1: Access to plane 0
                        0: No access to plane 1
                               1: Access to plane 1
                     0: No access to plane 2
                                1: Access to plane 2
                  0: No access to plane 3
                                 1: Access to plane 3
               Not used (0)

For reading operations, the read map select register of the graphics controller
must be changed. This register's layout is:

  7   6   5   4   3   2   1   0
Ŀ
                              

                           
  Ĵ    Number of plane to read from
                      
                       Not used (0)


 Displaying different pages 

To display one of the pages, you must set the offset of a page in the two
registers called Start Address High and Start Address Low of the CRT controller.
The high byte of the offset is placed in the start address high register,
the low byte in the start address low register.

You can write to another page than you're showing on the screen, using the
technique described above. With that in mind, you can do page-flipping (i.e.
draw something on one page, while displaying the other and then swapping them by
displaying the one you were drawing on and the one you were showing and do it
all again with the swapped pages) and hereby eliminating the flicker or vertical
retrace which is often annoying our presentation. Note that this manner is a
whole lot faster than copying 64 kB each time!


 320x400x256 

Well, where is that 400 pixels y resolution I promised you ?
This one is really unexpected (well, I mentioned it at the start of this
trainer): on the VGA card, there actually isn't a 200 y-resolution available.
Instead, to keep the addressing as simple as possible AND providing a 256 color
mode within the 256 kB boundary, the makers of the VGA card have come up with,
well, logic, but unexpected scheme. By the way, this is also the reason why the
pixels in 320x200x256 mode look so, like squares ( ;)). The lines displayed
from the memory are just being doubled as they are displayed on the screen.
So, one line really occupies two lines on the screen. With this solution, the
memory can contain only 200 lines, but the screen will display 400 lines.

Now we've unchained the planes, and are addressing them linear, we can set the
VGA to display 400 lines very simple.

The maximum scanline register of the CRT controller is build in this manner:

  7   6   5   4   3   2   1   0
Ŀ
                            

                          
            (Times-1) to copy a line on the screen
        
         EGA: No function
                                VGA: Bit 9 of start vertical blanking register
      EGA: No function
                                 VGA: Bit 9 of line compare register
   EGA: No function
                                  VGA: 200 points doubling mode

Bits 0-4:       Times-1 to copy a line. If, for example, these have the value 5,
                all lines will be displayed four times, bringing the real
                displayed lines to 200 / 4 = 50 lines.
Bit 5:          Bit 9 of the start vertical blanking register
Bit 6:          Bit 9 of the line compare register
Bit 7:          0 = line doubling off
                1 = line doubling on


Now, two pages are left. One starting at 0a000h:0000h and the other at
0a000h:8000h. Or, with the accommodation: 0a000h:0000h and 0a800h:0000h.


 Used registers 

When switching over to xmode from within BIOS mode 13h, some of the VGA
registers must be re-programmed. The registers used are:

From the CRT controller (controls the Cathode Ray Tube, or monitor):
- Maximum scanline register             (9h)
- Start address high byte              (0ch)
- Start address low byte               (0dh)
- Underline location register          (14h)
- Mode control register                (17h)

From the sequencer controller (controls the way memory is being displayed):
- Map mask register                     (2h)
- Memory mode register                  (4h)

From the graphics controller (controls reading/writing to VGA memory):
- Read map select register              (4h)
- Graphics mode register                (5h)
- Miscellaneous register                (6h)

The CRT controller is accessed through port 3d4h and 3d5h (mono: 3b4h and 3b5h).
The sequencer controller is accessed through ports 3c4h and 3c5h.
The graphics controller is accessed through ports 3ceh and 3cfh.


Ŀ
 BIOS MODE 13h -> 320x400x256 ۲


Follows: a complete step-by-step description of switching to the xmode,
         using ASM code to help you implementing:

In the code, I use macro's for the ease. I don't have to re-type each block of
statements (which reduces the errors). A macro is called by just typing its
name. If there are parameters valid for a macro, you must specify it/them behind
the macro's name, separated by ",".
You'll see what I'm trying to say when you see the source code hereafter.
Consider the following macro's:

Select          MACRO   Controller,Register
                mov     dx,controller           ; Select address register
                mov     al,register             ; to put register index number
                out     dx,al
                inc     dx                      ; Select data register
                in      al,dx                   ; Input current value to AL
                ENDM

Other           MACRO   Register
                dec     dx                      ; Select address register
                mov     al,register             ; to put register index number
                out     dx,al
                inc     dx                      ; Select data register
                in      al,dx                   ; Input current value to AL
                ENDM

Put             MACRO
                out     dx,al                   ; Save value of AL to register
                ENDM



To start, change to BIOS mode 13h using sub-function 0h of int 10h:

                mov     ax,13h
                int     10h

Then, change the memory mode register so that the chain4 as well as the odd/even
mode is disabled, but preserve the lowest two bits, coz' they are not of our
concern:

                select  seq_c,memory_mode
                and     al,00000011b            ; Clear & preserve lowest 2 bits
                or      al,00000100b            ; Chain4 & Odd/Even mode off
                put

Change the graphics mode register so that a linear mode is being used by
clearing bit number 4, but preserve the rest of the bits. Again, they are not of
our concern:

                select  gfx_c,graphics_mode     ; Set linear mode
                and     al,11101111b
                put

We do the same thing in the miscellaneous register of the graphics controller,
but we clear bit number 1 instead of bit 4:

                other   miscellaneous           ; Set linear mode
                and     al,11111101b
                put

Remember, we had to change from double-word mode to byte mode by turning of
double-word and word mode. We'll do this by clearing bit number 6 of the
underline location register of the CRT controller for the double-word mode, and
by setting bit number 6 of the mode control register of the same controller:

                select  crt_c,underline_loc     ; Double-word mode off
                and     al,10111111b
                put

                other   mode_control            ; Word mode off, byte mode on
                or      al,01000000b
                put

And last but not least, we turn off line doubling and line copying to get 400
lines on a screen by clearing bit number 7 and bit number 3 to 0 of the maximum
scanline register of the CRT controller:

                other   max_scan_line           ; 320x400x256
                and     al,01110000b
                put

With the map mask register of the sequencer controller, we can control which
planes to write to. As we want to clear all planes, we select all planes for
writing by setting bit number 3 to 0:

                select  seq_c,map_mask          ; All planes on for writing
                or      al,00001111b
                put

Finally, we're clearing all planes by writing a zero word 32768 times (setting
all the 256 kB to zero) to the VGA segment 0a000h (thus, starting at page 0):

                mov     ax,0a000h               ; Set ES to VGA segment (0a000h)
                mov     es,ax
                xor     di,di                   ; and DI to offset 0000h
                mov     cx,08000h               ; The number of words is 32768
                xor     ax,ax                   ; Put a zero word 32768 times to
                rep     stosw                   ; ES:DI



That's all there is !

Now, you're ready to get exciting and beautiful graphics in a higher resolution,
with still 256 colors, and two pages, for use with page-flipping !!


Ŀ
 DISCLAIMER ۲


Well, as usual, the author of this text is not responsible for any damage caused
by the use or misuse of this text, bla, bla, har, har, nag, nag, etc.......


Ŀ
 EPILOGUE ;) ۲


Hey, when you do any productions, using above explanation or something,
greet me !! I'd like that.....

You can usually contact me at EightBall, +31-546-829093, just write a private
message to The Bitripper. If that doesn't work, Ash soon has got his board up
and running again, so you can find me there also. I'll see you around...

Happy coding!

                        - The Bitripper -


Ŀ
 GREETS ۲


Greets go out to (alphabetical order):

Ash       - Hiya!
Evil      - Long time no see (hear no Evil, see no Evil ;))
HeXoN     - Having a good time?
Lord Addu - Hear you've got another job?
R.L.      - Don't know your current handle

and the rest of the people I forgot to mention here...
