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 6
                                                        8-3-96



  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. Records and basic file handling
          2.1. Records
          2.2. Files
        3. The dos and don'ts of file acessing
        4. Scrolling in text mode
        5. Graphics Part V - Loading a PCX file
          5.1. Introduction
          5.2. The PCX file structure
          5.3. Decoding a PCX file
        6. Hints and tips
        7. Points of view
        8. The adventures of Spellcaster, part 6

  1. Introduction

    1.1. About the magazine

    Welcome to number 6 of 'The Mag', brought to you, as usual, by Spellcaster,
  alias Diogo de Andrade. I know this issue is VERY late, but I got some exams
  and then my hard drive just cocked out... It still doesn't work, so I'm
  writing this in  the school's computers, that are a piece of shit, and I've
  very pissed ! It's the second time I write issue 6, because I already had
  finished it when my hard drive died...
    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.

    I've made an error in the previous issues. In the virtual screens part,
  there's a small piece of code that reads:

    Procedure InitVirt;
    Var A:Byte;
    Begin
         For A:=1 To Npages Do
         Begin
              GetMem(Virt[A],64000);
              VP[A]:=Segment(Virt[A]^);
         End;
    End.

    You should change the Segment keyword to Seg... Small mistake... You should
  read now:

    Procedure InitVirt;
    Var A:Byte;
    Begin
         For A:=1 To Npages Do
         Begin
              GetMem(Virt[A],64000);
              VP[A]:=Seg(Virt[A]^);
         End;
    End.

    Sorry about that... I'm only human...

    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 Setbal, 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 Setbal 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). 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).
    '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...

    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... The one who's skipping classes...
  I recommend you to contact me personally, if you can, especially if you
  are a member of the opposite sex (I'm a man, for those of you who are
  wondering).

    My adress is:
                 Praceta Carlos Manito Torres, n4/6C
                 2900 Setbal
                 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 -> Ubistc.Ubi.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), Alex "Darkfox" (thanks for letting me
  use your BBS), Joo 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 !


  2. Records and basic file handling

    Ok, this article is about files and records... First, I'll talk about

    2.1. Records

    Well, records are... ahh...er... records... I know this wasn't helpfull,
  but the best way to describe records is with an example. Imagine you wanted
  to build a program to keep track of all your friends' adresses and phone
  numbers. With the knowledge you have (assuming that you only know what I've
  been teaching you), you would have to do something like this:

       Var Names:Array[1..100] of String;
           Phone:Array[1..100] of String;
           Adress:Array[1..100] of String;

  Or something like this:

       Var Data:Array[1..100,1..3] of String;

    But this solution has several drawbacks... In the second example, you would
  have to remember that index 2 was the phone number and index 3 was the adress.
    With records, things get easier and simpler... You just have to make
  something like this:

       Type DataRec=Record
                          Name:String;
                          Phone:String;
                          Adress:String;
                    End;

       Var Data:Array[1..100] of DataRec;

    Now, you have an array called Data full of records... You can now access
  data in a perfectly straighward form...

       Data[1].Name:='Spellcaster';
       Data[1].Phone:='01-551155';

    They are treated as normal variables... The Name, Phone and Adress are the
  fields of record DataRec.
    This is an invalubale resource when building programs... I use them all the
  time.
    I think this is fairly simple, so I'll go on to

    2.2. Files

    There will come a time in your programming experiences that you'll have the
  need to access files in your computer, to read a picture, for instance. When
  that time comes, you better be prepared, so read this carefully... This is
  very basic file accessing, and it's only usefull to read some types of data.
  You can't use these concepts to read a PCX file. Read the next article for
  that.
    There is a special kind of variable, called the Text type variable, that is
  used to read ASCII coded text. It is declared as usual variables, but it isn't
  used like them...
    I'll do a small demonstration commented program, to exemplify...

    Program Test_18;                  { This program gets string from the }
                                      { user and dumps them to a file, called }
                                      { SPELL.TXT... The program ends when the }
                                      { user returns an empty string.}
    Var F:Text;                       { Defines variable F of type text }
        S:String;                     { Defines S as a string }

    Begin
         Assign(F,'Spell.Txt');       { Associates variable with file }
                                      { SPELL.TXT. It isn't important if the }
                                      { file exists or not... }
         ReWrite(F);                  { This sets up the file F for writing. }
         Repeat
               ReadLn(S);
               WriteLn(F,S);          { This writes the content of varible S }
                                      { to file F... }
         Until S='';
         Close(F);                    { This closes file F, and saves the }
                                      { changes made to it... }
    End.

    Now, another example...

    Program Test_19;                  { This program reads the contents of }
                                      { file MAG06.TXT and dumps it in the }
                                      { screen... }
    Var F:Text;                       { Defines variable F as type Text }
        S:String;                     { Defines var S as a string }

    Begin
         Assign(F,'Mag06.txt');       { Associates var F with file MAG06.TXT }
         Reset(F);                    { Prepares file F for reading. If the }
                                      { file doesn't exist, the program will }
                                      { give you an error message. }
         Repeat
               Readln(F,S);           { This reads a string from file F, and }
               WriteLn(S);            { stores it in var S }
         Until Eof(F);                { Repeats until End Of File F... }
         Close(F)                     { Closes file F }
    End;

    So, I think this is simple, even for a beginner... The Writeln and Readln
  procedures do the input and output to the file. The Reset and Rewrite keywords
  prepare the file for reading and writing. Notice that a file can't be open
  for reading AND writing simultaniously. The EOF function returns True if
  the file has already been totally read...
    Now, imagine you already had a file, and you wanted to add something in
  the end of it... Then you could use the Append keyword, instead of the Rewrite
  keyword. The difference between them is that Rewrite overwrites an existing
  file, and Append adds the data in the end.
    One last remark about files... In Pascal, all files are sequencial... This
  means that you, in order to access data in the middle, must access the data
  in the begginning. This also means you can't add data to the middle of a
  file.



  3. The dos and don'ts of file acessing

    This article is an extension to the last one... It develops further more
  the concept of files. It teachs you to access files of other types besides
  text files... The name doesn't have nothing to do with the article itself,
  but I liked the idea...

    Imagine you wanted to access a file and get a byte at a time... This would
  be impossible with variables of type text. So, variables of type file come
  into action... Variables of type file are similar to varibles of type text,
  but more flexible... It enables to read a specified number of bytes to a
  variable, instead of reading entire lines...
    As usual, I'll suply you with an example... You know the say: An example
  is worth more than a thousand bytes of text...

    Program Test_20;

    Var F:File;
        A:Array[1..20] Of Integer;
        B:Integer;

    Begin
         Assign(F,'Spell.Dat');
         Rewrite(F,1);
         For B:=1 To 20 Do A[B]:=Random(100);
         Blockwrite(F,A,Sizeof(A));
         Close(F);
    End.

    This little program generates an array with 20 random integers and 
  then it saves them to a file called 'Spell.Dat'.
    The Random(n) function gives a random integer in the 0..n range.
    The Blockwrite(File, Variable, Bytes) writes a certain number of 
  Bytes that are stored away on the Variable to a certain File. The 
  Variable can be any kind of variable, including user-defined variables.
    This is an unvaluble resource. I use BlockWrite and it's counterpart 
  BlockRead in almost every program I make.


    Program Test_21;

    Var F:File;
        A:Array[1..20] Of Integer;
        B:Integer;

    Begin
         Assign(F,'Spell.Dat');
         Reset(F,1);
         Blockread(F, A, Sizeof(A));
         Close(F);
         For B:=1 To 20 Do Writeln(A[B]);
         Readln;
    End.

    The above example reads the file created with the other program and 
  stores it on the array A. Then it types the values to the screen.
    Just one more thing I forgot to mention: You probably noticed the 
  different sintax of the Reset and the Rewrite keywords. I'm not sure 
  about what does it mean the number in front of the file identifier, but I 
  think it is the number of bytes to read at any one time. I always read
  1 byte at a time, so I always put a 1. If anyone smarter than me knows 
  what is that number, mail me !
    I'll finish this article with a piece of code I've been using for the
  last two issues sample programs. The procedure LoadPal reads a palette from
  disk and stores it in a RGBList (see the issue that talks about palette
  manipulation).

    Procedure LoadPal(Filename:String;Var Pal:RgbList);
    Var F:File;
    Begin
         Assign(F,Filename);
         Reset(F,1);
         Blockread(F,Pal,768);
         Close(F);
    End;

    This piece of code is pretty straightforward stuff, I think.


  4. Scrolling in text mode

    Ok... This is a tricky article to understand and to write. So I'll 
  try to do it the best I can. I wrote it because a reader asked it.
    This article is writen with the thought that you are understanding 
  the graphics tutorials.
    Text mode can be thought as similar to mode 13h, in the respect that 
  you could make a direct access to it, using the Mem keyword. The 
  differences are that the address of a text screen is B000h, instead of 
  A000h. Besides that, while $A000:0000 represented the first pixel on the 
  screen in mode 13h, $B800:0000 represents the first character on the 
  screen. 
    Moving on, we need to know with the VGA card registers. For scrolling 
  the text screen, we need to know this one:

--------------------------------------------------------------------------------
Port-Index: 08h              Port: 03d4h/3d5h
usage:      Preset row scan
            d7    Unused
            d6    Byte panning control
            d5    Byte panning control
            d0-d4 Preset row scan
Description: This changes the first row of pixels to be displayed. For 
             this article, we only need to know that if you do 
               Port[$03d4]:=8; 
               Port[$03d5]:=n;
             the first pixel to be desplayed on the screen 
             would be n. 
--------------------------------------------------------------------------------

    So, knowing this, the general algorythm is:

      You put the image, or whatever you want to scroll in in address 
        $B800:4000. This is just out of the visual screen.
  |-> You scroll the screen, by changing the first pixel to be desplayed.
  |   When you have scrolled sixteen pixels, you scroll in the memory the 
  |     image you want to scroll in, this is, you move the memory from 
  |     $B800:0160 to $B800:0000.
  |    You go back to here
  |                    |
  ----------------------

    Following this there is a piece of code that implements the above 
  algorythm. It is unoptimized. Experiment with it... Change the 
  values... Do something with it... This won't crash the computer... I 
  think... :)

    Program Test_22;

    {$X+}

    Uses Crt;

    Var F:File;
        Old:Byte;
        N,M:Integer;

    Procedure WaitVbl; Assembler;
    Label l1,l2;
    Asm
       mov dx,3dah
       l1:
          in al,dx
          and al,08h
          jnz l1
       l2:
          in al,dx
          and al,08h
          jz l2
    End;

    Begin
         Port[$3d4]:=8;
         Old:=Port[$3d5];  {This saves the old value... It is usually one...}
         Fillchar(Mem[$B800:4000],16000,0);  { This makes the image I
                                               want to scroll in be just a
                                               screen full of exlamation
                                               points... }
         For M:=0 To 50 Do
         Begin
              For N:=0 To 15 Do
              Begin
                   Port[$3d4]:=8;
                   Port[$3d5]:=N;
                   WaitVbl;
              End;
              Port[$3d4]:=8;
              Port[$3d5]:=0;
              Move(Mem[$B800:160],Mem[$B800:0],16000);
         End;
         Readkey;
         Port[$3d4]:=8;
         Port[$3d5]:=Old;
    End.



  5. Graphics Part V - Loading a PCX file

    5.1. Introduction

    Ok, this is part 5 of the Graphics In Mode 13h tutorial. This 
  issues's article is about reading a PCX file. This is quite simple, as 
  reading any kind of file... You just have to know the file's structure.
    Just for knowledge, the PCX file format was created by ZSoft, for their
  popular drawing program, PaintBrush... I don't know what makes it popular,
  because I prefer Electronic Art's Deluxe Paint II anytime !
  
    5.2. The PCX's file structure

         Byte      Item         Size   Description/Comments
         0         Manufacturer  1     Constant Flag, 10 = ZSoft .pcx
         1         Version       1     Version information
                                       0 = Version 2.5 of PC Paintbrush
                                       2 = Version 2.8 w/palette information
                                       3 = Version 2.8 w/o palette information
                                       4 = PC Paintbrush for Windows(Plus for
                                           Windows uses Ver 5)
                                       5 = Version 3.0 and > of PC Paintbrush
                                           and PC Paintbrush +, includes
                                           Publisher's Paintbrush . Includes
                                           24-bit .PCX files
         2         Encoding      1     1 = .PCX run length encoding
         3         BitsPerPixel  1     Number of bits to represent a pixel
                                       (per Plane) - 1, 2, 4, or 8
         4         Window        8     Image Dimensions: Xmin,Ymin,Xmax,Ymax
        12         HDpi          2     Horizontal Resolution of image in DPI*
        14         VDpi          2     Vertical Resolution of image in DPI*
        16         Colormap     48     Color palette setting
        64         Reserved      1     Should be set to 0.
        65         NPlanes       1     Number of color planes
        66         BytesPerLine  2     Number of bytes to allocate for a
                                       scanline plane.  MUST be an EVEN
                                       number. Do NOT calculate from Xmax-Xmin.
        68         PaletteInfo   2     How to interpret palette- 1 = Color/BW,
                                       2 = Grayscale (ignored in PB IV/ IV +)
        70         HscreenSize   2     Horizontal screen size in pixels. New
                                       field found only in PB IV/IV Plus
        72         VscreenSize   2     Vertical screen size in pixels. New
                                       field found only in PB IV/IV Plus
        74         Filler       54     Blank to fill out 128 byte header.  Set all
                                       bytes to 0

    NOTES:

    All sizes are measured in BYTES.
    All variables of SIZE 2 are integers.
    *HDpi and VDpi represent the Horizontal and Vertical resolutions which the
  image was created (either printer or scanner); i.e. an image which was
  scanned might have 300 and 300 in each of these fields.

    Ok, if the above listing didn't gave you a clue, think of a PCX file like
  this. It is a file composed in the following form. The first 128 bytes are
  the header, which contains lots of informatation about the PCX file, like the
  size of the picture, pallete information (in less than 256 color modes).
  Then comes the picture data, encoded with a run-lenght algorythm... I will
  explain this latter. Then comes a byte with the value 12, if a 256 color
  palette exists. If it exists, it will be stored in the following 768 bytes.
    To read a PCX file, you can do like this: first, set three records, like
  this:

    Type RGBItem=Record
                       Red:Byte;
                       Green:Byte;
                       Blue:Byte;
                 End;

         PCXHeader=Record
                         Manufacturer:Byte;
                         Version:Byte;
                         Encoding:Byte;
                         BitsPerPixel:Byte;
                         Window=Record
                                      Xmin:Integer;
                                      Ymin:Integer;
                                      Xmax:Integer;
                                      Ymax:Integer;
                                End;
                         HDpi:Integer;
                         VDpi:Integer;
                         Colormap:Array[0..15] Of RgbItem;
                         Reserved:Byte;
                         NPlanes:Byte;
                         BytesPerLine:Integer;
                         PaletteInfo:Integer;
                         HScreenSize:Integer;
                         VScreenSize:Integer;
                         Filler:Array[1..54] Of Byte;
                   End;

         RGBList=Array[0..255] Of RGBItem;

    Then, you read the header. You can do it with this:

      Var Head:PCXHeader;
      ......................
      ......................
      Assign(F,'IMAGE.PCX');
      Reset(F,1);
      BlockRead(F,Head,128);

    The above piece of code will read the header of the PCX file called
  IMAGE.PCX. Now the variable Head, of type PCXHeader will contain all the
  relevant data of the PCX file. In the example I will give you, we'll ignore
  the header and assume the picture is a standard mode 13h image (because this
  is a tutorial on mode 13h). But don't worry... Anything that will be said
  here can be adapted to any graphic mode.

    5.3. Decoding a PCX file

    You can now begin decoding the first scan line - read the first byte of
  data from the file. If the top two bits are set, the remaining six bits
  in the byte show how many times to duplicate the next byte in the file.
  If the top two bits are not set, the first byte is the data itself, with a
  count of one. Continue decoding the rest of the file like this.
    If you didn't understand what I was saying, think about this:
    You read a byte from the disk. Let's call this value A. If A is greater
  than 192, you read the next byte, and then you output it to the screen,
  A-192 times. It all becomes clearer with the piece of code I include next.
  This procedure is called LoadPCX, and it just requires the name of file.
  I'll assume that the graphics mode is already set. This procedure ignores
  the header and just reads mode13h files. The procedures PutPixel and
  SetPallete are user-defined before the LoadPCX file.

  Procedure LoadPCX(Filename:String);
  var Fil:File;
      Dx,Dy:Word;
      J,M:Byte;
      Ph:Word;
      Buff:Array[0..127] of byte;
      PCXPal:RgbList;

  Begin
       Assign(Fil,Filename);
       Reset(Fil,1);
       Blockread(Fil,Buf,128);
       Dx:=0;
       Dy:=0;
       Repeat
             Dx:=0;
             Repeat
                   BlockRead(Fil,J,1);
                   If J>192 Then
                   Begin
                        BlockRead(Fil,M,1);
                        Dec(J,192);
                        For Ph:=1 To J Do
                        Begin
                             PutPixel(Dx,Dy,M);
                             Inc(Dx);
                        End;
                   End
                   Else
                   Begin
                        PutPixel(Dx,Dy,J);
                        Inc(Dx);
                   End;
           Until Dx>=320;
           Inc(Dy);
     Until Dy=200;
     BlockRead(Fil,M,1);
     If M=12 Then
     Begin
          BlockRead(Fil,PCXPal,768);
          For M:=0 To 255 Do
          Begin
               PCXPal[M].R:=PCXPal[M].R Div 4;
               PCXPal[M].G:=PCXPal[M].G Div 4;
               PCXPal[M].B:=PCXPal[M].B Div 4;
          End;
          SetPalette(PCXPal);
     End;
     Close(Fil);
  End;

    In case you're wondering why did I, after I read the palette, divide it
  all by four, I'll explain... The registers of the VGA Palette have
  intensities that range from 0 to 63... The PCX file saves palette information
  from 0 to 255. So, before you use the palette, you must divide it all by
  four. I know it is stupid, but I didn't invented it !
    Also, the above code is very slow, because you read the data from the file
  one byte at a time. You can speed it up by creating a buffer that stores part
  of the file in order to reduce disk access... The speed-up is tremendous !
  I'll show how can it be done in next issue.


  6. Hints and Tips

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


    - Forward keyword (*)

      If you write that following piece of code:

      Procedure One;
      Begin
           Two;
      End;

      Procedure Two;
      Begin
      End;

      You would get an error, because when the compiler reaches to the call of
      procedure Two in procedure One, he doesn't know yet procedure Two...
      There are two ways of mending this. The first is to reverse the order the
      procedures appear. The second comes in hand in cases like the following:

      Procedure One;
      Begin
           Two;
      End;

      Procedure Two;
      Begin
           One;
      End;

      I know this would get an infinite cicle, but that's beyond the point.
      The only way to go around this is to use the forward keyword. The forward
      keyword informs the compiler that a certain procedure exists, so it will
      not give a 'Undefined Procedure' error. So, to validate the last piece
      of code, you would have to do it like this:

      Procedure One; Forward;
      Procedure Two; Forward;

      Procedure One;
      Begin
           Two;
      End;

      Procedure Two;
      Begin
           One;
      End;

    - Speeding up some routines (**)

      One way to optimize code is to calculate all the relevant stuff in an
      inner loop before the loop. For example, let's assume we have the
      following code:

      For A:=1 To 100 Do
      Begin
           For B:=1 To 200 Do
           Begin
                C:=A*50+B;
           End;
      End;

      This could be replaced by this faster code:

      For A:=1 To 100 Do
      Begin
           D:=A*50;
           For B:=1 To 200 Do
           Begin
                C:=D+B;
           End;
      End;

      The only drawback is the use of an extra variable, but that's almost
      always a constant... The more speed you want, the more memory you spend,
      and vice-versa.


  7. Points of view

    Well, I don't know what to talk about in this issue, so I think I'll 
  just ramble on...
    I'll start with a moan (as usual)... Why can't I get a musician and a 
  Gfx artist for my productions ? I really want to do something like a 
  demo or a game, but I can't because I can't do music and can't draw... 
  And I don't have a computer good enough to run 3D Studio (the only 
  drawing program I know that the person who uses it doesn't need to draw 
  well to create a masterpiece...). 
    Next, I'll send my respects to some demo and game making groups out 
  there... Especially the ones that don't charge anything for their 
  work... Not because I'm a cheap-stakes, it's just because those guys 
  programm for their love for the art, not for love for the money... Of 
  course, it isn't wrong to get money out of it... Money is good... But 
  I admire more a guy that spends lots of time developing a program to 
  release it free than I admire a guy that gets big bucks for doing the 
  same thing.
    And why every employer nowadays whats you to know Visual C/Basic, or 
  Windows 95 programming and other user-friendly shit like that. I HATE 
  WINDOWS... 95 and 3.1... I hate them all... They aren't made for 
  programmers... They are made for users... But the worse is that one day, 
  all that there is left is Win95... And we'll have to quit doing demos and 
  games, because most demos/games use resources that Win95 don't allow you 
  to use... It will be like a return to the stone-age in demo/game making.
    I'm just too melodramatic today, ain't I ? :)
  Weel, I don't know when the next issue will come, nor what will it 
  have, so keep your eyes peeled for it. I think I'll put, in the begginers
  part, a tutorial on how to create and use Pascal Units. In the graphics part
  I think I'll make an article on scrolling and I'm also thinking on including
  an article on Pointers (the second part of an article I've started in issue
  one). I'll also will try to squeeze the first of the Spellcaster Utilities,
  a series of programms to help you develop your programs. So I think the next
  issue will take longer to make that I thought in the first place. I have to
  code the first utilitie (I'm thinking about doing a palette editor).
  I'll try to make the best I can, as usual... Send all doubts to me. And
  your articles/articles suggestions.. I'd love to see them. I'll help if I
  can.


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

  Episode 6 - Hear no evil, see no evil

    I looked at the clock. It was 7 a.m. Only an escape plan could make 
  me rise so early. I looked at Karl. His eyes were very bright, as if he 
  was starting to cry. I prefered to believe that it was the sun rising up 
  ahead that was hurting his eyes.
  - Let's go... - I said, starting to walk down the hill, in direction to 
    the Sega Corporate Prison. I heard Gundsen's steps behind me.
  - Are you sure the virus will work ? - he asked, with a little fear on 
    his voice.
  - Positive... I've run tests with it. Relax... If the virus is in the 
    central computer, this will work...
  - And if it isn't ?
  - This will be the shortest jailbreak in history ! - I said with a dark 
    voice.
  - How did you got it into the system ?
  - I sent a disk to the warden... He probably downloaded it in the main 
    computer's memory.
  - What ?!! - shouted Gundsen, stopping. - Don't you know they scan 
    every disk with a virus-checker ?!
  - Of course I know... Relax... My virus is undetectable... It is 
    disguised like a game.
  - Ok... Ok... - said Gundsen, starting to walk again.
    We were almost two steps away from the wall of the prison, when Karl 
  spotted a droid above the wall, with it's eyes fixed on our position.
  - A guard drone... The prison is managed by them... - I said, in a 
    normal voice. - I think it is deactivated by my virus... As all the 
    other parts of the prison.
    I took a lazer gun out of my pocket and I started blasting the 
  wall... No guards appeared. It seemed my virus worked. We got into the 
  prison, and within minutes, we opened the doors to every cell in the 
  complex, making every prisoner there run away. I smiled, thinking of the 
  work Comptel would have to arrest them all again...
    Deathripper found his sister, and we all ran away to the the jetcar.
    As we all returned to the Brotherhood of the Rebel Programmer home 
  base, I was wondering if it was a good idea this new aquisition... 

                                             See you in the next issue
                                            Diogo "SpellCaster" Andrade