  ______/\__________________________      __  ________________ ___  /\_______
  \____   \  ________ _   _ ______  \    /  \|  \  ________   |   \/  ______/
  /   |    \  _)   \   \_/   \   |   \  /    \   \  _)   \    |    \______  \
 /    |     \       \   |     \  |    \/          \       \  / \    \    /   \
 \_____     /_______/___|     /_______/\____\_____/_______/_________/________/
     \_____/            |____/
                                                          Subscribers  : 2547
 DemoNews 141 - 02 February 1997                          Archive Size : 3997M

>------------------------------------------------------------------ Contents --

         Introduction
         Calendar
         Week In Review
         Top Downloads
         New Uploads
         Articles
           Software Design for Demos - Volume 3 .......... Kiwidog
           Advertisement : X'97 Takeover ................. HarleQuiN
         General Information

>-------------------------------------------------------------- Introduction --

 Hello all, and welcome to DemoNews 141.

 _____Introduction

 So much to print, so little time.  Even after releasing this 60k+ issue of
 DemoNews, I have another 110k worth of articles and reviews just waiting to
 be read.  An article from Trixter, 2 from Shaithis, tons of /music reviews...
 For just a little while, I'm probably going to be releasing 2 issues of
 DemoNews a week; your standard-style DemoNews on Sunday night, and a
 "catchup" issue either Wednesday or Thursday.

 It's bad enough that files sit in /incoming as long as they do.  It'd be a
 travesty to actually have them reviewed and not be able to print them in a
 timely fashion, agreed?  Anyway, I'm sure things 'll calm down in a month or
 so.

 _____(knock knock) Anybody home?

 With 2600+ subscribers to DemoNews, I expect a few new issues to bounce.
 After all, people leave or get kicked out of school, change jobs or are
 fired; email address are a dime a dozen and sometimes go away unexpectedly.
 You'd be surprised how many issues of DemoNews bounce each week.  Back in the
 good 'ole days, it'd be about 15 bounces per new issue.  It's recently grown
 to about 70 or 80.

 70 or 80 bounced issues x 60k per issue qualifies as mail bombing myself.
 Although the listserver is smart enough to unsubscribe non-functioning
 addresses, I still get that initial bounce.  And even though they get saved
 to a separate mailbox (thank you procmail), I still gotta sift through them
 since the occasional DemoNews reply gets mixed in there.

 Be kind.  If you know you're going to lose the address to which DemoNews is
 being sent, mail your friendly South African listserver@unseen.aztec.co.za
 with the words "unsubscribe demuan-list".

 _____%2B or +?

 I'd like to thank Knut Eldhuset who educated me on the finer points of
 encoded ascii in CGI search strings.  This was the tip I needed to fix a bug
 in the HA search engine that caused secondary searches for "****+" to fail.
 This gets Slam! rating of 6.

 _____Email Gripes

 HTML is not yet an acceptable email format.  Any mail sent to me in HTML only
 will be ignored and deleted.  On a related note, please learn how to
 uuencode/uudecode if you don't know already.

 _____The Cleansing of /incoming

 Our /incoming directory is very busy.  I want to take a minute to go over the
 basic rules for a happy uploading experience:

   1. must be .zip format (multi-file uploads may use .arj, .a01, etc.)
   2. file.txt description required with each file.zip
        please use /incoming/_forms/upload.frm (also see upload.exa)
        file.txt must be under 500 bytes!
        english only
   3. lower case, not UPPER CASE
   4. filenames must be 8 characters or less, not counting zip/arj extension
   5. files uploaded to appropriate subdirectory
   6. corrupted file.zip should be reuploaded as file.zip.good
   7. check to see if there is already a file named the same as yours
   8. only allowed to upload 1 production per day

   Any file breaking a rule is deleted automatically by script.

   Uploading means your file will stay on our site unless legitimate reasons
   are given for its removal.

 Please note that any files in /incoming that break rules #3 or #6 are deleted
 automatically at 4AM.  For files breaking #2, a second-chance script is used
 to try and generate a .txt file based on a file_id.diz within the .zip.  If
 that fails, the file is automatically deleted.

 Rule #8 might seem a bit odd.  Rephrased, it might read:

   8. if you upload 30 of your productions in one shot, one of our music
        reviewers gets stuck spending an unfair amount of time reviewing your
        music and ignoring everyone else's.

 I've deleted at least 200 unhappy files in the past 2 weeks.

 The official rules can be found in /incoming/.message

 _____South African Mirror Gone

 Please note that our mirror site at ftp.sun.ac.za has been discontinued. They
 simply don't have the resources anymore.

 _____Conclusion

 So what's with people sending html mail anyway?  Maybe I should start
 replying in tar-gzipped uuencoded style.

 Snowman / Hornet - r3cgm@hornet.org

>------------------------------------------------------------------ Calendar --

 Date         Event               Location  Contact Points
 ------------ ------------------- --------- ----------------------------------
 31 Jan 1997  PC96                Brazil    x@wm.com.br
                                            wm.com.br/~x/pc96.html

                                       * <-- YOU ARE HERE

 15 Feb 1997  General Probe 3     Poland    s146630@ire.pw.edu.pl
                                            neutron.elka.pw.edu.pl/~mszklano
 02 Mar 1997  Invasion            Finland   invasion@xuq.nullnet.fi
                                            www.koillismaa.fi/invasion
 23 Mar 1997  Millennium          Israel    mlitvak@ort.org.il
 26 Mar 1997  The Gathering       Norway    www.gathering.org
 28 Mar 1997  Mekka & Symposium   Germany   amable@aol.com
 28 Mar 1997  SiliConvention      Germany   www.siliconvention.com
 04 Apr 1997  X Takeover          Holland   x97take@dds.nl
 05 Apr 1997  Spring Break        USA (CA)  whutchin@sdcc13.ucsd.edu
                                            sdcc13.ucsd.edu/~whutchin
 11 Apr 1997  The Trip            Italy     keyby@jnet.it
                                            www.logicom.it/trip
 30 May 1997  Scream              Canada    scream97.educ.infinit.net
                                            furb@total.net
 22 Aug 1997  AntIQ               Hungary   aboy@ttk.jpte.hu
                                            www.jpte.hu/~aboy
 25 Aug 1997  The Place To Be 5   France    www.mygale.org/05/dadu

