Horizons Interactive Entertainment proudly presents

QB CULT MAGAZINE
Issue #1 - March 2000

Editor: Matthew R.Knight
Email: horizonsqb@hotmail.com

QBCM is available on the following sites:
http://qbversions.cjb.net
http://xybertech.cjb.net
Much thanks to the owners of the above sites for hosting QBCM.

Contents

1. Foreward
2. News
3. Your Letters
4. Ask QBCM
5. Tutorials
  1. Using the Modem in QBasic
  2. Introduction to QBasic, Pt. 1
  3. Understanding the VGA Palette
6. Hacks and Tricks
7. Game Reviews
8. Competitions
9. Classic QBasic Collection
10. Last Words

March 2000
Issue 1 - FOREWORD

Welcome to the very first issue of QB Cult Magazine!!!

A sheet of paper may carry the jottings of an idiot or a sonnet by Shakespeare, but by itself it is nothing. In the same way, a computer, however powerful it may be, is only what the programmer makes it, and therefore the science and art of programming has risen to great importance. Hence this magazine has been created with the intention of broadening the horizons of the Qbasic programming community.

This first issue is slightly skimpy, however it is my hope that future issues will be able to live up to the high standards created by magazines such as Qbasic: The Magazine, QBTimes, Basix Fanzine - all of which have sadly ceased to exist. It is my sincere promise to you, the qb programming community, that this magazine will continue to publish for as long as people are willing to read it. QBCM will not fade into oblivion as did the latter magazines, I can assure you. Every issue of QBCM will include news on whats happening in the qb world, tutorials, tips for power programming, game reviews, and many other exciting features, many of which have never even appeared in the pages of a qbasic magazine before! ^_^

Some of you may be wondering why I called this mag QB Cult. The reason is that for many of us Qbasic has become more than just a language - it has become a way of life. For some of us Qbasic is like our religion, and our bible is the qbasic help files. This magazine is dedicated to these people.

While the first issues of QBCM will be text based, I am intending on moving it over to html some time later this year.

If you have a website and you would like to host QBCM then email me and I'll send you the latest issues every month. Your website will also be advertised here in the mag!

QBCM is YOUR magazine, and it needs YOUR input. If you would like to write an article for the mag, send us news on your latest projects, or just write us a letter, then please email us at: horizonsqb@hotmail.com

Any contribution you can make will be greatly appreciated.

Happy reading!

NEWS

* Magnet Entertainment, one of the hottest upcoming qbasic companies, is busy coding a pixel*pixel scrolling engine, to replace the tile*tile one for their very promising upcoming RPG, Dark Aura. Magnet also recently released the Dark Aura trailer. Check out the Magnet Entertain- ment website at: http://www.geocities.com/magnetent
* Qbasic coding master, DarkDread, is planning on releasing a third and final demo for Distant Promises, which will apparantly have much more polished and optimised code. He is planning on making the game playable on at least a 386-20mhz! There is also some talk of completing his old RPG Lianne in the Dark Crown! That game was of course responsible for the whole RPG craze, which is still very much alive in the qb world today. Visit his website at: http://www.geocities.com/TimesSquare/Ring/1683
* The graphics in Nekrophidius's latest project, Killers, which has thus far all been ripped from other games, is being replaced with his own graphics. For this he is to be commended. Check out Nekrophidius's website at: http://lss.zext.net
* Razor Diskmag, the replacement magazine for Qbasic: The Magazine, seems to have stopped after only one issue. This is very sad news indeed.
* Oh dear, more sad news. Enhanced Creations - the company that brought us Wetspot 1 and 2, DirectQB, and RTE has left the qb scene. Of all the qbasic companies that have ever existed, EC has contributed more to our language than any other. They will be missed.

Okay, well thats all the news we have for this month. Please send us any news you have, on your latest projects or whatever, and we will print it in the next issue! This is a great way to advertise your upcoming games! =)

YOUR LETTERS

Since this is the first issue of QBCM ever, we obviously havent had any letters sent to us yet. Please write to us at horizonsqb@hotmail.com. We will try and print as many of the letters we recieve as possible.

ASK QBCM

