Spellcaster presents:


TTTTTTTTTT HH      HH EEEEEEEEEE    MM      MM    AAAA     GGGGGGGGG
    TT     HH      HH EE            MMM    MMM   AA  AA   GG
    TT     HH      HH EE            MM M  M MM  AA    AA  GG  
    TT     HHHHHHHHHH EEEEEE        MM  MM  MM  AAAAAAAA  GG   
    TT     HH      HH EE            MM      MM  AA    AA  GG    GGGG
    TT     HH      HH EE            MM      MM  AA    AA  GG      GG
    TT     HH      HH EEEEEEEEEE    MM      MM  AA    AA   GGGGGGGG

                                                        Issue 7
                                                        6-4-96


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-


  Index:

        1. Introduction
          1.1. About the magazine
          1.2. About the author
          1.3. Distribution
          1.4. Contribuitions
          1.5. Hellos and greets
        2. Mail Room
        3. 'Unit Gfx, Please Respond' - A true story
          3.1. What the hell is a Unit ?????
          3.2. Defining a Unit
              3.2.1. Interface
              3.2.2. Implementation
              3.2.3. Startup-Code
              3.2.4. The final Unit
              3.2.5. Valid and invalid instruction
          3.3. Other Unit-related stuff
          3.4. The CRT Unit
        4. Boolean Algebra - Another look at conditions
          4.1. NOT
          4.2. AND
          4.3. OR
          4.4. XOR
          4.5. Rules of Boolean Algebra
          4.6. Using Boolean algebra
        5. Our friend, the pointer - Part II
        6. The Lens Effect
          6.1. Transformations
          6.2. How to make the lens transformation
        7. Graphics Part VI - Scrolling Part I
          7.1. What is scrolling ?
          7.2. Wipe Scrolls
          7.3. Other Scrolls
        8. Hints and tips
        9. Points of view
       10. The adventures of Spellcaster, part 7


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-


  1. Introduction

    1.1. About the magazine

    Welcome to number 7 of 'The Mag', brought to you, as usual, by Spellcaster,
  alias Diogo de Andrade. This issue is quite large (for me, of course, that
  have to write it...).
    I know I told you last issue that I could put in this issue the first of
  the Spellcaster Utilities... Well, I didn't had time to code it, with other
  projects and stuff, so I think I'll postpone the utilities for the Easter
  vacation... If you have any suggestions for them, write to me...
    Also, a little add... I'm trying to change the logo on top, the one that
  says 'THE MAG', but my ANSI art sucks !! In fact, all my art sucks !!! I was
  born to code... :) So, if anyone out there wants to do a better logo for me,
  go ahead !!! NOTE- No strange codes, just plain ASCII chars... Not even
  ASCII-E characters, because I use (and sometimes write) this in a UNIX
  machine, and I don't know how to configure the simbols on the screen... :(

    This magazine is dedicated to all the programmers and would-be programmers
  out there, especially to those that can't access the Net easily to get
  valuable information, to those who wish to learn how to program anything,
  from demos to games, passing through utilities and all sort of thing your
  mind can think of, and to those that can't find the right information.

    When you read this magazine, I'll assume some things. First, I assume you
  have Borland's Turbo Pascal, version 6 and upwards (and TASM for the assembly
  tutorials). I'll also think you have a 80386 (or 386 for short; a 486 would
  be even better), a load of patience and a sense of humor. This last is almost
  essencial, because I don't receive any money for doing this, so I must have
  fun doing it. I will also take for certain you have the 9th grade (or
  equivelent). Finally, I will assume that you have the last issues of
  'The Mag', and that you have grasped the concepts I tried to transmit. If
  you don't have the issues, you can get them by mail, writing to one of the
  adresses shown below (Snail mail and Email).

    As I stated above, this magazine will be made especially for those who don't
  know where to get information, or want it all in the same place, and to those
  who want to learn how to program, so I'll try to build knowledge, building up
  your skills issue by issue. If you sometimes fail to grasp some concept, don't
  despair; try to work it out.
    That's what I did... Almost everything I know was learnt from painfull
  experience. If you re-re-re-read the article, and still can't understand it,
  just drop a line, by mail, or just plain forget it. Most of the things I 
  try to teach here aren't linked to each other (unless I say so), so if you
  don't understand something, skip it and go back to it some weeks later. It
  should be clearer for you then. Likewise, if you see any terms or words you 
  don't understand, follow the same measures as before.

    Ok, as I'm earing the Net gurus and other god-like creatures talking
  already, I'm just going to explain why I use Pascal.
  For starters, Pascal is a very good language, ideal for the beginner, like 
  BASIC (yech!), but it's powerfull enough to make top-notch programms.
  Also, I'll will be using assembly language in later issues, and Pascal makes
  it so EASY to use. 
  Finally, if you don't like my choice of language, you can stop whining. The
  teory behind each article is very simple, and common with any of the main
  languages (C, C++, Assembly - Yes, that's true... BASIC isn't a decent
  language).

    Just one last thing... The final part of the magazine is a little story
  made up by my distorted mind. It's just a little humor I like to write, and
  it hasn't got nothing to do with programming (well, it has a little), but, 
  as I said before, I just like to write it.

    1.2. About the author

    Ok, so I'm a little egocentric, but tell me... If you had the trouble of 
  writing hundreds of lines, wouldn't you like someone to know you, even by 
  name ?

    My name is Diogo de Andrade, alias Spellcaster, and I'm the creator, 
  editor and writer of this magazine. 
    I live in a small town called Setubal, just near Lisbon, the capital of
  Portugal... If you don't know where it is, get an encyclopedia, and look for
  Europe. Then, look for Spain. Next to it, there's Portugal, and Setubal is in
  the middle.

    I'm 18 years old, and I just made it in to the university (if you do want
  to know, I'm in the Technical Institute of Lisbon, Portugal), so I'm not 
  a God-Like creature, with dozens of years of practice (I only program by 
  eight years now, and I started in a Spectrum, progressing later to an Amiga.
  I only program in the PC for a year or so), with a mega-computer (I own a 
  386SX, 16 Mhz), that wear glasses with lens that look like the bottom of a 
  bottle (I use glasses, but only sometimes), that has his head bigger than a 
  pumpkin (I have a normal sized head) and with an IQ of over 220 (mine is 
  actually something like 180-190). I can program in C, C++, Pascal, Assembly
  and even BASIC (yech!).

    So, if I am a normal person, why do I spend time writing this ?
  Well, because I have the insane urge to write thousands of words every now
  and then, and while I'm at it, I may do something productive, like teaching
  someone. I may be young, but I know a lot about computers (how humble I am;
  I know, modesty isn't one of my qualities).

    Just one more thing, if you ever program anything, please send to me... I
  would love to see some work you got, maybe I could learn something with it.
  Also, give me a greet in your program/game/demo... I love seeing my name.

    1.3. Distribution

    I don't really know when can I do another issue, so, there isn't a fixed
  space of time between two issues. General rule, I will try to do one every two
  weeks, maybe more, probably less (Eheheheh). This is getting to an issue
  every month, so, I'll think I'll change the above text... :)
    'The Mag' is available by the following means:

    - Snail Mail : My address is below, in the Contributions seccion... Just
                   send me a disk and tell me what issues you want, and I
                   will send you them...

    - E-Mail : If you E-mail me and ask me for some issues, I will Email you
               back with the relevant issues attached.

    - BBS's : I don't know for sure what BBS's have or will have my magazine,
              but I will try to post it in the Skyship BBS.
              If you have a BBS and you want to receive 'The Mag', contact me.

                 Skyship BBS numbers: (351)+01-3158088
                                      (351)+01-3151435

    - Internet : You can access the Spellcaster page and take the issues out
                 of there in:

                 http://alfa.ist.utl.pt/~l42686

    1.4. Contributions

    I as I stated before, I'm not a God... I do make mistakes, and I don't 
  have (always) the best way of doing things. So, if you think you've spotted
  an error, or you have thought of a better way of doing things, let me know.
  I'll be happy to receive anything, even if it is just mail saying 'Keep it 
  up'. As all human beings, I need incentive.

    Also, if you do like to write, please do... Send in articles, they will be
  welcome, and you will have the chance to see your names up in lights.
    They can be about anything, for a review of a book or program that can
  help a programmer, to a point of view or a moan. I'm specially interested in
  articles explaining XMS, EMS, DMA and Soundblaster/GUS.

    If anyone out there has a question or wants to see an article about 
  something in particular, feel free to write... All letters will be answered,
  provided you give me your address.

    I'm also trying to start a new demo/game/utility group, and I need all sort 
  of people, from coders (sometimes, one isn't enough), musicians (I can 
  compose, but I'm a bit limited), graphics artists (I can't draw nothing) and
  spreaders... I mean, by a spreader, someone who spreads things, like this mag.
  If you have a BBS and you want it to include this magazine, feel free to
  write me... I don't have a modem, so I can only send you 'The Mag' by Email.

    You can also contact me personally, if you study on the IST (if you don't
  know what the IST is, you don't study there). I'm the freshman with the
  black hair and dark-brown eyes... Yes, the very_beutifull_but_not_so_tall_guy
  who spends ALL his time on campus...

    My adress is:
                 Praceta Carlos Manito Torres, n§4/6§C
                 2900 Set£bal
                 Portugal

    Email: dgan@rnl.ist.utl
           l42686@alfa.ist.utl.pt

    And if you want to contact me on the lighter side, get into one of the
  following talkers... To do that telnet to:

          Lost Eden -> Alfa.Ist.Utl.Pt  : Port 1414

              Talho -> Ubistc.Ubi.Pt    : Port 7000

              CItal -> Zeus.Ci.Ua.Pt    : Port 6969

    I'm almost always there in the afternoon... As you may have guessed already,
  my handle is Spellcaster (I wonder why...)...

    1.5. Hellos and greets

    I'll say hellos and thanks to all my friend, especially for those who put 
  up with my constant whining.
    Special greets go to Denthor from Asphyxia (for the excelent VGA trainers),
  Draeden from VLA (for assembly tutorials), Joaquim Elder Guerreiro, alias
  Dr.Shadow (Delta Team is still up), Joao Neves for sugestions, testing and
  BBS services, and all the demo groups out there.
    I will also send greets to everybody that responded to my mag... Thank
  you very much !
    Special hails go to: Ricardo 'Scorpio' Oliveira... Check out his page,
  it's great !! :)


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-


  2. Mail Room

    I've received a mail from a person that shall remain nameless (right,
  Greg ? :) ), asking were can we get information about coding on the Net.
  I'm no expert on InterNet, but I know a couple of sites were you can get
  stuff:

        - The Hornet Demo Archive: ftp.cdrom.com
            This site has _LOTS_ of stuff, including complete source code
            of some demos, and tutorials made by several demopeople.
            Besides source code and tutorials, you can get there all
            demos made by man... Well, almost all... :)

        - The Asphyxia Page: (don't remember the URL)
            This is the home site of the Asphyxia VGA Tutorials, made by
            Denthor... These are very recomendable tutorials, the best there
            are !! I love them, and it was they who got me into demo/game
            coding... They are similar to my Graphics tutorials, only better
            done... :)

        - Scorpio's Homepage: (I also don't remember this URL)
            This is the homepage of a friend of mine here in Portugal... He's
            a lot into DemoCoding, so he has LOTS and I mean LOTS of links to
            code related pages... Go get them !!

        - My home page: http://alfa.ist.utl.pt/~l42686
            My home page doesn't really have much about coding, except for
            'The Mag'... But you have there more links to other pages full of
            coding info... You can find the URL of the Asphyxia Page and of the
            Scorpio HomePage there...

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

    Because of various letters, I'm posting here an errata to 'The Mag'... It
  seems that, when I gave the SetColor procedure (back in issue 3) I made I
  mistake when writing it... The header of that procedure is like this:

               Procedure SetColor(Col,R,B,G:Byte);

    and it should be like this:

               Procedure SetColor(Col,R,G,B:Byte);

    You must swap the B and G variables... If you do this, the procedure should
  work fine... Thanks to the people that spotted this error...


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-

  3. 'Unit GFX, Please Respond' - A true story

    For starters, let me just say that the title of the article has got
  nothing to do with the article itself... It's just one of those titles I
  _HAD_ to put... Don't ask me why... :)

    This article is about Pascal Units...

    3.1. What the hell is a Unit ?????

    To put this simply, a unit is a bunch of routines and other stuff strung
  up together to be used by multiple programms... For example, imagine you
  made a procedure like this:

       Procedure StupidThing(A,B:Integer);
       Begin
            Writeln(A*B+B+A-B*B);  { This is just a stupid calculus }
       End;

    And you use it in lots of programs you make... Well, so you would have to
  Copy/Paste it a lot, or perhaps re-write it... That would SUCK !!! So, the
  nice guys at Borland joined up, took some elements of another programming
  language (invented by the same guy that invented Pascal, N.Wirth) called
  Modula-2 and created UNITS !
    How do you use a unit ?
    Well, you make one of the first lines of your program like this:

          Uses MyStUnit;

    And then, when you need procedure StupidThing, you don't have to write
  all the procedure in the procedure declaration area of your program... By
  using units, you make your program more organized, as you save precious time
  and fingertips... By using units, the following program would run:

      Program TestUnit;

      Uses MyStUnit;

      Begin
           StupidThing(1,2);
           StupidThing(3,4);
           StupidThing(5,6);
      End.

    Well, if you run out for the keyboard and wrote that program, and then you
  run it, you will get a 'File Not Found' error... :(
    That's because you haven't defined the unit !!!

    3.2. Defining a Unit

    To define a Unit, you just make this:

    - The first line of code in a unit must be

                        Unit <name>;

    - Then, the unit will be splited in three parts... The interface part,
      the implementation part and the startup-code part

      3.2.1. Interface

      This is were you define what can be acessed by a program... You will tell
    what procedures, functions, variables and other stuff can be called from
    your program... This section starts with the word 'Interface'. So the next
    piece of code is a valid Interface section:

             Interface

             Const SpellConst=1000;

             Type SpellRec=Record
                                 Alfa:Word;
                                 Beta:Byte;
                           End;

             Var SpellVar1:Integer;
                 SpellVar2:SpellRec;

             Procedure StupidThing(A,B:Integer);
             Function SpellFunc(A:Integer):Word;

      Note that you don't include the code of the procedure MyStupidThing in
    the interface section... That goes in the implementation seccion.

      3.2.2. Implementation

      This is were the code of the functions and procedures defined in the
    interface section, alongside with other variables, constants and types
    that are to be internally used by the procedures and functions, and that
    are not acessible by the main program. This section starts with the word
    'Implementation'. This is a valid counterpart of the above Interface
    section:

             Implementation

             Const HiddenConst=255;

             Procedure IntProc; { This is an internal procedure }
             Begin
                  Writeln('Hidden Constant=',HiddenConst);
             End;

             Procedure StupidThing(A,B:Integer);
             Begin
                  Writeln(A*B+B+A-B*B);
             End;

             Function SpellFunc(A:Integer):Word;
             Begin
                  SpellFunc:=Abs(A)*2;
                  IntProc;
             End;

      3.2.3. Startup-Code

      This is a small part of the unit, that is only usefull sometimes... It
    is a part of a program (like standart Pascal program), but it is only
    executed once, when the unit is linked (see the meaning of this down).
      This is a valid Startup-Code section, for the above examples:

             Begin
                  StupidThing(10,20);
             End.

      3.2.4. The final Unit

      The Unit I built in the example would become something like this:

             Unit MyStUnit;

             Interface

             Const SpellConst=1000;

             Type SpellRec=Record
                                 Alpha:Word;
                                 Beta:Byte;
                           End;

             Var SpellVar1:Integer;
                 SpellVar2:SpellRec;

             Procedure StupidThing(A,B:Integer);
             Function SpellFunc(A:Integer):Word;

             Implementation

             Const HiddenConst=255;

             Procedure IntProc; { This is an internal procedure }
             Begin
                  Writeln('Hidden Constant=',HiddenConst);
             End;

             Procedure StupidThing(A,B:Integer);
             Begin
                  Writeln(A*B+B+A-B*B);
             End;

             Function SpellFunc(A:Integer):Word;
             Begin
                  SpellFunc:=Abs(A)*2;
                  IntProc;
             End;

             Begin
                  StupidThing(10,20);
             End.

      When you have the whole unit code, you save it to disk ( NOTE: You must
    use the same name for the Unit and for the file you store the unit).
      Now, you can run the first program I gave you in this article...

      3.2.5. Valid and invalid instruction

      The folowing instructions are valid, using the above unit:

             - WriteLn(SpellConst);

             - Var A:SpellRec;

             - SpellVar1:=100;

             - SpellVar2.Alpha:=4362;

             - StupidThing(A,10);

             - A:=SpellFunc(-1002);

      And the following intructions are _NOT_VALID_ :

             - Writeln(HiddenConst);

             - IntPro;

    3.3. Other Unit-related stuff

      Number One: YOU CAN'T RUN A UNIT !!! :) Units are to be integrated in
                  a program (called the main program), and are of no use by
                  themselves...

      Number Two: The header of a procedure/function must be the same in the
                  interface and implementation sections.

      Number Three: When in the main program you call a Unit, that unit is
                    compiled and integrated in the main program... This is
                    called the linkage stage of compilation... Linking is
                    getting the units and the program together.

      Number Four: When you compile a Unit, a file is generated in disk. That
                   file has a TPU extension and the same name as the file of
                   the unit. So, if you compile 'MyStUnit.PAS', you will get
                   the file 'MyStUnit.TPU'. That file is in machine-code, and
                   you shouldn't erase it, because it makes subsequent
                   compilations faster. Don't worry, that Pascal is smart enough
                   to change the TPU file when you alter the PAS file (as long
                   as you compile it).

      Number Five: A Unit can call another Unit... Just add the Uses clause and
                   you can use the procedures and other stuff of another unit.
                   I generally place the Uses clause in the interface section,
                   altough you can put it in the implementation section, as long
                   as you don't use (for example) the records defined in the
                   child-unit in the interface section...

    3.4. The CRT Unit

    Just to end this article, I'll tell you about a GREAT GREAT GREAT Unit
  Pascal haves...  It is called the CRT units... It is in the Unit directory
  of your copy of Turbo Pascal 6, and it has lots of routines to work with
  text mode. I'll just tell you of some, so that you can have some fun with
  them:

       - GotoXY(X,Y) -> This procedure get's the cursor at the position (X,Y).
                        So, if you do:

                            GotoXY(10,10);
                            Write('ABC');

                        it will appear on the screen's position (10,10) the
                        word 'ABC'... The upper left corner of the screen is
                        (1,1).

       - TextColor(C) -> This changes the color of the text you write to color
                         C... You can use constants that are defined in unit
                         CRT, so you can write:

                            TextColor(Yellow);

                         The other colors available are:

                             Black, Blue, Green, Cyan, Red, Magenta,
                             Brown, LightGray, DarkGray, LightBlue,
                             LightGreen, LightCyan, LightRed,
                             LightMagenta and White.

                         If you want the text to blink, add 128 to the number
                         of the color... So, if you want text blinking in
                         yellow, do:

                            TextColor(Yellow+128);

       - TextBackground(C) -> This changes the background color of the text.
                              It is similar to TextColor, and you can use the
                              same constants and all, with the exception of
                              the lighter colors, that can't be used for
                              background (don't ask me why !!)...

       - Sound(Freq) -> Does a sound with a frequency of Freq.

       - NoSound -> Stops the sound played by the Sound Procedure (it is SOOOO
                    valuable for my ears !!)

       - ReadKey -> Waits for a key to be pressed and returns the character
                    corresponding to the key... So, if you do:

                            C:=ReadKey;

                    and you press the key A, variable C would hold the value
                    'A'...

       - KeyPressed -> Returns a boolean variable that states if a key as been
                       pressed or not.

    These are the more important ones... To wrap this article, I'll just say
  that you should master the basics of Units, because they are one of the
  more important things in Pascal... I use them _ALWAYS_ !!!!


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-


  4. Boolean Algebra - Another look at conditions

    I've talked about conditions in issue two, in a basic manner... In this
  issue we'll expand the knowledge built in that issue.

    I've said in that issue that boolean algebra is an algebra that gives
  only TRUE or FALSE as results... But what I didn't said back then is that
  you have lots of operations that give boolean results. I talked about
  operation with two operators (binary operations). They were operations that
  compared two operands of the same type (were they characteres or numbers).
  Now, I will show the use of boolean operations, that is, operation in which
  the operands are of type boolean. There is one unary operation (operation
  that only uses one operand), and several binary operations...

    4.1. NOT

    The NOT operation is fairly simple... Imagining you have a boolean
  variable or expression, if you NOTed it, it would inverse... Imagine this:

                 A:=10;
                 B:=5;
                 C:=A<B;
                 D:=NOT(C);

    Varibale C would have the value FALSE, but D would have the value TRUE...
  NOT inverts the operand... The truth table of this operation is the
  following:
                        _________________
                        |   A   | NOT A |
                        |---------------|
                        | TRUE  | FALSE |
                        | FALSE | TRUE  |
                        -----------------

    NOTE: The NOT operation is also know as negation, complement or first
  complement.

    4.2. AND

    The AND operation is a binary operation... It's simple to think of what is
  it's function... It combines two operands, and if the both operands are TRUE,
  it returns the value TRUE, otherwise it returns FALSE. Example:

                 A:=10;
                 B:=5;
                 C:=1;
                 D:=A>B;      -> This is TRUE
                 E:=A<B;      -> This is FALSE
                 F:=C<A;      -> This is TRUE
                 G:=D AND E   -> This is FALSE
                 H:=D AND F   -> This is TRUE

    Don't forget that:

                 D:=A>B;
                 E:=A<B;
                 G:=D AND E;

    is equal to:

                G:=(A>B) AND (A<B);

    Don't forget the parentesis, or you will get an error message (try to
  figure out why... :) ).
    The truth table is this:
                        ___________________________
                        |   A   |   B   | A AND B |
                        |---------------|---------|
                        | TRUE  | TRUE  |  TRUE   |
                        | TRUE  | FALSE |  FALSE  |
                        | FALSE | TRUE  |  FALSE  |
                        | FALSE | FALSE |  FALSE  |
                        ---------------------------

    4.3. OR

    The OR operation is a binary operation... Like in AND, it's name is self-
  -expainatory. It's simple to think of what is it's function... It combines
  two operands, and if any one of the operands are TRUE, it returns the value
  TRUE, otherwise it returns FALSE. Example:

                 A:=10;
                 B:=5;
                 C:=1;
                 D:=A>B;      -> This is TRUE
                 E:=A<B;      -> This is FALSE
                 F:=C>A;      -> This is FALSE
                 G:=D OR E    -> This is TRUE
                 H:=E OR F    -> This is FALSE

    The truth table is like this:
                        ___________________________
                        |   A   |   B   | A OR  B |
                        |---------------|---------|
                        | TRUE  | TRUE  |  TRUE   |
                        | TRUE  | FALSE |  TRUE   |
                        | FALSE | TRUE  |  TRUE   |
                        | FALSE | FALSE |  FALSE  |
                        ---------------------------

    4.4. XOR (eXclusive OR)

    The XOR operation is almost equal to the OR operation, except in the case
  in which A and B are both TRUE... In that case, A XOR B is equal to FALSE.

    The truth table is like this:
                        ___________________________
                        |   A   |   B   | A XOR B |
                        |---------------|---------|
                        | TRUE  | TRUE  |  FALSE  |
                        | TRUE  | FALSE |  TRUE   |
                        | FALSE | TRUE  |  TRUE   |
                        | FALSE | FALSE |  FALSE  |
                        ---------------------------

    4.5. Rules of Boolean Algebra

    There are some rules that can help simplify some complex boolean
  expressions. They are fairly intuitive and easy to demonstrate...
  They are the following:

      - X OR FALSE     = X
      - X OR TRUE      = TRUE
      - X OR X         = X
      - X OR NOT(X)    = TRUE

      - X AND TRUE     = X
      - X AND FALSE    = FALSE
      - X AND X        = X
      - X AND NOT(X)   = FALSE

      - NOT ( NOT(X))  = X

      (Commutative)
      - X OR Y         = Y OR X
      - X AND Y        = Y AND X

      (Associative)
      - X OR (Y OR Z)  = (X OR Y) OR Z
      - X AND (Y AND Z)= (X AND Y) AND Z

      (Distributive)
      - X AND (Y OR Z) = (X AND Y) OR (X AND Z)
      - X OR (Y AND Z) = (X OR Y) AND (X OR Z)

      (De Morgan)
      - NOT (X OR Y)   = NOT(X) AND NOT(Y)
      - NOT (X AND Y)  = NOT(X) OR NOT(Y)

    4.6. Using Boolean algebra

      You can use boolean algebra in expressions in your If, While and
    Repeat..Until sentences. Just use the rules suplied and it is easy.
    Examples:

             If (A>B) AND (B<C) Then ......

             If (A=B) OR (A>C) Then .......

             If Not(A=B) Then .............

             While Not(A<B) Do ............

             Repeat
             ..............................
             Until (A=B) AND (D=E);

    Hope this article was good and usefull... As always, I recommend you
  to experiment, in order to get higher learning... Remember, only the wise
  and the fools don't experiment, thus, they don't change... :)


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-


  5. Our friend, the pointer - Part II

    This article, as you may already guessed, is the follow-up to an article
  I made on issue one. If you don't recall, or if you didn't read it, get issue
  one and read it...

    The problem with the pointer structure of Part I of this article is that
  the size of the structure was rigid... It did had to be already defined.
  This is good for lookup tables, but it is no good for other uses...
  Check out this example:

    Lets imagine you wanted to make an image handling library, that could read
  images of various sizes and move them on the screen.
    You know that we should use pointers to store the images (because you can
  have the possibity that the combined sizes of the images is bigger than
  64 Kb). But, using the method taught in Part I, all the images should have
  the same size... But we want to have images of several sizes, so the size
  of a pointer must be determined at run-time, rather than in compile-time.
  If you are adventerous, you already have investigated further the GetMem and
  FreeMem procedures, and you already know how to do this. I will explain for
  the rest of you out there. This is an (incomplete) example:

           Type Image=Record
                            Xsize,Ysize:Word;
                            Data:Pointer;
                      End;
                      ..............
                      ..............
                      ..............
           Procedure LoadImage(Filename:String;Var Pic:Image);
           Var F:File;
           Begin
                Assign(F,Filename);
                Reset(F,1);
                BlockRead(F,Pic.Xsize,2); { Read the X size of the image);
                BlockRead(F,Pic.Ysize,2); { Read the Y size of the image);
                GetMem(Pic.Data,Xsize*Ysize);
                BlockRead(F,Pic.Data^,Xsize*Ysize);
                Close(F);
           End;
                     ...............
                     ...............
           Procedure KillImage(Var Pic:Image);
           Begin
                Freemem(Pic.Data,Pic.Xsize*Pic.Ysize);
           End;

    In the theory side, just think about this. You read first the horizontal
  and vertical sizes and store them in variables. Then, you know you need
  (Xsize*Ysize) bytes to store an image of that size, so you allocate them
  with GetMem. In the end, when the image is no longer needed, you deallocate
  the space of the pointer with Freemem... Did you understand ?
    You can dinamically allocate space, using GetMem and FreeMem...
    I think this is fairly simple to grasp concepts, that with practice become
  part of your nature...
    To end this article, I will leave with this problem... Imagine you needed
  a enlarging procedure, that given an image, it would expand the image to
  double it's size... You can't change the size of a pointer without first
  destroying the contents... There are ways to get around this... One of them
  is not suited for this example, but it will be the one that I will teach in
  the Part III of this series of articles. The other way, that can really be
  used in this example is to use another pointer, that stores the enlarged
  image...


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-


  6. The Lens Effect

    To explain the lens effect, I must first define how to do a
  transformation of any kind... Then, I'll explain how to do the maths for
  a lens... Reading just the first part, you get a nice idea on how to do
  mirroring, and other effects like that...

    6.1. Transformations

    Lets think of a transformation like this: you have a section of the
  screen on which you want to do a transformation.
    Consider the smallest rectangule that encompasses all the transformation.
    To increase speed, let's assume that the transformation is precalculated
  (this is different of an animation !). As the transformation is
  precalculated, you know the size of the blue rectangle. Let's call that
  size SIP (Size In Pixels).
  So, I need three arrays: ORIGIN[SIP], TRANS[SIP] and DEST[SIP].

  Note: I will build up an example of real code in Pascal, during the
        explanation... It will be in between {}.

         Assuming the size is 30x30
         const xsize=30;
               ysize=30;
         var ORIGIN, TRANS, DEST:array[1..xsize*ysize] of byte;

  Another note: When I talk about image, I'm talking about the part of the
                screen you want to process.

    ORIGIN stores the original image. You must update this array, everytime
  you change the image...

         Procedure UpdateOrigin(x,y:word);
         var a,b:integer;
         begin
              for a:=0 to xsize-1 do for b:=0 to ysize-1 do
                  ORIGIN[b*xsize+1]:=getpixel(a+x,b+y);
         end;

    The parameters on this procedure are the x and y coordinates of the
  upper left corner of the image.
    Getpixel is a routine that returns the color of the point at the given
  coordinates. This obviously depends on the resolution.

    Now, we must operate the transformation... We want to convert the array
  ORIGIN in the array DEST, with the effect... So, DEST is ORIGIN transformed...
    So, you must calculate each of the pixels of DEST with base on ORIGIN.
    You must determine the new value for each pixel of ORIGIN and store it in
  DEST... To know what is the new value, we use the array TRANS, that is a
  constant, and therefore can be calculated in advance. For each effect,
  this array is different, so you can use the same basic routines for lots
  of effects, just changing the calculation of TRANS.

    This array says for each pixel: the pixel at position A in DEST, should
  be the same as the pixel at position TRANS[A] in ORIGIN.
  So the formula is DEST[A] = ORIGIN[TRANS[A]] for all elements.
  The transformation is fast, and does not depend on the resolution/video-mode.

    We now copy the array DEST to the screen, and the transformation is
  complete.

    If you want the transformation to move (i.e. the lens move), you must
  update ORIGIN for every change in position. Note: Don't forget to replace
  the transformed image with the original image before you move...

    Just as an example of transfomation, here it is the calculation of a
  transformation array that magnifies the upper left corner by a factor
  of MAG (MAG is a variable of type byte).

              Procedure CalcMatrix;
              Begin
              For A:=0 To ysize-1 do
                  For B:=0 To dX-1 do
                  TRANS[A*xsize+B]:=(A div MAG)*Xsize+(B div MAG);
              End;

    Note: You should use a virtual screen if you don't want your screeen to
          flicker like mad !

    6.2. How to make the lens transformation

    Calculating the transformation matrix for the lens, here is were the
  trouble begins... This envolves lots of maths and a bit of thinking...

    Consider a sphere S, intersecting with a plane A. This defines a circle C in
  the plane. Define Rc as the ray of the circle C, Rs as the ray of the
  sphere S, and d as the distance from the centre of the sphere to the plane A.
    We know then that:
                             Rc^2 + d^2 = Rs^2           (1)

    If you want several lenses with the same radius, but different
  lens-strength, then you must preserve the same value for Rc. If the size
  of the transformed area is L by L pixels (the lens is circular, so the
  involved area is a square) then Rc should be L/2. The distance d determines
  the strength of the lens. So, knowing Rc and d, we can determine Rs.

    Suppose we're given L (so Rc = L/2), we made a choice for d, and we
  calculated the value of Rs. We now want to transform each pixel in the
  square (LxL).
    We simply check all pixels (2 loops: one for the X-axis and one for the
  Y-axis).
    We call the point we're transforming P. If P lies outside or on C, then the
  point isn't transformed. That is: TRANS(P)=P; if (x,y) are the coordinates of
  P than TRANS[x+y*L] := x+y*L.

    If P lies within the C, then the point will be transformed:
  the idea behind the effect is to project the points as if they are
  magnified, that is, the points within the circle must be projected from
  the center of the sphere to the sphere...

                                EYE
                                 |
                                \|/






                              _______
                            _-       -q      
                           /         /|\
                          /         / | \                 A
            -------------|---------i--p--|-----------------
                         | d      /      |
                         | ------O       |       <-- This is supposed to 
                                                     be circle... Don't 
                                                     blame me if my 
                                                     ASCII art sucks !! 
                                                     Ask me for a GIF if you 
                                                     want a clear picture..

    Hence, for a given point p, we determine the point q (see picture). That
  point q is the projection of some point i within the circle C, so from
  the point q, we draw a line to the centre of the sphere, thus defining
  the point i, which is the intersection of that line whith the plane. That
  is the transformation of the point p: TRANS(p)=i, because: if the point i
  was to be projected on the sphere, it would end up at the point q. Since
  we're looking straight onto the plane, the points q and p are the same
  (that is: they end up at the same point on your screen).

    When implementing, you can use some shortcuts:
  Lets say L and d are given. Then Rc=L/2;
  Consider the origin of a rectangular system in the centre of the circle C.
  The X-axis and the Y-axis are parallel to the plane A, in such a way that
  the square that is to be transformed, is defined as:

                   [-Rc,Rc] x [-Rc,Rc]

    The orientation of the Z-axis is such that the coordinates of the centre of the
  sphere are (0,0,-d). The sphere is given by:

                 x^2 + y^2 + (z+d)^2 = Rs^2                   (2)

    hence:  [ (1) ]

                 x^2 + y^2 + (z+d)^2 = Rc^2 + d^2              (3)

    Consider the point P within the circle C. Thus, its coordinates are:

           (Px,Py,0)     and       Px^2 + Py^2 < Rc^2        (4)


    The coordinates of the point Q can be found through this system:

        |   x = Px            A - defines the line, parrallel to the Z-axis
        |   y = Py                through the point P.
        |   x^2 + y^2 + (z+d)^2 = Rc^2 + d^2

    We immediatly find Qx and Qy (Qx=Px; Qy=Py), and for Qz we find:

        Px^2 + Py^2 + Qz^2 + 2*d*Qz + d^2 = Rc^2 + d^2

        Qz^2 + 2*d*Qz - Rc^2 + Px^2 + Py^2 = 0

        D = d^2 -  (Px^2 + Py^2 - Rc^2)                       (5)

        since  Rc^2 > Px^2 + Py^2    [ (4) ],  we find D>0, and

        Qz = 1+-sqrt(D).

    We find 2 solutions (the line intersects the sphere twice !), but consider
  only the one with Qz>0. We find coordinates for Q:

        (Qx,Qy,Qz) == (Px,Py,1+sqrt(D))    <see (5) for D>      (6)

    Finally, we find the coordinates of the point I through :

      (Sx,Sy,Sz) are the coordinates of the centre of the sphere
      (Sx,Sy,Sz) == (0,0,-d)

         |      ( z - Sz)  
         |  x = --------- * (Qx-Sx) + Sx        
         |      (Qz - Sz)                       < defines the line through
         |                                      < the centre of the sphere
         |      ( z - Sz)                       < and the point Q
         |  y = --------- * (Qy-Sy) + Sy        
         |      (Qz - Sz)
         |
         |  z = 0                               <- defines the plane A

         We find:

                  ( 0 - (-d) )
           Ix  =  ------------ * (Qx-0) + 0
                  ( Qz - (-d))

                  ( 0 - (-d) )
           Iy  =  ------------ * (Qy-0) + 0
                  ( Qz - (-d))

           Iz  =  0


         hence:
                      d
           Ix  =  --------- Qx
                   Qz + d

                      d
           Iy  =  --------- Qy
                   Qz + d

           Iz  =  0


    We know the coordinates of Q (they can be fully determined if the
  coordinates of P are known), and we know d, so I can be calculated.
    We could than say:

    TRANS[ (L/2+Px) + (L/2+Py) * L ] := (L/2+Ix) + (L/2+Iy) * L;

    Now, you can see (by just observing the drawing, or by checking the
  formulas) that if we find

     TRANS[p(Px,Py)]=i(Ix,Iy)

    then also

     TRANS[p( Px,-Py)]=i( Ix,-Iy)
     TRANS[p(-Px, Py)]=i(-Ix, Iy)
     TRANS[p(-Px,-Py)]=i(-Ix,-Iy)

    so that the entire transformation can be defined be calculating a
  quarter of the transformed area.

    So, get yourself coding... I don't have any working examples, and I
  didn't had time/pacience to code one, so try yourself... After the
  formulas, it should be fairly easy...

    This article is slightly different because I did it for a newsgroup, not
  for 'The Mag'... I apologize if you don't like it very much...


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-


  7. Graphics Part VI - Scrolling Part I

    This is the first of a two part article, dedicated to scrolling.

    There are so many ways to scroll, and so different concepts of scrolling
  that it is _VERY_ hard to write an article about it. But I'll do my best...

    NOTE: I have put _ALL_ the procedures given in previous numbers of 'The Mag'
          in a unit called MODE13h... This unit can be found with this issue of
          'The Mag'. This units is supposed to grow from issue to issue, so
          make sure you have it up to date...
          If you don't know what a unit is, refer to the first article of this
          issue...
          Also, with this issue, you'll get two PCX files, for the example
          programms. One of them ('SPELL.PCX') was drawn by me (I know, crappy
          egocentric picture), and the other ('LANDSCAP.PCX') was also 'drawn'
          by me in Vista Pro (I know it's hard to do a bad Vista picture).

    7.1. What is scrolling ?

    Scrolling is when you move the screen (or part of it) from one place to
  another... In other words, it is a translatation of the screen.
    Now, in computer terms, what's scrolling ?
    Scrolling is based on memory moves... You move the memory around in a way
  that it seems that the screen itself is moving... Confused already ? :)
    Tough this seams complicated, it is fairly easy... In the first part of
  this articles, I will explain you Wipe Scrolls, and other kinds of scrolls
  that I can't really define... I can't explain all about of scrolling, but
  I'll explain the concepts behind it, so if you think a little you can
  determine how to make the effect you require. Also, in this first part, I
  will only talk about full-screen scrolls... Partial scrolls will be discussed
  in part II of the Scrolling Saga !! :)

    7.2. Wipe Scrolls

    A wipe scroll is a type of scrolling that is used for cleaning the screen.
  For example, let's imagine you have a very nice PCX image displayed on your
  screen, and you want it to scroll up, until it disappears. This is fairly
  easy to do... You simply copy all lines on the screen to the line above that
  one. You do it like this:

       Program Scroll_Up;

       Uses Mode13h;            { This uses the Mode13h unit }

       Var A:Integer;

       Procedure ScrollUp;
       Begin
            WaitVbl;
            Move(Mem[VGA:320],Mem[VGA:0],63680);
       End;

       Begin
            Initgraph;
            LoadPCX('Spell.Pcx',VGA);
            For A:=0 To 200 Do ScrollUp;
            Readln;
            Closegraph;
       End.

    See the image going up until it disappears ?
    The Move instruction moves the second line to the first line, the third
  line to the second, and so forth, until the 200th line goes to the 199th
  line. The first line is discarted... If you still can't understand think
  about this: The address of the second line in mode 13h is A000:0320, and the
  address of the first line is A000:0000... So, to scroll up, you move the
  memory from A000:0320 to A000:0000... And, because you want scroll all lines
  from the second to the last, you move 64000-320 bytes, that is 63680 bytes.
    If you want to scroll down, you just move the memory from A000:0000 to
  A000:0320... Simple like this:

       Procedure ScrollDown;
       Begin
            WaitVbl;
            Move(Mem[VGA:0],Mem[VGA:320],63680);
       End;

    To scroll right or left isn't that easy. To scroll left, for example:

              A000:0001 moves to A000:0000
              A000:0321 moves to A000:0320
              And so forth...

    So, you can't move all the memory with just one command... To scroll
  left, you'll have to scroll each line individually... Like this:

       Procedure ScrollLeft;
       Var A:Byte;
       Begin
            WaitVbl;
            For A:=0 To 199 Do
            Move(Mem[VGA:(320*A+1)],Mem[VGA:(320*A)],319);
       End;

    And to scroll right:

       Procedure ScrollRight;
       Var A:Byte;
       Begin
            WaitVbl;
            For A:=0 To 199 Do
            Move(Mem[VGA:(320*A)],Mem[VGA:(320*A+1)],319);
       End;

    So far, so good, right ? WRONG !!! Try to scroll the other picture,
  LANDSCAP.PCX... Look at the trail it leaves behind. That's ugly, isn't it ?
    Well, why does it happen ?
    It happens because you don't change the first line (in the case of the
  ScrollDown), the last line (in the case of the ScrollUp), the first pixel
  of every line (in case of the ScrollRight) or the last pixel of every line
  (in case of the ScrollLeft). So, let's clear it to black... The new scroll
  procedures are like this:

       Procedure ScrollUp;
       Begin
            WaitVbl;
            Move(Mem[VGA:320],Mem[VGA:0],63680);
            Line(0,199,319,199,0,VGA);
       End;

       Procedure ScrollDown;
       Begin
            WaitVbl;
            Move(Mem[VGA:0],Mem[VGA:320],63680);
            Line(0,0,319,0,0,VGA);
       End;

       Procedure ScrollLeft;
       Var A:Byte;
       Begin
            WaitVbl;
            For A:=0 To 199 Do
               Move(Mem[VGA:(320*A+1)],Mem[VGA:(320*A)],319);
            Line(319,0,319,199,0,VGA);
       End;

       Procedure ScrollRight;
       Var A:Byte;
       Begin
            WaitVbl;
            For A:=0 To 199 Do
               Move(Mem[VGA:(320*A)],Mem[VGA:(320*A+1)],319);
            Line(0,0,0,199,0,VGA);
       End;

    The ideia is to put a black line in the certain place, so that it clears
  that part of the screen, so that the scroll won't leave a trail...

    7.3. Other Scrolls

    If you re-think the last concept, the one about clearing a part of the
  screen, you will be able to do a lot more effects... For instance, type
  the following code:

       Program Landscape;

       Uses Mode13h,Crt;

       Var Height:Integer;

       Procedure ScrollLeft;
       Var A:Byte;
       Begin
            WaitVbl;
            For A:=0 To 199 Do
               Move(Mem[VGA:(320*A+1)],Mem[VGA:(320*A)],319);
            Line(319,0,319,199,0,VGA);

            Height:=Height+Random(5)-2;
            If Height<2 Then Height:=2;
            Line(319,199-Height,319,199,1,VGA);

       End;

       Begin
            Randomize;
            Initgraph;
            SetColor(0,0,0,0);
            SetColor(1,0,63,0);
            Height:=50;
            Repeat
                  ScrollLeft;
            Until Keypressed;
            Closegraph;
       End.

    See the landscape (YECH!) scrolling right in the screen ? Ok, it isn't
  very nice, but it's just to show you something...
    Notice that in the ScrollLeft procedure we've added the following lines:

            Height:=Height+Random(5)-2;
            If Height<2 Then Height:=2;
            Line(319,199-Height,319,199,1,VGA);

    These are the lines that really draw the landscape... They insert a new
  column in the screen... Then, that column is scrolled with the rest of the
  picture. That gives the illusion of a landscape comming to sight. You can do
  this with all directions... Check out the Starfield program. The program
  will scroll a starfield 200 pixels in every direction, including diagonals...

       Program Starfield;

       Uses Mode13h,Crt;

       Var A:Byte;

       Procedure SetUpStarfield;
       Var A:Word;
       Begin
            { Set up colors... Grey scales }
            For A:=0 To 15 Do SetColor(A,A*4,A*4,A*4);
            { Put random starfield in screen }
            For A:=0 To 500 Do PutPixel(Random(320),Random(200),Random(16),VGA);
       End;

       Procedure ScrollUp;
       Begin
            WaitVbl;
            Move(Mem[VGA:320],Mem[VGA:0],63680);
            Line(0,199,319,199,0,VGA);
            PutPixel(Random(320),199,Random(16),VGA);
       End;

       Procedure ScrollDown;
       Begin
            WaitVbl;
            Move(Mem[VGA:0],Mem[VGA:320],63680);
            Line(0,0,319,0,0,VGA);
            PutPixel(Random(320),0,Random(16),VGA);
       End;

       Procedure ScrollLeft;
       Var A:Byte;
       Begin
            WaitVbl;
            For A:=0 To 199 Do
               Move(Mem[VGA:(320*A+1)],Mem[VGA:(320*A)],319);
            Line(319,0,319,199,0,VGA);
            PutPixel(319,Random(200),Random(16),VGA);
       End;

       Procedure ScrollRight;
       Var A:Byte;
       Begin
            WaitVbl;
            For A:=0 To 199 Do
               Move(Mem[VGA:(320*A)],Mem[VGA:(320*A+1)],319);
            Line(0,0,0,199,0,VGA);
            PutPixel(0,Random(200),Random(16),VGA);
       End;

       Begin
            Randomize;
            Initgraph;
            SetUpStarfield;
            For A:=0 To 199 Do ScrollUp;
            For A:=0 To 199 Do ScrollLeft;
            For A:=0 To 199 Do ScrollRight;
            For A:=0 To 199 Do ScrollDown;
            For A:=0 To 199 Do
            Begin
                 ScrollUp;
                 ScrollLeft;
            End;
            For A:=0 To 199 Do
            Begin
                 ScrollUp;
                 ScrollRight;
            End;
            For A:=0 To 199 Do
            Begin
                 ScrollDown;
                 ScrollRight;
            End;
            For A:=0 To 199 Do
            Begin
                 ScrollDown;
                 ScrollLeft;
            End;
            Readln;
            Closegraph;
       End.

    This article is far for completion, because there is so many thing to be
  said about scrolling, but I will leave that for part II... In that article,
  I'll discuss partial scrolls and tile scrolling, so look out for it !! :)
  I will also talk of paralax scrolling, tough that is just a matter of various
  scrolls moving at different speeds... That involves virtual screens, so it's
  quite complicated to talk, tough it's easy to implement...


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-


  8. Hints and Tips

                *   - Begginners tip
                **  - Medium tip
                *** - Advanced tip


    - Var keyword in procedures (*)

      Sometimes, you want to change the content of a variable that is passed
      to a procedure. There are two reasons to do this, but I will explain it
      later. This is not so easy as you may expect... For example:

             Program Test_Twenty_Something;   { I lost count !! :))) }

             Var B:Integer;

             Procedure Test(C:Integer);
             Begin
                  Writeln('Before in the procedure B=',C);
                  C:=10;
                  Writeln('After in the procedure B=',C);
             End;

             Begin
                  B:=5;
                  Writeln('Before in the main program B=',B);
                  Test(B);
                  Writeln('After in the main program B=',B);
                  Readln;
             End.

      If you run this, you will see that C:=10; in the procedure doesn't affect
      variable B in the main program, but only value C in the procedure. If you
      really want to change variable B, you must use the VAR keyword in the
      procedure declaration, like this: Procedure Test(Var C:Integer);
      If you test the above program with that alteration, you will get the
      desired effect.
      Why do you want to change a variable within a procedure ? Simple, because
      you need to in your program... Or that, or you want to make a procedure
      that returns an array. You can't return a whole array in a function, so
      you must use a procedure instead, passing the destination array as a
      parameter.


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-


  9. Points of View

    The other day, I was talking to a friend of mine, and he said: 'Spell, why
  don't you make you mag in C ?'. I turned to him and I said: 'Because I hate
  C !!!'... I found out that I'm equal to lots of people in the computerscene
  who hate something that don't use... This is very frequent:
  Subject A - So, what language/tracker/paint program do you use ?
  Subject B - Well, I use Pascal/OctaMed/Deluxe Paint IV...
  Subject A - Yech !! That's so lame !!! I use C/Scream Tracker/Animator, and
              they rule ! Your programs are so lame... I don't want people
              to see me talking with a lame person like you... Bye...
  I know this sounds stupid, but it happens... So, after I said that to my
  friend, I ammended saying: 'Really, I don't use C, because Pascal is easier
  and if I want speed or versatility I use 100% assembler...'.
    So, you should follow this simple rule: Just because someone dislikes a
  particular program/language/whatever, it doesn't mean that a person should
  be excluded because of that.
    Speaking only of languages... Lots of people don't regard me as a great
  programmer... They think I just plain SUCK because I use Pascal to code my
  utilities and to join things together... To that people, I just have one
  thing to say: Lucky you, because you don't have to enter a competition with
  me... Not because I would win, not at all, but because I would put a very
  big fight, using only my 'inferior' Pascal, with my 'useless' assembler code.
    And to those that think that assembler is stupid because it isn't portable,
  just think about this: Your dear little C and other languages alike were
  programmed in ASSEMBLER !!!! They must be... And you can't code a GOOD game
  or demo using only C++ or Visual Basic ! They aren't fast enough and they
  don't let you use the inner resources of the machine without needing a bit
  of assembly code... Just using the interrupt 10h you are using assembler !
  So grow up and learn how to code !! You don't work with a machine, you make
  the machine work for you... Maybe one day, with the P7 or the likes you will
  have so much speed that you can code in Basic and still knock out Second
  Reality out of the Best_Demo_Of_The_World spot, but still that doesn't make
  you as good a programmer as Psi of Future Crew, or other of my heroes in
  coding...
    So, I'll never pay any attencion to those who think I'm a fool/stupid
  because I use Pascal or Assembler... In the bottom-line, anyone that can use
  assembler can use C or any other language, and not everyone that can use C
  can use assembler... Never forget this... Your precious C compiler was writen
  in assembler... And all good things in life are writen in assembler (or they
  just stink) !
    I'm sorry this is agressive, but this is true... I'm not saying that C is
  crap, but I prefer Pascal... That is my choice, but I don't mind you using
  C... It's your choice... All I'm saying is that ASM rules !

    Ok, for my next issue, I'll probably finish the series of articles
  dedicated to pointers, and I'll make part II of the Scrolling Tutorial. Also,
  I'm going to begin a begginer's tutorial on how to make a simple text
  adventure... it will explain everything, from the basics (creating a storyline
  and making maps and stuff) to the implementation of the ideias...
    I'm also thinking of including an article on 'How to make a cool starfield',
  and more hints and tips and the adventures of Spellcaster... :) I'm going
  to try this issue faster, but I don't garanty anything, because I must first
  create the text adventure, so that I can teach how it was done... ;)


-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x


 10. The adventures of Spellcaster, the rebel programmer of year 2018.

  Episode 7 - Love in a Time of War

    We arrived at the Brotherhood's headquarters little after 8. There we could
  breath again... The escape has been a success.
  - Well, after this rather shacky start, I think you two need to be formally
    introduced... - said Gundsen, with a strange tone on his voice.
  For the first time since I opened the cells at the Sega Prison, I looked at
  Gundsen's sister eyes. I felt immediatly lost... My heart began to pound
  faster and faster. I thought I felt my legs trembling and drips of sweat
  beggining to flow in my whole body. I couldn't say or think anything... All
  I could see were those dark brown eyes, and the apparently soft and beutifull
  skin that was around them... Gundsen cough, as to call me to reality. It took
  me a couple more seconds to regain my self control, and to be able to look
  at rest of Gundsen's sister. She had straigh hair, with a very dark tone of
  brown, that runned down her head until it stopped near the neck. I tried to
  be discrete when I looked at her body. Her body was perfect in every aspect,
  with round curves and not a single piece of celulite, unusual for this time.
  I looked back at her face... Her eyes were glittering, and she had a faint
  smile on her beutifull lips. Something told me that I didn't was so discrete
  as I wanted... I smiled back.
  - Yuhhh !!! Spell !!! Diogo !!!! - shouted Karl, trying to get me back to
    reality. I didn't responded, and Karl kicked me in the ass, to wake me up.
  I lost my balance for a couple of seconds, for I wasn't expecting it, and I
  swinged my body, raising my leg, and halting it just before reaching Gundsen's
  face.
  - Lighten up, Spell !!! - he said. - I just wanted to wake you up...
  - Sorry, Karl... - I smiled. - I was a little distracted... - I continued,
  looking at the girl.
  - As I was saying, before you went to cybergroove, this is my sister,
    Kristie Gundsen, alias known as Excalibur... - Karl said to me. Then he
    looked at Kristie. - Kristie, this is Diogo 'Spellcaster' Andrade... He's
    helping me getting into Comptel system...
  - Pleased to meet you... - she said quickly to me, before looking again at
    Karl. - Are you still trying that stupid trick ?!!! I can't believe it !
    You tried for almost five years, without success, and you nearly got
    yourself killed because of that! It almost got you and it got Rick dead !
    And you are trying to do it again, this time with a guy that doesn't look
    like it can code jack-shit !!!! - she looked at me. - No offense
    intended...
  - None taken. - I said quitelly, leaving the room... I tought that I shouldn't
  get in the middle of a family's stuff... I went up to the top floor of the
  building were we had our HQ, and I looked at the sun, that was orange because
  of the pollution, and I said to myself:
  - Can it be ?... Could it happen to me ?... Is it possible... Love in a time
    of war ?!

                                             See you in the next issue
                                            Diogo "SpellCaster" Andrade