
                               
                           
                               
                                
              ======================================
             Hi-VGA advanced VGA programming tutorial

Hello all sceners, this is Cloaked Alien (aka can^scc) speeking.
I am a coder in a leading group called SCC, formerly known as UUP!
I code pascal and asm. (asm mostly!). This is a beginner/intermediate
VGA tutorial written to help all of you out there too make better
productions with a more perfect reality. Note: This tutorial is designed
for people that have somewhat experience with assembler and such HLLs!
But..why take your (and mine) time writing this shit? Lets begin!

-[ CONTENTS ]----------------------------------------------------------------
Part#  Topic                      Description
-----------------------------------------------------------------------------
  1    The Basics                Describing the first steps in advanced VGA
                                 progging

  2    More Advanced Features    Describing more advanced features of the VGA

  3    Optimizations             Teaches you to optimize your VGA-code

  4    3D programming            Fast-tutorials and 3d-sourcecode

  5    Informations Sources      Where the all the informations is from

  6    Epilogue                  Last words

  7    Contact Me                Some way of contacting me

  8    Disclaimer                Legal shit (computer-laws really suck!)
-----------------------------------------------------------------------------




1. THE BASICS
=============================================================================
The main thing you have to understand is that:
THE VIDEO MEMORY IS PROBABLY THE FASTEST MEMORY AVAILABLE IN THE COMPUTER,
I BELIEVE THAT IT EVEN OUTRUNS THE CACHE! And furthermore, it has a special
pin on the CPU, making it easier and more delicate to use when you prog the
PIC (read some other tutorial to find out what the PIC is, I can only say it
stands for Programmable IRQ Connector and manages all of the interrupt data).
           ^            ^   ^
First, let me explain some monitor hardware stuff:

The only thing that limits an monitors resolution is how many cables that
is connected to the screen. On modern SVGA-monitors, there is mostly 4
cables for each pixel, which gives (in a monitor with a maximum of 1280x1024
resolution with 32 bits color, which in turn gives 4 bytes, one byte per
cable) 1280 * 1024 * 4 = 5242880 cables (!) in your monitor, 4 cables making
each pixel glow. Physically, one pixel is a small plate made of a material
that glows when you put electricity on it in different colors depending on
how much power you feed it with. Each plate has (in most cases) 4 cables
connected between that plate and a controller that is located at the back of
the monitor. So, if we think for a couple of seconds, we find out that your
monitor is ALWAYS using a resolution of about 1024x768 (which is the average
max-resolution of all monitors supporting 32-bits color, maybe your monitor
uses a higher/lower res)!

If your videocard supports higher resolutions with that amount of colors,
but you monitor don't, you would make all of the cables burn up in your
monitor if you tried to set a unsupported videomode (like 1600x1280x64bpp)
since the monitor would pump the double voltage in each cable (64 bits power
on cables designed for 32 bit power).

Second, let me explain how that video pin on the cpu works:

The first thing you gotta do to access the video pin is to inititalize the
CPU for graphical access, and it is done like this:

----------------------------------------------------------------------------
1:        mov ax, 01013h      ; Get the VGA address
2:        xor edx, edx        ; Make sure to write to the right pin on CPU
3:        mov edx, ax         ; Set address to AX
4:        int 10h             ; Generate interrUUPt :)
5:        wait                ; Make sure the VGA waits for the CPU
6:        nop                 ; / Let the instruction pair  \
7:        nop                 ; \ on pentium and above CPUs /
8:        cld                 ; Clear direction flag
----------------------------------------------------------------------------

and here follows a more detailed description of each row:
1: MOV=Move, moves the correct address into the VGA
2: EDX must be empty, for else the system will crash (always make sure edx
   is empty when performing interrupt programming *general intel misstake*)
3: Tell the cpu what address we are using
4: Generate interrupt (interrupts are extremely fast low-lewel routines
   hardcoded by intel).
5: If the cpu doesnt wait for the data to get to its destenation, the data
   will be lost in the wires (cyberspace that is) in the motherboard.