>------------------------------------------------------------- Week In Review --

 -- /music  ------------------------------------------------------------------>

 :: Snowman / Hornet - r3cgm@hornet.org

 _____Introduction

 No room.  Must make short!

 _____The Good...

 Dee Musicdisk Two by Dee.  Excellent.  Download now!

 _____...The Bad, and The Ugly

 The "Kx Files" by Kxmode.  Lame... ripped off Jester's song.  Didn't even
 have the good sense to rip something obscure.  "Hey Trixter, I'll change the
 songtext to The Crossing and say I wrote it... think anyone 'll notice?"
 Ripping is the cardinal sin of the scene, an action so reprehensible that we
 have a special marker for it.  Slam!

 _____Conclusion

 I am making some people very angry with me by writing reviews like the one
 above.  That's ok folks, I just call them as I see them.

>------------------------------------------------------------- Top Downloads --

 This represents combined ftp/http transfers for the last 7 days.

 Total files downloaded   :     208,581
 Size of files downloaded :  35,807,147k

 Times File                             Description
 ----- -------------------------------- --------------------------------------

 -- /demos ------------------------------------------------------------------>

   181  /1995/a/animate.zip             Animate by Schwartz
   144  /1993/s/symbolog.zip            Symbology by Admire
   143  /1993/u/unreal11.zip            Unreal v1.1 by Future Crew
   135  /1993/0-9/2ndreal1.lzh          Second Reality by Future Crew [1/2]
   128  /1993/0-9/2ndreal2.lzh          Second Reality by Future Crew [2/2]
   127  /1995/n/nooon_st.zip            Stars (bugfixed) by Nooon
   108  /1995/c/countdwn.zip            Countdown by Realtech
   106  /1993/c/cd2_trn.lzh             Crystal Dreams 2 by Triton
   102  /1996/a/ai_strok.zip            Stroke by Ionic of Astroidea
    88  /1992/c_dream.lzh               Crystal Dreams by Triton

 -- /music ------------------------------------------------------------------>

    96  /songs/1995/s3m/a/aryx.zip      Aryx by K. Koch
    95  /songs/1996/s3m/a/athought.zip  Another Night of Thought by Zastar
    76  /songs/1996/s3m/i/im_empir.zip  The Hidden Empire by Karsten Koch
    74  /songs/1996/s3m/i/im_chron.zip  Chronologie Part 4 (remix) by Karsten
    70  /songs/1997/xm/m/mcd-rain.zip   Rain by MC Dreamer
    56  /disks/1996/f/fm-plast.zip      Blur Plastiq by Mellow-D of Five Music
    55  /songs/1993/s3m/skyrider.zip    Skyrider by Purple Motion of Future Cr
    54  /songs/1996/s3m/f/fm-mech8.zip  Mechanism Eight by Necros
    54  /songs/1996/s3m/c/ccs-eps.zip   Epsilon Eclipse by Mayhem
    53  /songs/1995/s3m/c/ctgoblin.zip  Catch That Goblin by Skaven

 -- /graphics --------------------------------------------------------------->

    26  /images/1994/i/incest5.zip      Incest by Pentalysion
    20  /programs/editors/fedit11.zip   Font Editor v1.1 by PiCoder
    20  /images/1996/a/airwar.zip       Air War by Grape
    18  /images/1996/a/aa_gargo.zip     The Gargoyle by Coolhand
    17  /images/1996/a/abc_pien.zip     Pani Pienkowa by Grass
    16  /programs/vector/veced300.zip   3D Vector Editor by Grey Cat
    16  /programs/editors/char_122.zip  Char Editor 1.22 by Escape
    16  /programs/convert/bmp2avi.zip   BMP to AVI by Paul Roberts
    15  /programs/editors/gfx2b93.zip   Grafx 2.00 Beta 93 by Sunset Design
    15  /images/1996/h/hardcore.zip      by Boss

 -- /code ------------------------------------------------------------------->

    63  /tutorials/denthor/tut01new.zip Tutorial 1 in C by Snowman of Hornet
    61  /3ds/3dsrdr12.zip               3D Studio .3DS File Reader v1.2 by Jar
    60  /effects/water/water.zip        Water by De-Phassed
    57  /effects/scroll/motionrd.zip    Motion Read Me by Patch of Avalanche
    56  /tutorials/denthor/tut04new.zip Tutorial 4 in C by Snowman of Hornet
    56  /effects/water/hq_water.zip     Heart Quake's water source by ARM of I
    53  /tutorials/denthor/tut09new.zip Tutorial 9 in C by Snowman of Hornet
    53  /tutorials/denthor/tut02new.zip Tutorial 2 in C by Snowman of Hornet
    52  /tutorials/denthor/tut06new.zip Tutorial 6 in C by Snowman of Hornet
    52  /tutorials/denthor/tut05new.zip Tutorial 5 in C by Snowman of Hornet

 -- /incoming --------------------------------------------------------------->

    96  /demos/idx-magn.zip
    77  /demos/ctswht95.zip
    73  /TP96/demo/alto.zip
    71  /TP96/demo/megademo.zip
    65  /code/wavepic.zip
    65  /code/midas060.zip
    64  /code/gb_fmint.zip
    61  /demos/fishlife.zip
    58  /demos/balistic.zip
    54  /code/rastrzep.zip

>--------------------------------------------------------------- New Uploads --

 All ratings are subjective.

 Filename                        Size Rated Description
 ------------------------------- ---- ----- ----------------------------------

 -- /demos ------------------------------------------------------------------>

 /1996/0-9/1k_intro.zip             1 ***+  1000 Byte Intro by Frenzy : 386DX
 /1996/b/burning1.zip             179 ***   Burning Chrome by Hellcore :
                                            | 486,GUS/SB
 /1996/d/dufhk.zip                  4 *+    BBS Harakiri by Darkness Unknown
                                            | Force : 486
 /1996/e/e9-fett.zip                4 ****  Fettina by Magic of Ethos 9 -
                                            | TP96:in4k:02:
 /1996/k/k_storm.zip                3 **+   BBS Dark Storm by Kloon
 /1996/k/kk-rvsf.zip              123 ***   Reverse (final) by Ketchup Killers
                                            | - WIR96:in64:09: : 486,SVGA,GUS
 /1996/m/marsvoya.zip               3 **+   Mars Voyage by Daze of TMB -
                                            | TP96:in4k:08:
 /1996/r/riplview.zip              56 **+   Ripple Viewer by Hellcore
 /1996/s/shaolin_.zip             543 ***   Shaolin by Live : GUS/SB
 /1996/s/spasmo.zip               632 **+   Spasmo Vidio by Hirn Tod
 /1996/s/stg_ntlf.zip              80 **    Not Too Late (final) by Skytech
                                            | Group - SAT96B:in64:06:
 /1996/t/timeout_.zip               3 **    Time Out by Zaifrun of Immaculate
                                            | - TP96:in4k:10:
 /1996/z/zrn-16.zip               148 **+   Zauron Is 16 by Index : 386,GUS/SB

 -- /music ------------------------------------------------------------------>

 /disks/1996/d/dna-unre.zip      1279 ***+  Unreleased - The Lost Collection
                                            | by DNA : The file DNA-UNRE.EXE
                                            | inside this .zip contained the
                                            | Alfons.1344 virus.  The
                                            | executable was removed on 29 Jan
                                            | 1997 and repacked.
 /disks/1996/e/et9-emsn.zip       364 ***   Emissions #1 by Ethos9 :
                                            | Collection of about 40 chip
                                            | songs... some good some bad.
 /disks/1996/g/g_bshift.zip      1309 ***+  Blueshift by Beek of Grey : Old
                                            | school style tracking dude.
                                            | Works well.  No interface.
 /disks/1996/k/kx-files.zip       912 [rip] The Kx Files by Kxmode of Phluid :
                                            | The song kx-break.mod "Breaking
                                            | The Chains" is directly ripped
                                            | from Jester's "Elysium".  Only
                                            | the sample text has been
                                            | changed.  Ripping is
                                            | dishonorable and Kxmode has
                                            | proven himself an untrustworthy
                                            | tracker.
 /disks/1996/m/mfx_co6.zip        869 ***   MFX - Compilation 6 by MFX : Wierd
                                            | slow trancy type tunes... long
                                            | samples... no interface.  Very
                                            | odd.  Very, very odd.
 /disks/1996/r/rr_cha-1.zip       903 ***+  Chapter X by Radical Rhythms [1/8]
                                            | : Includes 574k UNIVBE .zip
                                            | file, compressed and
                                            | uncompressed x-play/x-shell.
                                            | Most of the music is ok, but
                                            | they did a _really_ nice job
                                            | with the interface... give 'em a
                                            | star just for that.  For a disk
                                            | this large, it's well put
                                            | together.
 /disks/1996/r/rr_cha-2.zip      1325 ***+  Chapter X by Radical Rhythms [2/8]
 /disks/1996/r/rr_cha-3.zip      1405 ***+  Chapter X by Radical Rhythms [3/8]
 /disks/1996/r/rr_cha-4.zip      1308 ***+  Chapter X by Radical Rhythms [4/8]
 /disks/1996/r/rr_cha-5.zip      1012 ***+  Chapter X by Radical Rhythms [5/8]
 /disks/1996/r/rr_cha-6.zip      1147 ***+  Chapter X by Radical Rhythms [6/8]
 /disks/1996/r/rr_cha-7.zip      1178 ***+  Chapter X by Radical Rhythms [7/8]
 /disks/1996/r/rr_cha-8.zip      1456 ***+  Chapter X by Radical Rhythms [8/8]
 /disks/1996/s/slkkro_1.zip       871 ***+  First Music Pack by Sunlikamelo-D
                                            | : Relaxed, professional,
                                            | inventive and creative music.
                                            | Almost a 4 star.
 /disks/1996/s/sr-nueva.zip       675 **+   Nueva Dimension by Sunrise : Not
                                            | bad techno, but tries to put too
                                            | many chords in (and
                                            | unfortunately has poorly tuned
                                            | samples).  No interface.
 /disks/1996/s/stm121.zip        1203 ***   Disk-Volume 12 by SDC, TOM [1/2] :
                                            | Each song in here is in an
                                            | embedded .zip or .arj file,
                                            | highly unwieldly as music disks
                                            | go.  This is unfortunate because
                                            | the music is actually pretty
                                            | good and deserving of a higher
                                            | rating had the authors taken
                                            | time to package their tunes
                                            | professionally.  No interface.
 /disks/1996/s/stm122.zip        1282 ***   Disk-Volume 12 by SDC, TOM [2/2]
 /disks/1996/t/tm-skew1.zip      1405 ***   Skew by T-Matic [1/3] : A very
                                            | wide range of quality levels for
                                            | the songs in this music disk.
 /disks/1996/t/tm-skew2.zip      1425 ***   Skew by T-Matic [2/3]
 /disks/1996/t/tm-skew3.zip      1337 ***   Skew by T-Matic [3/3]
 /disks/1996/t/tripto3a.zip      1212 **+   Tripout 3 by Trip Productionz
                                            | [1/2] : A few tiny chip .mdl's,
                                            | some that have a really groovy
                                            | beat, no interface.
 /disks/1996/t/tripto3b.zip      1253 **+   Tripout 3 by Trip Productionz
                                            | [2/2]
 /disks/1996/v/vr-pack1.zip      1023 *+    Music Pack by VampRabbit : A new
                                            | tracker with a little ways to
                                            | go.  However, coming from Ohio
                                            | he is destined for success.
 /disks/1997/c/cchimera.zip      2947 *+    Contorted Chimera by Drop Zero,
                                            | Contrivance : Perhaps a bit
                                            | unpolished and heavy on the
                                            | high-hats.
 /disks/1997/d/dee213.zip        1400 ****+ Dee Musicdisk Two by Dee [1/3] :
                                            | Slam!  This is how a music disk
                                            | should be done.  Absolutely the
                                            | best interface I've seen for a
                                            | music disk since Epidemic.  Not
                                            | only that, but the interface is
                                            | configurable... you can actually
                                            | use it for your own productions.
                                            | The music kicks ass.  If you
                                            | only download a couple music
                                            | disks this year, be sure that
                                            | one of them is Dee Musicdisk
                                            | Two!
 /disks/1997/d/dee223.zip        1409 ****+ Dee Musicdisk Two by Dee [2/3]
 /disks/1997/d/dee233.zip        1285 ****+ Dee Musicdisk Two by Dee [3/3]
 /disks/1997/d/dzone.zip          777 ***   Danger Zone by DZone : DZone took
                                            | time at least to do an interface
                                            | for this disk.  Some songs
                                            | better than others.
 /disks/1997/n/ng-dura.zip       1850 ***+  Dura Master by Nearly Gods : Good
                                            | techno!  3 songs in AMF format,
                                            | with a nice player to go along.
                                            | Don't try to play these in Cubic
                                            | Player (out of memory) or under
                                            | Windows 95 (lose keyboard
                                            | handler).  Would have given this
                                            | 4 stars if there had been more
                                            | songs.
 /disks/1997/p/ph-0197a.zip      1233 ***+  Phluid 01/97 by pHluid [1/2] : One
                                            | of pHluid's better music
                                            | disks... some really great
                                            | tunes.  It's unfortunate that
                                            | Kxmode / pHluid was recently
                                            | caught ripping a song.
 /disks/1997/p/ph-0197b.zip      1295 ***+  Phluid 01/97 by pHluid [2/2]
 /disks/1997/r/rpinflrn.zip      1154 **    The Inflern by Mr. Mortal of Red
                                            | Power : This song could actually
                                            | get 4 stars if the samples were
                                            | updated and the pattern data
                                            | tweaked just a bit.
                                            | Structurally this disk is sound,
                                            | but the samples make it hard to
                                            | listen to.
 /disks/1997/s/s-new97.zip       1008 *+    New 97 by Space Invaders : Sounds
                                            | kind of like newbie music, but
                                            | with a lot of potential.
 /disks/1997/t/t_mellow.zip       952 ***   Melodramatic Tendencies by Troll :
                                            | Decent music, just needs a
                                            | little polishing.  Troll has
                                            | much potential.
 /disks/1997/t/triphop.zip       1266 ***   Triphop by Riders of Skyjump Team
                                            | : Some pretty hip-hoppidy songs
                                            | in here.
 /disks/1997/v/v-debut1.zip       796 ***   Debut by SML of VSL [1/3] : Songs
                                            | were a bit large (3 were 2 megs
                                            | each).  However, they were
                                            | pretty good.
 /disks/1997/v/v-debut2.zip       719 ***   Debut by SML of VSL [2/3]
 /disks/1997/v/v-debut3.zip      1017 ***   Debut by SML of VSL [3/3]
 /disks/1997/v/visions.zip       1248 **    Visions by Bitstream of Tunnel
                                            | Vision : Music isn't too bad but
                                            | the samples sound muffled.
                                            | Author needs to be more
                                            | aggressive with his style.  MDP
                                            | interface.

 -- /mags ------------------------------------------------------------------->

 /1996/pain0396.zip               271 **+   Pain March 1996 Issue by Pain
 /1996/pain0496.zip               335 **+   Pain April 1996 Issue by Pain
 /1996/pain0596.zip               197 **+   Pain May 1996 Issue by Pain
 /1996/pain0696.zip               157 **+   Pain June 1996 Issue by Pain
 /1996/pain0796.zip               144 **+   Pain July 1996 Issue by Pain
 /1996/pain0996.zip               151 **+   Pain September 1996 Issue by Pain
 /1996/pain1196.zip               260 **+   Pain November 1996 Issue by Pain
 /1997/pain0197.zip               410 ***   Pain January 1997 Issue by Pain
 /1997/rc-vol01.zip               210 **+   Volvo Issue 1 by Rectum Cauda

 -- /party ------------------------------------------------------------------>

 /invites/1996/ascen96n.zip        79 **    Atlantic Scene '96 Convite &
                                            | Regras by Atlantic Dreams : SB
 /invites/1996/atl96tro.zip        66 *+    Atlantic Scene '96 Invitation
                                            | Intro by Atlantic Dremas : SB
 /invites/1996/bdn3invi.zip       319 ***   BDN 3 Invitation Intro by Funk
 /invites/1996/jporno96.zip       608 **+   Jouluporno '96 Invitation Intro by
                                            | Complex, Orange

