**************************************
*     W E L C O M E  T O  T H E      *
*   G A M E S  'N  G R A P H I C S   *
*     T R A I N E R  S E R I E S     *
*            Chapter I               *
*                                    *
*            by Gerben               *
**************************************

A long time ago...
(HALT !!!  I mean Introduction)

Hello fellow programmers,

This trainer is ment to lead all the newbies in the world of programming
through the wild jungle of bits and bytes. When you read these trainers,
I think you'll be able at the end to make your own simple games and/or 
demo's. Oh no!! Not another trainer I hear you yelling!! There are good 
trainers like those of Denthor of Asphyxia. Sure I've to admit that, but 
I'll try to make a humble sequel to his fine set of trainers. This means 
that the first copple of trainers will be farely the same (I have to 
start somewhere...). So, if you read Denthor's trainers allready then 
skip those parts that sound familiar to you and dive into a somewhat more 
advanced chapter.

In this very first chapter I will explain how to get into graphics mode 
and how to draw something on the screen. In order to try the sources I'm 
giving you through this trainer I assume you have a computer capable of 
showing the 320x200x256 VGA-mode and you have a C-compiler good enough to 
work with inline assembler.

Why using 320x200x256 (or mode 13h so you like) to program our games and 
demo's? The answer is very simpel. This is the most popular, easy to 
program and fastest video mode there is. YES!! That's what we like: 
stunning graphics blown through your screen with an amazing speed! So 
let's wait no longer and find out how things work.

----------------------------------------------------------------------

How to get into mode 13h?

To accomplish this we only need a little bit of assembler. There are lots 
of manuals telling you how to do that. Basically they all come down to this:

- Put the desired mode into ax. (for our purpose 0013h)
- Call interrupt 10h

Sounds fine with me I hear you saying, but how I'm gonna do that? Well, 
take a closer look at the following piece of code.

  void SetVideoMode(int mode)
  {
    asm {
      mov ax, mode     // drop desired mode in ax
      int 0x10         // et voila...
    }
  }

It's that easy!! Nothing more, nothing less. From now on you only have to 
call this function using 13h as parameter and WOOPIE you're at the party!! 
To return to text mode you simply call this function again, except your 
parameter is this time 03h and you're back where all the fun started...

----------------------------------------------------------------------

Our first steps into the jungle

In mode 13h the video screen is 320 pixels wide and 200 pixels height with 
256 colors. This means that the total amount of memory needed to represent 
the screen is 320x200=64000 bytes. This is a little bit less than 64K, so 
we don't have to calculate the right adresses in memory each time we want 
to put a pixel on the screen! We only have to use the right segment! Ok, 
that's very nice, but where starts this little junk of memory? Let me tell 
you right away. It's starts at A000:0000 and it ends at A000:F9FF. A little 
calculation with hexadecimal math teach us that F9FF hexadecimal equals 
63999 decimal, so we have here 64000 bytes available (start to count from 
0). One long linear row of bytes to fill with little nice pixels. But heh, 
your screen is not linear, it has a second dimension, it's 2D! Therefore 
you have to calculate the right offset to put a pixel at any x, y location:

- Multiply the y coordinate by 320 (number of pixels per row)
- To this result add the x coordinate
- Use the final result as a pointer to the right adress
- Drop a value from 0-255 at this location

This results in the next algorithm: offset = y * 320 + x

And this is how to plug this baby into your programs:

  void PutPixel(int x, int y, unsigned char color)
  {
    videobuffer[y * 320 + x] = color;
  }

Pew, that's rather easy huh? Yes it is. After trying this at a couple of 
thousand locations your screen is starting to get messy. But no fear! We 
gather our cleaning waist products out of our kitchen and fresh-up the 
place... Wait!! We don't like cleaning!! Painting is much more fun!! OK, 
there we go. Why don't we paint the screen completely black? We could do 
something like this:

  for (y = 0; y = 200; y++)
  {
    for (x = 0; x = 320; x++)
    {
      PutPixel(x, y, 0);
    }
  }

Since this is rather slow (like the other sources :-)  we'll do this one 
in assembler:

  void FillScreen(unsigned char color)
  {
    asm {
      mov dx, 0xA000     // set es:di to A000:0000
      mov es, dx
      xor di, di
      mov cx, 32000      // number of words on screen
      mov al, color      // fill both ah and al
      mov ah, al         // with color
      rep stosw          // blaze!!
    }
  }

Just call this function and pass a color through. Clearing the screen is 
that simpel! You only have to set color to 0 and the job is done.

This is it for now. There is nothing left for me than giving you a little 
example how to implement these functions into your programs. Have fun with 
it and remember, if you have any questions, remarks or whatever you can 
always drop an email.

----------------------------------------------------------------------

  // gngtut01.c

  #include <stdio.h>
  #include <conio.h>

  #define  VGAMODE   0x13
  #define  TEXTMODE  0x03

  unsigned char far *videobuffer = (unsigned char far *)0xA0000000L;

  //------------------------------------------------------------
  void SetVideoMode(int mode)
  {
    asm {
      mov ax, mode     // drop desired mode in ax
      int 0x10         // et voila...
    }
  }

  //------------------------------------------------------------
  void PutPixel(int x, int y, unsigned char color)
  {
    videobuffer[y * 320 + x] = color;
  }

  //------------------------------------------------------------
  void FillScreen(unsigned char color)
  {
    asm {
      mov dx, 0xA000     // set es:di to A000:0000
      mov es, dx
      xor di, di
      mov cx, 32000      // number of words on screen
      mov al, color      // fill both ah and al
      mov ah, al         // with color
      rep stosw          // blaze!!
    }
  }

  //------------------------------------------------------------
  void main()
  {
    int x, y;

    SetVideoMode(VGAMODE);

    for (x = 0; x < 319; x++)
    {
      for (y = 0; y < 199; y++)
      {
        PutPixel(x, y, (x / 2) * (x / 2) / (y + 1));
      }
    }
    getch();

    FillScreen(9);
    getch();

    SetVideoMode(TEXTMODE);

    puts("This was the first example from the games 'n graphics trainer serie.");
    puts("You can send any comment or question to: gerben@igr.nl");
    puts("\nSee ya l8r...");

  }

----------------------------------------------------------------------

Disclaimer

Although the sources provided by this series are fully tested, you use them 
at your own risk. I hold no responsibility for any damage which may be 
caused by using this source. If anything goes wrong, too bad!! There is 
absolutely nothing I can do about it. Please report any problems or bugs to 
me and how they did occur. I hope you can live with this, or else too bad again!!