Dont you just hate it when you are really stuck on something in qbasic and no matter how hard you try you just cant figure it out? Doesnt it drive you completely nuts? Yep, I thought so, so thats why I included this section in the mag for ya! If you are stuck on something in qb then email us an we'll print the answer to your problem here in this section of the mag!

TUTORIALS

Aaah yes, this section is the very heart of any qbasic magazine. This section needs your input. We need people to write tutorials for us. If you have a tut for us then please email it to me. Any contributions here will be greatly appreciated.

This month we have some very interesting tuts for ya. Hope ya like 'em!

USING THE MODEM IN QBASIC

By Matthew R.Knight

The modem has probably been the most influential computing device that has yet been created. Its creation has resulted in a complete change in the world of business and advertising, has resulted in cheaper and more efficient international communication, and last, but certainly not least, has had a huge impact on both the computer professional and the hobbyist. To most, the modem is a little magic box that opens our computer to the world. In reality, it is very simple to use, and more importantly, to program. The modem takes bytes of data, turns it into a noise, and sends it over the phone line. Theoretically, if you could whistle fast enough and at the right pitches, you could send a file with the sounds you make. Basically, the computer sends a file over the modem like this: the modem sends an ASCII character to tell the other computer it is sending a file. It then breaks up that file into chunks and sends it in chunks of bytes. The modem then waits for an ASCII character from the other computer telling it that all is well, and to send the next chunk.

That is all very interesting, you say, but how do I do it in Qbasic? Well, that is very simple. There are just 4 commands you are going to need to do some modem communications! They are as follows:

OPEN COMOpen up the modem for use by Qbasic.
INPUT$Get data from the modem.
LOCTells you if the modem has any data from an outside source.
PRINT #Send data to the modem.

To start work with the modem, you have to open a "path" to it. This is just like opening a file, except you use the "OPEN COM" statement. Here is a sample:

OPEN "COM2:2400,N,8,1,RB2048,TB2048" FOR RANDOM AS #1

Now, you wonder what that all means, but it really is quite simple, you just must remember this little secret: opened devices (like the modem) act just like opened files! Now back to the example code above. I know it looks confusing at first, but dont worry, the only thing you need to concern your- self with is the number between "COM" and ":" and the number between ":" and ",N". All the other stuff deals with transmition settings and the RB TB things deal with uploading and downloading. The first value is the COM port number that your modem is on. Because Qbasic was made a long time ago, you only have access to ports 1 and 2. If your modem is on another port, dont worry, there is a way around that which involves switching the memory addresses on the COM ports. Dont worry about that now though, I'll go into that in another article some time.

The 2nd number is the Baud. BAUD is the speed of the modem. Qbasic cant access COM ports at any higher speed than 9600, so if you have a 56K modem, Qbasic can still use it, but it wont go any faster than 9600. Dont worry about this too much though, I am busy writing a library that gives you access to the modem at any speed.

To send data to your modem you use the PRINT #n statement, where n is the file number (in the example, 1.) But there is no point sending stuff like "Hello world" to your modem right now, because you are not connected to anything. All you have done with the "OPEN COM" statement, is made a path from your modem to your program so they can talk to each other.

Hmmm, this is quite a problem. So how do we get connected to something then? Well, when you want your modem to talk to an outside source, like a BBS, you have to tell the modem to dial a number. To do this you must know that all modems have a set of commands eched in their read-only-memory chips that allow them to do different things. You cant just say "Hey modem, dial 555-314-545", you gotta talk in the modems lingo! This is alot easier than it sounds. All of these commands begin with "AT". Here are the most used ones:

MODEM LANGUAGETRANSLATION TO ENGLISH
"ATDT###-###-####""Hey modem, dial ###-###-####"
"ATZ""Hang up the phone!"
"ATS0=#""Wait until you someone calls and the phone rings # number of times, then try to connect modems."
"ATM2H1L#""Set your speaker volume at # (1-3)"

So, if you wanted to call someone with the modem, you would first use an OPEN COM statement, to get the path between your modem and your prog set up, then you would use an INPUT statement to get the phone number to dial as a string, then use PRINT #n to talk to the modem. I think now is a pretty good time for an example! Here is a simple phone dialer:

(Replace COM# with the COM port your modem is on.)

CLS
PRINT "Openning a path to your modem..."
OPEN "COM2:2400,N,8,1,RB7048,TB7048" FOR RANDOM AS #1
PRINT "Please enter the phone number you wish to call"
INPUT PhoneNumber$
PRINT "Talking to your modem..."
PRINT #1, "ATDT"; PhoneNumber$
PRINT "There you go, pick up the phone and talk!"
PRINT "Press the ESC key to hang up!"
DO
LOOP UNTIL INKEY$ = CHR$(27)
PRINT #1, "ATZ"

Now that wasnt so hard was it? But here comes the biggest problem of modem control in Qbasic, HOW DO I READ WHAT COMES FROM THE MODEM? Well there is a little function called LOC that does this. The syntax is:

LOC(n) where n is the file number, which if you used my sample, would be 1.

LOC tells you where in a file you are. File? But I am trying to access the modem! As I said before, files and devices work the same way. But with a modem, LOC tells if it has received anything. Fine, now you know if the modem is getting stuff, but how do you know what it is getting? For that you use the INPUT$(x,y) statement. x is the number of bytes to get from a file/device and y is the number of the opened file/device.

x should ALWAYS be 1. I know this means that only 1 character can be read on each pass, but this way EVERY character is read, and none are skipped. If you were getting an 11 byte transmittion, and x was 2, only the first 10 characters would be read (because it is a multiple of 2.) The last part would be skipped. This is the way for NORMAL communications. Keep x as 1!

There is just one more modem command to talk about, namely, the "ATSO=#" command, which you use to wait for a call. But I think it is best explained with an example. Oh, what the heck, lets just put everything we have learned here together into a fully commented communications program. You can use this to call up any BBS and interact with it. Note that it has no uploading or downloading capabilities, though. I will have to cover this, along with some other stuff, in another tutorial some time.

CLS
PRINT "Simple Qbasic communications program."
PRINT "What COM port does your modem use?"
INPUT ">", port$
baud$ = "9600"          '9600 should work fine with most modems. If you have
                        'an older one use 2400.
'Open up that com port.
OPEN "COM" + port$ + ":" + baud$ + ",N,8,1,RB2048,TB2048" FOR RANDOM AS #1
			
PRINT "OPTIONS:"
PRINT "1-Dial up to another computer"
PRINT "2-Wait for a call"
PRINT "3-Quit"
DO
a = VAL(INKEY$)
LOOP UNTIL a >= 1 AND a <= 3    
IF a = 3 THEN CLOSE : SYSTEM
IF a = 2 THEN GOTO wait

PRINT "Number to call?"
INPUT ">", number$
PRINT #1, "ATDT" + number       'Tell the modem to dail the number.
GOTO chat
wait:
PRINT #1, "ATS0=1"              'Tell modem to conect after 1 ring.

'When a modem connects it returns "CONNECT ####"
'The next hunk of code waits until the modem connects before moving on

a$ = ""
DO
IF LOC(1) THEN a$ = a$ + INPUT$(1, 1)   'if anything in modem add it to a$
LOOP UNTIL INSTR(a$, "CONNECT")         'Wait until modem have connected.

chat:
'If you where waiting for a call, alot of ASCII characters will be printed
'on the screen. Dont worry, that just the computers getting in sync and
'talking. You also will not see what you type.

CLS
PRINT "You are now ready to chat, press ESC to quit."
DO
t$ = INKEY$
IF LEN(t$) THEN PRINT #1, t$    'if you typed something send it to the modem
				'this will be send by the modem to the other
				'computer
IF LOC(1) THEN r$ = INPUT$(1, 1)'if the is something to get, get it and save
				'it as r$
IF LEN(r$) THEN PRINT r$;       'if r$ <> "" then print it. the ";" means a
				'line is not started
LOOP UNTIL t$ = CHR$(27)        'keep doing this until ESC is pressed
PRINT #1, "ATZ"                 'tell the modem to hang up
CLOSE                           'close the open com statment

And thats it! Simple huh? Now you have a cool program that you can use to talk with your friends over the modem in Qbasic! Before I leave you to experiment with your newly aquired knowledge, I would like to extend my thanks to the following people who have helped me some way along the line with my programming in general: LordAcidus, Petter Holmberg, Tek, ZKman, and last but not least, Christian Garms. You guys have helped me alot.

Happy hacking everyone!

INTRODUCTION TO QBASIC SERIES, PART 1

By Matthew R.Knight

This article is dedicated solely to those who have never programmed before or know next to nothing about programming in QBasic. Starting here, the QB Cult magazine begins a step-by-step series that explains, from the beginning all you need to know to be able to create your own top quality programs successfully.

Many people find that after a while, the pre packaged programs and games that they've bought for their computer start to become a little boring and they begin to wonder if they can modify them or even write their own. But a computer can do nothing by itself. It must be given a list of instructions telling it in minute detail exactly what to do and how to go about achieving it. These instructions form what is called a program and the art and science of creating them is called programming.

There is nothing difficult about programming. You dont even have to be good at maths, unless of course, you want to write programs to perform mathematical tasks. All you need to begin with is to understand BASIC.

In order to write programs you are going to have to get a version of BASIC. As this magazine is dedicated to QuickBASIC users, you are going to have to download it, if you dont already have it. If you have a WINDOWS 95 CD then go to the directory OLDMSDOS and there you will find two files: QBASIC.EXE and QBASIC.HLP. Copy these files onto your hard drive, and then double click on the application QBASIC. You are now ready to write your first program in BASIC!

Let us begin by writing a small program and seeing what happens. This one will ask you to enter a number. It will then add one to that number and display the result. Type in the following program exactly as it is shown here, and once that has been done, push the F5 key to run the program.

REM Simple addition program
CLS
PRINT "Type in a number and push the ENTER key"
INPUT n
n = n + 1
PRINT "The number that you typed plus 1 is"; n

Let us examine what is actually going on in the above program. The first line of code uses the REM statement. REM stands for REMark. It is used to allow explanatory remarks to be inserted in a program. REM statements are not executed. Once a REM or its abbreviation, an apostrophe (') is encountered, the program ignores everything else until the next line of code.

The second line of code uses the CLS command. This stands for 'CLear Screen' and removes everything currently being displayed on the screen.

Line three uses a very usefull command called PRINT. This command outputs text to the screen. Everything that is in the inverted commas " " will be displayed. For example, if you had to type PRINT "Hello world" and run the program, Hello world would be displayed on the screen.

Line four uses the INPUT command. It allows you to enter something into a program. It is followed by what is called a variable. The variable is the name of the place in the computers memory where the information that you typed will be stored. The enter key must be pushed after the information has been entered, as seen in the simple addition program above. Please note that you may call the variable anything you like.

Line five tells the computer to add one to the variable named n.

The last line of code once again uses the PRINT command, however, in this case it is used far more cleverly. It displays a message and then displays the value of the variable n. This is done by the adding of a ; sign after the last " sign, and then writing the name of the variable whose contents you wish to display.

I will now give you another example. This one is quite simular to the above with the exception that the variables will be used to store letters and words instead of numbers. To achieve this, a dollar sign $ will be added to the end of the name of the variable, for example: W$ In adding a $ sign to the end of the name of the variable, you tell the computer that you wish to store letters/text in the variable instead of numbers. These kinds of variables that store text are called string variables. This program also demonstrates that you can use several letters to form the name of a variable. Type out the following program exactly as shown here, and then run it by pushing the F5 key.

REM This program asks for your name and displays it
CLS
PRINT "Enter your name and then press the ENTER key"
INPUT NAME$
PRINT "Hello"; NAME$; "how are you doing?"

Okay, now you have learned how to work with variables, and how to display the values they contain. However, so far we have only been able to add and subtract values from the numeric variables, what if we want to multiply and divide numbers? Well, lets see if we can answer that question by means of an example. We will also use INPUT in a slightly better way. Type out the following program exactly as it is seen here, and then push the F5 key when done to see how it works.

REM Multiplying and dividing numbers in Qbasic
CLS
INPUT "Enter your first number and then press the ENTER key"; Number1
INPUT "Enter your second number and then press the ENTER key"; Number2
PRINT "Number 1 multiplied by number 2 = "; Number1 * Number2
PRINT "Number 1 divided by number 2 = "; Number1 / Number2

Well, that brings us to the end of part one in the series of this helpfull section for beginners. With what you have learned here you can easily create some nice text adventure games, or even some simple business software. Next month we will be looking at loop structures and graphics.

Happy programming! (is there any other kind?)

UNDERSTANDING THE VGA PALETTE

By Brian Bartels

Palette Basics:

Have you ever noticed while making some graphics for some crappy QBasic game that the default VGA palette is really ugly? Have you ever wondered if you can change those colors. Well, you can. It is a very simple process. The first thing you must understand is that every color that your monitor can display is made up of the three primary colors red, green, and blue, or RGB. To change the RGB values for a given color all you have to do is use this command: PALETTE color, red+(green*256)+(blue*65536) The red, green and blue can range from 0 to 63. The higher the number, the greater the brightness of the color. It's that simple!

Advanced Topics:

Now that you have played around with PALETTE for a while you have probably noticed that it is extremely slow. The QBasic PALETTE statement is slow for two reasons, the first being that it has to do all of that math (red+ green*256+blue*65536) every time you use it, the second being that every time you use it it waits for the screen to refresh, which makes this statement tottaly unusable for fading in, out, or to another palette. How do you get around this problem? Well, you simply write your own PALTTE subroutine that doesn't do all of that math and doesn't wait for the screen to refresh. This can easily be accomplished with four simple OUT commands. Here is the code for an extremely fast palette setting routine:

SUB setpal (col%, r%, g%, b%)
OUT &H3C8, col%
OUT &H3C9, r%
OUT &H3C9, g%
OUT &H3C9, b%
END SUB

Now that you have a palette routine that is really fast you can do cool stuff like fading the entire screen in or out or to another palette. Fading palettes is a lot simpler than is sounds. The first thing you have to do is think of each color as three values red, green, and blue. First lets just discuss how to generate a gradient between two colors. Ok, lets say than color number 26 is bright red, meaning that its red value is 63 (the max value) and its green and blue values are both 0. Lets also say that color 65 is bright blue, meaning that its blue value is 63 and its red and green values are both zero. Ok, what we wan't to do is make all the colors in between 26 and 65 be a gradient of colors 26 and 65. So, first we are going to store the first RGB values (color 26) in three variables, we will call them r1%, g1%, and b1%. We will also store the second RGB values (color 65) in three arrays, we will call them r2%, g2%, and b2%. Then we have to figure out how many steps of the gradient we want which is simply 65-26. Then we must figure out how much to add on to the r, g, and b values for each level of the gradient we will do this with this code:

numofsteps% = 65 - 26
rinc# = (r2% - r1%) / numofsteps%
ginc# = (g2% - g1%) / numofsteps%
binc# = (b2% - b1%) / numofsteps%

Then it is simply a matter of making a FOR loop that adds these increments to the colors in our gradient sequentially like this:

r# = r1%
g# = g1%
b# = b1%
FOR col% = 27 to 64
   r# = r# + rinc#
   g# = g# + ginc#
   b# = b# + binc#
   setpal col%, INT(r#), INT(g#), INT(b#)
NEXT

Now, all of the colors in between 26 and 65 are a gradient. Wow, wasn't that fun?! If you haven't already figured it out, fading in or out a palette, or even fading to another palette is very simple. You basically do the same thing we just discussed except that instead of having one starting value and one ending value and gradients in between you have 256 starting values, 256 ending values, and 256 increment values. You should have an array called startpal which will be dimensioned with thew following line:

DIM startpal(2,255)

You will notice that this array is two dimensional, that is becuase we need to store red, green, and blue values for all 256 colors, this array works like this:

startpal(0, col%) = red value of col%
startpal(1, col%) = green value of col%
startpal(2, col%) = blue value of col%

We will also need three more arrays called endpal, palinc, and pal. These three arrays will be dimensioned exactly the same as with startpal except that endpal will contain the destination RGB values for every color, palinc will contain the RGB increments for every color and pal will be the current palette and will be what we add the increments to each time. The only thing you have to remember when doing this is that when you do the computations for the incrments and when you add on the incremtns you have to do it for every color. To fade in a palette you would simply make all the startpal values equal zero and make endpal be the palette you want to fade in. Fading out a palette is done the same way except backwards. Fading to another palette is done by making startpal equal you current palette and endpal the palette you want to fade to. The number of steps you use will determine how fast the palette fades. Here is the code for fading.

DIM startpal(2,255) AS INTEGER
DIM endpal(2,255) AS INTEGER
DIM pal(2,255) AS DOUBLE
DIM palinc(2,255) AS DOUBLE
steps% = 50

'set startpal and endpal here

FOR col% = 0 TO 255
   FOR j% = 0 TO 2
      palinc(j%, col%) = (endpal(j%, col%) - startpal(j%, col%)) / steps%
   NEXT
NEXT
FOR col% = 0 TO 255
   FOR j% = 0 TO 2
      pal(j%, col%) = startpal(j%, col%)
   NEXT
NEXT
FOR q% = 0 TO steps%
   FOR col% = 0 TO 255
      FOR j% = 0 TO 2
         pal(j%, col%) = pal(j%, col%) + palinc(j%, col%)
      NEXT
   NEXT
   FOR col% = 0 TO 255
         setpal col%, INT(pal(0, col%)), INT(pal(1, col%)), INT(pal(2, col%))
   NEXT
NEXT

That's all there is to it!

Well, thats all the tutorials we have for you this month. Next month we will hopefully have many many more! =) Please remember to send us a tut sometime.

PROGRAMMING HACKS AND TRICKS - TIPS FOR POWER PERFORMANCE

This section is likely to be of much use to many programmers out there as it contains many tips for getting the most out of Qbasic. If you know any tips, hacks, or tricks then please email 'em to us and we'll print them!

Trick 1 - Rebooting the computer

There are many ways to do this, but I have listed here 3 ways which always work. Here ya go:

For a COLD BOOT:

SHELL "ECHO G = FFFF:0000 | DEBUG"      

The above only works if DEBUG.EXE is in a pathed directory.

Here's another method:

The SHELL one is slower than the next method. It also leaves 2 files behind with gibberish names that Debug makes. This next method is a better method to use.

DEF SEG = &HFFFF                      
CALL Absolute(0)

For a WARM BOOT:

DEF SEG = 0
POKE &H473, &H12        'FLAG for WARM BOOT
POKE &H472, &H34        'FLAG for WARM BOOT
DEF SEG = &HFFFF
CALL Absolute(0)

Trick 2 - Auto centering text

Here are two subs which are very usefull in making the text auto center. Cen40 is mainly used in SCREEN mode 1, 7, and 13, but it just depends on the WIDTH setting. Use Cen on 80 WIDTH.

SUB Cen(txt$, row)
LOCATE row, 39 - LEN(txt$) / 2: PRINT txt$
END SUB

SUB Cen40(txt$, row)
LOCATE row, 19 - LEN(txt$) / 2: PRINT txt$
END SUB

Trick 3 - Page flipping in 13h

Heh, this is a tricky one. The easiest way to achieve this is to get a library, such as DirectQB, and let it do the work for you. If you are one of those people who doesnt want to give other people any credit in your games then this tip will be of much help to you:

As you probably already know, everything on your screen at any time when in SCREEN 13 is stored in memory. The place in memory where all the pixels on your screen is stored is 64k big. Right, as you may already have guessed, you could make an array with 64000 elements and treat each one as a pixel. That would give you page flipping in 13h right? Wrong! The problem is qbasic wont allow you to make an array that big. What can we do? Well, remember that an integer takes up 2 bytes, and 1 byte equals 1 pixel. So if you create an array of 32000 integers, its 64000 bytes in size, and you can treat each byte as a pixel! However, to access each byte you are going to need to use PEEK and POKE! Here's some code:

DIM VScreen%(32000)  'Create the virtual screen.
DEF SEG = VARSEG(VScreen%(0))  'Change the seg to the seg of VScreen.
POKE (VARPTR(VScreen%(0)) + (y% * 320) + x%), col%  'PSET to it.
col% = PEEK(VARPTR(VScreen(0)) + (y% * 320) + x%)  'POINT from it.

It is not wise to use too many virtual screens as they take up too much memory.

Okay, so now you know how to make a virtual screen in memory and you know how to PSET to it and POINT from it. But how do you make whats on the virtual screen flip over to the real screen? Well, for this we are going to have to use some assembly. Noooooooooo you say? Yes! ASM is great for this sort of thing, and very fast! The following example program includes an asm page flipping routine, and a demonstration of how to use it:

'Example program demonstating page flipping in SCREEN 13. Written by
'Matthew R.Knight of Horizons Interactive Entertainment. Feel free to use
'this code as you wish.
DIM VS1%(32000)  'Create the 1st virtual screen.
DIM VS2%(32000)  'Create the 2nd virtual screen.

'ASM Screen page copying routine.
PageCopy$ = ""
PageCopy$ = PageCopy$ + CHR$(&H1E)                          ' PUSH DS
PageCopy$ = PageCopy$ + CHR$(&H55)                          ' PUSH BP
PageCopy$ = PageCopy$ + CHR$(&H89) + CHR$(&HE5)             ' MOV BP,SP
PageCopy$ = PageCopy$ + CHR$(&H8B) + CHR$(&H46) + CHR$(&HE) ' MOV AX,[BP+0E]
PageCopy$ = PageCopy$ + CHR$(&H8E) + CHR$(&HD8)             ' MOV DS,AX
PageCopy$ = PageCopy$ + CHR$(&H8B) + CHR$(&H76) + CHR$(&HC) ' MOV SI,[BP+0C]
PageCopy$ = PageCopy$ + CHR$(&H8B) + CHR$(&H46) + CHR$(&HA) ' MOV AX,[BP+0A]
PageCopy$ = PageCopy$ + CHR$(&H8E) + CHR$(&HC0)             ' MOV ES,AX
PageCopy$ = PageCopy$ + CHR$(&H8B) + CHR$(&H7E) + CHR$(&H8) ' MOV DI,[BP+08]
PageCopy$ = PageCopy$ + CHR$(&HB9) + CHR$(&H0) + CHR$(&H7D) ' MOV CX,7D00
PageCopy$ = PageCopy$ + CHR$(&HF3)                          ' REPZ
PageCopy$ = PageCopy$ + CHR$(&HA5)                          ' MOVSW
PageCopy$ = PageCopy$ + CHR$(&H5D)                          ' POP BP
PageCopy$ = PageCopy$ + CHR$(&H1F)                          ' POP DS
PageCopy$ = PageCopy$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0)  ' RETF 0008

'Fill VS1%
FOR N = 0 TO 32000
VS1%(N) = N
NEXT

CLS
PRINT "VS1% Press any key..."
SLEEP
FOR N = 0 TO 32000
PRINT VS1%(N);
NEXT
PRINT
PRINT "Press any key..."
SLEEP

CLS
PRINT "VS2% Press any key..."
SLEEP
FOR N = 0 TO 32000
PRINT VS2%(N);
NEXT
PRINT
PRINT "Press any key..."
SLEEP

CLS
PRINT "Now we are going to move the contents of VS1% into VS2% via and ASM"
PRINT "routine. This involves copying all the memory allocated to VS1% to"
PRINT "VS2%. This same routine and principle could be used for page flipping"
PRINT "in SCREEN 13!!! as it copies chunks of 64K of memory!!!!  =)"
PRINT
PRINT "Press any key..."
SLEEP

FromSeg% = VARSEG(VS1%(1))
FromOff% = VARPTR(VS1%(1))
ToSeg% = VARSEG(VS2%(1))  'If you wanted to copy an array straight to the 
                          'screen then this would be = &HA000
ToOff% = VARPTR(VS2%(1))  'and this would be = 0

DEF SEG = VARSEG(PageCopy$)
CALL ABSOLUTE(BYVAL FromSeg%, BYVAL FromOff%, BYVAL ToSeg%, BYVAL ToOff%, SADD(PageCopy$))
DEF SEG

CLS
PRINT "Copying complete....Lets now see VS2% Press any key..."
SLEEP
FOR N = 0 TO 32000
PRINT VS2%(N);
NEXT

'additional testing:
PRINT
COLOR 2: PRINT "Just some additional tests:"
COLOR 4
PRINT "VS1%(0)"; VS1%(0)
PRINT "VS1%(287)"; VS1%(287)
PRINT "VS1%(288)"; VS1%(288)
PRINT "VS1%(32000)"; VS1%(32000)
COLOR 5
PRINT "VS2%(0)"; VS2%(0)
PRINT "VS2%(287)"; VS2%(287)
PRINT "VS2%(288)"; VS2%(288)
PRINT "VS2%(32000)"; VS2%(32000)
PRINT
PRINT "Press any key..."
SLEEP

CLS
COLOR 9
PRINT "So this works! Is this cool or what? Page flipping in 13h!  =)"

All you have to do to when using the above asm routine to copy a virtual screen to the actual screen is make ToSeg% = &HA000 and make ToOff% = 0. The example program above using the routine clearly shows how to copy one virtual screen to another.

Well, thats all there is to it. Now you know how to do page flipping in SCREEN 13!

Thats all the tips, hacks and tricks we have for this month. You can be sure that next month we will have twice as many for ya! ^_^

Once again, if you have any tips, hacks or tricks for us then please email them to us at horizonsqb@hotmail.com and we will print them.

GAME REVIEWS

In this section we will be reviewing qbasic games. If you have a qbasic game then email us at horizonsqb@hotmail.com and tell us where we can get the game from and we will review it here in the mag! Please DO NOT email us the game.

COMPETITIONS

There are two competitions that we will be holding every month. They are as follows:
(1) Mini Game of the Month: this is a competition for the best qb game under 20KB. The winners game will be included with the mag each month!
This month the winner is Andreas Collvin for his little basketball game angle.bas. The game has been included with this months issue of the mag! Check it out!
(2) Graphic demo of the month: this competition is for the best graphic demo program under 20KB. The winners demo will be included with the mag each month!
This month the winner is Danny Beardsley for his awesome bump animation demo. Seriously guys, this demo is spectacular, and best of all, it has been included with this months issue of the mag! Check it out! The file is demo.bas. We recommend that you compile it - it then runs 15 times faster!

If you would like to enter either of the above monthly competitions then email me and tell me where I can get the game from or you can just email it to me. Just remember that the game or demo must be no bigger than 20KB.

CLASSIC QBASIC COLLECTION

This is a section which I think will be very interesting to many of you. The section is basically about the old days of qbasic, when there was no internet and we all had to upload and download qbasic stuff from BBS's! Every month we will take a look at a time in Qbasic's history when something big was happening, and then we'll compare it to today.

This month's topic in the classic qb collection is Raytracers. I thought this would be an interesting one since they are 'the' thing in qbland today. Most of us know all about Enhanced Creations's Project RT - a raytracer almost as good as Doom. There are also countless other raytracers being made as we speak. But where did it all start?

It all began with Peter Cooper and his raytracer many many years ago - 1995 I think. It was a tiny program, very slow, very blocky, and it had no hit detection on the walls. It was Pathetic, but it was the first raytracer that the qb world had ever seen so everyone was amazed by it. This old program has been included with this month's issue of QBCM! The file is ray1.bas.

Soon after the release of Peter's raytracer the first modification of it came along by Victor Woeltjen. It was extremely slow, but it did add some simple textures and a backdrop. It has also been included with this issue of QBCM - the file is txtreng.bas.

Victor obviously made no attempt to speed the engine up, and everyone noticed this, so they all did what they could to speed it up. Once they had done that, they changed some more stuff, added some stuff, changed some stuff, added....er, you get the picture! and then they all uploaded their modified versions of Victors program. In turn, these programs were edited, which in turn......er, here I go again! =) Soon the internet was just bombarded with tons of raytracers! Many of those old raytracers can still be found on the web today. Just look around and you'll find lots of them.

Anyway, years have passed since those days. Many of the really cool raytracers around today are actually modifications of programs that were modifications of Peter Coopers engine that started it all!

Well, thats it for this article. I hope you found it interesting. Now everytime you see a fantastic new qbasic raytracer come along, just think back to the days where it all began!

LAST WORDS

Well, thats it for this issue - the first issue ever of QBCM! I hope you liked it! Next month's issue will hopefull be twice as good as this! ^_^

Once again, please email us any tutorials, news, tips, letters and we will be sure to print them in the next issue of QBCM. I am only able to check my email once every two weeks so dont expect a reply right away though.

Thanks for reading!

Cya!