GENWiki

Premier IT Outsourcing and Support Services within the UK

User Tools

Site Tools


archive:programming:astrainer

Hello there.

My name is Denthor (Grant Smith) of the South African demo group ASPHYXIA. This is a trainer that have been writing on and off for the last few months in order to help out budding young graphics programmers. Currently there are nine tutorials in all, each with a text file and accompianing pascal source file. Also included are two or three "bonus" pascal files with various effects.

I have left the files in their origional form, so they contain some local stuff which you can ignore.

PLEASE LEAVE A RESPONSE! Any comments/criticisms/flames/suggestions etc are very welcome (I love getting mail!)

Leave all comments to smith9@batis.bis.und.ac.za

Hope to hear from you soon!

                        DENTHOR, coder for ...
      _____   _____   ____   __   __  ___  ___ ___  ___  __   _____
     /  _  \ /  ___> |  _ \ |  |_|  | \  \/  / \  \/  / |  | /  _  \
     |  _  | \___  \ |  __/ |   _   |  \    /   >    <  |  | |  _  |
     \_/ \_/ <_____/ |__|   |__| |__|   |__|   /__/\__\ |__| \_/ \_/
                     smith9@batis.bis.und.ac.za
  The great South African Demo Team! Contact us for info/code exchange!    
                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 1 ]==–

þ Introduction

Hi there! This is Denthor of ASPHYXIA, AKA Grant Smith. This training program is aimed at all those budding young demo coders out there. I am assuming that the reader is fairly young, has a bit of basic Std. 6 math under his belt, has done a bit of programming before, probably in BASIC, and wants to learn how to write a demo all of his/her own.

This I what I am going to do. I am going to describe how certain routines work, and even give you working source code on how you do it. The source code will assume that you have a VGA card that can handle the 320x200x256 mode. I will also assume that you have Turbo Pascal 6.0 or above (this is because some of the code will be in Assembly language, and Turbo Pascal 6.0 makes this incredibly easy to use). By the end of the first "run" of sections, you will be able to code some cool demo stuff all by yourself. The info you need, I will provide to you, but it will be you who decides on the most spectacular way to use it.

Why not download some of our demos and see what I'm trying to head you towards.

I will be posting one part a week on the Mailbox BBS. I have the first "run" of sections worked out, but if you want me to also do sections on other areas of coding, leave a message to Grant Smith in private E-Mail, or start a conversation here in this conference. I will do a bit of moderating of a sort, and point out things that have been done wrong.

In this, the first part, I will show you how you are supposed to set up your Pascal program, how to get into 320x200x256 graphics mode without a BGI file, and various methods of putpixels and a clearscreen utility.

NOTE : I drop source code all through my explanations. You needn't try

     to grab all of it from all over the place, at the end of each part I
     add a little program that uses all the new routines that we have
     learned. If you do not fully understand a section, leave me
     private mail telling me what you don't understand or asking how I
     got something etc, and I will try to make myself clearer. One
     last thing : When you spot a mistake I have made in one of my
     parts, leave me mail and I will correct it post-haste.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Disclaimer

Hi again, sorry that I have to add this, but here goes. All source code obtained from this series of instruction programs is used at your own risk. Denthor and the ASPHYXIA demo team hold no responsibility for any loss or damage suffered by anyone through the use of this code. Look guys, the code I'm going to give you has been used by us before in Demos, Applications etc, and we have never had any compliants of machine damage, but if something does go wrong with your computer, don't blame us. Sorry, but that's the way it is.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ The MCGA mode and how you get into it in Pascal without a BGI

Lets face it. BGI's are next to worthless for demo coding. It is difficult to find something that is slower then the BGI units for doing graphics. Another thing is, they wern't really meant for 256 color screens anyhow. You have to obtain a specific external 256VGA BGI to get into it in Pascal, and it just doesn't make the grade.

So the question remains, how do we get into MCGA 320x200x256 mode in Pascal without a BGI? The answer is simple : Assembly language. Obviously assembly language has loads of functions to handle the VGA card, and this is just one of them. If you look in Norton Gides to Assembly Language, it says this …

INT 10h, 00h (0) Set Video Mode

  Sets the video mode.
     On entry:      AH         00h
                    AL         Video mode
     Returns:       None
     Registers destroyed:      AX, SP, BP, SI, DI

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

This is all well and good, but what does it mean? It means that if you plug in the video mode into AL and call interrupt 10h, SHAZAM! you are in the mode of your choice. Now, the MCGA video mode is mode 13h, and here is how we do it in Pascal.

Procedure SetMCGA; BEGIN

asm
      mov     ax,0013h
      int     10h
end;

END;

There you have it! One call to that procedure, and BANG you are in 320x200x256 mode. We can't actually do anything in it yet, so to go back to text mode, you make the video mode equal to 03h, as seen below :

Procedure SetText; BEGIN

asm
      mov     ax,0003h
      int     10h
end;

END;

BANG! We are back in text mode! Now, cry all your enquiring minds, what use is this? We can get into the mode, but how do we actually SHOW something on the screen? For that, you must move onto the next section ….

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Clearing the screen to a specific color

Now that we are in MCGA mode, how do we clear the screen. The answer is simple : you must just remember that the base adress of the screen is $a000. From $a000, the next 64000 bytes are what is actually displayed on the screen (Note : 320 * 200 = 64000). So to clear the screen, you just use the fillchar command (a basic Pascal command) like so :

    FillChar (Mem [$a000:0],64000,Col);

What the mem command passes the Segment base and the Offset of a part of memory : in this case the screen base is the Segment, and we are starting at the top of the screen; Offset 0. The 64000 is the size of the screen (see above), and Col is a value between 0 and 255, which represents the color you want to clear the screen to.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Putting a pixel on the screen (two different methoods)

If you look in Norton Guides about putting a pixel onto the screen, you will see this :

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

  Writes a pixel dot of a specified color at a specified screen
  coordinate.
  On entry:      AH         0Ch
                 AL         Pixel color
                 CX         Horizontal position of pixel
                 DX         Vertical position of pixel
                 BH         Display page number (graphics modes with more
                            than 1 page)
  Returns:       None
  Registers destroyed:      AX, SP, BP, SI, DI

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

As seen from our SetMCGA example, you would write this by doing the following:

Procedure INTPutpixel (X,Y : Integer; Col : Byte); BEGIN

asm
   mov        ah,0Ch
   mov        al,[col]
   mov        cx,[x]
   mov        dx,[y]
   mov        bx,[1]
   int        10h
end;

END;

The X would be the X-Coordinate, the Y would be the Y-Coordinate, and the Col would be the color of the pixel to place. Note that MCGA has 256 colors, numbered 0 to 255. The startoff pallette is pretty grotty, and I will show you how to alter it in my next lesson, but for now you will have to hunt for colors that fit in for what you want to do. Luckily, a byte is 0 to 255, so that is what we pass to the col variable. Have a look at the following.

  CGA = 4 colours.
  4x4 = 16
  EGA = 16 colors.
  16x16 = 256
  VGA = 256 colors.
  Therefore an EGA is a CGA squared, and a VGA is an EGA squared ;-)

Anyway, back to reality. Even though the abouve procedure is written in assembly language, it is slooow. Why? I hear your enquiring minds cry. The reason is simple : It uses interrupts (It calls INT 10h). Interrupts are sloooow … which is okay for getting into MCGA mode, but not for trying to put down a pixel lickety-split. So, why not try the following …

Procedure MEMPutpixel (X,Y : Integer; Col : Byte); BEGIN

Mem [VGA:X+(Y*320)]:=Col;

END;

The Mem command, as we have seen above, allows you to point at a certain point in memory … the starting point is $a000, the base of the VGA's memory, and then we specify how far into this base memory we start. Think of the monitor this way. It starts in the top left hand corner at 0. As you increase the number, you start to move across the screen to your right, until you reach 320. At 320, you have gone all the way across the screen and come back out the left side, one pixel down. This carries on until you reach 63999, at the bottom right hand side of the screen. This is how we get the equation X+(Y*320). For every increased Y, we must increment the number by 320. Once we are at the beginning of the Y line we want, we add our X by how far out we want to be. This gives us the exact point in memory that we want to be at, and then we set it equal to the pixel value we want.

The MEM methood of putpixel is much faster, and it is shown in the sample program at the end of this lesson. The ASPHYXIA team uses neither putpixel; we use a DMA-Straight-To-Screen-Kill-Yer-Momma-With-An-Axe type putipixel which is FAST. We will give it out, but only to those of you who show us you are serious about coding. If you do do anything, upload it to me, I will be very interested to see it. Remember : If you do glean anything from these training sessions, give us a mention in your demos and UPLOAD YOUR DEMO TO US!

Well, after this is the sample program; have fun with it, UNDERSTAND it, and next week I will start on fun with the pallette.

See you all later,

  1. Denthor
                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 2 ]==–

þ Introduction

Hi there again! This is Grant Smith, AKA Denthor of ASPHYXIA. This is the second part of my Training Program for new programmers. I have only had a lukewarm response to my first part of the trainer series … remember, if I don't hear from you, I will assume that you are all dead and will stop writing the series ;-). Also, if you do get in contact with me I will give you some of our fast assembly routines which will speed up your demos no end. So go on, leave mail to GRANT SMITH in the main section of the MailBox BBS, start up a discussion or ask a few questions in this Conference, leave mail to ASPHYXIA on the ASPHYXIA BBS, leave mail to Denthor on Connectix, or write to Grant Smith,

                     P.O.Box 270
                     Kloof
                     3640

See, there are many ways you can get in contact with me! Use one of them!

In this part, I will put the Pallette through it's paces. What the hell is a pallette? How do I find out what it is? How do I set it? How do I stop the "fuzz" that appears on the screen when I change the pallette? How do I black out the screen using the pallette? How do I fade in a screen? How do I fade out a screen? Why are telephone calls so expensive? Most of these quesions will be answered in this, the second part of my Trainer Series for Pascal.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is the Pallette?

A few weeks ago a friend of mine was playing a computer game. In the game there was a machine with stripes of blue running across it. When the machine was activated, while half of the the blue stripes stayed the same, the other half started to change color and glow. He asked me how two stripes of the same color suddenly become different like that. The answer is simple: the program was changing the pallette. As you know from Part 1, there are 256 colors in MCGA mode, numbered 0 to 255. What you don't know is that each if those colors is made up of different intensities of Red, Green and Blue, the primary colors (you should have learned about the primary colors at school). These intensities are numbers between 0 and 63. The color of bright red would for example be obtained by setting red intensity to 63, green intensity to 0, and blue intensity to 0. This means that two colors can look exactly the same, eg you can set color 10 to bright red and color 78 to color bright red. If you draw a picture using both of those colors, no-one will be able to tell the difference between the two.. It is only when you again change the pallette of either of them will they be able to tell the difference. Also, by changing the whole pallette, you can obtain the "Fade in" and "Fade out" effects found in many demos and games. Pallette manipulation can become quite confusing to some people, because colors that look the same are in fact totally seperate.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do I read in the pallette value of a color?

This is very easy to do. To read in the pallette value, you enter in the number of the color you want into port $3c7, then read in the values of red, green and blue respectively from port $3c9. Simple, huh? Here is a procedure that does it for you :

Procedure GetPal(ColorNo : Byte; Var R,G,B : Byte);

{ This reads the values of the Red, Green and Blue values of a certain
  color and returns them to you. }

Begin

 Port[$3c7] := ColorNo;
 R := Port[$3c9];
 G := Port[$3c9];
 B := Port[$3c9];

End;

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do I set the pallette value of a color?

This is also as easy as 3.1415926535897932385. What you do is you enter in the number of the color you want to change into port $3c8, then enter the values of red, green and blue respectively into port $3c9. Because you are all so lazy I have written the procedure for you ;-)

Procedure Pal(ColorNo : Byte; R,G,B : Byte);

{ This sets the Red, Green and Blue values of a certain color }

Begin

 Port[$3c8] := ColorNo;
 Port[$3c9] := R;
 Port[$3c9] := G;
 Port[$3c9] := B;

End;

Asphyxia doesn't use the above pallete procedures, we use assembler versions, which will be given to PEOPLE WHO RESPOND TO THIS TRAINER SERIES (HINT, HINT)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do I stop the "fuzz" that appears on my screen when I change the

      pallette?

If you have used the pallette before, you will have noticed that there is quite a bit of "fuzz" on the screen when you change it. The way we counter this is as follows : There is an elctron beam on your monitor that is constantly updating your screen from top to bottom. As it gets to the bottom of the screen, it takes a while for it to get back up to the top of the screen to start updating the screen again. The period where it moves from the bottom to the top is called the Verticle Retrace. During the verticle retrace you may change the pallette without affecting what is on the screen. What we do is that we wait until a verticle retrace has started by calling a certain procedure; this means that everything we do now will only be shown after the verticle retrace, so we can do all sorts of strange and unusual things to the screen during this retrace and only the results will be shown when the retrace is finished. This is way cool, as it means that when we change the pallette, the fuzz doesn't appear on the screen, only the result (the changed pallette), is seen after the retrace! Neat, huh? ;-) I have put the purely assembler WaitRetrace routine in the sample code that follows this message. Use it wisely, my son.

NOTE : WaitRetrace can be a great help to your coding … code that fits

     into one retrace will mean that the demo will run at the same
     speed no matter what your computer speed (unless you are doing a lot
     during the WaitRetrace and the computer is slooooow). Note that in
     the following sample program and in our SilkyDemo, the thing will run
     at the same speed whether turbo is on or off.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do I black out the screen using the pallette?

This is basic : just set the Red, Green and Blue values of all colors to zero intensity, like so :

Procedure Blackout;

{ This procedure blackens the screen by setting the pallette values of
  all the colors to zero. }

VAR loop1:integer; BEGIN

WaitRetrace;
For loop1:=0 to 255 do
  Pal (loop1,0,0,0);

END;

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do I fade in a screen?

Okay, this can be VERY effective. What you must first do is grab the pallette into a variable, like so :

 VAR Pall := Array [0.255,1..3] of BYTE;

0 to 255 is for the 256 colors in MCGA mode, 1 to 3 is red, green and blue intensity values;

Procedure GrabPallette; VAR loop1:integer; BEGIN

For loop1:=0 to 255 do
  Getpal (loop1,pall[loop1,1],pall[loop1,2],pall[loop1,3]);

END;

This loads the entire pallette into variable pall. Then you must blackout the screen (see above), and draw what you want to screen without the construction being shown. Then what you do is go throgh the pallette. For each color, you see if the individual intensities are what they should be. If not, you increase them by one unit until they are. Beacuse intensites are in a range from 0 to 63, you only need do this a maximum of 64 times.

Procedure Fadeup; VAR loop1,loop2:integer;

  Tmp : Array [1..3] of byte;
    { This is temporary storage for the values of a color }

BEGIN

For loop1:=1 to 64 do BEGIN
    { A color value for Red, green or blue is 0 to 63, so this loop only
      need be executed a maximum of 64 times }
  WaitRetrace;
  For loop2:=0 to 255 do BEGIN
    Getpal (loop2,Tmp[1],Tmp[2],Tmp[3]);
    If Tmp[1]<Pall[loop2,1] then inc (Tmp[1]);
    If Tmp[2]<Pall[loop2,2] then inc (Tmp[2]);
    If Tmp[3]<Pall[loop2,3] then inc (Tmp[3]);
      { If the Red, Green or Blue values of color loop2 are less then they
        should be, increase them by one. }
    Pal (loop2,Tmp[1],Tmp[2],Tmp[3]);
      { Set the new, altered pallette color. }
  END;
END;

END;

Hey-presto! The screen fades up. You can just add in a delay before the waitretrace if you feel it is too fast. Cool, no?

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do I fade out a screen?

This is just like the fade in of a screen, just in the opposite direction. What you do is you check each color intensity. If it is not yet zero, you decrease it by one until it is. BAAASIIIC!

Procedure FadeDown; VAR loop1,loop2:integer;

  Tmp : Array [1..3] of byte;
    { This is temporary storage for the values of a color }

BEGIN

For loop1:=1 to 64 do BEGIN
  WaitRetrace;
  For loop2:=0 to 255 do BEGIN
    Getpal (loop2,Tmp[1],Tmp[2],Tmp[3]);
    If Tmp[1]>0 then dec (Tmp[1]);
    If Tmp[2]>0 then dec (Tmp[2]);
    If Tmp[3]>0 then dec (Tmp[3]);
      { If the Red, Green or Blue values of color loop2 are not yet zero,
        then, decrease them by one. }
    Pal (loop2,Tmp[1],Tmp[2],Tmp[3]);
      { Set the new, altered pallette color. }
  END;
END;

END;

Again, to slow the above down, put in a delay above the WaitRetrace. Fading out the screen looks SO much more impressive then just clearing the screen; it can make a world of difference in the impression your demo etc will leave on the people viewing it. To restore the pallette, just do this :

Procedure RestorePallette; VAR loop1:integer; BEGIN

WaitRetrace;
For loop1:=0 to 255 do
  pal (loop1,Pall[loop1,1],Pall[loop1,2],Pall[loop1,3]);

END;

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

Well, there are most of those origional questions answered ;-) The following sample program is quite big, so it might take you a while to get around it. Persevere and thou shalt overcome. Pallette manipulation has been a thorn in many coders sides for quite some time, yet hopefully I have shown you all how amazingly simple it is once you have grasped the basics.

I need more feedback! In which direction would you like me to head? Is there any particular section you would like more info on? Also, upload me your demo's, however trivial they might seem. We really want to get in contact with/help out new and old coders alike, but you have to leave us that message telling us about yourself and what you have done or want to do.

IS THERE ANYBODY OUT THERE!?!

P.S. Our new demo should be out soon … it is going to be GOOOD … keep

   an eye out for it.
        [ And so she came across him, slumped over his keyboard
          yet again . 'It's three in the morning' she whispered.
          'Let's get you to bed'. He stirred, his face bathed in
          the dull light of his monitor. He mutters something.
          As she leans across him to disconnect the power, she
          asks him; 'Was it worth it?'. His answer surprises her.
          'No.' he says. In his caffiene-enduced haze, he smiles.
          'But it sure is a great way to relax.'                  ]
                                         - Grant Smith
                                            Tue 13 July, 1993
                                             2:23 am.

See you next week!

  1. Denthor
                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 3 ]==–

þ Introduction

Greetings! This is the third part of the VGA Trainer series! Sorry it took so long to get out, but I had a running battle with the traffic department for three days to get my car registered, and then the MailBox went down. Ahh, well, life stinks. Anyway, today will do some things vital to most programs : Lines and circles.

Watch out for next week's part : Virtual screens. The easy way to eliminate flicker, "doubled sprites", and subjecting the user to watch you building your screen. Almost every ASPHYXIA demo has used a virtual screen (with the exception of the SilkyDemo), so this is one to watch out for. I will also show you how to put all of these loose procedures into units.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith in private mail here on

                the Mailbox BBS.
          2) Write a message here in the Programming conference here
                on the Mailbox (Preferred if you have a general
                programming query or problem others would benefit from)
          3) Write to ASPHYXIA on the ASPHYXIA BBS.
          4) Write to Denthor, Eze or Livewire on Connectix.
          5) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
          6) Call me (Grant Smith) at 73 2129 (leave a message if you 
                call during varsity)
                

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Circle Algorithim

You all know what a circle looks like. But how do you draw one on the computer?

You probably know circles drawn with the degrees at these points :

                              0
                            ÜÛ|ÛÜ
                           ÛÛÛ|ÛÛÛ
                      270 ----+---- 90
                           ÛÛÛ|ÛÛÛ
                            ßÛ|Ûß
                             180

Sorry about my ASCI ;-) … anyway, Pascal doesn't work that way … it works with radians instead of degrees. (You can convert radians to degrees, but I'm not going to go into that now. Note though that in pascal, the circle goes like this :

                             270
                            ÜÛ|ÛÜ
                           ÛÛÛ|ÛÛÛ
                      180 ----+---- 0
                           ÛÛÛ|ÛÛÛ
                            ßÛ|Ûß
                              90

Even so, we can still use the famous equations to draw our circle … (You derive the following by using the theorem of our good friend Pythagoras)

                   Sin (deg) = Y/R
                   Cos (deg) = X/R

(This is standard 8(?) maths … if you haven't reached that level yet, take this to your dad, or if you get stuck leave me a message and I'll do a bit of basic Trig with you. I aim to please ;-))