(6 - 7:) This is extreme overkill; only for experienced coders! This will
  make the instruction pair on the (intel not cyrix!) pentium.
  it will make the code run about twice as fast (not necessary though).
8. cld = clear direction flag. This is if you want to WRITE to the video
  (for ex. writing pixels) memory. std = store direction flag, this is if you
  want to READ from the VGA (for ex. reading pixels)!
=============================================================================

2. MORE ADVANCED FEATURES OF THE VGA
=============================================================================
You COULD put a pixel on the screen using the snip of code above and then
writing to the linear memory at A000h, but another very fast and compatible
way of putting pixels on the screen is by using the Intel interrUUPt 10h,
function 12 (0Ch):

----------------------------------------------------------------------------
1:        mov ah, 0Ch         ; As I just said, function 12
2:        mov al, color       ; Set AL to color (color = dword = 0 - 16.8
                              ; million)
3:        mov cx, X           ; X position
4:        mov dx, Y           ; Y position
5:        mov bh, Vesa bank   ; If you are using VESA modes, this is the bank
                              ; you want to write to
6:        int 10h             ; Generate interrupt

(         nop * 2 )           ; Just add these if LOTS of int 10's is used 

(if you dont want to take advantage of the Pyramid-3D chip, this is enough!)

7:        fist ebx, ecx       ; Generate VGA-cosine table to memory
8:        mov ax, [bx]        ; Retrieve location of chip-BIOS
9:        mov ds, ax          ; Set destination segment to that location
10:       invlpg              ; Special operation (OVERKILL!!) - Get TLB
11:       xchg ebx, edx       ; Set offset according to the SVGA-3D chip
12:       int 2Fh             ; Generate SVGA-interrupt
              
13:       nop  
14:       nop  
                              ; Approx total number of cycles this proc
                                takes to perform: 28-30. Fast ENOUGH! :)
----------------------------------------------------------------------------

And again, I describe each line more closely:
1: Always when dealing with interrupt usage, set AH to which CPU pin to
   communicate with, in this case 0Ch - Set pixel
2: Tell what color the pixel should have. This can be a value between 0 and
   16.8 million ( 32 bits per pixel (looks *GOOD*) )
3: Tell what X-position the pixel should have (up to 3200)
4: The same, but for Y (up to 2560)
5: Tell the interrupt if you are writing to monitor or virtual buffer
6: Call the VGA/VESA interrupt 10h

[ THIS CODE PUTS A CONVENTIONAL HI-COLOR PIXEL ON THE SCREEN, BUT IF YOU WANT
  TO TAKE ADVANTAGE OF THE PYRAMID-3D (or compatibles) FUNKTIONS, YOU NEED: ]

7: fIST = FPU-instruction storage, and by fIST:ing ebx with ecx, you tell
   the chip that you want a VGA-cosine table (very good optimization in this
   case. Why? you ask. Because WE'RE GONNA NEED IT!)
8: Get location of the chip's BIOS into AX
9: Set destination-segment register to that very location
10: Special operation that is only implemented on 386 and above, and takes
    2 cycles to execute! This loads the VESA-interrupt table into the
    8021-chip
11: Now we know where the 3D-bios is. Call it by executing a interrupt 2Fh
12: Go! Put a pixel with the current style (flat/constant/gouraud/env/phong)
13: Let the instruction pair on pentiums (great optimization)

There... Now this might look like extremely advanced code to you, but when
you take a look at it and read the comments, it all should appear to be
purely logical and effective code. I know, for example, that Doomsday use
this putpixel-routine in there latest demo released at Asm97: Boost. And HOW
do you like those colors?
=============================================================================

3. OPTIMIZATIONS
=============================================================================
Here follows some optimizations that is good to know about when programming
VGA:

1. NEVER read/set pixels many times after eachother! READ all pixels first if
   you have to read pixels, and THEN set! This is because you have to set the
   CPU for reading/setting each time, and it takes time! Up to 20 cycles!

2. Putting two NOPs after each int 10h and int 2Fh is a good idea if you plan
   to put LOADS of pixels in a row, since the CPU will work much-much smoother
   and without any cache-collisions.

3. NEVER think "My code will go faster with a lower amount of colors"! It
   WON'T. If you use the latest putpixel routine it will go equally fast on
   256c modes and 16Mc modes! Just mail me for an explanation how 16M colors
   can go as fast as 256 colors. I don't have time do explain that here.

4. Locating your doublebuffers (aka virtual screens) in the videomemory is a
   extremely good idea if your demo doesn't use all of the 1 Meg standard
   amount of videomemory today. To move 256k at 32-bit offset VIDBUF in the
   videomemory to the 32-bit offset A0000h in the conventional memory, use
   this snippet of code:

        (push some registers)

          mov ax, 01013h      ; Get VGA address
          xor edx, edx        ; Clear EDX state
          mov edx, VIDBUF     ; Source offset
          bswap edx           ; Set EDX to little-endian byte order
          int 10h             ; GO!!!!
          wait                ; Let the data be cut!
          nop                 ; Pentium pairing (no effect on 486s)
          nop                 ; Pentium pairing (no effect on 486s)
          add ax, 00100h      ; Function 0113h - Set VGA address
          xor ecx, ecx        ; Clear ECX state
          mov ecx, 0A0000h    ; Target offset
          mov ebx, 40000h     ; 256k 
          bswap ecx           ; Set ECX to little-endian byte order
          int 10h             ; GO!!!!
          wait                ; Let the data be pasted!
          nop                 ; Pentium pairing (no effect on 486s)
          nop                 ; Pentium pairing (no effect on 486s)

         (pop some registers)

   That's a FAST one. Now you think "Hey! I estimate that one to a LOT of
   cycles! How can it be fast!?", but do not fear; the videomemory is so much
   faster that normal RAM that it fully compensates that. Furthermore, the
   int 10h service 10h - Get VGA address is so EXTREMELY fast that it even
   more outruns the normal "rep movsd" (or whatever you use) operation! With
   this baby, I can copy 7540 512k-screens per second on my P90. I call that
   enough :).
=============================================================================

4. 3D PROGRAMMING
=============================================================================
Sorry, yet to be implemented, since I still haven't got any experience with
3D-code using the AVGI (Advanced VGA Graphics Interpreter) methods mentioned
up there... Look for a newer version of this document (VGA02.TXT?).
=============================================================================

5. INFORMATIONS SOURCES
=============================================================================
The information about the VGA-block and the CPU utilization code was found in
the following books:

      ADVANCED 32-BIT VGA PROGRAMMING
      Christopher D. Watkins and Stephen B. Coy
      M&T Books, Inc., 1996
      ISBN: 1-55851-247-0
      Price: $44.95

      PHOTOREALISM USING CPU AND VGA
      Michael Hughes and Robert R. Lundstrom
      Digimedia Press, Inc., 1994
      ISBN: 1-55851-383-3
      Price: $34.95

The information about advanced 3D chips and their APIs can be found in:

      ADVANCED GRAPHICS PROGRAMMING IN WATCOM C
      Roger Stevens and Christopher D. Watkins
      M&T Books, Inc., 1997
      ISBN: 1-55851-171-7
      Price: $39.95
=============================================================================

6. EPILOGUE
=============================================================================
Well, that just about finishes it. If you use any of the techniques I have
described, I would very much appreciate some credits for it in your future
production. For an executable file that shows the power of this technique,
look at my homepage (URL below). See ya in the next version of Hi-VGA!
=============================================================================

7. CONTACT ME
=============================================================================
Here are some ways of contacting me:


      Via E-mail:

      canscc@guests.coolcaps.com    -     Primary adress, try this first
      barbatron_ste@hotmail.com     -     To my friend (helped me with asm)
      canuup@hotmail.com            -     Try to avoid this one. Slow feedbak

      Via World-Wide-WWW:

      http://hem2.passagen.se/barba666/
       or
      http://www.koolwebb.arla.se/~heikos/scc/
       OR
      http://www.itdata.solna.se/uup/main.html

=============================================================================

8. DISCLAIMER
=============================================================================
Sorry, yet to be implemented. Look for a newer version of this document
(VGA02.TXT?).
=============================================================================






      