>------------------------------------------------------------------ Articles --

 ---------------------------------------------------------------------------->

 :: "Software Design for Demos - Volume 3"
 :: Kiwidog - chargrove@mail.ravensoft.com

 _____Introduction

 Many happy returns!

 After a couple articles of warm-up info to get everyone going, it's time to
 finally start writing some code ('bout time eh? :)

 This issue we'll be designing our screen class (actually classes, plural, as
 you'll soon see) that we started talking about at the end of the last
 article, as the beginning of a (probably pretty substantial) code base we'll
 be writing over the next several articles.

 It's highly unlikely I'll be able to cover the whole layout of the screen
 info this issue, due to the immense size of what needs to be covered, so
 we'll probably be doing this over the next several articles before moving on
 to the next big topic.

 I don't know how long this issue alone will end up being, but my gut tells me
 it's gonna be a doozy, so hold on. :)

 _____The Usual "But First..."

 But First... :)

 I got a couple mails this past week regarding the last article, and a few
 folks got a bit confused on the whole constructor/destructor thing. Don't
 worry, once you see 'em in action here with the screen classes it should all
 make perfect sense, so be patient. :)

 Also, I've gotten a good volume of mail about what to do with the 3D series,
 and an overwhelming majority of you said you just wanted me to release the
 articles alone in a .zip to get them out there, so that's what I'm going to
 do.  It might be another week before I do so (I've been tied up in work
 related stuff for a little while), but the new zip will be called
 HRN_DN3D.ZIP, and will contain the articles for the first 5 of the series
 that went out here in DemoNews, along with five subsequent articles covering
 Gouraud Shading, Texture Mapping, Arbitrary Cameras, 3D Clipping, and Spline
 Paths, respectively.  After some final touchups this week I'll release it;
 hopefully that'll be enough info to keep busy for a while. :)

 Also, during the naming conventions section of the last article I talked
 about prefixes and suffixes, and how for classes I use a prefix/suffixless
 system for my own code since all the classes were very intuitively named.
 Welp, I broke that "15 character" barrier I talked about during the week, so
 in order to not be a hypocrite, I switched to using a prefix.  Since I've
 seen the "C_" prefix in a lot of places, I decided to give it a try and it
 seems to work well.  Fortunately since I haven't written any major code with
 you guys yet, I can start out with this convention from the outset as far as
 the article series goes. So all the classes you'll see written in the series
 from this point on will start with capital C in the name.

 Just FYI. :)

 Ok, I guess that's all the initial junk, and since I doubt I've got a lot of
 free space to ramble this time, we better jump on in... :D

 _____Of Cabbages and Kings

 '"The time has come," the walrus said, "to talk of other things." And while
 the walrus probably wasn't coding, he does have a point.

 Sometimes you have to sit back for a little bit and think about what it
 really is you want to do before you end up doing something rash.  The problem
 is, demo coding by nature tends to be very _very_ rash, so this can be a
 major task mentally.  But it's a good habit to get into, because once you can
 get used to designing things even slightly in advance of actually coding
 them, it makes everything go that much smoother.  The longer you think about
 your design beforehand, the more bugs, restrictions, and potential
 improvements you'll catch in your head before you even lay a finger on the
 keyboard.

 So before we start coding our screen class, let us ponder. :)

 One thing we know we want is non-mode-specific graphics.  While doing
 multiple color bit-depths is certainly the most difficult part of this, since
 all the primitives change, we should at LEAST be able to do multiple
 resolutions at the same bit depth without any hassles, and have at least
 support somewhere for doing primitives for other bit depths.

 Also, we know we want it to be non-platform-specific enough to where it
 shouldn't be all too evil to port the video code between DOS and say, DirectX
 under Win95.  If the design is good enough, very little code should change
 relatively in order for everything else to still work.

 Part of this non-specificness also brought up the idea of not having screens
 bound to any mode at all, so that we could use the same primitives for
 arbitrary buffers, bitmaps, dirty rectangles (for situations where they're
 needed), and so on.

 Sound like a lot to shoot for?  It is, but it's feasible. :)

 _____Planes, Trains, and Devices

 This section will probably seem rather confusing at first.  Don't worry about
 it, I'm just giving a rough overview of what we're about to do. :) Note that
 of course this is just one of an infinite number of design possibilities; if
 you like it that's wonderful, but basically I just want to stir up the
 gears... as long as this gets you thinking, I've accomplished my goal. :)

 Because we want three major things from this (arbitrary resolution, arbitrary
 bit depth, and arbitrary platform), we're gonna need a bit of indirection in
 our code to get everything done.  We're gonna have some kind of "universal"
 CScreen that everything above the video layer uses, sure, but CScreen itself
 is gonna need to pass some of its responsibility to other classes...
 otherwise it would be too hardwired for the kinda design we want.

 Let's look at the "arbitrary platform" one first, since it seems like it
 would supersede the other two.  If we think about it, DOS and Win95 only
 really differ in the end by how the video operations work.  Instead of just
 setting modes and blitting in Win95, you go through DirectDraw (or some other
 abstraction mechanism).  So the very first thing we'll want is to delegate
 the hardware specific stuff, like mode sets and blits, to another layer.
 Since most everyone uses offscreen buffers and blits them these days, doing
 an abstraction like this is painless... the linear offscreen buffers can be
 handled by CScreen while this "other layer" takes care of putting it
 onscreen.

 Now before we decide what that layer should do exactly, let's look at the
 other two requirements.  The easiest of the two left is arbitrary resolution.
 As far as the CScreen-side buffering stuff goes, this just means a change in
 the buffer sizes and the resulting scanline lookup tables. But on the
 hardware side, if you decide to use a screen as a fullscreen mode, you're
 gonna need another layer below the initial hardware layer, one which is
 different for every fullscreen video mode you use.  This means now we have
 CScreen at the highest level, a platform-specific level below that, and then
 another mode-specific level below the platform-specific level.  Will that
 take care of all the hardware abstraction stuff we need? Hopefully, but let's
 check the last requirement, arbitrary bit depth, to make sure.

 Bit depth doesn't just affect the hardware mode sets and blits and stuff. It
 also affects your drawing primitives, because if you want any speed
 whatsoever you'll want primitives that are different for each color bit
 depth.  Fortunately there are only a few depths to choose from, and even then
 you might not use all of them (8 bit palettized and 24 bit truecolor are the
 most likely grades), so this isn't a big deal.  BUT it does add another layer
 of abstraction.  Where's that layer go?  Well, since the hardware aspect of
 bit depth variation (the mode sets and blits) is already taken care of by the
 fact that we have a layer to cover all of those modes _regardless_, the only
 thing left to deal with is the primitives problem.

 We could have put our primitives (drawing lines, cutting and pasting
 rectangles, etc) directly into our CScreen class if we were restricting
 ourselves to one depth like 256 colors.  But by abstracting the primitives
 layer from CScreen as well, we cover that problem.

 That should take care of all our abstraction... finally, we might also want
 some kind of unified daemon-ish class that there's only one of, to control
 how the platforms and primitives are applied, as well as to control a couple
 other useful globalized things like automatically blitting the active
 "fullscreen" CScreen, etc.

 So that's five things total... the screen, the platform layer, the mode layer
 under the platforms, the primitives layer, and the unified hub. The names I
 gave the classes for these:

 - CScreen, for the screen class that interfaces with the outside world,

 - CVidControl, for the platform "control" mechanism dealing with the mode
   "devices" underneath,

 - CVidDevice, for each device itself, dealing with a particular mode

 - CVidPen, for the primitives, since the primitives act like a pen to draw on
   the screen, and

 - CVideoDaemon, a class acting as a hub, where only one of them exists which
   I named mVD (even though this isn't really a "daemon" in the true sense, I
   name my single-instance classes like this because it's easy to recognize
   their global purpose... all of my department daemon instances start with a
   lowercase m for main with an abbreviation, in this case mVD; I'm just
   clarifying incase it sounds odd).

 I know the classes may sound kinda wacky and huge, but each one's not really
 that big honestly.  Hopefully the layout doesn't sound too confusing; if so,
 just keep reading and you'll probably pick up on it.

 Now, if you code DOS exclusively, you'll only need one CVidControl, maybe
 called vid_ControlDOS or whatever.  In addition, if you only support a couple
 fullscreen modes like Mode 13h or certain VESA modes, you'll only need to
 code concrete devices for those modes in particular.  Also, if you only
 support 256 color modes, you'll only need one concrete pen as well, for 8-bit
 color.  The point of this architecture is simply EXTENSIBILITY, so that if
 you want to add extra support, it'll be easier to build more functionality in
 to the system later on.

 _____Slipping On Concrete

 If you've gotten confused by terms I've been using like layers being "under"
 one another, or coding "concrete" versions of a class, it means we'll be
 taking advantage of another big thing object-oriented programming allows...

 Inheritance.

 Inheritance is when you declare classes that "inherit" all the abilities of
 their ancestor classes... nearly all the data, the functions, etc.  But
 inherited (descendent) classes can add extra stuff to the mix, as well as
 replace functions given in their ancestors.  And when you have a function
 somewhere that takes a class parameter that's an ancestor of other classes,
 the descendents can _also_ be used as parameters to those functions. Don't
 worry about understanding it now, as I'll be going over it later in this
 article when we start writing our video code.

 Actually, why don't we start the code now... :)

 _____CVidDevice - No Guts, No Glory

 Since I doubt I have enough space to write all five classes in this issue,
 we'll start off taking care of the abstract CVidDevice class and showing a
 concrete class of it, to deal with video mode devices.  The reason to start
 off with the devices before the others is simple; they don't need as much to
 exist beforehand... makes 'em easier to explain :)

 The abstract video device only has set the ground rules for doing a couple
 things: Setting a video mode, blitting a buffer to that video mode, and
 setting a palette entry (since palettized modes need this).  There are a few
 other interfacing functions such as setting the device name and "registering"
 the device with the commanding CVidControl, but the core operational stuff is
 only a few functions.  I should be using the term "methods", since class
 functions are called methods, but you get the idea. :)

 The first code I need to give is a header containing general definitions used
 by just about every other file you'll see from me.

 NOTE: Throughout the code you'll see references to "Colony" and the
 abbreviations "CL" and "COL".  This is because my engine is called Colony
 (the group name is Terraformer so it fits), and the vast majority of the code
 I use will be directly from this code base.  Hence, since this is not just
 example code but code that _is_ being used by its creator, should you use it
 in your own code base I'd appreciate some greets or other recognition in your
 production.  I already go to great lengths to write these articles, let alone
 give out my code base, so the last thing I need is to get my hard work
 ripped.  A greeting is all I ask.

 I say this because I had a rather INFURIATING experience earlier this month
 on EFNet #c where one guy came on and said "check 0ut my kewl 3d codeZ" and
 offered an xdcc.  Since I was curious as to exactly how "kewl" his code was,
 I got the dcc offering and took a look.

 The guy had taken the supplement source from my 3D series article #2 and
 ripped it VERBATIM, except he took out all the comments and put his own nick
 at the top.  Needless to say I got right back on IRC and looked for him to
 give him a piece of my mind, only to find that he had /quit while I was
 reading (hopefully after realizing who he dcc'ed to).  I haven't seen him
 since, although I'd love the honor. >|0

 So, once again, if you use my code at all, please give some recognition in
 the end result.  And as a warning, if I find someone ripping my code again
 _and_ claiming it as their own like that guy did, I will cease writing any
 more articles without question and you'll have them to blame, by name. I
 tolerate a lot of things in life, but plagiarism is NOT one of them.

 Now that that's said,

 ----begin COLDEFS.H----

 //************************************************************************
 //**    COLDEFS.H
 //**    Colony Engine Version 0.3
 //**    Definitions Header
 //**    Include for all .H files
 //************************************************************************

 #ifndef _COLDEFS_H_
 #define _COLDEFS_H_

 #define _COLONY_VERSION_ 0.3

 // typedefs
 typedef unsigned char byte;
 typedef unsigned short word;
 typedef unsigned long dword;
 typedef signed char sbyte;
 typedef signed short integer;
 typedef signed long longint;

 #endif

 ----end COLDEFS.H------

 Here's the class header for CVidDevice, CVIDDEVI.H.  I'll explain each
 piece of it next...

 ----begin CVIDDEVI.H----

 #ifndef _C_CVIDDEVICE_H_
 #define _C_CVIDDEVICE_H_

 //**************************************************************************
 //**
 //**    - CVIDDEVICE.H
 //**    Colony Engine Version 0.3
 //**    Header - CVidDevice class module
 //**    LM 1-4-97 Chris Hargrove
 //**
 //**************************************************************************

 //**************************************************************************
 //**    HEADERS
 //**************************************************************************

 #include <coldefs.h>

 //**************************************************************************
 //**    DEFINITIONS
 //**************************************************************************

 #define VID_256 8
 #define VID_64k 16
 #define VID_16M 24

 //**************************************************************************
 //**    EXTERNAL CLASS DECLARATION
 //**************************************************************************

 class CVidControl;

 //**************************************************************************
 //**
 //**    CLASS CVidDevice
 //**
 //**************************************************************************

 class CVidDevice
 {
 private:
     dword xRes;
     dword yRes;
     dword bitDepth;
     char *sysmarker;
     dword type;
     char *devname; // mode title
     char *devinfo; // any other misc text
     void *devdata; // device information, optional

 protected:
     CVidControl *vidImp; // control interface

     void SetDevName(char *ndevname);
     void SetDevInfo(char *ndevinfo);
     void SetDevData(void *ndevdata);

 public:

 // Constructors

     CVidDevice(CVidControl *nVidImp, dword nxRes, dword nyRes,
                dword ntype);
     virtual ~CVidDevice();

 // Operators

 // Functions - Implemented by concrete devices as much as possible

     // general mode operations
     virtual void Activate();
     virtual void Blit(void *src); // fullscreen blit

     // color operations
     virtual void SetPalIndex(dword index, byte r, byte g, byte b);
     virtual void GetPalIndex(dword index, byte &rr, byte &rg, byte &rb);

     // info
     void GetModeInfo(dword &rxRes, dword &ryRes, dword &rbitDepth);
     char *GetDevName();
     char *GetDevInfo();
     void *GetDevData();

 // Friends

 };

 //**************************************************************************
 //**
 //**    END CLASS
 //**
 //**************************************************************************

 #endif

 ----end CVIDDEVI.H------

 Look menacing?  Don't worry, it's simpler than you might think. :)

 The first thing is the standard #include <coldefs.h>, which was listed above.
 Notice the < > instead of " ".... for convenience I added my code's main
 directory as an include directory in my makefiles, so files like coldefs.h
 could be used universally without path information.  You might find something
 like this very handy as well. :)

 The three defines given are just aliases to bit depths, and the external
 "class CVidControl;" is to let the rest of the header (and compiler) know
 that there exists a class data type called CVidControl, so don't be alarmed
 when it's used here in various parameters.  The actual class definition for
 CVidControl will in another one of the .H files, so it'll be resolved when it
 comes time to compile CVIDDEVI.CPP.

 The rest of the file is the class definition itself, and as you can see
 there's a bit of meat in there.  In order to explain it, we'll have to cover
 a few terms such as "public" "private" and "protected", as well as the term
 "virtual" you see a few times up there. :)

 _____The Untouchables

 One of the big things in object oriented programming is being able to hide
 information from other objects.  While you can't completely "hide" the class
 structure itself in C++ due to the classes usually being in headers, you can
 still hide stuff as far as the compiler is concerned.  Within a class,
 "public:" "private:" and "protected:" are used to accomplish this.

 "private:" means anything after it is private to that object alone.  That
 means the members (variables) and/or methods listed can only be accessed or
 called from within the object's methods and nowhere else.  For example, in
 this class, the "dword xRes" member is only accessible by this object's
 members.  As far as every other object is concerned, that member doesn't
 exist; they can't see it.

 "public:" means the exact opposite... the members and methods listed are
 totally public, out in the open, and accessible by everyone and everything.
 Generally a lot of methods will be public, but you'll want to keep public
 members to a minimum.

 "protected:" is sort of a mixture of the two, and it deals with the
 inheritance thing I mentioned earlier in the article.  Protected member
 variables and methods are private to just about everything, _except_ derived
 classes.  Derived classes are the descendents I talked about, and we'll be
 making classes derived from CVidDevice to do "concrete" devices like I
 mentioned.  Any derived classes automatically has access to protected stuff,
 while non-derived classes don't; to them, it's the same as private.

 You'll see up there that we have the device's mode resolution (xRes, yRes,
 and bitDepth), type (at present same as bitDepth but left for expansion) and
 some information extras private to the object.  Any access to these members
 from the outside world has to go through this class's methods, so you control
 what can see or modify them.

 The controlling interface vidImp and functions for setting device info are
 protected, because while the rest of the world shouldn't be able to use them,
 derived (concrete) classes will want them to say what mode they're for, what
 controller they use, etc.

 Finally there are a whole bunch of public methods, which I separate into four
 groups, "constructors", "operators", "functions", and "friends". Operators
 and Friends I'll get to later on in the series; we don't need them for now.
 Functions are just general method functions like you're familiar with.  But I
 think we should take another look at the first group...

 _____What Goes Up Must Come Down

 "Constructors" lists all of the constructors and destructors for the class.
 While these don't necessarily need to be public (there are a couple neat
 things you can do with protected constructors for example), most of them will
 be.  I mentioned constructors and destructors briefly in the last article,
 but now we get to see them put to practical use.

 There's only one constructor listed:

     CVidDevice(CVidControl *nVidImp, dword nxRes, dword nyRes,
                dword ntype);

 Notice that it takes parameters, in this case four of them.  This is a very
 powerful feature of C++ over C; the fact that you can declare an object of a
 class and have it take parameters in the declaration right from the start...
 this way you can initialize the object any way you see fit.  Assuming we had
 a CVidControl called vid_ControlDOS, we could instantiate a CVidDevice called
 "exampleDev" like this:

     CVidDevice exampleDev(&vid_ControlDOS, 320, 200, VID_256);

 And it would instantly call the appropriate constructor matching those
 parameters when exampleDev is declared.  This means that you can have
 functions get called _before_ main() is even called, if you happen to declare
 any objects globally.  Very cool indeed.  Plus, if you happen to have
 multiple constructors with the same number of parameters, then the compiler
 will choose the one that matches the parameters, within limits (you can
 sometimes get "ambiguous" errors where the compiler doesn't know which one to
 pick, so make sure if you do make constructors in this fashion that they're
 fairly explicit).

 Because of the whole construction-upon-declaration system, C++ also
 eliminates the need to declare all variables before any code in a function is
 started.  You can declare a variable anywhere in a function now, and if
 there's a constructor involved, it'll be called then.

 Now one thing we _don't_ have in this class is a "default" constructor,

     CVidDevice();

 The default constructor is the constructor called if you just declare a class
 instance without any variables.  Normally a default constructor is just
 "assumed" to exist if no other constructors are given, and it'll just
 construct the object by filling all the members with zeros or whatever. But
 once you declare any explicit constructors like we did, that assumption
 disappears.  As a result, if you tried this:

     CVidDevice exampleDev;

 you'd get a compiler error saying that there was no constructor for that form
 of declaration.  This is good, because for CVidDevice, and hopefully all
 classes derived from it, we don't want a default.

 Now on to the other half of this process, the destructor.

 A destructor, listed just like a default constructor but with a ~ at the
 front, is automatically called when the object goes out of scope.  For local
 instances, this means when the function ends.  For globals, it's called after
 either main() ends or you call exit() to end the program prematurely.  The
 "virtual" at the front of this destructor is something totally unrelated (and
 not used for all destructors by any means); I'll get to that in a moment.

 Destructors are incredibly handy to tearing down an object that was built up
 throughout the course of the program.  For example, if you allocate memory
 for a member pointer, you can have the destructor automatically deallocate
 it.  If you use a linked list inside, you can make it automatically walk the
 list and deallocate everything.  It's the object's janitor, so to speak. :)

 Now, the only two things left up there that might be confusing for you C
 coders are the term "virtual", and that little referencing operator & used in
 the declarations of a few of those methods.  We'll tackle the & operator
 first, since it's quick to explain.

 _____References Available Upon Request

 C++ is happy to present another wonderful way to pass by reference, thanks to
 the & operator.  Where in C the only way to pass by reference was with a
 pointer using the * operator in the function declarations, C++ allows you to
 use & as well.  & is the same as * except that inside the function, it looks
 like passing by value.  It internally substitutes all the value references
 with pointer references.  For example, look at the following two functions:

     void blah1(int *baygle)
     {
         *baygle = 3;
     }

     void blah2(int &baygle)
     {
         baygle = 3;
     }

 In C++ these two are functionally equivalent; the pointer reference has
 automatically been inserted for baygle in the second function because the &
 operator was used in the formal parameters.  Because of this, calling blah2
 doesn't require putting an address-of & at the front of an int passed in,
 either...

     int temp;
     blah1(&temp);
     blah2(temp);

 Basically this mechanism is very handy but can also be pretty dangerous; once
 you use the & operator in a declaration, it's up to YOU to remember that what
 you're passing in is by reference not value, and modifying the parameters
 WILL alter the actual parameter.  So when debating whether to use * or &,
 choose, but choose wisely. :)

 Okay, now on to the last of the (possibly) unfamiliar stuff...

 _____Don't Look At Me, It Was Him!

 In order to explain virtual functions, we have to go back to the whole
 inheritance thing.  As I said, inheritance allows classes to "descend" from
 other classes, and to take on their functionality automatically, subsequently
 being able to replace any inherited ancestor functions they desire, plus add
 any new ones.  Declaring a derived class is a piece of cake...

     class v320x200 : public CVidDevice
     {
     public:

     // Constructors

         v320x200(CVidControl *nVidImp);

     // Operators

     // Functions

         void Activate();
         void Blit(void *src);

     // Friends

     };

 Just by adding that ": public CVidDevice" in the declaration, we've just
 inherited every public and protected member and method of CVidDevice as our
 own.  If a function ever takes a CVidDevice as a parameter, we can throw in a
 v320x200 instead and the compiler will gladly accept.  Derived classes are
 happily welcomed where their ancestors tread. :)

 A real life example would be animals... if we had an animal class, we could
 derive classes like mammal, amphibian, fish, etc.  From there we derive even
 more classes from those derived classes, to describe different families and
 species.  But while those classes may be derived, they're all still animals
 and should be accepted as such.

 So when we derive a class from an ancestor, all the public stuff from the
 ancestor is passed on to the derived class, and these derived classes can be
 accepted as parameters to functions using their ancestors.

 BUT this introduces a small problem.  If we pass a class as a parameter into
 some function and inside the function we use one of that class's methods, how
 does the compiler know what method is being used?  The only thing it can do
 at compile time is assume that we mean that class's method itself, and not a
 method from a derived class (which might also be passed in) which could have
 overwritten the method.  But that might not be what we want.

 For example, say we have an ancestor class "Spider" with a method called
 "SearchForFood();"  Now many spiders just eat other insects so the method for
 the generic spider class would involve the spider walking around the web and
 searching for anything that it trapped.

 But what about a derived class "BlackWidowSpider" ?  A black widow might also
 eat its husband after mating, so that's another feeding option.  Hence we'd
 replace the SearchForFood method with another method that's more specific to
 the black widow's feeding style.

 Now if we had a function called SpiderThink(Spider &activeSpider), where one
 of the options was to call activeSpider.SearchForFood(), how is the compiler
 gonna know if we're gonna called SpiderThink with a regular spider or a black
 widow?  If it doesn't know what (if any) derived classes are gonna be used
 instead, it can't generate code, so by default it assumes you mean the
 generic spider's SearchForFood method.  That would be bad for the black
 widow, since that would keep her from enjoying probably one of her favorite
 meals.

 Isn't there any way for the compiler to know that sometimes you might wanna
 use a derived class instead, so it'll wait until runtime to determine which
 method to use?

 There is.  Welcome to virtual functions.

 By adding the word "virtual" to the beginning of a function's declaration
 inside a base class, the compiler is told "derived classes should have their
 functions called instead if they replace the base, so wait until runtime to
 resolve any calls for this method".  You might think every method function
 should be virtual due to how natural it is, but honestly there's no reason
 for it a lot of the time... not all classes are intended to have descendents,
 and not all references to a class are intended to use derived ones, so you
 really only need to use it when you think it applies.

 There's also a small overhead issue... since the resolution of the method is
 done at runtime, the compiler will generate sets of function pointers in
 order to know what to choose.  While this is a pretty trivial performance
 cost, it's something you wouldn't want to abuse in a putpixel for example.
 Fortunately you don't have to go much higher up than a putpixel before the
 cost of making a function virtual is effectively meaningless, so there's
 nothing to worry about (I find it funny how many people come telling me how
 horrible virtual functions are... well of course you don't use them inside a
 pixel-by-pixel loop, but you wouldn't use selective function pointers in a
 pixel-by-pixel loop either now would you?  I thought virtual functions would
 be a horrible slowdown at first, but as long as you use them wisely they're
 nothing to be worried about).

 Now in our CVidDevice class, we have five virtual functions; the destructor,
 the Activate function (setting the video mode for fullscreen), the blit, and
 the two palette set/get methods.  Note that you can't make a constructor
 virtual directly (how can you virtualize declaring a variable, when you have
 to know what you're declaring? :)  but every other method, including the
 destructor, is game.

 We certainly want to virtualize the destructor because derived devices might
 add extra stuff to deallocate (dunno why they would want to, but it could
 happen) and since you never know what might be allocating or deallocating a
 device, it's a good idea.  None of my code yet has done anything more than
 declare a prototype instance of each derived (concrete) device, so making the
 destructor non-virtual wouldn't make any difference so far, but I like to
 leave the option open.

 The other four are obviously intended to be virtual... that's the whole point
 of this abstraction layer, being able to call a mode set or blit without
 having to know which specific mode or which blitter to call at compile time.
 We wanna dynamically deal with modes, so we need to dynamically deal with
 what functions need calling.  Simple as that. :)

 (BTW: You can do virtual constructors indirectly by making a virtual method
 designed to create a new instance of the current class and pass back the
 pointer to the caller; it's a design pattern often called a "factory
 method"... you'll probably see them along with many other design patterns
 later on in the series).

 _____Whoa

 Holy cow, I've broken 32k in this article... WAY more than I intended, and I
 still haven't scratched the surface.  We still have yet to spell out
 CVIDDEVI.CPP, as well as the other four primary classes for this video
 system, so we've got another few articles left with this topic before moving
 on, that much is for sure.  We'll finish up with the devices next time, then
 take a look at CVidControl, since the two go hand in hand. :)

 Until then, :)

 Chris Hargrove
 a.k.a. Kiwidog / Terraformer, Hornet alumni
 Technology Programmer, Raven Software
 email: <chargrove@mail.ravensoft.com>

 Disclaimer: These articles are in no way affiliated with Raven Software, and
 represent the views and opinions of the author solely.

 ---------------------------------------------------------------------------->

 :: "Advertisement : X'97 Takeover"
 :: HarleQuiN / SuccesS - arjen@vin.nl

 Nostalgia and SuccesS invite you to X'97 Takeover!
 04-06 April 1997, The Auditorium, Eindhoven.

 That's right, Holland's phattest, dopest, funkiest and fantasticest party
 returns once again! Come on down, and taste the atmosphere, the competitions,
 the live performances and some of the craziest, zaniest weirdos ever to sit
 behind a computer screen!

 For more information, please use the following media...

 x97take@dds.nl
 http://www.hacom.nl/~jal/X97-Takeover

 We really hope you're able to come!

>------------------------------------------------------- General Information --

 _____The Hornet Archive

 Master Site : USA (California)   - (ftp|www).hornet.org/pub/demos
 Mirrors     : Portugal           - ftp.telepac.pt/pub/demos
               Sweden             - ftp.luth.se/pub/msdos/demos
               USA (Wisconsin)    - ftp.uwp.edu/pub/demos
               USA (Pennsylvania) - ftp.co.iup.edu/code (from /demos/code)

 _____DemoNews

 New issues - /incoming/info
 Old issues - /info/demonews
 Supplemental files - /info/dn_other

 How to subscribe:  Mail - listserver@unseen.aztec.co.za
                    Body - subscribe demuan-list FIRST_NAME LAST_NAME   _or_
                    Body - subscribe demuan-list HANDLE

                    DemoNews is sent to your e-mail's "Reply-To" field.

 How to unsubscribe:  Mail - listserver@unseen.aztec.co.za
                      Body - unsubscribe demuan-list

 _____Contact Address

 questions@hornet.org

>------------------------------------------------------------------------------

EODN