Where Y = your Y-coord

    X = your X-coord
    R = your radius (the size of your circle)
    deg = the degree

To simplify matters, we rewrite the equation to get our X and Y values :

                   Y = R*Sin(deg)
                   X = R*Cos(deg)

This obviousy is perfect for us, because it gives us our X and Y co-ords to put into our putpixel routine (see Part 1). Because the Sin and Cos functions return a Real value, we use a round function to transform it into an Integer.

   Procedure Circle (oX,oY,rad:integer;Col:Byte);
   VAR deg:real;
       X,Y:integer;
   BEGIN
     deg:=0;
     repeat
       X:=round(rad*COS (deg));
       Y:=round(rad*sin (deg));
       putpixel (x+ox,y+oy,Col);
       deg:=deg+0.005;
     until (deg>6.4);
   END;

In the above example, the smaller the amount that deg is increased by, the closer the pixels in the circle will be, but the slower the procedure. 0.005 seem to be best for the 320x200 screen. NOTE : ASPHYXIA does not use this particular circle algorithm, ours is in assembly language, but this one should be fast enough for most. If it isn't, give us the stuff you are using it for and we'll give you ours.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Line algorithms

There are many ways to draw a line on the computer. I will describe one and give you two. (The second one you can figure out for yourselves; it is based on the first one but is faster)

The first thing you need to do is pass what you want the line to look like to your line procedure. What I have done is said that x1,y1 is the first point on the screen, and x2,y2 is the second point. We also pass the color to the procedure. (Remember the screens top left hand corner is (0,0); see Part 1)

Ie. o (X1,Y1)

              ooooooooo
                       ooooooooo
                                oooooooo  (X2,Y2)

Again, sorry about my drawings ;-)

To find the length of the line, we say the following :

         XLength = ABS (x1-x2)
         YLength = ABS (y1-y2)

The ABS function means that whatever the result, it will give you an absolute, or posotive, answer. At this stage I set a variable stating wheter the difference between the two x's are negative, zero or posotive. (I do the same for the y's) If the difference is zero, I just use a loop keeping the two with the zero difference posotive, then exit.

If neither the x's or y's have a zero difference, I calculate the X and Y slopes, using the following two equations :

         Xslope = Xlength / Ylength
         Yslope = Ylength / Xlength

As you can see, the slopes are real numbers. NOTE : XSlope = 1 / YSlope

Now, there are two ways of drawing the lines :

         X = XSlope * Y
         Y = YSlope * X

The question is, which one to use? if you use the wrong one, your line will look like this :

      o
         o
            o

Instead of this :

      ooo
         ooo
            ooo

Well, the solution is as follows :

  • \``|``/*
  • \|/*
  1. —+—-
  • /|\*
  • /``|``\*

If the slope angle is in the area of the stars (*) then use the first equation, if it is in the other section (`) then use the second one. What you do is you calculate the variable on the left hand side by putting the variable on the right hand side in a loop and solving. Below is our finished line routine :

Procedure Line (x1,y1,x2,y2:integer;col:byte); VAR x,y,xlength,ylength,dx,dy:integer;

  xslope,yslope:real;

BEGIN

xlength:=abs (x1-x2);
if (x1-x2)<0 then dx:=-1;
if (x1-x2)=0 then dx:=0;
if (x1-x2)>0 then dx:=+1;
ylength:=abs (y1-y2);
if (y1-y2)<0 then dy:=-1;
if (y1-y2)=0 then dy:=0;
if (y1-y2)>0 then dy:=+1;
if (dy=0) then BEGIN
  if dx<0 then for x:=x1 to x2 do
    putpixel (x,y1,col);
  if dx>0 then for x:=x2 to x1 do
    putpixel (x,y1,col);
  exit;
END;
if (dx=0) then BEGIN
  if dy<0 then for y:=y1 to y2 do
    putpixel (x1,y,col);
  if dy>0 then for y:=y2 to y1 do
    putpixel (x1,y,col);
  exit;
END;
xslope:=xlength/ylength;
yslope:=ylength/xlength;
if (yslope/xslope<1) and (yslope/xslope>-1) then BEGIN
  if dx<0 then for x:=x1 to x2 do BEGIN
                 y:= round (yslope*x);
                 putpixel (x,y,col);
               END;
  if dx>0 then for x:=x2 to x1 do BEGIN
                 y:= round (yslope*x);
                 putpixel (x,y,col);
               END;
END
ELSE
BEGIN
  if dy<0 then for y:=y1 to y2 do BEGIN
                 x:= round (xslope*y);
                 putpixel (x,y,col);
               END;
  if dy>0 then for y:=y2 to y1 do BEGIN
                 x:= round (xslope*y);
                 putpixel (x,y,col);
               END;
END;

END;

Quite big, isn't it? Here is a much shorter way of doing much the same thing :

function sgn(a:real):integer; begin

   if a>0 then sgn:=+1;
   if a<0 then sgn:=-1;
   if a=0 then sgn:=0;

end;

procedure line(a,b,c,d,col:integer); var u,s,v,d1x,d1y,d2x,d2y,m,n:real;

  i:integer;

begin

   u:= c - a;
   v:= d - b;
   d1x:= SGN(u);
   d1y:= SGN(v);
   d2x:= SGN(u);
   d2y:= 0;
   m:= ABS(u);
   n := ABS(v);
   IF NOT (M>N) then
   BEGIN
        d2x := 0 ;
        d2y := SGN(v);
        m := ABS(v);
        n := ABS(u);
   END;
   s := INT(m / 2);
   FOR i := 0 TO round(m) DO
   BEGIN
        putpixel(a,b,col);
        s := s + n;
        IF not (s<m) THEN
        BEGIN
             s := s - m;
             a:= a +round(d1x);
             b := b + round(d1y);
        END
        ELSE
        BEGIN
             a := a + round(d2x);
             b := b + round(d2y);
        END;
   end;

END;

This routine is very fast, and should meet almost all of your requirements (ASPHYXIA used it for quite a while before we made our new one.) In the end program, both the new line routine and the circle routine are tested. A few of the procedures of the first parts are also used.

Line and circle routines may seem like fairly trivial things, but they are a vital component of many programs, and you may like to look up other methods of drawing them in books in the library (I know that here at the varsity they have books for doing this kind of stuff all over the place) A good line routine to look out for is the Bressenhams line routine … there is a Bressenhams circle routine too … I have documentaiton for them if anybody is interested, they are by far some of the fastest routines you will use.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

Varsity has started again, so I am (shock) going to bed before three in the morning, so my quote this week wasn't written in the same wasted way my last weeks one was (For last week's one, I had gotten 8 hours sleep in 3 days, and thought up and wrote the quote at 2:23 am before I fell asleep.)

      [  "What does it do?" she asks.
         "It's a computer," he replies.
         "Yes, dear, but what does it do?"
         "It ..er.. computes! It's a computer."
         "What does it compute?"
         "What? Er? Um. Numbers! Yes, numbers!" He smiles
            worriedly.
         "Why?"
         "Why? Well ..um.. why?" He starts to sweat.
         "I mean, is it just something to dust around, or does
            it actually do something useful?"
         "Um...you can call other computers with it!" Hope lights
            up his eyes. "So you can get programs from other computers!"
         "I see. Tell me, what do these programs do?"
         "Do? I don't think I fol..."
         "I see. They compute. Numbers. For no particular reason." He
            withers under her gaze.
         "Yes, but..."
         She smiles, and he trails off, defeated. She takes another look
             at the thing. "Although," she says, with a strange look in
             her eyes. He looks up, an insane look of hope on his
             face. "Does it come in pink?" she asks.
                                                                         ]
                                                   - Grant Smith
                                                      Tue 27 July, 1993
                                                       9:35 pm.

See you next time,

  1. Denthor
                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 4 ]==–

þ Introduction

Howdy all! Welcome to the fourth part of this trainer series! It's a little late, but I am sure you will find that the wait was worth it, becase today I am going to show you how to use a very powerful tool : Virtual Screens.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith in private mail here on

                the Mailbox BBS.
          2) Write a message here in the Programming conference here
                on the Mailbox (Preferred if you have a general
                programming query or problem others would benefit from)
          3) Write to ASPHYXIA on the ASPHYXIA BBS.
          4) Write to Denthor, Eze or Livewire on Connectix.
          5) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
          6) Call me (Grant Smith) at 73 2129 (leave a message if you
                call during varsity)

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is a Virtual Screen and why do we need it?

Let us say you are generating a complex screen numerous times on the fly (for example scrolling up the screen then redrawing all the sprites for each frame of a game you are writing.) Do you have any idea how awful it would look if the user could actually see you erasing and redrawing each sprite for each frame? Can you visualise the flicker effect this would give off? Do you realise that there would be a "sprite doubling" effect (where you see two copies of the same sprite next to each other)? In the sample program I have included a part where I do not use virtual screens to demonstrate these problems. Virtual screens are not the only way to solve these problems, but they are definately the easiest to code in.

A virtual screen is this : a section of memory set aside that is exactly like the VGA screen on which you do all your working, then "flip" it on to your true screen. In EGA 640x350x16 you automatically have a virtual page, and it is possible to have up to four on the MCGA using a particular tweaked mode, but for our puposes we will set one up using base memory.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Setting up a virtual screen

As you will have seen in the first part of this trainer series, the MCGA screen is 64000 bytes big (320x200=64000). You may also have noticed that in TP 6.0 you arn't allowed too much space for normal variables. For example, saying :

VAR Virtual : Array [1..64000] of byte;

would be a no-no, as you wouldn't have any space for your other variables. What is the solution? I hear you enquiring minds cry. The answer : pointers! Pointers to not use up the base 64k allocated to you by TP 6.0, it gets space from somewhere else in the base 640k memory of your computer. Here is how you set them up :

Type Virtual = Array [1..64000] of byte; { The size of our Virtual Screen }

   VirtPtr = ^Virtual;                  { Pointer to the virtual screen }

VAR Virscr : VirtPtr; { Our first Virtual screen }

  Vaddr  : word;                        { The segment of our virtual screen}

If you put this in a program as it stands, and try to acess VirScr, your machine will probably crash. Why? Because you have to get the memory for your pointers before you can acess them! You do that as follows :

Procedure SetUpVirtual; BEGIN

GetMem (VirScr,64000);
vaddr := seg (virscr^);

END;

This procedure has got the memory for the screen, then set vaddr to the screens segment. DON'T EVER LEAVE THIS PROCEDURE OUT OF YOUR PROGRAM! If you leave it out, when you write to your virtual screen you will probably be writing over DOS or some such thing. Not a good plan ;-).

When you have finished your program, you will want to free the memory taken up by the virtual screen by doing the following :

Procedure ShutDown; BEGIN

FreeMem (VirScr,64000);

END;

If you don't do this your other programs will have less memory to use for themselves.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Putting a pixel to your virtual screen

This is very similar to putting a pixel to your normal MCGA screen, as discussed in part one… here is our origonal putpixel :

Procedure PutPixel (X,Y : Integer; Col : Byte); BEGIN

Mem [VGA:X+(Y*320)]:=col;

END;

For our virtual screen, we do the following :

Procedure VirtPutPixel (X,Y : Integer; Col : Byte); BEGIN

Mem [Vaddr:X+(Y*320)]:=col;

END;

It seems quite wasteful to have two procedures doing exactly the same thing, just to different screens, doesn't it? So why don't we combine the two like this :

Procedure PutPixel (X,Y : Integer; Col : Byte; Where : Word); BEGIN

Mem [Where:X+(Y*320)]:=col;

END;

To use this, you will say something like :

Putpixel (20,20,32,VGA); PutPixel (30,30,64,Vaddr);

These two statements draw two pixels … one to the VGA screen and one to the virtual screen! Doesn't that make you jump with joy! ;-) You will have noticed that we still can't actually SEE the virtual screen, so on to the next part …

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How to "Flip" your virtual screen on to the true screen

You in fact already have to tools to do this yourselves from information in the previous parts of this trainer series. We will of course use the Move command, like so :

Move (Virscr^,mem [VGA:0],64000);

simple, eh? Yuo may want to wait for a verticle retrace (Part 2) before you do that, as it may make the flip much smoother (and, alas, slower).

Note that most of our other procedures may be altered to support the virtual screen, such as Cls etc. (see Part 1 of this series), using the methoods described above (I have altered the CLS procedure in the sample program given at the end of this Part.)

We of ASPHYXIA have used virtual screens in almost all of our demos. Can you imagine how awful the SoftelDemo would have looked if you had to watch us redrawing the moving background, text and vectorballs for EACH FRAME? The flicker, doubling effects etc would have made it awful! So we used a virtual screen, and are very pleased with the result. Note, though, that to get the speed we needed to get the demo fast enough, we wrote our sprites routines, flip routines, pallette routines etc. all in assembly. The move command is very fast, but not as fast as ASM ;-)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

I am writing this on the varsity computers in between lectures. I prefer writing & coding between 6pm and 4am, but it isn't a good plan when varsity is on ;-), so this is the first part of the trainer series ever written before 9pm.

I have been asked to do a part on scrolling the screen, so that is probably what I will do for next week. Also, ASPHYXIA will soon be putting up a small demo with source on the local boards. It will use routines that we have discussed in this series, and demonstrate how powerful these routines can be if used in the correct manner.

Some projects for you to do :

1) Rewrite the flip statement so that you can say :
      flip (Vaddr,VGA);
      flip (VGA,Vaddr);
    ( This is how ASPHYXIAS one works )
2) Put most of the routines (putpixel, cls, pal etc.) into a unit,
   so that you do not need to duplicate the procedures in each program
   you write. If you need help, leave me mail.

See you next week

  1. Denthor
                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 5 ]==–

þ Introduction

Hello! This is Denthor here with the 5 part of the ASPHYXIA VGA Trainer Series : The Scrolling Saga. I have had many requests for information on scrolling, so I decided to make it this weeks topic. Note that I do make reference to my recently released program TEXTER5, which should be available from wherever you get this message. (Note to Sysops : If you put the trainer series up on your boards, please add WORMIE.ZIP and TEXTER5.ZIP as they both suppliment this series)

By the way, sorry for the delay in the appearance of this part. Tests, projects and a few wild days of sin at the Wild Coast all conspired against the prompt appearance of this part. Also note I need more input as to what I should do future parts on, so leave me mail.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith in private mail here on

                the Mailbox BBS.
          2) Write a message here in the Programming conference here
                on the Mailbox (Preferred if you have a general
                programming query or problem others would benefit from)
          3) Write to ASPHYXIA on the ASPHYXIA BBS.
          4) Write to Denthor, Eze or Livewire on Connectix.
          5) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
          6) Call me (Grant Smith) at 73 2129 (leave a message if you
                call during varsity)

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is scrolling?

If you have ever seen a demo, you have probably seen some form of scrolling. Our SILKYDEMO has quite a nice example of scrolling. What it is is a long row of text moving across your screen, usually from right to left, eg :

                                     H     : Step 1
                                    He     : Step 2
                                   Hel     : Step 3
                                  Hell     : Step 4
                                 Hello     : Step 5
                                Hello      : Step 6

etc. etc. See the program attatched for an example of scrolling.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What do we scroll?

Usually, letters. Most groups put greetings and information in their 'scrollies', as they are termed. You can also scroll and entire screen using the scrolling technique. Scrolling your text is a hell of a lot less boring then just having it appear on your screen. Unfortunately, 'scrollies' have been used so many times in demos they are wearing a bit thin, so usually they are accompanied by a cool picture or some nice routine happening at the same time (In our SILKYDEMO we had a moving checkerboard and colour bars going at the same time).

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do we scroll from side to side?

The theory behind scrolling is quite easy. Let us imagine that we are scrolling a 16x16 font grabbed by TEXTER (;-)) across the top of the screen (ie. 320 pixels) As we know, the VGA screen starts at zero at the top left hand part of the screen, then counts up to the right to 319, then goes back to the left hand side one pixel down at 320. (See Tut 1) This means that a 16*320 scroller takes up the space 0 to 5119 on the screen. In ascii this looks like this :

          (0)   .                                    .  (319)
          (320) .                                    .  (639)
                          "             "           "
         (4800) .                                    .   (5119)

Simple enough. Now what we do is we put down the first Y-line of the first character onto the very right hand side of the screen , like so :

            For loop1:=1 to 16 do
              Putpixel (319,loop1-1,font['A',1,loop1],vga);

This will draw some stuff on the very right hand side. Your screen should now look like this :

          (0)   .                                   X.  (319)
          (320) .                                   X.  (639)
                          "             "           "
         (4800) .                                   X.   (5119)

Next, we move each line one to the left, ie :

            For loop1:=0 to 15 do
              Move (mem[VGA:loop1*320+1],mem[VGA:loop1*320],320);

This scrolls the screen from right to left, which is the easiest to read. To scroll the screen from left to right, swap the +1 onto the other side of the command. Also, to increase the size of the portion scrolled, increase the 15 to however many lines from the top you wish to scroll-1.

After this move, your screen will look like this :

          (0)   .                                  X .  (319)
          (320) .                                  X .  (639)
                          "             "           "
         (4800) .                                  X .   (5119)
                                                    ^
                                              Note this space

What you then do is draw in the next line on the right hand side, move it, draw the next line, move it etc. etc. Tah-Dah! You have a scrolly! Fairly simple, isn't it?

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do we scroll up or down?

To scroll up or down is also fairly simple. This can be used for 'movie credit' endings (I once wrote a little game with a desert scrolling down with you being a little robot on the bottom of the screen). The theory is this : Draw the top line (or bottom line) then move the entire screen :

           Move (mem[vga:0],mem[vga:320],63680);
                     { 64000 - 320 = 63680 }

For scrolling down, or :

           Move (mem[vga:320],mem[vga:0],63680);

For scrolling up. You then draw the next line and repeat.

Because of the simplicity of coding in a scrolly, most demos have one. It is usually best to have something extra happening on the screen so that the viewer doesn't get too bored, even, as I say, if it is only a really nice picture.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

The University of Natal, Durban, Science Dept., now has 10 new 486's! This is a great boon, as now I can program nice routines during frees (even though I am a Commerce Student (Shhhhh) ;-) ). I can now use those previously wasted hours that I spent socialising and making friends coding instead ;-)

I suggest you get a copy of TEXTER, for coding demos with fonts, or in fact almost any graphics application, it is an amazing help, and we have used it for *ALL* our demos. (P.S. We have written many demos, but many have been written for companies and have not been released for the general public) NOTE : For TEXTER's test program TEST.PAS, add {$X+} {$R-} if you have range checking on (I code with it off.)

          [  "I'm from the Computer Inspection Agency, sir,
                 I'm here to check your computer. Here is
                 my identification."
             "Certainly. Have a look, I'm clean. I don't have
                 any pirated software."
             The C-man pushes past him and sits in front of the
                 computer. He notes the fact that the computer
                 is currently off with a look of disdain. He
                 makes a note on his clipboard. He boots up.
             "What is this?" he asks, pointing at the screen.
             "It's MasterMenu" stutters the man. "I wrote it
                 myself!"
             "Do you know what the penalty is for using junk
                 like this on a private machine?" The C-man smiles.
                 "This is a two-month sentance in itself!"
             "I'm sorry sir! It won't happen again!"
             "I know. I'll make sure of that." He smiles again.
             The C-man runs through the hard drive, checking for
                 illeagal software, bad programs and anti-government
                 propaganda. He notes with satisfaction that he has
                 enough to put this weenie away for ten years, not that
                 it mattered. He usually could just make something up.
             He comes to the last entry on the aphebetised menu tree.
                 His hands jerk away from the keyboard. Then, tentatively,
                 he types in the three letters of doom. He looks at the
                 man, who is backing away with wide eyes and his hands
                 outstretched in front of him, as if to ward off a blow.
             The C-man smiles, his lips a thin, hard line.
             "Windows!"
                                                                   ]
                                                         - Grant Smith
                                                             1:55pm
                                                               16/9/93

Cheers,

  1. Denthor
                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 6 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hi there! I'm back, with the latest part in the series : Pregenerated arrays. This is a fairly simple concept that can treble the speed of your code, so have a look.

I still suggest that if you haven't got a copy of TEXTER that you get it. This is shareware, written by me, that allows you to grab fonts and use them in your own programs.

I downloaded the Friendly City BBS Demo, an intro for a PE BBS, written by a new group called DamnRite, with coder Brett Step. The music was excellent, written by Kon Wilms (If I'm not mistaken, he is an Amiga weenie ;-)). A very nice first production, and I can't wait to see more of their work. I will try con a local BBS to allow me to send Brett some fido-mail.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith in private mail here on

                the Mailbox BBS.
          2) Write a message here in the Programming conference here
                on the Mailbox (Preferred if you have a general
                programming query or problem others would benefit from)
          3) Write to ASPHYXIA on the ASPHYXIA BBS.
          4) Write to Denthor, Eze or Livewire on Connectix.
          5) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
          6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity)

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Why do I need a lookup table? What is it?

A lookup table is an imaginary table in memory where you look up the answers to certain mathematical equations instead of recalculating them each time. This may speed things up considerably. Please note that a lookup table is sometimes referred to as a pregenerated array.

One way of looking at a lookup table is as follows : Let us say that for some obscure reason you need to calculate a lot of multiplications (eg. 5*5 , 7*4 , 9*2 etc.). Instead of actually doing a slow multiply each time, you can generate a kind of bonds table, as seen below :

ÉÍÑÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍÑÍÍÍÍÍÍ» ÇÄÅĶ 1 ³ 2 ³ 3 ³ 4 ³ 5 ³ 6 ³ 7 ³ 8 ³ 9 º ÇÄÁÄ×ÍÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍÍØÍÍÍÍÍ͵ º 1 º 1 ³ 2 ³ 3 ³ 4 ³ 5 ³ 6 ³ 7 ³ 8 ³ 9 ³ ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´ º 2 º 2 ³ 4 ³ 6 ³ 8 ³ 10 ³ 12 ³ 14 ³ 16 ³ 18 ³ ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´ º 3 º 3 ³ 6 ³ 9 ³ 12 ³ 15 ³ 18 ³ 21 ³ 24 ³ 27 ³ ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´ º 4 º 4 ³ 8 ³ 12 ³ 16 ³ 20 ³ 24 ³ 28 ³ 32 ³ 36 ³ ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´ º 5 º 5 ³ 10 ³ 15 ³ 20 ³ 25 ³ 30 ³ 35 ³ 40 ³ 45 ³ ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´ º 6 º 6 ³ 12 ³ 18 ³ 24 ³ 30 ³ 36 ³ 42 ³ 48 ³ 54 ³ ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´ º 7 º 7 ³ 14 ³ 21 ³ 28 ³ 35 ³ 42 ³ 49 ³ 56 ³ 63 ³ ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´ º 8 º 8 ³ 16 ³ 24 ³ 32 ³ 40 ³ 48 ³ 56 ³ 64 ³ 72 ³ ÇÄÄÄ×ÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄ´ º 9 º 9 ³ 18 ³ 27 ³ 36 ³ 45 ³ 54 ³ 63 ³ 72 ³ 81 ³ ÈÍÍÍÊÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ

This means that instead of calculating 9*4, you just find the 9 on the top and the 4 on the side, and the resulting number is the answer. This type of table is very useful when the equations are very long to do.

The example I am going to use for this part is that of circles. Cast your minds back to Part 3 on lines and circles. The circle section took quite a while to finish drawing, mainly because I had to calculate the SIN and COS for EVERY SINGLE POINT. Calculating SIN and COS is obviously very slow, and that was reflected in the speed of the section.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do I generate a lookup table?

This is very simple. In my example, I am drawing a circle. A circle has 360 degrees, but for greater accuracy, to draw my circle I will start with zero and increase my degrees by 0.4. This means that in each circle there need to be 8000 SINs and COSes (360/0.4=8000). Putting these into the base 64k that Pascal allocates for normal variables is obviously not a happening thing, so we define them as pointers in the following manner:

      TYPE   table = Array [1..8000] of real;
      VAR    sintbl : ^table;
             costbl : ^table;

Then in the program we get the memory for these two pointers. Asphyxia was originally thinking of calling itself Creative Reboot Inc., mainly because we always forgot to get the necessary memory for our pointers. (Though a bit of creative assembly coding also contributed to this. We wound up rating our reboots on a scale of 1 to 10 ;-)). The next obvious step is to place our necessary answers into our lookup tables. This can take a bit of time, so in a demo, you would do it in the very beginning (people just think it's slow disk access or something), or after you have shown a picture (while the viewer is admiring it, you are calculating pi to its 37th degree in the background ;-)) Another way of doing it is, after calculating it once, you save it to a file which you then load into the variable at the beginning of the program. Anyway, this is how we will calculate the table for our circle :

  Procedure Setup;
  VAR deg:real;
  BEGIN
    deg:=0;
    for loop1:=1 to 8000 do BEGIN
      deg:=deg+0.4;
      costbl^[loop1]:=cos (rad(deg));
      sintbl^[loop1]:=sin (rad(deg));
    END;
  END;

This will calculate the needed 16000 reals and place them into our two variables. The amount of time this takes is dependant on your computer.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do I use a lookup table?

This is very easy. In your program, wherever you put

             cos (rad(deg)),

you just replace it with :

             costbl^[deg]

Easy, no? Note that the new "deg" variable is now an integer, always between 1 and 8000.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Where else do I use lookup tables?

Lookup tables may be used in many different ways. For example, when working out 3-dimensional objects, sin and cos are needed often, and are best put in a lookup table. In a game, you may pregen the course an enemy may take when attacking. Even saving a picture (for example, a plasma screen) after generating it, then loading it up later is a form of pregeneration.

When you feel that your program is going much too slow, your problems may be totally sorted out by using a table. Or, maybe not. ;-)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

As you have seen above, lookup tables aren't all that exciting, but they are useful and you need to know how to use them. The attached sample program will demonstrate just how big a difference they can make.

Keep on coding, and if you finish anything, let me know about it! I never get any mail, so all mail is greatly appreciated ;-)

Sorry, no quote today, it's hot and I'm tired. Maybe next time ;-)

  1. Denthor

ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸

                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 7 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hello! By popular request, this part is all about animation. I will be going over three methods of doing animation on a PC, and will concerntrate specifically on one, which will be demonstrated in the attached sample code.

Although not often used in demo coding, animation is usually used in games coding, which can be almost as rewarding ;-)

In this part I will also be a lot less stingy with assembler code :) Included will be a fairly fast pure assembler putpixel, an asm screen flip command, an asm icon placer, an asm partial-flip and one or two others. I will be explaining how these work in detail, so this may also be used as a bit of an asm-trainer too.

By the way, I apologise for this part taking so long to be released, but I only finished my exams a few days ago, and they of course took preference ;-). I have also noticed that the MailBox BBS is no longer operational, so the trainer will be uploaded regularly to the BBS lists shown at the end of this tutorial.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write a message in the Programming conference on the
                For Your Eyes Only BBS (of which I am the Moderator )
                This is preferred if you have a general programming query
                or problem others would benefit from.
          4) Write to Denthor, Eze or Livewire on Connectix.
          5) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
          6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity)
          7) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
                mention the word Denthor near the top of the letter.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ The Principals of Animation

I am sure all of you have seen a computer game with animation at one or other time. There are a few things that an animation sequence must do in order to give an impression of realism. Firstly, it must move, preferably using different frames to add to the realism (for example, with a man walking you should have different frames with the arms an legs in different positions). Secondly, it must not destroy the background, but restore it after it has passed over it.

This sounds obvious enough, but can be very difficult to code when you have no idea of how to go about achieving that.

In this trainer I will discuss various methods of meeting these two objectives.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Frames and Object Control

It is quite obvious that for most animation to succeed, you must have numerous frames of the object in various poses (such as a man with several frames of him walking). When shown one after the other, these give the impression of natural movement.

So, how do we store these frames? I hear you cry. Well, the obvious method is to store them in arrays. After drawing a frame in Autodesk Animator and saving it as a .CEL, we usually use the following code to load it in :

TYPE icon = Array [1..50,1..50] of byte;

VAR tree : icon;

Procedure LoadCEL (FileName : string; ScrPtr : pointer); var

Fil : file;
Buf : array [1..1024] of byte;
BlocksRead, Count : word;

begin

assign (Fil, FileName);
reset (Fil, 1);
BlockRead (Fil, Buf, 800);    { Read and ignore the 800 byte header }
Count := 0; BlocksRead := $FFFF;
while (not eof (Fil)) and (BlocksRead <> 0) do begin
  BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
  Count := Count + 1024;
end;
close (Fil);

end;

BEGIN

Loadcel ('Tree.CEL',addr (tree));

END.

We now have the 50x50 picture of TREE.CEL in our array tree. We may access this array in the usual manner (eg. col:=tree [25,30]). If the frame is large, or if you have many frames, try using pointers (see previous parts)

Now that we have the picture, how do we control the object? What if we want multiple trees wandering around doing their own thing? The solution is to have a record of information for each tree. A typical data structure may look like the following :

TYPE Treeinfo = Record

                x,y:word;       { Where the tree is }
                speed:byte;     { How fast the tree is moving }
                Direction:byte; { Where the tree is facing }
                frame:byte      { Which animation frame the tree is
                                  currently involved in }
                active:boolean; { Is the tree actually supposed to be
                                  shown/used? }
              END;

VAR Forest : Array [1..20] of Treeinfo;

You now have 20 trees, each with their own information, location etc. These are accessed using the following means :

                Forest [15].x:=100;

This would set the 15th tree's x coordinate to 100.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Restoring the Overwritten Background

I will discuss three methods of doing this. These are NOT NECESSARILY THE ONLY OR BEST WAYS TO DO THIS! You must experiment and decide which is the best for your particular type of program.

METHOD 1 :

Step 1 : Create two virtual pages, Vaddr and Vaddr2. Step 2 : Draw the background to Vaddr2. Step 3 : Flip Vaddr2 to Vaddr. Step 4 : Draw all the foreground objects onto Vaddr. Step 5 : Flip Vaddr to VGA. Step 6 : Repeat from 3 continuously.

In ascii, it looks like follows …

  +---------+           +---------+           +---------+
  |         |           |         |           |         |
  |  VGA    | <=======  |  VADDR  |  <======  |  VADDR2 |
  |         |           | (bckgnd)|           | (bckgnd)|
  |         |           |+(icons) |           |         |
  +---------+           +---------+           +---------+

The advantages of this approach is that it is straightforward, continual reading of the background is not needed, there is no flicker and it is simple to implement. The disadvantages are that two 64000 byte virtual screens are needed, and the procedure is not very fast because of the slow speed of flipping.

METHOD 2 :

Step 1 : Draw background to VGA. Step 2 : Grab portion of background that icon will be placed on. Step 3 : Place icon. Step 4 : Replace portion of background from Step 2 over icon. Step 5 : Repeat from step 2 continuously.

In terms of ascii …

    +---------+
    |      +--|------- + Background restored (3)
    |      * -|------> * Background saved to memory (1)
    |      ^  |
    |      +--|------- # Icon placed (2)
    +---------+

The advantages of this method is that very little extra memory is needed. The disadvantages are that writing to VGA is slower then writing to memory, and there may be large amounts of flicker.

METHOD 3 :

Step 1 : Set up one virtual screen, VADDR. Step 2 : Draw background to VADDR. Step 3 : Flip VADDR to VGA. Step 4 : Draw icon to VGA. Step 5 : Transfer background portion from VADDR to VGA. Step 6 : Repeat from step 4 continuously.

In ascii …

   +---------+           +---------+
   |         |           |         |
   |   VGA   |           |  VADDR  |
   |         |           | (bckgnd)|
   | Icon>* <|-----------|--+      |
   +---------+           +---------+

The advantages are that writing from the virtual screen is quicker then from VGA, and there is less flicker then in Method 2. Disadvantages are that you are using a 64000 byte virtual screen, and flickering occurs with large numbers of objects.

In the attached sample program, a mixture of Method 3 and Method 1 is used. It is faster then Method 1, and has no flicker, unlike Method 3. What I do is I use VADDR2 for background, but only restore the background that has been changed to VADDR, before flipping to VGA.

In the sample program, you will see that I restore the entire background of each of the icons, and then place all the icons. This is because if I replace the background then place the icon on each object individually, if two objects are overlapping, one is partially overwritten.

The following sections are explanations of how the various assembler routines work. This will probably be fairly boring for you if you already know assembler, but should help beginners and dabblers alike.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ The ASM Putpixel

To begin with, I will explain a few of the ASM variables and functions :

<NOTE THAT THIS IS AN EXTREMELY SIMPLISTIC VIEW OF ASSEMBLY LANGUAGE! There are numerous books to advance your knowledge, and the Norton Guides assembler guide may be invaluable for people beginning to code in assembler. I haven't given you the pretty pictures you are supposed to have to help you understand it easier, I have merely laid it out like a programming language with it's own special procedures. >

There are 4 register variables : AX,BX,CX,DX. These are words (double bytes) with a range from 0 to 65535. You may access the high and low bytes of these by replacing the X with a "H" for high or "L" for low. For example, AL has a range from 0-255.

You also have two pointers : ES:DI and DS:SI. The part on the left is the segment to which you are pointing (eg $a000), and the right hand part is the offset, which is how far into the segment you are pointing. Turbo Pascal places a variable over 16k into the base of a segment, ie. DI or SI will be zero at the start of the variable.

If you wish to be pointing to pixel number 3000 on the VGA screen (see previous parts for the layout of the VGA screen), ES would be equal to $a000 and DI would be equal to 3000. You can quite as easily make ES or DS be equal to the offset of a virtual screen.

Here are a few functions that you will need to know :

    mov   destination,source       This moves the value in source to
                                   destination. eg  mov ax,50
    add   destination,source       This adds source to destination,
                                   the result being stored in destination
    mul   source                   This multiplies AX by source. If
                                   source is a byte, the source is
                                   multiplied by AL, the result being
                                   stored in AX. If source is a word,
                                   the source is multiplied by AX, the
                                   result being stored in DX:AX
    movsb                          This moves the byte that DS:SI is
                                   pointing to into ES:DI, and
                                   increments SI and DI.
    movsw                          Same as movsb except it moves a
                                   word instead of a byte.
    stosw                          This moves AX into ES:DI. stosb
                                   moves AL into ES:DI. DI is then
                                   incremented.
    push register                  This saves the value of register by
                                   pushing it onto the stack. The
                                   register may then be altered, but
                                   will be restored to it's original
                                   value when popped.
    pop register                   This restores the value of a pushed
                                   register. NOTE : Pushed values must
                                   be popped in the SAME ORDER but
                                   REVERSED.
    rep  command                   This repeats Command by as many
                                   times as the value in CX

SHL Destination,count ; and SHR Destination,count ; need a bit more explaining. As you know, computers think in ones and zeroes. Each number may be represented in this base 2 operation. A byte consists of 8 ones and zeroes (bits), and have a range from 0 to 255. A word consists of 16 ones and zeroes (bits), and has a range from 0 to 65535. A double word consists of 32 bits.

The number 53 may be represented as follows : 00110101. Ask someone who looks clever to explain to you how to convert from binary to decimal and vice-versa.

What happens if you shift everything to the left? Drop the leftmost number and add a zero to the right? This is what happens :

              00110101     =  53
               <-----
              01101010     =  106

As you can see, the value has doubled! In the same way, by shifting one to the right, you halve the value! This is a VERY quick way of multiplying or dividing by 2. (note that for dividing by shifting, we get the trunc of the result … ie. 15 shr 1 = 7)

In assembler the format is SHL destination,count This shifts destination by as many bits in count (1=*2, 2=*4, 3=*8, 4=*16 etc) Note that a shift takes only 2 clock cycles, while a mul can take up to 133 clock cycles. Quite a difference, no? Only 286es or above may have count being greater then one.

This is why to do the following to calculate the screen coordinates for a putpixel is very slow :

         mov    ax,[Y]
         mov    bx,320
         mul    bx
         add    ax,[X]
         mov    di,ax

But alas! I hear you cry. 320 is not a value you may shift by, as you may only shift by 2,4,8,16,32,64,128,256,512 etc.etc. The solution is very cunning. Watch.

  mov     bx,[X]
  mov     dx,[Y]
  push    bx
  mov     bx, dx                  {; bx = dx = Y}
  mov     dh, dl                  {; dh = dl = Y}
  xor     dl, dl                  {; These 2 lines equal dx*256 }
  shl     bx, 1
  shl     bx, 1
  shl     bx, 1
  shl     bx, 1
  shl     bx, 1
  shl     bx, 1                   {; bx = bx * 64}
  add     dx, bx                  {; dx = dx + bx (ie y*320)}
  pop     bx                      {; get back our x}
  add     bx, dx                  {; finalise location}
  mov     di, bx

Let us have a look at this a bit closer shall we? bx=dx=y dx=dx*256 ; bx=bx*64 ( Note, 256+64 = 320 )

dx+bx=Correct y value, just add X!

As you can see, in assembler, the shortest code is often not the fastest.

The complete putpixel procedure is as follows :

Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);

{ This puts a pixel on the screen by writing directly to memory. }

BEGIN

Asm
  push    ds                      {; Make sure these two go out the }
  push    es                      {; same they went in }
  mov     ax,[where]
  mov     es,ax                   {; Point to segment of screen }
  mov     bx,[X]
  mov     dx,[Y]
  push    bx                      {; and this again for later}
  mov     bx, dx                  {; bx = dx}
  mov     dh, dl                  {; dx = dx * 256}
  xor     dl, dl
  shl     bx, 1
  shl     bx, 1
  shl     bx, 1
  shl     bx, 1
  shl     bx, 1
  shl     bx, 1                   {; bx = bx * 64}
  add     dx, bx                  {; dx = dx + bx (ie y*320)}
  pop     bx                      {; get back our x}
  add     bx, dx                  {; finalise location}
  mov     di, bx                  {; di = offset }
  {; es:di = where to go}
  xor     al,al
  mov     ah, [Col]
  mov     es:[di],ah              {; move the value in ah to screen
                                     point es:[di] }
  pop     es
  pop     ds
End;

END;

Note that with DI and SI, when you use them :

    mov   di,50      Moves di to position 50
    mov   [di],50    Moves 50 into the place di is pointing to

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ The Flip Procedure

This is fairly straightforward. We get ES:DI to point to the start of the destination screen, and DS:SI to point to the start of the source screen, then do 32000 movsw (64000 bytes).

procedure flip(source,dest:Word);

{ This copies the entire screen at "source" to destination }

begin

asm
  push    ds
  mov     ax, [Dest]
  mov     es, ax                  { ES = Segment of source }
  mov     ax, [Source]
  mov     ds, ax                  { DS = Segment of source }
  xor     si, si                  { SI = 0   Faster then mov si,0 }
  xor     di, di                  { DI = 0 }
  mov     cx, 32000
  rep     movsw                   { Repeat movsw 32000 times }
  pop     ds
end;

end;

The cls procedure works in much the same way, only it moves the color into AX then uses a rep stosw (see program for details)

The PAL command is almost exactly the same as it's Pascal equivalent (see previous tutorials). Look in the sample code to see how it uses the out and in commands.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In Closing

The assembler procedures presented to you in here are not at their best. Most of these are procedures ASPHYXIA abandoned for better ones after months of use. But, as you will soon see, they are all MUCH faster then the original Pascal equivalents I originally gave you. In future, I hope to give you more and more assembler procedures for your ever growing collections. But, as you know, I am not always very prompt with this series (I don't know if even one has been released within one week of the previous one), so if you want to get any stuff done, try do it yourself. What do you have to lose, aside from your temper and a few rather inventive reboots ;-)

What should I do for the next trainer? A simple 3-d tutorial? You may not like it, because I would go into minute detail of how it works :) Leave me suggestions for future trainers by any of the means discussed at the top of this trainer.

After the customary quote, I will place a listing of the BBSes I currently know that regularly carry this Trainer Series. If your BBS receives it regularly, no matter where in the country you are, get a message to me and I'll add it to the list. Let's make it more convenient for locals to grab a copy without calling long distance ;-)

          [  There they sit, the preschooler class encircling their
                mentor, the substitute teacher.
             "Now class, today we will talk about what you want to be
                when you grow up. Isn't that fun?" The teacher looks
                around and spots the child, silent, apart from the others
                and deep in thought. "Jonny, why don't you start?" she
                encourages him.
             Jonny looks around, confused, his train of thought
                disrupted. He collects himself, and stares at the teacher
                with a steady eye. "I want to code demos," he says,
                his words becoming stronger and more confidant as he
                speaks. "I want to write something that will change
                peoples perception of reality. I want them to walk
                away from the computer dazed, unsure of their footing
                and eyesight. I want to write something that will
                reach out of the screen and grab them, making
                heartbeats and breathing slow to almost a halt. I want
                to write something that, when it is finished, they
                are reluctant to leave, knowing that nothing they
                experience that day will be quite as real, as
                insightful, as good. I want to write demos."
             Silence. The class and the teacher stare at Jonny, stunned. It
                is the teachers turn to be confused. Jonny blushes,
                feeling that something more is required.  "Either that
                or I want to be a fireman."
                                                                   ]
                                                     - Grant Smith
                                                          14:32
                                                             21/11/93

See you next time,

  1. DENTHOR

These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹ ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º ºConnectix BBS º(031) 266-9992 ºALL º * º * º * º ºFor Your Eyes Only BBS º(031) 285-318 ºA/H º * º * º * º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ

Open = Open at all times or only A/H Msg = Available in message base File = Available in file base Past = Previous Parts available

                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 8 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hello everybody! Christmas is over, the last of the chocolates have been eaten, so it's time to get on with this, the eighth part of the ASPHYXIA Demo Trainer Series. This particular part is primarily about 3-D, but also includes a bit on optimisation.

If you are already a 3-D guru, you may as well skip this text file, have a quick look at the sample program then go back to sleep, because I am going to explain in minute detail exactly how the routines work ;)

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write a message in the Programming conference on the
                For Your Eyes Only BBS (of which I am the Moderator )
                This is preferred if you have a general programming query
                or problem others would benefit from.
          4) Write to Denthor, EzE or Goth on Connectix.
          5) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
          6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity)
          7) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
                mention the word Denthor near the top of the letter.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Optimisation

Before I begin with the note on 3-D, I would like to stress that many of these routines, and probably most of your own, could be sped up quite a bit with a little optimisation. One must realise, however, that you must take a look at WHAT to optimise … converting a routine that is only called once at startup into a tightly coded assembler routine may show off your merits as a coder, but does absolutely nothing to speed up your program. Something that is called often per frame is something that needs to be as fast as possible. For some, a much used procedure is the PutPixel procedure. Here is the putpixel procedure I gave you last week:

Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); BEGIN

Asm
  push    ds                      { 14   clock ticks }
  push    es                      { 14 }
  mov     ax,[where]              { 8  }
  mov     es,ax                   { 2 }
  mov     bx,[X]                  { 8  }
  mov     dx,[Y]                  { 8  }
  push    bx                      { 15 }
  mov     bx, dx                  { 2  }
  mov     dh, dl                  { 2  }
  xor     dl, dl                  { 3  }
  shl     bx, 1                   { 2  }
  shl     bx, 1                   { 2  }
  shl     bx, 1                   { 2  }
  shl     bx, 1                   { 2  }
  shl     bx, 1                   { 2  }
  shl     bx, 1                   { 2  }
  add     dx, bx                  { 3  }
  pop     bx                      { 12 }
  add     bx, dx                  { 3  }
  mov     di, bx                  { 2 }
  xor     al,al                   { 3  }
  mov     ah, [Col]               { 8  }
  mov     es:[di],ah              { 10 }
  pop     es                      { 12 }
  pop     ds                      { 12 }
End;

END;

                          Total = 153 clock ticks

NOTE : Don't take my clock ticks as gospel, I probably got one or two

     wrong.

Right, now for some optimising. Firstly, if you have 286 instructions turned on, you may replace the 6 shl,1 with shl,6. Secondly, the Pascal compiler automatically pushes and pops ES, so those two lines may be removed. DS:[SI] is not altered in this procedure, so we may remove those too. Also, instead of moving COL into ah, we move it into AL and call stosb (es:[di]:=al; inc di). Let's have a look at the routine now :

Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); BEGIN

Asm
  mov     ax,[where]              { 8  }
  mov     es,ax                   { 2 }
  mov     bx,[X]                  { 8  }
  mov     dx,[Y]                  { 8  }
  push    bx                      { 15 }
  mov     bx, dx                  { 2  }
  mov     dh, dl                  { 2  }
  xor     dl, dl                  { 3  }
  shl     bx, 6                   { 8  }
  add     dx, bx                  { 3  }
  pop     bx                      { 12 }
  add     bx, dx                  { 3  }
  mov     di, bx                  { 2 }
  mov     al, [Col]               { 8  }
  stosb                           { 11 }
End;

END;

                          Total = 95 clock ticks

Now, let us move the value of BX directly into DI, thereby removing a costly push and pop. The MOV and the XOR of DX can be replaced by it's equivalent, SHL DX,8

Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler; asm

  mov     ax,[where]              { 8  }
  mov     es,ax                   { 2  }
  mov     bx,[X]                  { 8  }
  mov     dx,[Y]                  { 8  }
  mov     di,bx                   { 2  }
  mov     bx, dx                  { 2  }
  shl     dx, 8                   { 8  }
  shl     bx, 6                   { 8  }
  add     dx, bx                  { 3  }
  add     di, dx                  { 3  }
  mov     al, [Col]               { 8  }
  stosb                           { 11 }

end;

                          Total = 71 clock ticks

As you can see, we have brought the clock ticks down from 153 ticks to 71 ticks … quite an improvement. (The current ASPHYXIA putpixel takes 48 clock ticks) . As you can see, by going through your routines a few times, you can spot and remove unnecessary instructions, thereby greatly increasing the speed of your program.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Defining a 3-D object

Drawing an object in 3-D is not that easy. Sitting down and plotting a list of X,Y and Z points can be a time consuming business. So, let us first look at the three axes you are drawing them on :

                  Y    Z
                 /|\  /
                  | /
           X<-----|----->
                  |
                 \|/

X is the horisontal axis, from left to right. Y is the vertical axis, from top to bottom. Z is the depth, going straight into the screen.

In this trainer, we are using lines, so we define 2 X,Y and Z coordinates, one for each end of the line. A line from far away, in the upper left of the X and Y axes, to close up in the bottom right of the X and Y axes, would look like this :

{ x1 y1 z1 x2 y2 z2 }

  ( (-10,10,-10),(10,-10,10) )

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Rotating a point with matrixes

NOTE : I thought that more then one matix are matrisese (sp), but my

     spellchecker insists it is matrixes, so I let it have it's way 
     ;-)

Having a 3-D object is useless unless you can rotate it some way. For demonstration purposes, I will begin by working in two dimensions, X and Y.

Let us say you have a point, A,B, on a graph.

                    Y
                    |  /O1 (Cos (a)*A-Sin (a)*B , Sin (a)*A+Cos (a)*B)
                    |/      (A,B)
             X<-----|------O-->
                    |
                    |

Now, let us say we rotate this point by 45 degrees anti-clockwise. The new A,B can be easily be calculated using sin and cos, by an adaption of our circle algorithm, ie.

         A2:=Cos (45)*A - Sin (45)*B
         B2:=Sin (45)*A + Cos (45)*B

I recall that in standard 8 and 9, we went rather heavily into this in maths. If you have troubles, fine a 8/9/10 maths book and have a look; it will go through the proofs etc.

Anyway, we have now rotated an object in two dimensions, AROUND THE Z AXIS. In matrix form, the equation looks like this :

 [  Cos (a)   -Sin (a)      0        0     ]    [  x ]
 [  Sin (a)    Cos (a)      0        0     ]  . [  y ]
 [     0         0          1        0     ]    [  z ]
 [     0         0          0        1     ]    [  1 ]

I will not go to deeply into matrixes math at this stage, as there are many books on the subject (it is not part of matric maths, however). To multiply a matrix, to add the products of the row of the left matrix and the column of the right matrix, and repeat this for all the columns of the left matrix. I don't explain it as well as my first year maths lecturer, but have a look at how I derived A2 and B2 above. Here are the other matrixes :

Matrix for rotation around the Y axis :

 [  Cos (a)      0       -Sin (a)    0     ]    [  x ]
 [     0         1          0        0     ]  . [  y ]
 [  Sin (a)      0        Cos (a)    0     ]    [  z ]
 [     0         0          0        1     ]    [  1 ]

Matrix for rotation around the X axis :

 [     1         0                   0     ]    [  x ]
 [     0       Cos (a)   -Sin (a)    0     ]  . [  y ]
 [     0       Sin (a)    Cos (a)    0     ]    [  z ]
 [     0         0          0        1     ]    [  1 ]

By putting all these matrixes together, we can translate out 3D points around the origin of 0,0,0. See the sample program for how we put them together.

In the sample program, we have a constant, never changing base object. This is rotated into a second variable, which is then drawn. I am sure many of you can thing of cool ways to change the base object, the effects of which will appear while the object is rotating. One idea is to "pulsate" a certain point of the object according to the beat of the music being played in the background. Be creative. If you feel up to it, you could make your own version of transformers ;)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Drawing a 3D point to screen

Having a rotated 3D object is useless unless we can draw it to screen. But how do we show a 3D point on a 2D screen? The answer needs a bit of explaining. Examine the following diagram :

            |         ________-------------
        ____|___------      o Object at X,Y,Z     o1 Object at X,Y,Z2

Eye → O)|_ | ——__

            |                 -------------- Field of vision
          Screen

Let us pretend that the centre of the screen is the horizon of our little 3D world. If we draw a three dimensional line from object "o" to the centre of the eye, and place a pixel on the X and Y coordinates where it passes through the screen, we will notice that when we do the same with object o1, the pixel is closer to the horizon, even though their 3D X and Y coords are identical, but "o1"'s Z is larger then "o"'s. This means that the further away a point is, the closer to the horizon it is, or the smaller the object will appear. That sounds right, doesent it? But, I hear you cry, how do we translate this into a formula? The answer is quite simple. Divide your X and your Y by your Z. Think about it. The larger the number you divide by, the closer to zero, or the horizon, is the result! This means, the bigger the Z, the further away is the object! Here it is in equation form :

     nx := 256*x div (z-Zoff)+Xoff
     ny := 256*y div (z-Zoff)+Yoff

NOTE : Zoff is how far away the entire object is, Xoff is the objects X

     value, and Yoff is the objects Y value. In the sample program,
     Xoff start off at 160 and Yoff starts off at 100, so that the
     object is in the middle of the screen.

The 256 that you times by is the perspective with which you are viewing. Changing this value gives you a "fish eye" effect when viewing the object. Anyway, there you have it! Draw a pixel at nx,ny, and viola! you are now doing 3D! Easy, wasn't it?

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Possible improvements

This program is not the most optimised routine you will ever encounter (;-)) … it uses 12 muls and 2 divs per point. (Asphyxia currently has 9 muls and 2 divs per point) Real math is used for all the calculations in the sample program, which is slow, so fixed point math should be implemented (I will cover fixed point math in a future trainer). The line routine currently being used is very slow. Chain-4 could be used to cut down on screen flipping times.

Color values per line should be added, base object morphing could be put in, polygons could be used instead of lines, handling of more then one object should be implemented, clipping should be added instead of not drawing something if any part of it is out of bounds.

In other words, you have a lot of work ahead of you ;)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

There are a lot of books out there on 3D, and quite a few sample programs too. Have a look at them, and use the best bits to create your own, unique 3D engine, with which you can do anything you want. I am very interested in 3D (though EzE and Goth wrote most of ASPHYXIA'S 3D routines), and would like to see what you can do with it. Leave me a message through one of the means described above.

I am delving into the murky world of texture mapping. If anyone out there has some routines on the subject and are interested in swapping, give me a buzz!

What to do in future trainers? Help me out on this one! Are there any effects/areas you would like a bit of info on? Leave me a message!

I unfortunately did not get any messages regarding BBS's that carry this series, so the list that follows is the same one from last time. Give me your names, sysops!

Aaaaargh!!! Try as I might, I can't think of a new quote. Next time, I promise! ;-)

Bye for now,

  1. Denthor

These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹ ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º ºConnectix BBS º(031) 266-9992 ºALL º * º º º ºFor Your Eyes Only BBS º(031) 285-318 ºA/H º * º * º * º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ

Open = Open at all times or only A/H Msg = Available in message base File = Available in file base Past = Previous Parts available

                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 9 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hi there! ASPHYXIA is BACK with our first MegaDemo, Psycho Neurosis! A paltry 1.3MB download is all it takes to see the group from Durbs first major production! We are quite proud of it, and think you should see it ;)

Secondly, I released a small little trainer (a trainerette ;-)) on RsaPROG and Connexctix BBS mail, also on the ASPHYXIA BBS as COPPERS.ZIP It is a small Pascal program demonstrating how to display copper bars in text mode. Also includes a check for horizontal retrace (A lot of people wanted it, that is why I wrote the program) (ASPHYXIA … first with the trainer goodies ;-) aargh, sorry, had to be done ))

Thirdly, sorry about the problems with Tut 8! If you had all the checking on, the tutorial would probably die on the first points. The reason is this : in the first loop, we have DrawPoints then RotatePoints. The variables used in DrawPoints are set in RotatePoints, so if you put RotatePoints before DrawPoints, the program should work fine. Alternatively, turn off error checking 8-)

Fourthly, I have had a surprisingly large number of people saying that "I get this, like, strange '286 instructions not enabled' message! What's wrong with your code, dude?" To all of you, get into Pascal, hit Alt-O (for options), hit enter and a 2 (for Enable 286 instructions). Hard hey? Doesn't anyone EVER set up their version of Pascal?

Now, on to todays tutorial! 3D solids. That is what the people wanted, that is what the people get! This tutorial is mainly on how to draw the polygon on screen. For details on how the 3D stuff works, check out tut 8.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to Denthor, EzE or Goth on Connectix.
          3) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
          4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity)
          5) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
                mention the word Denthor near the top of the letter.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How to draw a polygon

Sounds easy enough, right? WRONG! There are many, many different ways to go about this, and today I'll only be showing you one. Please don't take what is written here as anything approaching the best method, it is just here to get you on your way…

The procedure I will be using here is based on something most of us learned in standard eight … I think. I seem to recall doing something like this in Mrs. Reids maths class all those years ago ;)

Take two points, x1,y1 and x2,y2. Draw them :

                + (x1,y1)
                 \
                   \  <-- Point a somewhere along the line
                     \
                       + (x2,y2)

Right, so what we have to do is this : if we know the y-coord of a, what is it's x-coord? To prove the method we will give the points random values.

               + (2,10)
                \
                  \  <-- a.y = 12
                    \
                      +  (15,30)

Right. Simple enough problem. This is how we do it :

 (a.y-y1) = (12 - 10)  {to get a.y as though y1 was zero}
 *(x2-x1) = *(15 - 2)  {the total x-length of the line}
 /(y2-y1) = /(30 - 10) {the total y-length of the line}
      +x1 = +2         { to get the equation back to real coords}

So our equation is : (a.y-y1)*(x2-x1)/(y2-y1)+x4 or

                    (12-10)*(15-2)/(30-10)+2
    which gives you :
                    2*13/20+2 = 26/20+2
                              = 3.3

That means that along the line with y=12, x is equal to 3.3. Since we are not concerned with the decimal place, we replace the / with a div, which in Pascal gives us an integer result, and is faster too. All well and good, I hear you cry, but what does this have to do with life and how it relates to polygons in general. The answer is simple. For each of the four sides of the polygon we do the above test for each y line. We store the smallest and the largest x values into separate variables for each line, and draw a horizontal line between them. Ta-Dah! We have a cool polygon!

For example : Two lines going down :

  
              +             +
             / <-x1     x2->|   <--For this y line
           /                |
         +                  +

Find x1 and x2 for that y, then draw a line between them. Repeat for all y values.

Of course, it's not as simple as that. We have to make sure we only check those y lines that contain the polygon (a simple min y, max y test for all the points). We also have to check that the line we are calculating actually extends as far as where our current y is (check that the point is between both y's). We have to compare each x to see weather it is smaller then the minimum x value so far, or bigger then the maximum (the original x min is set as a high number, and the x max is set as a small number). We must also check that we only draw to the place that we can see ( 0-319 on the x ; 0-199 on the y (the size of the MCGA screen))

To see how this looks in practice, have a look at the sample code provided. (Mrs. Reid would probably kill me for the above explanation, so when you learn it in school, split it up into thousands of smaller equations to get the same answer ;))

Okay, that's it! What's that? How do you draw a vertical line? Thats simple …

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Drawing a vertical line

Right, this is a lot easier than drawing a normal line (Tut 5 .. I think), because you stay on the same y value. So, what you do is you set ES to the screen you want to write to, and get DI to the start of the y-line (see earlier trainers for a description of how SEGMENT:OFFSET works.

IN : x1 , x2, y, color, where

         asm
           mov    ax,where
           mov    es,ax
           mov    di,y
           mov    ax,y
           shl    di,8   { di:=di*256 }
           shl    ax,6   { ax:=ax*64 }
           add    di,ax  { di := (y*256)+(y*64) := y*320 Faster then a
                           straight multiplication }

Right, now you add the first x value to get your startoff.

           add    di,x1

Move the color to store into ah and al

           mov    al,color
           mov    ah,al       { ah:=al:=color }

then get CX equal to how many pixels across you want to go

           mov    cx,x2
           sub    cx,x1   { cx:=x2-x1 }

Okay, as we all know, moving a word is a lot faster then moving a byte, so we halve CX

           shr    cx,1    { cx:=cx/2 }

but what happens if CX was an odd number. After a shift, the value of the last number is placed in the carry flag, so what we do is jump over a single byte move if the carry flag is zero, or execute it if it is one.

          jnc     @Start  { If there is no carry, jump to label Start }
          stosb           { ES:[DI]:=al ; increment DI }
      @Start :            { Label Start }
          rep     stosw   { ES:[DI]:=ax ; DI:=DI+2; repeat CX times }

Right, the finished product looks like this :

Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;

{ This draws a horizontal line from x1 to x2 on line y in color col }

asm

mov   ax,where
mov   es,ax
mov   ax,y
mov   di,ax
shl   ax,8
shl   di,6
add   di,ax
add   di,x1
mov   al,col
mov   ah,al
mov   cx,x2
sub   cx,x1
shr   cx,1
jnc   @start
stosb

@Start :

rep   stosw

end;

Done!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

This 3D system is still not perfect. It needs to be faster, and now I have also dumped the problem of face-sorting on you! Nyahahahaha!

         [ My sister and I were driving along the other day when she
             asked me, what would I like for my computer.
           I thought long and hard about it, and came up with the
             following hypothesis. When a girl gets a Barbie doll, she
             then wants the extra ballgown for the doll, then the
             hairbrush, and the car, and the house, and the friends
             etc.
           When a guy gets a computer, he wants the extra memory, the
             bigger hard drive, the maths co-pro, the better
             motherboard, the latest software, and the bigger monitor
             etc.
           I told my sister all of this, and finished up with : "So as
             you can see, computers are Barbie dolls for MEN!"
           She called me a chauvinist. And hit me. Hard.
                                                                 ]
                                                     - Grant Smith
                                                         19:24
                                                           26/2/94

See you next time!

  1. Denthor

These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹ ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º ºConnectix BBS º(031) 266-9992 ºALL º º * º * º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ

Open = Open at all times or only A/H Msg = Available in message base File = Available in file base Past = Previous Parts available

Does no other BBS's ANYWHERE carry the trainer? Am I writing this for three people who get it from one of these BBS's each week? Should I go on? (Hehehehe … I was pleased to note that Tut 8 was THE most downloaded file from ASPHYXIA BBS last month … )

                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 10 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Wow! The trainer has finally reached part 10! This will also be the first part introduced simultaneously to local BBS's and the INTERNET at the same time! Yes folks, I put up a copy of previous tutorials onto various ftp sites, and awaited the flames saying that the net.gurus already knew this stuff, and why was I wasting disk space! The flames did not appear (well, except for one), and I got some messages saying keep it up, so from now on I will upload all future trainers to ftp sites too (wasp.eng.ufl.edu , cs.uwp.edu etc.). I will also leave a notice in the USENET groups comp.lang.pascal and comp.sys.ibm.pc.demos when a new part is finished (Until enough people say stop ;-))

I can also be reached at my new E-Mail address,

               smith9@batis.bis.und.ac.za

Well, this tutorial is on Chain-4. When asked to do a trainer on Chain-4, I felt that I would be walking on much travelled ground (I have seen numerous trainers on the subject), but the people who asked me said that they hadn't seen any, so could I do one anyway? Who am I to say no?

The sample program attached isn't that great, but I am sure that all you people out there can immediately see the potential that Chain-4 holds.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to Denthor, EzE or Goth on Connectix.
          3) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          5) Write to smith9@batis.bis.und.ac.za in E-Mail.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is Chain-4?

You people out there all have at least 256k vga cards. Most of you have 512k vga cards, and some have 1MB vga cards. But what you see on your screen, as discussed in previous trainers, is 64k of data! What happened to the other 192k??? Chain-4 is a method of using all 256k at one time.

The way this is done is simple. 1 screen = 64k. 64k * 4 = 256k. Therefore, chain-4 allows you to write to four screens, while displaying one of them. You can then move around these four screens to see the data on them. Think of the Chain-4 screen as a big canvas. The viewport, the bit you see out of, is a smaller rectangle which can be anywhere over the bigger canvas.

   +----------------------------+ Chain-4 screen
   |          +--+              |
   |          |  | <- Viewport  |
   |          +--+              |
   |                            |
   +----------------------------+

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ The size of the chain-4 screen

The Chain-4 screen, can be any size that adds up to 4 screens.

For example, it can be 4 screens across and one screen down, or one screen across and 4 screens down, or two screens across and two screens down, and any size in between.

In the sample program, the size is a constant. The size * 8 is how many pixels across there are on the chain-4 screen, ie

 Size = 40   = 320 pixels across = 1 screen across, 4 screens down
 Size = 80   = 640 pixels across = 2 screens across, 2 screens down

etc.

We need to know the size of the screen for almost all dealings with the Chain-4 screen, for obvious reasons.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Layout of the chain-4 screen, and accessing it

If you will remember all the way back to Part 1 of this series, I explained that the memory layout of the MCGA screen is linear. Ie, the top left hand pixel was pixel zero, the one to the right of it was number one, the next one was number two etc. With Chain-4, things are very different.

Chain-4 gets the 4 screens and chains them together (hence the name :)). Each screen has a different plane value, and must be accessed differently. The reason for this is that a segment of memory is only 64k big, so that we could not fit the entire Chain-4 screen into one segment.

All Chain-4 screens are accessed from $a000, just like in MCGA mode. What we do is, before we write to the screen, find out what plane we are writing to, set that plane, then plot the pixel. Here is how we find out how far in to plot the pixel and what plane it is on :

Instead of the linear model of MCGA mode, ie :

      ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
      ³00³01³02³03³04³05³06³07³08³09³10³11³ ...

Each plane of the Chain-4 screen accesses the memory in this way :

     Plane 0 :
      ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
      ³00³  ³  ³  ³01³  ³  ³  ³02³  ³  ³  ³ ...
     Plane 1 :
      ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
      ³  ³00³  ³  ³  ³01³  ³  ³  ³02³  ³  ³ ...
     Plane 2 :
      ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
      ³  ³  ³00³  ³  ³  ³01³  ³  ³  ³02³  ³ ...
     Plane 3 :
      ÚÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄÂÄÄ¿
      ³  ³  ³  ³00³  ³  ³  ³01³  ³  ³  ³02³ ...

In this way, by choosing the right plane to write to, we can access all of the 256k of memory available to us. The plane that we write to can easily be found by the simple calculation of x mod 4, and the x coordinate is also found by x div 4. We work out our y by multiplying it by the size of our chain-4 screen.

NOTE : It is possible to write to all four planes at once by setting the

     correct port values.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Uses of Chain-4

The uses of Chain-4 are many. One could write data to one screen, then flip to it (the move_to command is almost instantaneous). This means that 64k of memory does not need to be set aside for a virtual screen, you are using the vga cards memory instead!

Scrolling is much easier to code for in Chain-4 mode.

It is possible to "tweak" the mode into other resolutions. In our demo, our vectors were in 320x240 mode, and our dot vectors were in 320x400 mode.

The main disadvantage of chain-4 as I see it is the plane swapping, which can be slow. With a bit of clever coding however, these can be kept down to a minimum.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ The sample programs

The first sample program is GFX.PAS. This is a until in which I have placed most of our routines from previous tuts. All the procedures and variables you can see under the INTERFACE section can be used in any program with GFX in the USES clause. In other words, I could do this :

USES GFX,crt;

BEGIN

Setupvirtual;
cls (vaddr,0);
Shutdown;

END.

This program would compile perfectly. What I suggest you do is this : Rename the file to a name that suites you (eg your group name), change the first line of the unit to that name, then add all useful procedures etc. to the unit. Make it grow :-).

The second file is the sample program (note the USES GFX,crt; up near the top!). The program is easy to understand and is documented. The bit that I want to draw your attention to is the constant, BIT. Because I am distributing this file to many places in text form, not binary form, I could not just add a .CEL file with the program. So what I did was write some text in one color then saved it as a .CEL . I then wrote a ten line program that did the following : Moving from left to right, it counted how many pixels were of color zero, then saved the byte value to an array. When it came across color one, is counted for how long that went on then saved the byte value and saved it to an array and so on. When it was finished, I converted the array into a text file in the CONST format. Not too cunning, but I thought I had better explain it ;-)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

There are other documents and sample programs available on Chain-4 and it's like : Try XLIB for one…

Finally! Some BBS's have joined my BBS list! (Okay, only two new ones, but it's a start ;-)) All you international BBS's! If you will regularly download the tuts from an FTP site, give me your names!

I own a car. The car's name is Bob. A few days ago, Bob was in an accident, and now has major damage to his front. Knowing insurance, I probably won't get much, probably nothing (the other guy wasn't insured, and I am only 18 :( ). I will probably have to find work in order to pay for my repairs. The point to this meandering is this : I am upset, so if you think you are getting a quote, you can just forget it.

Oh, well. Life goes on!

See you next time,

  1. Denthor

These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹ ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º ºConnectix BBS º(031) 266-9992 ºALL º º * º * º ºPOP! º(012) 661-1257 ºALL º º * º * º ºPure Surf BBS º(031) 561-5943 ºA/H º º * º * º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ

For international users : If you live outside the Republic of South Africa, do the following : Dial +27, dont dial the first 0, but dial the rest of the number. Eg, for the ASPHYXIA BBS : +27-31-765-5312

Open = Open at all times or only A/H Msg = Available in message base File = Available in file base Past = Previous Parts available

                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 11 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hello again everybody!

The reason _this_ one is delayed (every single trainer has been so far ;)) is mainly due to a birthday (my 19th), and numerous tests at the university (ugh!). But anyway, here it is. The sample program this time is on cross-fading. The reason for this is that many people have commented that I should be moving over to a few basic demo effects now that we have most of the basics of VGA programming. I was also thinking of either doing sound in a future version of this trainer, or starting a separate "ASPHYXIA Sound Tutorial" series. Comments?

One major difference between this trainer and previous ones is that I am including binary files (pictures in this case). This means that it will not be available in the message bases of selected boards anymore, and it must be obtained from the file base. Notice will however be given of it's existence in the message base.

Asphyxia has formalised things a bit, and we now have a few official distribution sites for all our demos and trainers. If you would like your BBS to become a distribution site, please email me at smith9@batis.bis.und.ac.za and I will send you the necessary info.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to Denthor, EzE, Goth, Fubar or Nobody on Connectix.
          3) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          5) Write to smith9@batis.bis.und.ac.za in E-Mail.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is a "Crossfade"?

This is a simple question. When you are watching a TV program, you will often see one picture on the screen, which slowly fades to a new picture, with the new picture becoming more and more prominent and the old one becoming less and less prominent. This is a crossfade. Easy huh?

Perhaps, but it is not that easy to code on a computer…

In most demos, there is a crossfade of two colors, black and white, for example : The words 'MYDEMOTEAM' appears in large with letters, then crossfades to 'PRESENTS' in large white letters.

I decided to allow the programmer to have a bit of color to his crossfade, and the sample program can handle a many color crossfade.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How does a crossfade work?

Here comes the clever bit.

To do a crossfade, we load in two pictures, FROM and TO. Then, for every pixel in which they are different, put a new pixel in a third screen.

For example, wherever there is pixel color 9 on screen 1 and pixel color 45 on screen 2, put pixel color 1 on the third screen. You then repeat this for all combinations of pixels on screen one and two, and put the results into screen 3. Here it is in ascii …

Screen 1     Screen 2     Screen 3
 .1...        .3...        .1...
 .....        ..2..        ..2..
 ...8.    +   ...1.    =   ...3.
 .1...        ....2        .4..2

Note how the values on screen 3 are sequential? We keep a count for this… The two "2"'s on screen 3 are identical, so we do not use a new color for it…

We also keep to pallettes … source and dest.

For the above example source[1] would be the pallette of 1 in screen 1, and dest[1] would be the pallette of 3 in screen 2 (Note that screen 1 and screen 2 have different pallettes)

When we are finished with the picture, we flip screen 3 to the vga and do the following : move the pallette from source to dest or vice versa. Thats it. No fancy screen manipulations for the crossfade, we just change the pallette. Cool, huh? It also means that you can be doing fun stuff in the foreground with unused pallette colors without your program executing at two frames per second ;)

The sample program is fully documented, and you shouldn't have a problem deciphering it… If you ever use this effect in a demo or game, greet me! :-)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Problems with crossfades

The main problem with crossfading is this : there may only be 256 colors on screen 3, in other words, only 256 combinations of colors. In the sample program, if you load up two pics with more then 256 combinations, the program gives an error message and exits to dos. To sort this problem out, you can do two things : reduce the number of places where the two pictures intersect, or squeeze down the pallette, using Autodesk Animators "SQUEEZE" command. This reduces the number of colors used by the picture, and therefore reduces the number of combinations. The picture does however lose a bit of quality.

The second problem with crossfading is this : It hogs most of the colors. Whatever you want to do in the foreground, make sure you do it with as few colors as possible.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

So, what do you think? Should I continue with demo effects, or should I find more basic things to do? Perhaps I should stop and just do sound coding from now on? It is up to you, so leave me mail.

You will notice that the sample program can load in any .CEL files, you needn't be restricted by the ones I have given you. Try crossfading a few of your own pictures and see how it turns out. The picture of the robot was draw by Fubar for our demo Psycho Neurosis, and I then squeezed down the pallette somewhat in order for the crossfade to work. The word "ASPHYXIA" was drawn by me, also in Autodesk Animator.

Oh well, I had better get this off quickly, today is the last time for the next few days that I can get on to the Net. I will also be voting tomorrow! If I see a CNN camera, I'll wave (Thats me, the one on the left in the red shirt! ;-)) The next trainer will be coming from the New South Africa (TM)

See you next time! - Denthor

  1. 9:16, 26 April, 1994

PS. Does anyone in Holland with net access want to act as a courier between myself and the Accidental Connection BBS? Please leave me mail at smith9@batis.bis.und.ac.za ….

The following are official ASPHYXIA distribution sites :

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹ ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º ºConnectix BBS º+27-31-266-9992 ºALL º ºPOP! º+27-12-661-1257 ºALL º ºPure Surf BBS º+27-31-561-5943 ºA/H º ºWasted Image º407-838-4525 ºALL º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ

Leave me mail if you want to become an official Asphyxia BBS distribution site.

(I will find out the country code for Wasted Image later…)

                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 12 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hello! :-)

Well, a lot has happened since the last trainer, which is the reason for the amazingly long delay. First, the elections. These were quite easy actually, I went and watched a move (Demolition Man) (Election day special, all movies R2, which is about 50 US cents), then went and voted after most voters had gone home, so no long lines ;-). Soon after were exams. These did not go too well, and I am not looking forward to the results. Finally, I got measles and pneumonia at the same time and was sent off to hospital for a few days. All in all, not events which are conducive to coding! This has meant that the trainer has been delayed, and ASPHYXIA was not able to enter into the local democompo, Dexterity '94, which we were hoping to do well in. Oh well, onward and upward!

This trainer is on full screen scrolling in Chain-4, by request. This is actually very easy to do (and smooth), and holds a lot of potential, as I am sure you can immediately imagine.

A few more things : People have been saying they have had hassles sending me email, and I have found that this is because they forget the numbers in my name. They send mail to smith@batis… which does not exist, or smith@beastie… which is my brothers account. He is getting a bit sick of forwarding my mail to me ;). The two address are :

     smith9@batis.bis.und.ac.za
     smith0@beastie.cs.und.ac.za

I have lost about 200k worth of email, chalk it up to my beginner status at Unix. The test to see if your mail got through? I have answered _every_ email message sent to me (no easy task), so if you haven't got a reply, please resend the message.

You can now also send a group message to all members of Asphyxia. Just send mail to asphyxia@beastie.cs.und.ac.za and we will all get a copy … which could mean numerous replies to one querey ;)

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to Denthor, EzE, Goth, Fubar or Nobody on Connectix.
          3) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          5) Write to smith9@batis.bis.und.ac.za in E-Mail.
          6) Write to asphyxia@beastie.cs.und.ac.za

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is full screen scrolling?

I seem to recall doing this in a previous tut, but here goes again! Full screen scrolling is when the entire screen moves in a particular direction, with the new picture scrolling on to the screen. Um. Think of movie credits. The screen, filled with text, is scrolled off the top of the screen while the new text is scrolled on from the bottom. This is full screen scrolling.

Full screen scrolling is not limited to movie credits. Games like Raptor have you flying over a scrolling landscape while you are shooting down the bad guys. In this tutorial we will be doing vertical scrolling, but the code can very easily be altered for horizontal scrolling too.

Remember that we will be using Chain-4 to do our scrolling, so you may want to brush up on tut 10 in which that was covered. I will assume a brief knowledge of how chain-4 works for this tutorial.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ The theory

The theory behind full screen scrolling in Chain-4 is acually very simple.

Picture if you will, a screen that is two monitors high. Chain-4 actually has four, but for this we only need two. Now, for this screen that is two monitors high, we can only see one monitors worth. Here it is in ASCII

  +-------------+  Screen two monitors high
  |             |
  |             |
  |             |
  |             |
  |+-----------+|
  ||           ||
  ||           ||<- This is the bit we can see, one monitors worth
  ||           ||
  |+-----------+|
  +-------------+

We can move the bit we can see up or down the enlarged screen. So, for example, if the screen two monitors high had a picture on it, we could move the bit we see up and down to try glimpse the entire picture. Think of it in this way : The screen is a large painting, but we can only see though a small magnifing glass. We can move this magnifing glass around the painting, but can never see the painting all at once.

This actually works in our favour. Anything done outside the bit we are looking through cannot be seen, so we can do our work without changing our screen.

On to scrolling. The method we will use this time is as follows :

1) Draw the next line to be seen just above and just below the part we

 can see.
    +------------+ The enlarged screen
    |            |
    |            |
    |111111111111|  The new part of the picture
    |+----------+|
    ||          || The bit we can see
    |+----------+|
    |111111111111|  The new part of the picture
    +------------+

2) Move the view up one pixel so that the new part of the picture is

 visible at the top of the screen.

3) Repeat Steps 1) and 2) until the whole screen is filled. Our screen

 will look as follows :
   +---------------+
   |+-------------+|
   ||3333333333333||
   ||2222222222222|| Viewscreen
   ||1111111111111||
   |+-------------+|
   |333333333333333|
   |222222222222222|
   |111111111111111|
   +---------------+

Check this picture with steps 1) and 2), you will see that this is correct.

4) Set our viewport to the bottom of the enlarged screen.

   +---------------+
   |333333333333333|
   |222222222222222|
   |111111111111111|
   |+-------------+|
   ||3333333333333||
   ||2222222222222|| New position of viewscreen
   ||1111111111111||
   |+-------------+|
   +---------------+

As you can see, the bit we will be looking at is exactly the same as before, we are now just at the bottom of the larger screen instead of the top!

5) Jump back to 1). The entire sequence can begin again, and we can have

 infinate scrolling in the upward direction. Clever huh?

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Our code

In the sample code, we have 21 different icons. What we do is decide what the next row of icons is going to consist of. We then draw the next line of pixels above and below the viewscreen according to what icons we are displaying. We then scroll up one pixel and begin again. When we have completed a row of icons, we randomly select a new row and begin again. Our icons are 16x16, so exactly 20 fit across a 320 pixel screen.

When we hit the top of our enlarged screen, we flip down to the bottom which looks exactly the same as the screen we have left. In this manner we have obtained smooth, infinate full screen scrolling!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Extra bits

As you will see from the code, it would be the work of but a few minutes to extend our landscape across the two unused screens, thereby allowing limited horizontal movement along with our vertical movement. In fact, the entire routine could easily be made to be a horizontal scrolling routine.

A map of sorts could be generated, with one byte equalling one terrain type. In this manner, the terrain scrolled over could be set, as in a flying game (Flying Shark, Raptor etc). The terrain could also easily be replaced with letters for our movie-style credits.

Free direction scrolling, ie scrolling in all directions, is a very different matter, with very different methods to get it to work. Perhaps this will be discussed in a later trainer. But for now, work with this, know it, understand it, and think up many great things to do with it! How about a full screen text scrolly? A game? Go wild!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

Well, I hope you enjoyed this, the latest trainer. The sample program is a little short, but that is because the concept is so simple. Attached is a file, PICCS.DAT, which contains the terrain and letters for the sample program. They were .CEL's, which I loaded into the des^ variable, which I then dumped to disk, for easy access later. The .CEL's were drawn on short notice, but still produces some nice terrain.

I have recieved a few requests for future trainers, and most of them are for effects, so I guess that is what will be done from now on. A surprising number have told me not to do a sound trainer and stick with graphics stuff, with only a few asking for sound stuff, so I will hold off on that until there is more of a demand.

I am still open to suggestions for future trainers, and of course suggestions for improving the series. Leave me mail!

Hmm. A quote? Okay, let me think ….

      [    The little devil sat atop the alpine slopes, frolicking in the
         snow.  He threw a snowball at a nearby squirrel, which
         missed. The resulting avalance buried two villages and a ski
         resort.
           The little devil was scared. Avalances were bad for
         business. The locals would form team spirit, be nice to
         each other and work together and free those trapped beneath
         the snow, which created even more goodwill. The man
         downstairs didn't like goodwill. He didn't like it at
         all.
           In the blink of an eye the devil was in his penthouse
         apartment, dressed in his usual suit. He picked up the phone.
         Dialing was for mortals.
           "Hello, Micros..."
           "This is Mister Crowley", interrupted the devil.
           There were sounds of thumping on the other side of the
         phone, then there was a new voice. "Hello, Bill here, we
         haven't heard from you in a while, Mister Crowley." The fear
         of the man on the other end was almost tangible. The devil
         smiled.
           "Hello Bill. Something has come up."
           "No!" The man on the other side almost shouted with terror.
         "Not Win..."
           "Yes, Bill. It is time."
           "Havn't I paid enough for my sins? Just that one night..."
         The man was almost sobbing.
           "You are touching me, Bill. But nevertheless, it is time."
           "No." The man sounded beaten, alone.
           "Yes. Bill, it is time for a new update."
                                                                     ]
                                                    - Grant Smith
                                                        14:23
                                                          23-7-94

See you next time!

  1. Denthor

The following are official ASPHYXIA distribution sites :

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹ ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º ºC-Spam BBS º410-531-5886 ºALL º ºConnectix BBS º+27-31-266-9992 ºALL º ºPOP! º+27-12-661-1257 ºALL º ºPure Surf BBS º+27-31-561-5943 ºA/H º ºSoul Asylum º+358-0-5055041 ºALL º ºWasted Image º407-838-4525 ºALL º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ

Leave me mail if you want to become an official Asphyxia BBS distribution site.

 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸

                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 13 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hello again! Here I am, cooped up at home, recovering from my illness with nothing to do, so of course it is the perfect time to write another trainer! After the long delay between parts 11 and 12, two trainers in two days doesn't sound like a bad idea.

This trainer is on starfields, which is by request of more then one person. This is quite an easy effect, and you should have no trouble grasping the concept behind it. I will be doing a 3d starfield, a horizontal starfield is very easy with you merely incrementing a x-value for each star for each frame. I am not even going to bother doing code for that one (unless requested).

So I am off to go grab my antibiotics pills and I will be right back with the tutorial! ;-)

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to Denthor, EzE, Goth, Fubar or Nobody on Connectix.
          3) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          5) Write to smith9@batis.bis.und.ac.za in E-Mail.
          6) Write to asphyxia@beastie.cs.und.ac.za

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is a 3d starfield?

I am not even sure if I should do this bit. Go watch any episode of Star Trek, the movies, Star Wars, or just about any sci-fi movie. Somewhere there will be a scene where you can see stars whizzing past the viewscreen, with the ones that are further away moving slower then the ones that are passed quite close to.

This is a 3d starfield. If you look closely, you will see that all the stars seem to originate from a point, the point you are travelling towards. This is an illusion which thankfully happens automatically, you don't have to code for it ;)

Starfields look very nice, and can make a big difference to an otherwise black background. It also makes a great screen saver ;-)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do they work?

This is actually quite simple. Imagine if you will, each star in the heavens having an x,y and z coordinate, with you being at 0,0,0. Easy? Right. Now, if you were to say move forward, ie. increase your z value, to you you will still be at 0,0,0 , but all the stars z values would have appeared to decrease by the exact same amount.

In easier language, we decrease the z value of all the the stars so that they come closer to you, and eventually whizz past.

This solves all our problems. Stars that are close to us on the x and y scales will pass us by faster then those that are very far from us on the x and y scales. The only thing we must watch out for is that no star is at 0,0 , ie. exactly in front of us, otherwise there will be a collision which will not look good.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do we code this?

The first thing to be done is to generate our starfield. This is quite easy, with us choosing x values between -160 and 160, and y values between -100 and 100 randomly. Each z is sequentially greater for each star so that we don't get large areas with no stars. We must remember to check that there are no stars at 0,0!

Okay, now we start the actual viewing section. Here are the steps :

1) Convert our 3-d coords into their 2-d versions. Have a look at tut 8

 to see how this is done, but basically we divide by z.

2) Clear away all old stars that may be on the screen.

3) Draw all our stars according to our 2-d values we have calculated in

 1)

4) Move all the stars either closer to us or further away from us by

 decreasing or increasing their z values respectively.

5) If a star's z value has passed into the negative, place it at the

 very back of our "queue" so that it will come around again

6) Jump back to 1) ad-infinitum.

That is, as they say, it. In our sample program the steps have been neatly placed into individual procedures for easy reading.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What next?

Okay, so now we have a cool looking starfield. What next? How about adding left and right motion? A menu or a scrolly in the foreground? How about figuring out how a star tunnel works? A cool 3d routine going in front of the stars?

A starfield can make just about any routine look just that much more professional, and can itself be improved to be a great effect all on it's own.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

So, this was yet another effect in the series. Do you still want more effects, or what? Leave me mail with further ideas for trainers. I may not do it if you don't ask for it!

Oh, well, the medicine has been taken, it is time for me to go. Hello to all those people who have sent me mail, and those great guys on #coders in IRC (you know who you are). Wow. That is the first greets I have ever done in a trainer. Hmm. Maybe I'm just ill ;-)

Happy coding people!

  1. Denthor

19:28

      24-7-94

The following are official ASPHYXIA distribution sites :

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹ ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º ºC-Spam BBS º410-531-5886 ºALL º ºConnectix BBS º+27-31-266-9992 ºALL º ºPOP! º+27-12-661-1257 ºALL º ºSoul Asylum º+358-0-5055041 ºALL º ºWasted Image º407-838-4525 ºALL º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ

Leave me mail if you want to become an official Asphyxia BBS distribution site.

                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 14 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hello there. Exams are just around the corner (again :( ), so I thought I better get round to doing the next trainer. As usual, there seems to have been a big delay between this one and the last one… sorry about that ;-)

Well, this trainer is mainly on four things : Glenzing, faster polys, fixed point and assembler. The sample program is basically tut 9 rewritten to include the above.

I'll go through them in order, and hopefully you won't have any hassles grasping the concepts. By the way, do any of you read the text files? I find myself answering questions via E-Mail etc. that were discussed in the text sections of the trainers … oh well, I'll just ramble along anyway ;-)

Please dont send any mail to smith9@batis.bis.und.ac.za anymore … I don't know for how much longer the account will be valid (How can a non-BIS person get onto the BIS UNIX machine in the BIS2 directory? If his name is Denthor I suppose ;-) Oh well, I got about 8 months use out of it. The account expires on Christmas day anyway…) So anyway, please leave all messages to denthor@beastie.cs.und.ac.za

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
          5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
             us at once.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is glenzing?

This is an easy one. Imagine, in a 3D object, that all the sides are made out of colored glass. That means that every time you look through that side, everything behind it is tinged in a certain color.

In ascii …

        +---------+
        |      <--|---Light blue
        |         |
   +--------+     |
   |    | <-|-----|---Dark blue
   |    +---|-----+
   |     <--|---------Light blue
   +--------+

So where the two sides overlap, the color values of the two sides are added. Easy huh? It is also easy to code. This is how you do it :

Set up your pallette to be a nice run of colors. Draw your first poly. While drawing poly 1, instead of plonking down a set pixel color, grab the

backgrond pixel, add 1 to it, then put the result down.

Draw your second poly. While drawing poly 2, instead of plonking down a set pixel color, grab the

backgrond pixel, add 2 to it, then put the result down.

and so forth.

So if the color behind poly 1 was 5, you would place pixel 6 down instead.

If you do this for every single pixel of every single side of your 3d object, you then have glenzing going. This is obviously slightly slower then just drawing an item straight, but in the sample program it goes quite quickly … this is because of the following sections…

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Faster Polygons

In Tut 9, you probably noticed that we were using a multiply for every single line of the poly that we drew. This is not good. Let's find out how to speed it up, shall we…

With the multiply method, we went through every line, to find out the minimum x and maximum x value for that line.

                         +
                 ------/---\------- Find min x and max x, draw a line
                     /       \        between them.
                   +           +
                     \       /
                       \   /
                         +

How about if we found out all the min and max x's for every line first, then just went through an array drawing them. We could do it by "scanning" each side in turn. Here is how we do it :

                        + 1
                      /
                    /
                2 +

We go from point one to point two. For every single y we go down, we move a constant x value. This value is found like this :

         xchange := (x1-x2)/(y1-y2)

Remember gradients? This is how you calulated the slope of a line waaay back in school. You never thought it would be any use, didn't you ;-)

Anyway, with this value, we can do the following :

  For loop1:=y1 to y2 do BEGIN
    [ Put clever stuff here ]
    x:=x+xchange;
  END;
  

and we will go through all the x-values we need for that line. Clever, huh?

Now for the clever bit. You have an array, from 0 to 199 (which is all the possible y-values your onscreen poly can have). Inside this is two values, which will be your min x and your max x. You start off with the min x being a huge number, and the max x being a low number. Then you scan a side. For each y, check to see if one of the following has happened : If the x value is smaller then the xmin value in your

              array, make the xmin value equal to the x value
            If the x value is larger then the xmax value in your
              array, make the xmax value equal to the x value

The loop now looks like this :

  For loop1:=y1 to y2 do BEGIN
    if x>poly[loop1,1] then poly[loop1,1]:=x;
    if x<poly[loop1,1] then poly[loop1,1]:=x;
    x:=x+xchange;
  END;

Easy? Do this for all four sides (you can change this for polys with different numbers of sides), and then you have all the x min and x max values you need to draw your polygon.

In the sample program, if you replaced the Hline procedure with one that draws solid lines, you could use the given drawpoly for solids.

Even this procedure is sped up by the next section, on fixed point.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is fixed point?

Have you ever noticed how slow reals are? I mean slooooow. You can get a massive speed increase in most programs by replacing your reals with integers, words etc. But, I hear you cry, what happens to the much needed fraction bit after the decimal point? The answer? You keep it. Here's how.

Let us say you have a word, which is 16 bits. If you want to use it as a fixed point value, you can separate it into 2 sections, one of which holds the whole value, and one which holds the fraction.

           00000000  00000000   <-Bits
           Whole     Fraction
           

The number 6.5 would therefore be shown as follows :

Top byte : 6

           Bottom byte :  128
           

128 is half (or .5) of 256, and in the case of the fraction section, 256 would equal one whole number.

So let us say we had 6.5 * 2. Using reals this would be a slow mul, but with fixed point …

          Top Byte    :  6     
          Bottom Byte :  128
          Value       :  1664   <-This is the true value of the word
                                   ie. (top byte*256)+bottom byte).
                                   this is how the computer sees the 
                                   word.
           1664 shl 1 = 3328    <-shl 1 is the same as *2, just faster.
          Top byte    :  13
          Bottom byte :  0

As you can see, we got the correct result! And in a fraction of the time that a multiplication of a real would have taken us. You can add and subtract fixed point values with no hassles, and multiply and divide them by normal values too. When you need the whole value section, you can just read the high byte, or do the following

           whole = word shr 8
       eg  1664 shr 8 = 6
       

As you can see, the fraction is truncated. Obviously, the more bits you set aside for the fraction section, the more accurate your calculation is, but the lesser the maximum whole number you can have. For example, in the above numbers, the maximum value of your whole number was 256, a far cry from the 65535 a normal (non fixed point) word's maximum.

There are a lot of hassles using fixed point (go on, try shift a negative value), most of which have to do with the fact that you have severely decreased the maximum number you may have, but trust me, the speed increase is worth it (With longintegers, and/or extended 386 registers, you can even have 16x16 fixed point, which means high accuracy and high maximum values)

Try write a program using fixed point. It is not difficult and you will get it perfect easily. Trust me, I'm a democoder ;-)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Assembler

In the sample program I used one or two assembler commands that I havent discussed with you … here they are …

imul  value      This is the same as mul, but for integer values. It
                   multiplies ax by the value. If the value is a word,
                   it returns the result in DX:AX
sal  register,value   This is the same as shl, but it is arithmetic,
                        in other words it works on integers. If you
                        had to shl a negative value, the result would
                        mean nothing to you.
rcl  register,value   This is the same as shl, but after you have
                        shifted, the value in the carry flag is placed
                        in the now-vacated rightmost bit. The carry
                        flag is set when you do an operation where the
                        result is greater then the upmost possible
                        value of the variable (usually 65535 or 32767)
                        eg mov ax,64000
                           shl ax,1     {<- Carry flag now = 1}
                           

For more info on shifting etc, re-read tut 7, it goes into the concept in detail.

The sample program is basically Tut 9 rewritten. To see how the assembler stuff is working, do the following … Go into 50 line mode (-Much- easier to debug), then hit [Alt - D] then R. A little box with all your registers, segments etc and their values will pop up. Move it down to where you want it, then go back to the program screen (Hit Alt and it's number together), and resize it so that you have both it and the register box onscreen at once (Alt - 5 to resize) … then use F4, F7 and F8 to trace though the program (you know how). The current value of the registers will always be in that box.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

Well, that is about it. The sample program may start as being a little intimidating to some when they first look at it, just remember to read it with tut 9, very little is different, it's just with fixed point and a bit of assembler.

Before I forget, with Tut 13, the program crashes if you have error checking on. This is how you sort it out :

1) Turn off error checking or 2) Make logo a pointer, and get and free the memory or 3) Read the logo directly to screen or 4) Use the {$M ……} command with various values at the top of the

   program till it works.
   

I prefer options 3 or 2, but hey … the problem was that the logo was rather large (16k), and Pascal likes complaining ;-)

I am in doubt as to weather to continue doing quotes … here is a conversation I had with Pipsy, after the group conversation got around to weather we were normal or not …

Me : I'm normal. Pipsy : No your not. Me : Prove it. Pipsy : Just look at your quotes in your trainers. Me : What? You think those are weird? Pipsy : Too weird. Me : You mean that there is a weirdness line, and I crossed it? Pipsy : Yes.

Bit of a conversation killer that, so we stopped there.

Anyway, this trainer won't have a quote in it … how about a disclaimer instead? Feel free to use it in your messages …


The views expressed above are mine and not Novells. In fact, I've never worked for them in my life!

Byeeee….

  1. Denthor

18:57

      9-9-94

The following are official ASPHYXIA distribution sites :

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹ ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º ºC-Spam BBS º410-531-5886 ºALL º ºPOP! º+27-12-661-1257 ºALL º ºSoul Asylum º+358-0-5055041 ºALL º ºWasted Image º407-838-4525 ºALL º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ

Leave me mail if you want to become an official Asphyxia BBS distribution site.

                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 15 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hello again. As you can see, this tut is very soon after the last one. This is because of two reasons … 1) The PCGPE ][ will be out soon, so I thought I would make sure I have more then just four new trainers for it, and 2) I am usually so late between tuts, I thought I would make up for it.

There is a discussion going on in Usenet, mostly saying that trainers etc. should be written a bit more formally and none of this gay banter and familiar language should be used. My "quotes" would definately be out ;-) But, until I get paid for doing this (and there don't seem to be any takers on that score), I will continue to write in this manner. My apologies to those who dont like this, but hey, its free, what did you expect?

This trainer is on plasmas, and the sample program actually became quite large, mostly due to the fact that there was some plasma stuff I wanted to try out.

The concept is very simple, at least for this plasma, so you shouldn't have any problems understanding it … AFTER you have read the text file … jumping straight into the source may be hazardous to your brain.

Plasmas are a great way to wow your friends by their wierd shapes and forms. I was at one stage going to write a game where the bad guy just had two circular plasmas instead of eyes… I am sure you will find creative and inventive new ways of doing and using plasmas.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
          5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
             us at once.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How do plasmas work?

I will only cover one type of plasma here … a realtime plasma of course. Other types of plasmas include a static picture with a pallette rotation…

When you get right down to it, this method of realtime plasmas is merely an intersection of four COS waves. We get our color at a particular point by saying :

    col := costbl[one]+costbl[two]+costbl[three]+costbl[four];

The trick is getting the four indexes of that cos table array to create something that looks nice. This is how we organise it : Have two of them being indexes for vertical movement and two of them being indexes for horizontal movement.

This means that by changing these values we can move along the plasma. To draw an individual screen, we pass the values of the four to another four so that we do not disturb the origional values. For every pixel across, we add values to the first two indexes, then display the next pixel. For every row down, we add values to the second two indexes. Sound complex enough? Good, because that what we want, a complex shape on the screen.

By altering the origional four values, we can get all sorts of cool movement and cycling of the plasma. The reason we use a cos table is as follows : a cos table has a nice curve in the value of the numbers … when you put two or more together, it is possible to get circular pictures … circles are hard to do on a computer, so this makes it a lot easier…

Okay, now you can have a look at the source file, all I do is put the above into practice. I did add one or two things though …

Background : This is just a large array, with the values in the array being added to the plasma at that pixel.

Psychadelic : This cycles through about 7000 colors instead of just rotating through the base 256.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Clever fading

You will notice when the sample program fades in and out that the colors all reach their destination at the same time … it other words, they don't all increment by one until they hit the right color then stop. When done in that way the fading does not look as professional.

Here is how we do a step-crossfade.

Each r,g,b value can be between 0 and 64. Have the pallette we want to get to in bob and the temporary pallette in bob2. For each step, from 0 to 63 do the following :

   bob2[loop1].r:=bob[loop1].r*step/64;

That means if we are halfway through the crossfade (step=32) and the red value is meant to get to 16, our equation looks like this :

  r:=16*32/64
   r=8

Which is half of the way to where it wants to be. This means all colors will fade in/out with the same ratios… and look nicer.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Rotating the pallette

I have done this one before I think .. here it is …

move color 0 into temp

move color 1 into color 0 move color 2 into color 1 move color 3 into color 2 and so on till color 255

move temp into color 255

And you pallette is rotating. Easy huh? Recheck tut 2 for more info on pallette rotation

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

The text file was a bit short this time, but that is mostly because the sample file is self explanitory. The file can however be speeded up, and of course you can add certain things which will totally change the look of the plasma.

As always, I am on the lookout for more ideas for future tuts, if you have some, mail me!

No quote today, this lan doesn't encourage creative thinking ;) However, there will be quotes in future as I have been told that some people like them. Even Pipsy said this while we were playing Ctrl-Alt-Del (two player game, one has to hit ctrl and alt as the other hits del, and the person hitting the del has to do it quickly so that the computer doesnt reboot. If the computer reboots the person who was hitting ctrl and alt has won. I thought I was doing really badly against Pipsy until I found out that the computer had frozen ;-))

Byeeee….

  1. Denthor

14:11

      16-9-94

The following are official ASPHYXIA distribution sites :

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹ ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º ºC-Spam BBS º410-531-5886 ºALL º ºPOP! º+27-12-661-1257 ºALL º ºSoul Asylum º+358-0-5055041 ºALL º ºWasted Image º407-838-4525 ºALL º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ

Leave me mail if you want to become an official Asphyxia BBS distribution site.

                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 16 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hi there. This trainer is on the scaling of an arbitrary sized bitmap to screen in two dimensions. The sample program seems to work quite quickly, and the code is document. The scaling procedure is however totally in assembler … hopefully this won't cause to many problems.

EzE has released a trainer! It is on the speeding up of 3D for normal 3D and for virtual worlds. Check it out, it is quite good (even though I get a bit of ribbing in his quote ;-)) It will be in PCGPE ][, to be released shortly.

I have set up a mailserver (that doesn't seem to work all the time, but the ones that miss I post manually). It works like this :

Send mail to denthor@beastie.cs.und.ac.za with the subject line : request-list … it will automatically mail you back with a list of subject lines with which you can grab certain files. You will then mail me with the subject line of a specific file and it will send you a uuencoded version of that file automatically. Cool, huh?

Remember, no more mail to smith9@batis.bis.und.ac.za, send it all to denthor@beastie.cs.und.ac.za ! Thanks.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
          5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
             us at once.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ What is scaling?

I think that most of you know this one already, but here goes. Let us say you have a picture (10x10 pixels) and you want to draw it to a different size (say 5x7 pixel), the process of altering the picture to fit into the new size is called scaling. Scaling only works on rectangular areas.

With scaling to can easily strech and shrink your bitmaps.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Okay, so how do we code it?

Right. The way I am going to do scaling is as follows :

For the horizontal area, I am going to calculate a certain step value. I will then trace along the bitmap, adding this step to my position, and placing the nearest pixel on to the screen. Let me explain this simpler …

Let us say I have a 10 pixel wide bitmap. I want to squish it into 5 pixels. Along the bitmap, I would draw every second pixel to screen. In ascii :

1234567890   13579
+--------+   +---+
|        |   |   |
| bitmap |   |   |dest
|        |   |   |
+--------+   +---+

As you can see, by stepping through every second pixel, I have shrunk the bitmap to a width of 5 pixels.

The equation is as follows :

          step = origionalwidth / wantedwidth;

Let us say we have a 100 pixel wide bitmap, which we want to get to 20 pixels.

          step = 100 / 20
          step = 5

If we draw every fifth pixel from the origional bitmap, we have scaled it down correctly! This also works for all values, if step is of type real.

We also find the step for the height in the same way.

Our horizontal loop is as follows :

     For loop1:=1 to wantedwidth do BEGIN
       putpixel (loop1,height,bitmap[round (curpos)],vga);
       curpos:=curpos+xstep;
     END;

And the vertical loop is much the same. Easy huh? So east in fact, I wrote the procedure in pure assembler for you ;-) … don't worry, it's commented.

In the sample program, instead of using reals I have used fixed point math. Refer to tut 14 if you have any hassles with fixed point, it is fairly straightforward.

I also use psuedo 3-d perspective transforms to get the positions smooth… after Tut8, this should be a breeze.

There are no new commands in the assembler for you, so you should get by with what you learned in tut7/8 … whew! A lot of back referencing there ;) We really are building on our knowledge :)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

Well, that is about it. As you can see the concept is easy, and in fact fairly obvious, but that didn't stop me from having to sit down with a pencil and a piece of paper a few months ago and puzzle it out ;-)

I have a lot of work ahead of me for a while, so this may be the last trainer for a few months … unless I can find some free time available. So please be patient!

     [ "Sir! My computer has just gone haywire!"
       "What?" shouts the CO. "That is a multimilliondollar machine!
         find out what's wrong! This is a critical time lieutenant!"
       "Yes sir"
       The young lieutenant furiously types away at the keyboard, but
         the machine totally ignores her.
       "What is going on, soldier?"
       "I don't know sir! It is just doing totally arbitrary things
         after it's assigned tasks are completed. In the computer world
         this is known as Denthorisms."
       The computer starts to make random beeps, and prints out a payroll
         program.
       "Get it working NOW soldier"
       The lieutenant ignores him, and contines typing. She gets partial
         control of the system, she can run programs, but the computer is
         continually running arb tasks in the background. One of the
         techhies who have gathered behing her suddenly cries "Hey! It's
         accessing the missile codes! It wants to launch them!"
       The typing gathers speed, but to no avail. Another techhie says
         "I could disconnect the computer from the link, but that would take
         hours! And this thing will have the codes in under five minutes
         at the speed it's going!"
       A smile forms on the lieutanants face, and she leans back in her chair.
       "What the hell are you doing?" yells the CO. "Why have you stopped?"
       Again ignoring him, the lieutenant instead turns to the techhie. "Go
         disconnect the machine, I know how to get you the time you need."
       "How on earth will you do that? The machines going at top speed!"
       She smiles again, leans forward, types in three letters and hits the
         carriage return. The computer grinds to a halt.
       The smile breaks into a grin. "Maybe it _does_ have it's uses after
         all."
                                                                      ]
                                                       - Grant Smith
                                                           15:30
                                                             23-9-94

Byeeeee…..

The following are official ASPHYXIA distribution sites :

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹ ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º ºC-Spam BBS º410-531-5886 ºALL º ºPOP! º+27-12-661-1257 ºALL º ºSoul Asylum º+358-0-5055041 ºALL º ºWasted Image º407-838-4525 ºALL º ºReckless Life º351-01-716 67 58ºALL º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ

Leave me mail if you want to become an official Asphyxia BBS distribution site.  ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸

                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 17 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Hi there everybody. It's a new year, but the parties are over and it's time to get coding again!

My mailserver died. Various sysadmins decided it was time to upgrade the OS, and wound up nuking the hard drive :-( … this means that request-list is not working at the moment, and I have probably lost lots of mail.

denthor@beastie.cs.und.ac.za is still the account to write to, and hopefully the mailserver will be back up in the near future.

There are various C/C++ conversions of my trainer, best of which seem to be those by Snowman … he runs through the text files with C++ updates (and seems to point out my previous mistakes with glee ;-), as well is giving a fully documented C++ conversion of the source … very nice stuff.

Also, my trainers are being put on a World Wide Web site … it is still under construction, but go to http://www.cit.gu.edu.au/~rwong my site is at http://goth.vironix.co.za/~denthor … it is currently pretty awful, anyone want to write a nice one for me? ;)

I have just about finished Asphyxia's new game, I will let you all know when it is completed.

Tut 16 dies with large bitmaps … the way to sort this out is to decrease the accuracy of the fixed point from 256 to 128 … then you can have bitmaps up to 512 pixels wide. I will be putting an updated scale routine in the gfx4.pas unit.

This tutor is on a few demo effects (pixel morphs and static) … after this one, I will go on to more theory … perhaps some more 3d stuff, such as gourad shading etc. Comments?

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
          5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
             us at once.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Pixel Morphing

Have you ever lain down on your back in the grass and looked up at the cloudy sky? If you have, you have probably seen the clouds move together and create wonderful shapes … that cloud plus that cloud together make a whale … a ship … a face etc.

We can't quite outdo mother nature, but we can sure give it a shot. The effect I am going to show you is where various pixels at different starting points move together and create an overall picture.

The theory behind it is simple : Each pixel has bits of data associated with it, most important of which is as follows :

This is my color This is where I am This is where I want to be.

The pixel, keeping it's color, goes from where it is to where it wants to be. Our main problem is _how_ it moves from where it is to where it wants to be. A obvious approach would be to say "If it's destination is above it, decrement it's y value, if the destination is to the left, decrement it's x value and so on."

This would be bad. The pixel would only ever move at set angles, as you can see below :

              Dest   O-----------------\
                                         \  <--- Path
                                           \
                                             \
                                              O Source

Doesn't look very nice, does it? The pixels would also take different times to get to their destination, whereas we want them to reach their points at the same time, ie :

   Dest 1   O-------------------------------O Source 1
   Dest 2   O-----------------O Source 2

Pixels 1 and 2 must get to their destinations at the same time for the best effect. The way this is done by defining the number of frames or "hops" needed to get from source to destination. For example, we could tell pixel one it is allowed 64 hops to get to it's destination, and the same for point 2, and they would both arrive at the same time, even though pixel 2 is closer.

The next question, it how do we move the pixels in a straight line? This is easier then you think…

Let us assume that for each pixel, x1,y1 is where it is, and x2,y2 is where it wants to be.

 (x2-x1) = The distance on the X axis between the two points
 (y2-y1) = The distance on the Y axis between the two points

If we do the following :

dx := (x2-x1)/64;

we come out with a value in dx wich is very useful. If we added dx to x1 64 times, the result would be x2! Let us check…

dx = (x2-x1)/64
dx*64 = x2-x1         { Multiply both sides by 64 }
dx*64+x1 = x2         { Add x1 to both sides }

This is high school math stuff, and is pretty self explanitory. So what we have is the x movement for every frame that the pixel has to undergo. We find the y movement in the same manner.

dy := (y2-y1)/64;

So our program is as follows :

Set x1,y1 and x2,y2 values
dx:= (x2-x1)/64;
dy:= (y2-y1)/64;
for loop1:=1 to 64 do BEGIN
  putpixel (x1,y1)
  wait;
  clear pixel (x1,y1);
  x1:=x1+dx;
  y1:=y1+dy;
END;

If there was a compiler that could use the above pseudocode, it would move the pixel from x1,y1 to x2,y2 in 64 steps.

So, what we do is set up an array of many pixels with this information, and move them all at once … viola, we have pixel morphing! It is usually best to use a bitmap which defines the color and destination of the pixels, then randomly scatter them around the screen.

Why not use pixel morphing on a base object in 3d? It would be the work of a moment to add in a Z axis to the above.

The sample program uses fixed point math in order to achieve high speeds, but it is basically the above algorithm.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Static

A static screen was one of the first effects Asphyxia ever did. We never actually released it because we couldn't find anywhere it would fit. Maybe you can.

The easiest way to get a sreen of static is to tune your TV into an unused station … you even get the cool noise effect too. Those people who build TV's really know how to code ;-)

For us on a PC however, it is not as easy to generate a screen full of static (unless you desperately need a new monitor)

What we do is this :

Set colors 1-16 to various shades of grey. Fill the screen up with random pixels between colors 1 and 16 Rotate the pallette of colors 1 to 16.

That's it! You have a screenfull of static! To get two images in one static screen, all you need to do is fade up/down the specific colors you are using for static in one of the images.

A nice thing about a static screen is that it is just pallette rotations … you can do lots of things in the foreground at the same time (such as a scroller).

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing

Well, that is about it … as I say, I will be doing more theory stuff in future, as individual demo effects can be thought up if you know the base stuff.

Note the putpixel in this GFX3.PAS unit … it is _very_ fast .. but remember, just calling a procedure eats clock ticks… so imbed putpixels in your code if you need them. Most of the time a putpixel is not needed though.

PCGPE ][ will be out on the 10th of Feburary. All the new tutors will be on it (if you aren't reading this from it right now! ;-) … grab a copy of it, it is a very useful ting to have handy.

I have found out that these tutors have been distributed inside paper magazines … please remember that Denthor and Asphyxia retain full copyright to the series (as mentioned earlier in the series), and if you want to use a version in a magazine, CONTACT ME FIRST … I will probably also modify it/cut out various unneccesary things … other then that, you must not alter the files without my permission, or at least leave a copy of the origional with the update. Maybe I could even start up a nice column for some magazine or other :)

Sorry 'bout that, but it had to be said …

I am writing a column for the Demuan list, a Florida-based electronic magazine … pick it up off ftp.eng.ufl.edu … I have written various articles, all bordering on quote-like design.

There are more BBS's to be added to the list at the end, but I don't have them here… this tut has taken long enough ;-)

Byeeeee….

  1. Denthor

The following are official ASPHYXIA distribution sites :

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹ ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º ºC-Spam BBS º410-531-5886 ºALL º ºPOP! º+27-12-661-1257 ºALL º ºSoul Asylum º+358-0-5055041 ºALL º ºWasted Image º407-838-4525 ºALL º ºReckless Life º351-01-716 67 58ºALL º ºMach 5 BBS º+1 319-355-7336 ºALL º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ

Leave me mail if you want to become an official Asphyxia BBS distribution site.

                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 18 ]==–

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction

Welcome back! I know, I know, you all all shocked that this tut is out so soon after the last one, but the reason for this is that I want to have Tut 20 out by the time PCGPE ][ is released. I probably won't get that far, but I'll try! ;)

This tut is on file packing, and putting everything into one executeable file. For tut 19, I am thinking of doing a bit more on explaining assembler, and perhaps demonstrating with a fire effect or something.

My mailserver is back up, thanks to Nobody (that's his handle). You write to denthor@beastie.cs.und.ac.za with the subject line request-list. The mailserver checks each incoming letter for this subject line, and if it finds one of the specific strings, it mails you back a certain file. I never get to see these messages! If you want to mail me personally, give your message a unique subject name! Anyway, you can request all the tuts through this mailserver.

I hope you are all subscribed to the Demuan List! If not, ftp it off ftp.eng.ufl.edu every sunday. I am writing a "humor" column there until someone can figure out something else I could write ;-).

Pipsy wants mail! She is at cowan@beastie.cs.und.ac.za and wants to chat :) Go on, mail her. The co-founder of ctrl-alt-del, she is also a good graphics coder.

If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail

                on the ASPHYXIA BBS.
          2) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
          5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
             us at once.

NB : If you are a representative of a company or BBS, and want ASPHYXIA

     to do you a demo, leave mail to me; we can discuss it.

NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling

      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Loading a PCX file

This is actually quite easy. The PCX file is divided into three sections, mainly a 128 byte header, a data section, and a 768 byte pallette.

You can usually ignore the 128 byte header, but here it is :

0 Manufacturer 10 = ZSoft .PCX file 1 Version 2 Encoding 3 Bits Per Pixel 4 XMin, Ymin, XMax, YMax (2 bytes each) 12 Horizontal Resolution (2 bytes) 14 Verticle Resolution (2 bytes) 16 Color pallette setting (48 bytes) 64 Reserved 65 Number of color planes 66 Bytes per line (2 bytes) 68 1 = Color 2 = Grayscale (2 bytes) 70 Blank (58 bytes)

That makes 128 bytes.

The pallette file, which is 768 bytes, is situated at the very end of the PCX file. The 769'th byte back should be the decimal 12, which indicates that a VGA color pallette is to follow.

There is one thing that we have to do to get the pallette correct in VGA … the PCX pallette values for R,G,B are 0 to 255 respectively. To convert this to our standard (VGA) pallette, we must divide the R,G,B values by 4, to get them into a range of 0 to 63.

Actually decoding the image is very simple. Starting after the 128 byte header, we read a byte.

If the top two bits of this byte are not set, we dump the value to the screen.

We check bits as follows :

if 1)

1)
temp and $c0) = $c0) then …(bits are set)… else …(bits are not set) C0 in hex = 11000000 in binary = 192 in decimal Let's look at that more closely…
temp  and  c0h
temp  and  11000000b
That means, when represented in bit format, both corresponding bits have to be set to one for the result to be one. 0 and 0 = 0 1 and 0 = 0 0 and 1 = 0 1 and 1 = 1 In the above case then, both of the top two bits of temp have to be set for the result to equal 11000000b. If it does not equal that, the top two bits are not both set, and we can put the pixel. So
if ((temp and $c0) = $c0) then BEGIN
END else BEGIN
  putpixel (screenpos,0,temp,vga);
  inc (screenpos);
END;
If the top two bits _are_ set, things change. The bottom six bits become a loop counter, which the next byte is repeated.
if ((temp and $c0) = $c0) then BEGIN
{ Read in next byte, temp2 here.}
  for loop1:=1 to (temp and $3f) do BEGIN
    putpixel (screenpos,0,temp2,vga);
    inc (screenpos);
  END;
END else BEGIN
  putpixel (screenpos,0,temp,vga);
  inc (screenpos);
END;
There is our PCX loader. You will note that by and'ing temp by $3f, I am and'ing it by 00111111b … in other words, clearing the top two bits. The sample program has the above in assembler, but it is the same procedure… and you can read tut 19 for more info on how to code in assembler. In the sample I assume that the pic is 320x200, with a maximum size of 66432 bytes. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ File packing The question is simple .. how do I get all my files into one executeable? Having many small data files can start to look unprofessional. An easy way to have one .exe and one .dat file when dealing with many cel's etc. is easy …. you would alter your load procedure, which looks as follows : VAR temp : Array [1..5,1..256] of byte; Procedure Init; BEGIN
loadcel ('pic1.cel',temp[1]);
loadcel ('pic2.cel',temp[2]);
loadcel ('pic3.cel',temp[3]);
loadcel ('pic4.cel',temp[4]);
loadcel ('pic5.cel',temp[5]);
END; For one complile you would do this : VAR temp : Array [1..5,1..256] of byte; Procedure Init; VAR f:File; BEGIN
loadcel ('pic1.cel',temp[1]);
loadcel ('pic2.cel',temp[2]);
loadcel ('pic3.cel',temp[3]);
loadcel ('pic4.cel',temp[4]);
loadcel ('pic5.cel',temp[5]);
assign (f,'pic.dat');
rewrite (f,1);
blockwrite (f,temp,sizeof(temp));
close (f);
END; From then on, you would do : VAR temp : Array [1..5,1..256] of byte; Procedure Init; VAR f:File; BEGIN
assign (f,'pic.dat');
reset (f,1);
blockread (f,temp,sizeof(temp));
close (f);
END; This means that instead of five data files, you now have one! You have also stripped the 800 byte cel header too :) … note that this will work for any form of data, not just cel files. The next logical step is to include this data in the .exe file, but the question is how? In an earlier tutorial, I converted my data file to constants and placed it inside my main program. This is not good mainly because of space restrictions … you can only have so many constants, and what if your data file is two megs big? Attached with this tutorial is a solution. I have written a program that combines your data files with your executeable file, no matter how big the data is. The only thing you have to worry about is a small change in your data loading methods. Lets find out what. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Using the file packer Normally you would load your data as follows : Procedure Init; BEGIN
loadcel ('bob.bob',temp);
loadpcx ('den.pcx',VGA);        { Load a PCX file }
loaddat ('data.dat',lookup);    { Load raw data into lookup }
END; Easy, hey? Now, using the file packer, you would change this to : USES fpack; Procedure Init; BEGIN
total := 3;
infodat[1] := 'bob.bob';
infodat[2] := 'den.pcx';
infodat[3] := 'data.dat';
loadcel (1,temp);
loadpcx (2,VGA);
loaddat (3,lookup);
END; Not too difficult? Now, this is still using the normal data files on your hard drive. You would then run PACK.EXE, select the program's .exe as the base, then select "bob.bob", "den.pcx" and "data.dat", in order (1, 2, 3). Hit "c" to contine, and it will combine the files. Your programs .exe file will be able to run independantly of the separate data files on disk, because the data files are imbedded with the .exe. Let us take a closer look at the load procedures. Normally a load procedure would look as follows : Procedure LoadData (name:string; p:pointer); VAR f:file; BEGIN
assign (f,name);
reset (f,1);
blockread (f,p^,filesize(f);
close (f);
END; In FPack.pas, we do the following : Function LoadData (num:integer; p:pointer):Boolean; VAR f:file; BEGIN
If pack then BEGIN
  assign (f,paramstr(0));
  reset (f,1);
  seek (f,infopos[num]);
  blockread (f, p^, infopos[num+1]-infopos[num]);
  close (f);
END else BEGIN
  assign (f,infodat[num]);
  reset (f,1);
  blockread (f, p^, filesize (f));
  close (f);
END;
END; As you can see, we just have two special cases depending on weather or not the .exe file has been packed yet. NOTE : After you have packed the file, you CAN NOT pklite it. You can
     however pklite the .exe _before_ you run pack.exe ... in other
     words, you can not use pklite to try pack your data files.
PACK.EXE does have a limitation … you can only pack 24 data files together. If you would like it to do more, mail me … It should be easy to increase the number. In the sample program, FINAL.EXE is the same as temp.pas, except it has it's PCX embedded inside it. I ran pack2.exe, selected final.exe and eye.pcx, hit "C", and there it was. You will notice that eye.pcx is not included in the directory … it is now part of the exe! eye.pcx was draw by Gary Morton of iCANDi Design. The other pcx is an old one draw by Fubar. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing Well, that's about it for this trainer… next one (as I have mentioned twice already ;) will be on assembler, with a flame routine thrown in. Any good html programmers out there? My web page really needs help ;-) As soon as I figure out how, I will also be creating a mailing list, in which people with internet addresses will be able to get all new trainers dilivered directly into their mailbox's. I hope to announce something in tut 20. This tut has been a bit of a departure from normal tuts … aside from the PCX loading routines, the rest has been "non programming" oriented … don't worry, next weeks one will be back to normal. Byeeeee….
  1. Denthor
The following are official ASPHYXIA distribution sites : ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹ ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º *Moving* ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º *Moving* ºC-Spam BBS º410-531-5886 ºALL º ºPOP! º+27-12-661-1257 ºALL º ºSoul Asylum º+358-0-5055041 ºALL º ºWasted Image º407-838-4525 ºALL º ºReckless Life º351-01-716 67 58ºALL º ºMach 5 BBS º+1 319-355-7336 ºALL º ºHouse of Horror º+1 513-734-6470 ºALL º ºZero Level º+39 6-810-9934 ºALL º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ Leave me mail if you want to become an official Asphyxia BBS distribution site.
                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 19 ]==–
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction Hi there. As promised in Tut 18, this trainer is on assembler. For those people who already know assembler quite well, this tut is also on the flame effect. Okay, here is the total list of ways to get my trainers : http://goth.vironix.co.za/~denthor (WWW) ftp.eng.ufl.edu pub/msdos/demos/code/graph/tutor (FTP) denthor@beastie.cs.und.ac.za Subject : request-list (EMAIL) As well as the BBS numbers shown at the end … I will add a few ftp sits to that list (x2ftp.oulu.fi etc.) Tut 20? How about 3d shading, hidden surface removal etc? Mail me :) If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
                on the ASPHYXIA BBS.
          2) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
          5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
             us at once.
NB : If you are a representative of a company or BBS, and want ASPHYXIA
     to do you a demo, leave mail to me; we can discuss it.
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Assembler - the short version Okay, there are many assembler trainers out there, many of which are probably better then this one. I will focus on the areas of assembler that I find important … if you want more, go buy a book (go for the Michael Abrash ones), or scour the 'net for others. First, let us start off with the basic set up of an assembler program. DOSSEG This tells your assembler program to order your segments in the same manner that high level languages do. .MODEL <MODEL> <MODEL> can be : Tiny Code + Data < 64k (Can be made a COM file)
               Small      Code < 64k          Data < 64k
               Medium     Code > 64k          Data < 64k
               Compact    Code < 64k          Data > 64k
               Large      Code > 64k          Data > 64k
               Huge       Arrays > 64k
.286 Enable 286 instructions … can be .386 ; .386P etc. .STACK <size> <size> will be the size of your stack. I usually use 200h .DATA Tells the program that the data is about to follow. (Everything after this will be placed in the data segment) .CODE Tells the program that the code is about to follow. (Everything after this will be placed in the code segment) START : Tells the program that this is where the code begins. END START Tells the program that this is where the code ends. To compile and run an assembler file, we run tasm bob tlink bob I personally use tasm, you will have to find out how your assembler works. Now, if we ran the above file as follows : DOSSEG .MODEL SMALL .286 .STACK 200h .DATA .CODE START END START You would think that is would just exit to dos immediately, right? Wrong. You have to specifically give dos back control, by doing the following : START
      mov     ax,4c00h
      int     21h
END START Now if you compiled it, it would run and do nothing. Okay, let us kick off with registers. Firstly : A bit is a value that is either 1 or 0 This is obviously quite limited, but if we start counting in them, we can get larger numbers. Counting with ones and zeros is known as binary, and we call it base 2. Counting in normal decimal is known as base 10, and counting in hexidecimal is known as base 16.
  Base 2 (Binary)     Base 10 (Decimal)    Base 16 (Hexidecimal)
       0                      0                       0
       1                      1                       1
       10                     2                       2
       11                     3                       3
       100                    4                       4
       101                    5                       5
       110                    6                       6
       111                    7                       7
       1000                   8                       8
       1001                   9                       9
       1010                   10                      A
       1011                   11                      B
       1100                   12                      C
       1101                   13                      D
       1110                   14                      E
       1111                   15                      F
As you can see, you need four bits to count up to 15, and we call this a nibble. With eight bits, we can count up to 255, and we call this a byte. With sixteen bits, we can count up to 65535, and we call this a word. With thirty two bits, we can count up to lots, and we call this a double word. :) A quick note : Converting from binary to hex is actually quite easy. You break up the binary into groups of four bits, starting on the right, and convers these groups of four to hex.
    1010 0010 1111 0001
=      A    2    F    1
Converting to decimal is a bit more difficult. What you do, is you multiply each number by it's base to the power of it's index …
A2F1 hex
= (A*16^3) + (2*16^2) + (F*16^1) + (1*16^0) = (10*4096) + (2*256) + (15*16) + (1) = 40960 + 512 + 240 + 1 = 41713 decimal The same system can be used for binary. To convert from decimal to another base, you divide the decimal value by the desired base, keeping a note of the remainders, and then reading the results backwards.
             16   |   41713
             16   |   2607    r   1       (41713 / 16 = 2607 r 1)
             16   |   162     r   F       (2607 / 16 = 162 r 15)
             16   |   10      r   2       (162 / 16 = 10 r 2)
                  |   0       r   A       (10 / 16 = 0 r 10)
Read the remainders bacckwards, our number is : A2F1 hex. Again, the same method can be used for binary. The reason why hex is popular is obvious … using bits, it is impossible to get a reasonable base 10 (decimal) system going, and binary get's unwieldly at high values. Don't worry too much though : most assemblers (like Tasm) will convert all your decimal values to hex for you. You have four general purpose registers : AX, BX, CX and DX Think of them as variables that you will always have. On a 286, these registers are 16 bytes long, or one word. As you know, a word consists of two bytes, and in assembler you can access these bytes individualy. They are separated into high bytes and low bytes per word.
 High Byte |  Low Byte
 0000 0000 | 0000 0000  bits
 [--------Word-------]
The method of access is easy. The high byte of AX is AH, and the low byte is AL … you can also access BH, BL, CH, CL, DH and DL. A 386 has extended registers : EAX, EBX, ECX, EDX … you can access the lower word normally (as AX, with bytes AH and AL), but you cannot access the high word directly … you must ror EAX,16 (rotate the binary value through 16 bits), after which the high word and low word swap … do it again to return them. Acessing EAX as a whole is no problem … mov eax,10 ; add eax,ebx … these are all vaild. Next come segments. As you have probably heard, computer memory is divided into various 64k segments (note : 64k = 65536 bytes, sound familiar?) A segment register points to which segment you are looking at. An offset register points to how far into that segment you are looking. One way of looking at it is like looking at a 2d array … the segments are your columns and your offsets are your rows. Segments and offsets are displayed as Segment:Offset … so $a000:50 would mean the fiftieth byte in segment $a000. The segment registers are ES, DS, SS and CS. A 386 also has FS an GS. These values are words (0-65535), and you cannot access the high or low bytes separately. CS points to you your code segment, and usually if you touch this your program will explode. SS points to your stack segment, again, this baby is dangerous. DS points to your data segment, and can be altered, if you put it back after you use it, and don't use any global variables while it is altered. ES is your extra segment, and you can do what you want with it. The offset registers are DI, SI, IP, SP, BP. Offset registers are generally asscociated with specific segment registers, as follows : ES:DI DS:SI CS:IP SS:SP … On a 286, BX can be used instead of the above offset registers, and on a 386, any register may be used. DS:BX is therefore valid. If you create a global variable (let's say bob), when you access that variable, the compiler will actually look for it in the data segment. This means that the statement : ax = bob could be ax = ds:[15] A quick note : A value may be signed or unsigned. An unsigned word has a range from 0 to 65535. A signed word is called an integer and has a range -32768 to 32767. With a signed value, if the leftmost bit is equal to 1, the value is in the negative. Next, let us have a look at the stack. Let us say that you want to save the value in ax, use ax to do other things, then restore it to it's origional value afterwards. This is done by utilising the stack. Have a look at the following code : mov ax, 50 ; ax is equal to 50 push ax ; push ax onto the stack mov ax, 27 ; ax is equal to 27 pop ax ; pop ax off the stack At this point, ax is equal to 50. Remember we defined the stack to be 200h further up? This is part of the reason we have it. When you push a value onto the stack, that value is recorded on the stack heap (referenced by SS:SP, SP is incremented) When you pop a value off the stack, the value is placed into the variable you are poping it back in to, SP is decremented and so forth. Note that the computer does not care what you pop the value back in to … mov ax, 50 push ax pop bx Would set the values of both ax and bx to 50. (there are faster ways of doing this, pushing and poping are fairly fast though) push ax push bx pop ax pop bx would swap the values of ax and bx. As you can see, to pop the values back in to the origional variables, you must pop them back in the opposite direction to which you pushed them. push ax push bx push cx pop cx pop bx pop ax would result in no change for any of the registers. When a procedure is called, all the parameters for that procedure are pushed onto the stack. These can actually be read right off the stack, if you want to. As you have already seen, the mov command moves a value… mov <dest>, <source> Note that dest and source must be the same number of bits long… mov ax, dl would not work, and neither would mov cl,bx However, mov cx,dx
       mov  ax,50
       mov  es,ax
are all valid. Shl I have explained before, it is where all the bits in a register are shifted one to the left and a zero added on to the right. This is the eqivalent of multiplying the value by two. Shr works in the opposite direction. Rol does the same, except that the bit that is removed from the left is replaced on the right hand side. Ror works in the opposite direction. div <value> divides the value in ax by value and returns the result in al if value is a byte, placing the remainder in ah. If value is a word, the double word DX:AX is divided by value, the result being placed in ax and the remainder in dx. Note that this only works for unsigned values. idiv <value> does the same as above, but for signed variables. mul <value> If value is a byte, al is multiplied by value and the result is stored in ax. If value is a word, ax is multiplied by value and the result is stored in the double word DX:AX imul <value> does the same as above, but for signed variables. The j* commands are fairly simple : if a condition is met, jump to a certain lable. jz <label> Jump if zero ja <label> Jump above (unsigned) jg <label> Jump greater (signed) and so forth. An example … cmp ax,50 ; Compare ax to 50 je @Equal ; If they are equal, jump to label @equal call MyProc Runs procedure MyProc and then returns to the next line of code. Procedures are declared as follows : MyProc proc near
         ret    ; Must be here to return from where it was called
MyProc endp Variables are also easy : bob db 50 creates a variable bob, a byte, with an initial value of 50. bob2 dw 50 creates a variable bob2, a word, with an initial value of 50. bob3 db 1,2,3,4,5,65,23 creates bob3, an array of 7 bytes. bob4 db 100 dup (?) creates bob4, an array of 100 bytes, with no starting value. Go back and look at tut 7 for a whole lot more assembler commands, and get some sort of reference guide to help you out with others. I personally use the Norton Guides help file to program assembler. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Fire Routines To demonstrate how to write an assembler program, we will write a fire routine in 100% assembler. The theory is simple… Set the pallette to go from white to yellow to red to blue to black. Create a 2d array representing the screen on the computer. Place high values at the bottom of the array (screen) for each element, do the following :
Take the average of the four elements under it
  • Current element
123
                       4  Other elements
Get the average of the four elements, and place the result in the current
element.
Repeat Easy, no? I first saw a fire routine in the Iguana demo, and I just had to do one ;) … it looks very effective. With the sample file, I have created a batch file, make.bat … it basically says :
      tasm fire
      tlink fire
So to build and run the fire program, type : make fire The source file is commented quite well, so there shouldn't be any problems. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing As you can see, the sample program is in 100% assembler. For the next tut I will return to Pascal, and hopefully your new found assembler skills will help you there too. Byeeeee….
  1. Denthor
The following are official ASPHYXIA distribution sites : ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍ» ºBBS Name ºTelephone No. ºOpen º ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍ͹ ºASPHYXIA BBS #1 º+27-31-765-5312 ºALL º ºASPHYXIA BBS #2 º+27-31-765-6293 ºALL º ºC-Spam BBS º410-531-5886 ºALL º ºPOP! º+27-12-661-1257 ºALL º ºSoul Asylum º+358-0-5055041 ºALL º ºWasted Image º407-838-4525 ºALL º ºReckless Life º351-01-716 67 58ºALL º ºMach 5 BBS º+1 319-355-7336 ºALL º ºHouse of Horror º+1 513-734-6470 ºALL º ºZero Level º+39 6-810-9934 ºALL º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍͼ Leave me mail if you want to become an official Asphyxia BBS distribution site.
                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 20 ]==–
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction Hi all! It has been a _long_ time since my last trainer (as I am sure many of you have noticed) A lot has happened between now and the last trainer… but for once I won't bore you with the details ;) I do have a full time job though, coding C++ applications. I have taken over the production of the PCGPE from Mark Feldman. He is mailing all the articles written so far, and as soon as I get them I will get to work on releasing the PCGPE II. Mark is working on the Windows GPE. This trainer is on 3d hidden face removal and face sorting. I was going to add shading, but that can wait until a later trainer. For conveniance I will build on the 3d code from tut 16(?). The maths for face removal is a bit tricky, but just think back to your old High School trig classes. I have noticed that in my absence, one or two people have started their own trainer series. Read Hornet DemoNews for a great column by Trixter covering some of the more tricky demo effects. Well, on with the trainer! If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
                on the ASPHYXIA BBS.
          2) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during varsity). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
          5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
             us at once.
NB : If you are a representative of a company or BBS, and want ASPHYXIA
     to do you a demo, leave mail to me; we can discuss it.
NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
      quite lonely and want to meet/help out/exchange code with other demo
      groups. What do you have to lose? Leave a message here and we can work
      out how to transfer it. We really want to hear from you!
http://goth.vironix.co.za/~denthor (WWW) ftp.eng.ufl.edu pub/msdos/demos/code/graph/tutor (FTP) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Face Sorting There are many ways to sort faces in a 3d object. For now, I will show you just about the easiest one of the lot. Say you have to polygons….
  1. —–P1
  1. —————–P2
                 Eye
As you can see, P1 has to be drawn before P2. The easiest way to do this is as follows: On startup, find the mid point of each of the polys, through the easy equations,
      x = (P2.1.x + P2.2.x + P2.3.x + p2.4.x)/4
      y = (P2.1.y + P2.2.y + P2.3.y + p2.4.y)/4
      z = (P2.1.z + P2.2.z + P2.3.z + p2.4.z)/4
NOTE : For a triangle you would obviously only use three points and divide by three. Anyway, now you have the X,Y,Z of the midpoint of the polygon. You can then rotate this point with the others. When it comes time to draw, you can compare the resulting Z of the midpoint, sort all of the Z items, and then draw them from back to front. In the sample program I use a simple bubble sort… basically, I check the first two values against each other, and swap them if the first is bigger then the second. I continue doing this to all the numbers until I run through the entire list without swapping once. Bubble sorts are standard seven computer science topics… perhaps borrow a text book to find out more about them and other (better) sorting methods. The above isn't perfect, but it should work 90% of the time. But it still means that when you are drawing a cube, you have to draw all 6 sides every frame, even though only three or so are visible. That is where hidden face removal comes in… =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Hidden Face Removal Pick up something square. A stiffy disk will do fine. Face it towards you, and number all the corners from one to four in a clockwise direction.
              1 +-------------+ 2
                |             |
                |             |
                |             |
                |             |
              4 +-------------+ 3
Now rotate the stiffy disk on all three axese, making sure that you can still see the front of the disk. You will notice that whenever you can see the front of the disk, the four points are still in alphabetical order. Now rotate it so that you can see the back of the stiffy. Your points will now be :
              2 +-------------+ 1
                |             |
                |             |
                |             |
                |             |
              3 +-------------+ 4
The points are now anti-clockwise! This means, in it's simplest form, that if you define all your poygon points in a clockwise order, when drawing you ignore the polys that are anticlockwise. (Obviously when you define the 3d object, you define the polygons facing away from you in an anticlockwise order) To find out weather a poly's points are clockwise or not, we need to find it's normal. Here is where things start getting fun. In school, you are told that a normal is perpendicular to the plane. In ascii :
                    | Normal
                    |
                    |
      --------------------------- Polygon
As you can see, the normal is at 90 degrees to the surface of the poly. We must extend this to three dimensions for our polygons. You'll have to trust me on that, I can't draw it in ascii :) To find a normal, you only need three points from your poly (ABC) : A(x0,y0,z0), B(X1,Y1,Z1), C(X2,Y2,Z2) then the vector normal = AB^AC = (Xn,Yn,Zn) with
      Xn=(y1-y0)(z0-z2)-(z1-z0)(y0-y2)
      Yn=(z1-z0)(x0-x2)-(x1-x0)(z0-z2)
      Zn=(x1-x0)(y0-y2)-(y1-y0)(x0-x2)
We are interested in the Z normal, so we will use the function :
normal:=(x1-x0)(y0-y2)-(y1-y0)(x0-x2);
The result is something of a sine wave when you rotate the poly in three dimensions. A negative value means that the poly is facing you, a posotive value means that it is pointing away. The above means that with a mere two muls you can discount an entire poly and not draw it. This method is perfect for "closed" objects such as cubes etc. I am anything but a maths teacher, so go borrow someones math book to find out more about surface normals. Trust me, there is a lot more written about them then you think. An extension of calculating your normal is finding out about light-sourcing your polygons. Watch for more information in one of the next few tutors. A combination of the above two routines should work quite nicely in creating 3d objects with little or no overlapping. The example file will show you the two methods and how well they work. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing As you can see, the above was quite easy. I have a few ideas for tut 21, so keep watch for it. Also keep an eye open for PCGPE ][ (but don't mail me asking when it's due! I already get too many of those! ;-) My sister got married a few days ago. The worst part was that I was forced to cut my hair. My hair was quite long (slightly longer then when the pic on my web page was taken), and it is all quite depressing. Anyway, the wedding was great, so it wasn't all for nothing. I hope to get tut 21 and possibly 22 out before christmas, but I will be on holiday from the 18th. I will be in Cape Town sometime after christmas day for a week or two, so if you're there I'll meet you on the cable car :-) I wrote a quote for this tut, but I have decided I didn't like it. I'll try do better for tut 21 ;) Byeeeee…..
  1. Denthor
14-12-95 PS. I seem to have lost my list of distribution sites… could you all re-mail me your details? Thanks.
                 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
                 ³         W E L C O M E         ³
                 ³  To the VGA Trainer Program   ³ ³
                 ³              By               ³ ³
                 ³      DENTHOR of ASPHYXIA      ³ ³ ³
                 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
                   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
                     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
  1. -==[ PART 21 ]==–
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Introduction Hi there! It's been quite a long time (again) since the last tutorial … I'll bet some of you had given up one me ;-) Today is my 21st birthday, so I decided it would be the perfect time to finish up this trainer which I have been meaning to send out for weeks. It's on texure mapping. I know, I know, I said light sourcing, then gourad, then texture mapping, but I got enough mail (a deluge in fact ;) telling me to do texure mapping… I'll be using the code from Tut 20 quite extensively, so make sure you know whats going on in there… well, on with the show! BTW, I've improved my web page quite a bit… give it a visit, I want to really ramp up that hit count :) If you would like to contact me, or the team, there are many ways you can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
                on the ASPHYXIA BBS.
          2) Write to :  Grant Smith
                         P.O.Box 270 Kloof
                         3640
                         Natal
                         South Africa
          3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
                call during work hours). Call +27-31-73-2129 if you call
                from outside South Africa. (It's YOUR phone bill ;-))
          4) Write to denthor@goth.vironix.co.za in E-Mail.
          5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
             us at once.
http://www.vironix.co.za/~grants (WWW) ftp.eng.ufl.edu pub/msdos/demos/code/graph/tutor (FTP) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ Free Direction Texture Mapping There are two things you should know before we begin. Firstly, I am cheating. The texture mapping I am going to show you is not perspective-correct, with clever divides for z-placement etc. This method looks almost as good and is quite a bit faster too. Secondly, you will find it all rather easy. The reason for this is that it's all rather simple. I first made the routine by sitting down with some paper and a pencil and had it on the machine in a few hours. A while later when people on the net started discussing their methods, they were remarkably similar. Let me show you what I mean. Let us assume you have a texture of 128x128 (a straight array of bytes [0..127, 0..127]) which you want to map onto the side of a polygon. The problem of course being that the polygon can be all over the place, with one side longer then the other etc. Our first step is to make sure we know which end is up… let me demonstrate…
                    1
                  +
               /    \
            /         \
        4 +            +  2
            \        /
              \   /
                +
                3
Let us say that the above is the chosen polygon. We have decided that point 1 is the top left, point 3 is bottom right. This means that
1 - 2   is the top of the texture
2 - 3   is the right of the texture
3 - 4   is the bottom of the texture
4 - 1   is the left of the texture
The same polygon, but rotated :
                    3
                  +
               /    \
            /         \
        2 +            +  4
            \        /
              \   /
                +
                1
Although the positions of the points are different, point 1 is still the top left of our texture. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ How to put it to screen Okay, so now you have four points and know which one of them is also the top left of our texture. What next? If you think back to our tutorial on polygons, you will remember we draw it scanline by scanline. We do texture mapping the same way. Lets look at that picture again :
                    1
                  +
             a /    \  b
            /         \
        4 +            +  2
            \        /
              \   /
                +
                3
We know that point 1 is at [0,0] in our texture. Point 2 is at [127,0], Point 3 is at [127,127], and Point 4 is at [0,127]. The clever bit, and the entire key to texture mapping, is making the logical leap that precisely half way between Point 1 and Point 2 (b), we are at [64,0] in our texture. (a) is in the same manner at [0,64]. That's it. All we need to know per y scanline is : The starting position on the x axis of the polgon line The position on the x in the texture map referenced by that point The position on the y in the texture map referenced by that point The ending position on the x axis of the polgon line The position on the x in the texture map referenced by that point The position on the y in the texture map referenced by that point Let me give you an example. Let's sat that (a) and (b) from the above picture are on the same y scanline. We know that the x of that scanline is (say) 100 pixels at the start and 200 pixels at the end, making it's width 100 pixels. We know that on the left hand side, the texture is at [0,64], and at the right hand side, the texture is at [64,0]. In 100 pixels we have to traverse our texture from [0,64] to [64,0]. Assume at the start we have figured out the starting and ending points in the texture
textureX = 0;
textureY = 64;
textureEndX = 64;
textureEndY = 0;
dx := (TextureEndX-TextureX)/(maxx-minx);
dy := (TextureEndY-TextureY)/(maxx-minx);
for loop1 := minx to maxx do BEGIN
  PutPixel (loop1, ypos, texture [textureX, textureY], VGA);
  textureX = textureX + dx;
  textureY = textureY + dy;
END;
Do the above for all the scanlines, and you have a texture mapped polygon! It's that simple. We find our beginning and ending positions in the usual fasion. We know that Point 1 is [0,0]. We know that Point 2 is [127,0]. We know the number of scanlines on the y axis between Point 1 and Point 2.
textureDX = 127/abs (point2.y - point1.y)
We run though all the y scanlines, starting from [0,0] and adding the above formula to the X every time. When we hit the last scanline, we will be at point [127,0] in the texure. Repeat for all four sides, and you have the six needed variables per scanline. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= þ In closing As you can see, texture mapping (this type at least) is quite easy, and produces quite a good result. You will however notice a bit of distortion if you bring the polygon too close. This can be fixed by a) Subdividing the polygon, so the one is made up of four or more smaller polygons. Much bigger, but works; b) Using more accurate fixed point; or c) Figuring out perspective correct texture mapping, mapping along constant-z lines etc. When people write me, they often refer to my "tutes". This stems back to Mark Feldman calling them such in the PCGPE. I always though a "tute" was something you did with your car to gain someones attention. I dunno, maybe its an Australian thing ;-) I have been coding almost exclusively in C/C++ for the past year or so. Sorry guys, thats all they will pay me for ;) Anyway, the trainers will continue to be in Pascal for ease of understanding by beginners, but if someone (*ahem* Snowman) doesn't start converting them to C soon, I will do it myself. He also corrected any mistakes I made while he was converting, so I'd prefer he did it (sort of a proofreader after release…) Send me presents! It's my birthday! Byeeeee…..
  1. Denthor
16-04-96
/data/webs/external/dokuwiki/data/pages/archive/programming/astrainer.txt · Last modified: 2007/05/16 00:14 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki