REM 'Letter from the Editor
Welcome to Issue 4 of Qbasic: The Magazine
ON KEY 'Hot List
News from the QB world
INPUT 'Your Stuff
Survey results plus yer letters!
! mov //Asm Intro
Petter Holmberg presents the start of a new asm series
OPEN 'Welcome to QBASIC!
New to QB? Your PRINT and LINE is right 'ere!
REM 'Lib or not to Lib
Should you use progs like dqb or Dash?
PRINT 'Too Much qb
Seav tells us "You know you've had TOO much qb when...
PRINT 'Memory Limits
What are qb's memory limits? How can you get around them?
END 'Next Issue
What's up in our next issue?

By ZKman

Hello, and welcome to the biggest Qbasic magazine EVER! This month, there has been a LOT of news...check out the Hot List and you'll see what I mean. From the passing of Milo to the announcement of a Mario World clone, there's a lot to feast your eyes on this time around.

But what do have in the way of features? TONS! 19day enthusiastically endorses DirectQB1.1 in his review; what can you say about an ASM lib that natively uses EMS? NetherGoth brings us another article for beginners with GET...PUT; everything from masks to BSAVE can be found in this article. Pete presents us with an article about the RPG glut; why do so many QB rpg's look the same?...but are still gobbled up by the handful. Aaron Severn's wonderfully extensive SVGA tutuorial comes to an end this issue with Part III. Here you'll find some ASM samples for SVGA as well as a program that shows you how to do SVGA. Hal_8900 tells us about the biggest battle in QB today...QB4.5 vs C++. Here's what's good and bad with both, and how C++ stacks up against our beloved QB. Finally, I review the BIGGEST release this month for QB, and probably the biggest since Wetspot 2....SFB2 by Lbt1st. Find out why this game is mucho cool.

In other news, I'd like to wonder why people put down RPG's so much. As soon as some people hear about an RPG, they immediately thrash it... just because it's an RPG doesn't mean it's a copy...have an open mind!

Keep Codin'

zkman

Back to top

Compiled by ZKman

09.24.98 1:00AM: Milo has passed away

   Last month,  Qbasic: the magazine  reported that Milo 
   (aka Gradius) had fallen into a coma and had been given only 
   2 days to live. Although the entire QB community prayed for
   his recovery, Milo passed away on September 24, 1998 at
   1:00 AM. 
   
   "Milo Seldacek's memorial Guestbook" has been set up at
   Neozones. Be sure to visit and check out what
   others have said about Milo and his contributions to Qbasic.
   Milo will be remembered most for the way he helped anyone
   who needed it and also for 2 of his games: Monospace Shooter,
   a 2 color, super fun, superbly animated, space shooter with a
   deadly AI and NitroFire EX, one of the First hi-color racers in
   QB and still considered one of the best in that genre.

Microsoft cracks down on Qb piracy

   According to a recent leader from the manager of the QB top 50,
   The Interactive Digital Software Association (IDSA) is working
   with Microsoft to shut down and possibly seek legal action 
   against web pages that offer a free download of Qbasic 4.5,
   PDS7.1 or Visual Basic on the grounds of piracy.  The Qbt50
   urged sites to remove qb4.5 from their site so they aren't 
   shut down. Many members of the QB community continue their
   fight to make QB4.5 free, however, and, although it is tougher
   now, you can still find qb4.5 on some smaller sites if you've
   lost your "one and only copy (wink)".

No more QB? Enhanced Creations new hobby

   Based on reports from the Enhanced Creations website, it is
   rumoured that Enhanced, creators of Wetspot, Wetspot 2, and
   DirectQB will be lowering their QB output in favor of coding
   with DJCPP, a C compiler. It is presumed that this will not
   affect future versions of DirectQB. Based on the site, it 
   seems that Petter Holmberg is the one more interested in
   this new platform and Angelo Mottola has many more Qb products
   lined up.

Tsugumo's The Game: CANCELLED!

   The Game, whose demo released last year by Tsugumo was
   hailed as one of the greatest graphical achievements in Qb
   of all time, has been Cancelled.  The demo was basically
   just a showoff of the graphics engine and Tsu apparently
   thought that the gameplay just wasn't original enough to
   continue.
   
   Other than Darkdread's "lianne and the dark crown", no qb
   game has been more influential that "the Game". It's graphic
   style has been used in many upcoming RPG's, such as Eldim,
   Marconian Dreams and Relics, and it's cancellation is sad
   news for all those awaiting the ambitious full version.

Pb3d: Qbasic's new dimension

   Marko Dokic's latest release of his 3d engine must be seen.
   This engine does some stuff in 3d that has never been done
   before, like Bilinear Filtering, Phong Shading, and
   Environment Maps. The package comes with many 3d objects to
   feast your eyes on and can be had from quixoft

Analogue: Leaving QB forever?

   Analogue (aka Apester) posted a webboard message recently that,
   in effect, the QB scene is not fun for him anymore, and he was
   done with it.  According to the post, at least for now, the
   next version of the great ApeDraw tile editor and his RPG,
   Marconian Dreams, have been indefinitely put on hold. We hope
   that Analogue changes his mind and comes back to the best
   coding community in the world!

SFB2: Lbt1st releases his super cool fighter

   SFB2, the wireframe fighter built using Lbt1st's Slash engine,
   (see the full review), was released on the 4th of
   October to much acclaim. Hailed as the greatest fighter of
   all time by many (replacing the aging Sphere Fighter), Lbt1st
   sets a new benchmark for Qb games and offers many interesting
   gameplay ideas like the awareness bar, and also features a 
   super-cool particle engine. Check it out!

Minigames: The next big thing?

   An insane number of Minigames have been released this past
   month, leading many to wonder whether mini games are the wave
   of the future. These games, usually made in a weekend, have
   offered such topics as Bus-driving and pizza delivery.  Qbasic:
   the Magazine doesn't think that minigames will ever 
   totally supplant the current crop of big projects, but some
   of them look to be very interesting.

Neo's Qboard: Should it be members only?

 
   Due to the increasing amount of flaming and pornography posts
   on Neozones' Qboard, many are suggesting that he implement
   a "members only" setup. Basically, you would have to sign in
   before you posted and if you posted porn or something like that,
   it would be easier to track and keep you from coming back to
   the board.  Neo has already started tracking IP addresses, so
   a members only board seems a logical next step.

Latest Game updates:

   Quite a bit this month in the way of announcements...
   
   Super Mario World clone:  Danny Gump of VirtuaSoft (DashX,
   The Mystical Journey) has announced that he will be develop-
   ing a Super Mario World clone for QB!  The demo shown on 
   his site shows the game to use the exact music and graphics
   as SMW for the Super NES, but the animation is a bit choppy
   at this point. Other than that, the game looks INCREDIBLE!
   SMW clone uses the Dash set of libraries to do the double
   layering that Shigeru Miyamoto's classic is known for. We
   look forward to it! Go check out the demo now at Danny's
   site,VirtuaSoft.

   Slash Development Kit:  Lbt1st (SFB2) has announced that he
   will be releasing a Slash Developers Kit sometime in the next
   few months. Slash is the wireframe and particle engine that is
   used in SFB2 and animates objects VERY smoothly, so this could
   usher in a new wave of wireframe games. What kind of tutorials
   will be included in SDK is not known, but if you're starting a
   3d product, be sure and check this one out. 

   Yousuf Philips is in the process of creating some stuff we've 
   never seen in terms of graphic loading for QB.  You can see
   early versions of OPENPCX, OPENBMP, and OPENAVI, which is the
   first avi opener in QB!  Right now, the bmp opener only does
   8 bit and the avi player only does 24-bit in black and white,
   but Qbasic: The Magazine has learnt that a 24-bit fast-
   loading, perfect bmp opener has already been completed and that
   a 24-bit color .avi opener is nearly finished! Be sure and check 
   them out.

   Late Breaking game announcements...Marcade is developing a
   C+C type game called Low Radiation. Not much about it is known,
   but strat games are severely underrepresented in QB now, and
   this game should help alleviate the problem...QMIDI 4.0 has
   been released by Jesse Dorland! More on this next issue...
   A new RPG announcement that looks like it might have potential
   is "Beyond Destiny". More on this later...
   

Oops!

   Okay, we admit, there were a couple...umm...mistakes in last 
   issue.  First, the address for alternate logic was printed 
   wrong. Be sure and check out their wonderful stack of tutorials
   at this address. Also, we mentioned that Zapbatz'
   upcoming "colony" was a Space Combat sim: it is in fact a 
   futuristic SimCity like game. Sorry!

That's all the latest news for this month. Remember, if you have any news or rumours, send them along to Qbasic: The Magazine

Back to Top

By ZKman

Here's what you had to say about last month. Be sure and send us more letters soon!

I visited your page and noticed you have an area for upcoming stuff. Could you put WoodLands on there? Thanks. Really good page, by the way.

Pyrus

Pyrus is referring to the "Visionaries Exchange". This is a 
collection of all the QB dev houses and their current pro-
jects. We want all to join! Find out what to send us by going
to the submit page.

Hello, Grand Scimitar Studios,

I just want to tell you how good Qbasic Magazine is. I decided to write an article for the October issue. You don't have to put it in, I would understand. I like to write, and I like QBASIC, so here you go: (enclosed article: Why the QBASIC RPG craze won't die - editor)

Pete

As you can see, Pete's article is included in this issue. If
you can write or just want to get somethin' off you mind, send
it in to Qbasic: The Magazine. We'll publish most articles
we recieve.

qbasic: the magazine reserves the right to edit any letter recieved for purposes of clarity and space. But you already knew that.

Here's the results of the first survey from Qbasic: The Magazine!

    Favourite Game  |  Favourite utility  | Looking forward to
    1. Wetspot 2       1. DirectQB          1. Pasco Soccer (t)
    2. Dark Ages       2. DashX             1. Dark Ages 2 (t)
    3. Star Wrek (t)   3. PP 256 (t)        1. Wanderlust (t)
    3. M. Shooter (t)  3. Qmidi (t)         1. Vampira (t)
    3. Wrath of S. (t) 3. QBsvga (t)        1. SVGA dash (t)
    3. Sfb2 (t)                             1. Space-a-roo 2 (t)
                                            1. Woodlands (t)

Help us break the tie! Vote today by emailing your votes for:
favourite game
favourite utility
Game/utility that you're most looking forward to.
Send your vote here

Welcome to our new section: Must Downloads. Everyone knows that there are a god-awful amount of qb games out there, but what's worth downloading? These, my friend. Here, you'll find a list of the best of the best in QB progs. See something that should be here? Tell us and we'll check it out. You HAVE to have this stuff!

Dark Ages
One of the most engaging QB games ever, as well as one of the only complete rpg's. This was featured in PC Gamer! Check it out!

Groov Buggies
The best QB racer ever. Although it has some control problems and some clipping glitches, this wireframer set a new standard.

Lianne...in the Dark Crown
Darkdread best and most complete game. Many hours of gameplay, and featuring a battle system that's been imitated in countless qb projects since. Not to mention you get cat food from the enemies!

Monospace Shooter
Gradius' 2 color side-scrolling space shooter. Featuring very detailed enemies, flickerless animation and a devious AI, this game is a classic

Wetspot & Wetspot 2
Wetspot, the bubble-bobble like block-pushing action game was one of the best QB games when it came out, but W2 is just incredible. Super midi sound, great fast graphics, tons of variety, an insane number of levels...everything you could want. GET this game. Now.

SFB2
One of only 2 fighters in QB (the other being Sphere Fighter) this newly released game is Super-fab. Even though it's wireframe, it has cool particles and smooth animation as well as rippin' gameplay.

PP256
Called the best tile editor in QB ever, PP256 has loads of tile-editing options at your disposal. If you use tiles in your game, you can't live without this.

DirectQB/DashX/Blast!
These 3 sets of libraries take QB graphics to the extreme. They all have strenghts and weaknesses, but you should check them all out before you start a big project. You'll save a lot of coding plus get a big speed increase (and in DQB's case, save memory). Try these now.

QMIDI2.0
This is the best version of Qmidi. Play .mid's in your game! And version 2.0 only has a footprint of a few KB's, so this is super cool.

Pb3d
Marko Dokic's 3d routines. Phong shading, gourard shading, environment mapping, you name it- it's here. If you want to see how to do good 3d, come here!

Neozones

For everything you can say about the site being updated about once a millenium and how the webboard has had lots of problems (you need only look on the Hot List every month to find out what they are), you can't deny what a great resource Neo's site is. The QCity collection of programs is very extensive (although it is missing some of the newer stuff). The Ask Tek section has answers to near every question that newbies ask...if you're stuck on something, be sure and check ask tek first. And the webboard...this thing is alive! Tons of posts (more than any other Qb board that I know of) and most people there are willing to help you with any problem you need. Qbasic: The Magazine is proud to present Neozones with the very first "Site of The Month" award. Check it out.

Back to Top

By NetherGoth

(Editor's Note: This article uses techniques for SCREEN 13. They may not work in other screen modes)

The following is what I have found out through trial and error (as well as a bit of logical guesswork). While I have found it to work on every machine I have tried it with, do not assume it is so for your machine. Instead, pro- ceed with caution. While none of this should cause major problems (ie. I do not believe it will trash your machine or anything), a wrong step could cause your machine to lock up, forcing you to reboot. Anyway, this is intended for informational purposes only. I cannot be held responsible for the use/abuse of the information contained herein, nor can I be held responsible for any damage done to the person or the machine on which the examples contained in this document are run upon. Just the standard disclaimer to CMA!

If you find this information useful, and choose to include the techniques in your own code, please be kind and mention my name. You don't have to do this (hell, if I mentioned everyone's name I have learned from, that list would be a mile long!), but it would be nice.

I wish to thank Jason Grooms - for guiding my first steps into the wonderful world of assembler (back then, 6809), and to Brent Dill, for showing me how to do strange and crazy stuff with GET/PUT, and a host of other tips. Brent, if your read this, contact me. I'm on the 'Net. I know you are worth your salt to find me. L8r!

Calculating the buffer size for GET/PUT in mode 13:

1. Take the width of the area you are getting (in pixels) and multiply it by the height (in lines). This will give you the total number of bytes in the area for the buffer.

2. Find the total number of WORDs to use by dividing the number of bytes by two. We need the total number of WORDs because the smallest variable type we can use is an integer, which is WORD size (2 bytes).

3. We now have the amount of space needed to store the area we want to GET. But BASIC needs a couple of more pieces of information in order for GET and PUT to operate correctly. These two pieces of information are the width and the height of the image! It needs these two items in order for the PUT routine to know when to stop drawing. So, the width and the height of the image area must be stored with the image data itself. These two values are placed into their own WORDs at the start of the buffer. We must add on two WORDs to accomodate this.

4. We now have the total number of WORDs needed to DIMension an integer array to hold our image data. Because the base of the array starts at zero, we will subtract one from our total number of WORDs to DIMension our array:

	DIM buffer%(# of WORDs)

5. Our buffer data layout looks like so:

	WORD	DESCRIPTION
	----	--------------------------------------------------
	   0	Width, contained in the high byte of the WORD.
		This value is in bits (!), and so must be divided
		by 8 to find out the number of pixels (bytes).
	   1    Height, contained in the high byte of the WORD.
		Value in number of lines.
	   2	Start of data...
	   .
	   .
	   .
	  XX	End of data...

Example:

1. We have a 16x16 sprite. So we need 256 bytes in order to hold an area this big.

2. We need the number of WORDs, so we divide by 2, giving us 128 WORDs.

3. We add two words to accomodate the width and height values needed by PUT, giving us a total of 130 WORDs.

4. We subtract 1, and dimension our array:

	DIM buffer%(129)

5. Our buffer data layout looks like so:

	WORD	DESCRIPTION
	----	--------------------------------------------------
	   0	Width, contained in the high byte of the WORD.
		This value is in bits (!), and so must be divided
		by 8 to find out the number of pixels (bytes).
	   1    Height, contained in the high byte of the WORD.
		Value in number of lines.
	   2	Start of data...
	   .
	   .
	   .
	 129	End of data...

Multiple Image Buffers for GET/PUT:

What was shown above was an example for a simple buffer to hold a single image to be used in GET/PUT. Using the above simple example, we would just do the following

		GET(0,0)-(15,15),buffer%
		PUT(100,100),buffer%,PSET

in order to GET/PUT a single simple image. But what if we needed 30 sprites (say for a game)? We could do this

		DIM buffer1%(129), buffer2%(129),...,buffer30%(129)

then use GET/PUT to move everything around, but this is wasteful, and not very easy to work with. What if we wanted animation? What then?

Fortunately, there is an easy way out, using what is called offsetting. We have a buffer of a set size we are GETing and PUTing with. What isn't being shown is what is called the offset. An offset is a number added to a fixed value to obtain a new start value. When we dimension an array, the start of that array is obtained and kept by BASIC (we can use VARSEG and VARPTR to find it if we wanted to). If we say DIM a%(20), then say a%(2)=15, we have used an offset of 2 from the start of the array and placed 15 at that pos- ition in memory. A similar thing is done by GET/PUT. Note the following:

		DIM buffer%(129)
		GET(0,0)-(15,15),buffer%

is the same as:

		DIM buffer%(129)
		GET(0,0)-(15,15),buffer%(0)

We just didn't use the offset of zero in the first example! What would happen if we did the following?:

		DIM buffer%(129)
		GET(0,0)-(15,15),buffer%(10)

We would get an error. This is because we need 130 WORDs of space for the area we are trying to GET, and we only have a total of 130 WORDs to play with. By trying to put an offset of 10 into the mix, we overrun the end of the array by 10 WORDs! The following would work:

		DIM buffer%(139)
		GET(0,0)-(15,15),buffer%(10)

Now WORD number 10 would hold our width and WORD number 11 our height, and 12 through 139 would hold our data. We could then PUT(100,100),buffer%(10),PSET and everything would work fine. Now what would happen if we PUT(100,100), buffer%(0),PSET? We would either get an error or garbage, because PUT wouldn't have the correct width and height info in the first two WORDs! So, we need to keep track of the size so we know what offsets we can use when GETing and PUTing our images.

Our example is a 16x16 sprite. We would like to have 30 of these for our ultra cool game we are writing. We need 130 WORDs for each of these sprites (2 for width/height, 128 for data), and we want 30 sprites, so we need a buffer that is 3900 WORDs long (130 WORDs x 30 sprites). We know that every 130 WORDs is a new sprite, so that will be our offset. If we set our offset to 0, then we are on the first sprite, 130 is the second, 260 is the third, and so on. The following shows how:

		DIM sprite%(3899)
		spritenum%=2
		GET(0,0)-(15,15),sprite%(spritenum%*130)
		spritenum%=5
		PUT(100,100),sprite%(spritenum%*130),PSET

Before you can put a sprite, you obviously need to GET it, so that PUT has the width/height info to work with. So lines 4 and 5 wouldn't work in our example unless we changed line 2 to "spritenum%=5".

We now have an easy way to GET/PUT a whole mess of sprites on the screen using a single buffer that is easily accessible. We could do simple animation with this system. Say our first five sprites were already in the buffer and they were an animation of some type. To flip through them, we would do the following:

		FOR spritenum%=0 TO 4
		  PUT(100,100),sprite%(spritenum%*130),PSET
		NEXT spritenum%

It is that easy.

Our buffer layout now looks like this, for those interested:

	WORD	DESCRIPTION
	----	--------------------------------------------------
	   0	Width, contained in the high byte of the WORD.
		This value is in bits (!), and so must be divided
		by 8 to find out the number of pixels (bytes).
	   1    Height, contained in the high byte of the WORD.
		Value in number of lines.
	   2	Start of sprite0 data...
	   .
	   .
	   .
	 129	End of sprite0 data...

	 130	Width, contained in the high byte of the WORD.
		This value is in bits (!), and so must be divided
		by 8 to find out the number of pixels (bytes).
	 131    Height, contained in the high byte of the WORD.
		Value in number of lines.
	 132	Start of sprite1 data...
	   .
	   .
	   .
	 259	End of sprite1 data...

	 260	Width, contained in the high byte of the WORD.
		This value is in bits (!), and so must be divided
		by 8 to find out the number of pixels (bytes).
	 261    Height, contained in the high byte of the WORD.
		Value in number of lines.
	 262	Start of sprite2 data...
	   .
	   .
	   .
	 389	End of sprite2 data...

And so on...

The only other thing you need to keep in mind is buffer size versus sprite size. As noted before, a 16x16 sprite needs 130 WORDs in order to store it completely in an array. When you have multiple sprites in an array, there is a limit to the size of your array you can have. This limit is 64K - 65536 bytes, or 32768 WORDs. To find out how many sprites you can store in a single array, divide 32768 by the number of WORDs required for each sprite. Drop any values after the decimal (that is, take the integer, drop the remainder), and this is the maximum number of sprites you can store. For our example of a 16x16 sprite (130 WORDs), this works out to be 252 sprites. Take that number and multiple by the number of WORDs per sprite, subtracting 1, to use for DIMensioning the array: DIM buffer%(32759).

The following table breaks down common sprite sizes and array dimensions:

	Sprite Size  Number  Array Size (in WORDs)
	-----------  ------  ---------------------------------
	   8 x 8       963   34 for sprite, 32741 for array
	  16 x 16      252   130 for sprite, 32759 for array
	  32 x 32       63   514 for sprite, 32381 for array
	  64 x 64       15   2050 for sprite, 30749 for array

If you need more sprites, you can split them over two arrays. Animation and such becomes more difficult to handle, but it can be done.

Also remember, the larger the sprite, the more data the computer has to shove around. Stay away from the 64 x 64 sprites, except for maybe big bosses or such. These things are memory HOGS. The only other limit to be aware of is QBASIC's 160K limit on program AND code size. One buffer of sprites (252 sprites) will eat almost 64K, leaving you with less than 100K to put the rest of your code in! QuickBASIC and PowerBASIC users shouldn't have any problem though. Some of these problems may be overcome by using EMS routines to shove the sprite data into extended memory, though.

GETing and PUTing without The BOX:

If you have ever used GET and PUT, you know that when you PUT, a "box" is left around your image obliterating anything under and around your sprite. This looks very ugly and unprofessional in a game. The following shows the best way to get rid of this problem, using a method called sprite masking.

1. First, for each and every sprite you create, create a "mask" for it. This mask is the same size and shape as the original sprite, only it consists of only two colors, 0 and 255 (or &H0 and &HFF for you hex folks). Color all visible portions of the sprite (those portions you want to obscure the background) with color 0. Color all invisible portions of the sprite (those protions you want the background to show through) with color 255. Remember, you need one mask for each sprite, and this will knock your sprite count down by half, so keep it in mind when designing your game.

2. To display your sprite, simply PUT the mask image down using the AND op- erator, then place the sprite image down using the OR operator. The AND and OR operators are called bitwise boolean operators, and have the following truth tables:

	        AND			OR
	-------------------	-------------------
	IN1	IN2	OUT	IN1	IN2	OUT
	-------------------	-------------------
	0	0	0	0	0	0
	1	0	0	1	0	1
	0	1	0	0	1	1
	1	1	1	1	1	1

These tables basically mean the following. If you take two bits and AND or OR them together, the result equals a 1 or a 0 depending on the inputs and the relationship between them in the truth tables for the operator in question. If you understand this - read on. If you understand this and are 10 - 14 years old, you don't need college (just kidding ;).

Now, for what we are doing, we have a background of different byte values (which consist of a series of bits). Our mask only has two values in it, the byte 0 (00000000 in binary) and the byte 255 (11111111 in binary). Let me show you how the magic works:

   A.	Our Background Image	AND	Mask	=	Result

	11110110		      11111111		11110110
	11110110		      11000011		11000010
	11110110		      11000011		11000010
	11110110		      11000011		11000010
	11110110		      11111111		11110110

  B.	Our Result	       OR      Sprite	=	Result

	11110110		      00000000		11110110
	11000010		      00111100		11222210
	11000010		      00111100		11222210
	11000010		      00111100		11222210
	11110110		      00000000		11110110

If you notice, I have used 2s in place of 1s on the final result to show the example better. Those 2s should really be 1s, so don't let that throw you. Suffice to say, if you look carefully, we have placed our 8 x 5 sprite on the background, without the border showing.

GETing and PUTing without The BOX, method 2:

The next best way to GET and PUT without the box showing, is to simply not draw those pixels in the first place. The only way to do that (short of mod- ifying BASIC itself) is to write your own PUT routine, to skip over any pixel of a defined color (0 in our case). This would have two advantages: Number one, your sprite could be drawn faster because you only set the pixels you need, and number two, you wouldn't double your buffer requirements for sprites because you would only need the sprites, and could eliminate the masks! All sounds good until you try to write the thing in BASIC...it is horribly slow (ok, on a fast system, it runs at an acceptable pace). The only way to get around this is to code it in a lower level language (or at least one that can compile down to a faster version). I have done this, and you can find the results of my labor in the ABC Packets. It is called the Blast! library. It allows you to do the above, and much more. Check it out!

nethersoft@hotmail.com

www.fortunecity.com/skyscraper/terabyte/277

Back to Top

By Pete

Since about January first, the QBASIC community has gone crazy about Sprite based RPG's. Ever since Dark Crown has been released, everyone's wanted to make an RPG. Everyone from newbies to experienced programmers all want to make the all-new epic RPG to take the QBASIC community by storm. Very few RPG's have been finished since the infamous Darkdread disapeared. The reason is that a lot of programmers are very lazy, and have other things to do. RPG's get put on hold, because programmers don't have time, or get too frusterated by "Out of Memory"or other errors to continue. They are usually not taken off of hold, and the idea of the RPG fades in the programmers mind, after a few hours of work, a demo, and ten screenshots are completed. It's pathetic that programmers with so much potential can fail...

We've talked about why RPG's fail, but not why they are started. I think the reason that RPG's are started, and why programmers like to play them so much is because programmers like to do things themselves. They like to figure out puzzles, make goals, and most of them like epic, (mostly fantasy) stories. And of course, all programmers have a passion for playing video games. If you mix these ingredients together, you've got a person that wants to make their own game with a long, epic fantasy story, make their own decisions, not go through some C++ programmer's courses that he lays out in his order, with a story that can't be different every time you play.

What I'm trying to say is that programmers have personalities and hobbies, and are not copies of the other people in their school that do have personalities. They can make their own decisions, and don't depend on someone else to do things for them. They want to play role playing games because they want to play the role of a character, just like they want to play the role of their lives. They want to make an RPG for the same reason: they want make an epic story where you (the player) make the choices for him or her, and make their own story. And they want to do it on QuickBASIC-their hobby.

Now, if you would excuse me, I have to go work on my brand new, epic RPG that's going to take the world by storm. Or not...

Back to Top

By ZKman

SFB2, a wireframe fighter released on October 4th by Lbt1st is the BEST qbasic fighting game ever. Admittenly, it only was going against fairly old titles like "Stick Fighter" and "Sphere Fighter" (which, when released, was one of the best looking qbasic games!). The engine works very well, the graphics, although improvable, do the job, and the help (Dojo Master) is fairly good.

This game offers quite a lot in the way of new gameplay ideas in a fighter; some have not even been seen in professional titles. The basic way to kill a guy (the object of the game is to kill all 12 other fighters) is to punch and kick him till his health goes down, but that's not the only way to win. Each player has an awareness bar...making a big hit on the opponent causes his bar to go down, but it you try a special move (of which there are many!), your awareness will drop. So, if you just use special "super-attacks" and don't fight up-close, you'll kill yourself before you kill the opponent! Also, you can kill your enemy by knocking him into spikes on the wall or ceiling in some levels. Mucho cool!

Graphically, the game looks ok, but has some problems. First, the engine (SLASH) is an all wireframe (like Groov Buggies). Although doing flat-shading might decrease the speed, Qbasic: the Magazine is sure that the game would still play at a good-framerate with the lambert shading, especially if it was done with the asm codes. Also, the wireframe causes some clipping problems; occasionally, it seems as if you're walking right thru the enemy! The final problem is the text...it's regular, background-destroying SCREEN 12 text...it doesn't look pretty. On the other hand, the animation of the characters is supreme, they look very natural when they punch and kick, almost like mo-cap! The particle engine looks very cool too; lots of little red bloods come out of a guy when you pop 'im (heheh).

SFB2 offers alot in the way of customizability. You can assign attributes to your players hand strength, leg strength, etc. (which changes what specials you have available to you). You can even give your guy a big swinging ponytail! The interface is sort of clunky, though, so it might be hard to figure out the first time around.

SFB2 is a fun QB game, and a must download for anyone interested in seeing how to do a good Qbasic game. It's not the greatest ever, but it's sure to eat up a bit of your time, especially considering the amount of strat guides/cheat codes that are being released for it. A very commendable effort; be sure and pick it up.

Back to Top

By 19day

With the recent releases of Dash and the evidant obsolesance of Blast!, one might wonder if things could get any more confusing, but alas, Angelo Mottola of Enhanced Creations (WS2) has brought into the scene, his own lib, called DIRECTQB.

This lib is actually quite good, not to mention to auto EMS handling with saves mucho mem, but most of it's functions are quite good, and are basically the same as Dash's.

Dash has a sprite scaler and rotator, and DirectQB is going to have them soon, and you can see the two of them playing catch-up against the other, each making versions of the others' subs. DirectQB's flaw though, is in this newest version, 1.1, where it continually crashed on me when trying to play sounds (but from EMS no less) but I'm sure those will be ironed out in no time.

How does DQB stack up against DASH, well, rather nicely really. The EMS support pushes it's rank up high, and it's potential is staggering, but DASH, I'm sure, will meet the challenge.

But in a direct comparison, here is a small test I preformed, this is not to represent the entire lib's preformance, just a hint of info...

I compared the putting of sprites with DirectQB and DashX, I made an ALL.QLB than contained DQB and DASHX in one. I made a simple 30*30 sprite that was GET'ed normally, and put it at 1,1 using DQB and then DASHX. The loop was similar for both...

a! = timer
for k% = 1 to 20000
'the put, whichever one was being tested
next k%
b! = timer
times! = b! - a!

Both were identical, and both just pasted the sprite directly to the screen, as this was just a test of sprite speed. And here are the results on my P2 MMX 233 comp...

DirectQB: 3.621094 seconds
DashX : 3.132813 seconds

This may be different on other comps, but this is what I got, and since TIMER would have been equally inefficient for both, I regard the results as accurate. I tried running it a few times, and the results were basically the same, with only a changed in the 5th sigdig.

I give, DirectQB a rating of 9 out of 10, and I'm sure it will get that extra point when it has been completed.

(Editors Note: This is a review of Version 1.1: Version 1.11 fixed the bug in the sound player and a font maker is in development independently by 19day)

Back to Top

By Hal_8900

First things first

QB and C++ can't really be compared one next to the other. Obviously, there hasn't been a new version of QB since the early 90's. C++, however, is still constantly updated, which automatically puts it ahead of QB. This wouldn't be that much of a problem, except 386s were still common in 1992, but nowadays, with processors like the K6-2, QB doesn't have the same built-in capabilities as the new versions of C++ that appear regularly.

Learners-language syndrome

Another point that should be recognized, is that C++ ISN'T an acronym for Beginners All-purpose Instruction Code. BASIC is.And since Quick BASIC is an obvious derivative of BASIC, it will be inherently easier to learn. Some people would also take this to mean that it is not as powerful as other languages, but this is not necessarily true. I'm not saying that C++ ISN'T easy to learn, but the beginning programmer would generally find it easier to use QB first. This ease-of-use is one thing that's a definite plus for QB. Well, enough of the jabbering, back to the point. Just because QB may be an EASIER language to learn, that doesn't mean that it is less powerful than c++. There has been a lot debate about the power of QB and the power of C++, but I still believe that QB IS as powerful as C++, it just isn't as easy to access that power. I remember way back when, a lot of people thought that you couldn't access EMS or XMS in QB. Nowadays, there are quite a few methods to go about accessing the two. Other people thought that SVGA Color (16-bit, 24-bit) wasn't easily accessible in QB. That's what I thought too while making some SVGA color routines of my own. One day, however, I stumbled across Aaron Severn's QB site and found his SVGA routines for high-res and 15 and 16 bit color. There are quite a few other myths about what QB "can't" do, but I am too tired to think of them hehe. The point is, there are a lot of things QB CAN do, if the programmer really puts his mind to it.

To lib or not to lib

As of late, there has been A LOT of discussion on whether or not libraries should be used in QB. Right now, though, I'll talk about C++. One of the big points for the "QB IS BETTER THAN C++" group is that C++ can't operate without it's precious libraries. While this is true to an extent, those people have their facts kind of mixed up. You can't make a decent C++ program without using any of the built-in .h files, *BUT* this actually helps C++ more than it hinders it. When you want to make a simple text program, you really only need the IOSTREAM.H file and the STRING.H file. In QB, when you make a simple little text program, you get all the text functions, and all the input functions, and all the math functions, and all the graphics functions, and so on included. This is why programs made in QB are generally a little larger than other programs. Now, back to libs in QB. I think libraries like DirectQB are great. They help the programmer make a 2-week game look like they spent a lot more time on it, without 1 months worth of effort. Although I talk to Drew Vogel on IRC once in a while, I disagree with his opinion that "libs suck!" Not everyone wants to spend two months working in assembly to make the routines to make their pac-man game awesome, especially if there's someone out there who's already made the routines they need, AND they're giving 'em away! Of course, there is always 1 rule that goes along with using libs: Give credit where it's due - Don't say, yeah, I did EVERYTHING in this game myself! I'm sure it wouldn't kill ya to let the world know that you used BLAST!.

To sum it all up

I know I didn't get a lot accomplished through this little paper. Really, you are the only person that can decide whether or not QB is as good as C++. But before you go rant and rave about how QB is better than C++ or vice versa, make sure you know the ins and outs of each language. I still have the opinion that you can do anything in QB that you can do in C++ or any other language, but, it may be just is a little harder to do it in QB.

Back to Top

By Aaron Severn

(This article is continued from Issue 2. This is all the appendixes and they show you EXACTLY what everything does....also look for an 'svgalib' program at the bottom of this article)

4 Appendices
------------

Appendix A - Required TYPE definitions and descriptions
-------------------------------------------------------

VgaInfoBlock, returned by VESA function &H00.

    TYPE VgaInfoBlock
        VESASignature AS STRING * 4
        VESAVersion AS INTEGER
        OEMStringPtr AS LONG
        Capabilities AS STRING * 4
        VideoModePtr AS LONG
        TotalMemory AS INTEGER
        Reserved AS STRING * 236
    END TYPE


VESASignature - contains the characters "VESA".
VESAVersion - specifies what version of the VESA standard is in use. The higher byte specifies the major version number. The lower byte specifies the minor version number. Features of older versions are guaranteed to work in later versions.
OEMStringPtr - a far pointer to a null terminated OEM-defined string which may be used to identify the video chip, video board, memory configuration, etc. to hardware specific display drivers.
Capabilities - describes what general features are supported. The bits are defined as follows.

                      0    - DAC is switchable
                              0 - DAC is fixed width, with 6-bits per
                                   primary color.
                              1 - DAC width is switchable.
                      1-31 - Reserved
  

VideoModePtr - a far pointer to a list of supported SVGA (VESA defined as well as OEM-specific) mode numbers. Each mode number occupies one word (16 bits). The list of mode numbers is terminated by a -1 (&HFFFF). It is still the applications responsibility to verify the availability of modes in this list with the Return SVGA mode information (VESA function &H01) call.
TotalMemory - indicates the amount of memory installed on the VGA board. Its value represents the number of 64k blocks of memory currently installed.

ModeInfoBlock, returned by VESA function &H01.

    TYPE ModeInfoBlock
        ModeAttributes AS INTEGER
        WinAAttributes AS STRING * 1
        WinBAttributes AS STRING * 1
        WinGranularity AS INTEGER
        WinSize AS INTEGER
        WinASegment AS INTEGER
        WinBSegment AS INTEGER
        WinFuncPtr AS LONG
        BytesPerScanLine AS INTEGER
        XResolution AS INTEGER
        YResolution AS INTEGER
        XCharSize AS STRING * 1
        YCharSize AS STRING * 1
        NumberOfPlanes AS STRING * 1
        BitsPerPixel AS STRING * 1
        NumberOfBanks AS STRING * 1
        MemoryModel AS STRING * 1
        BankSize AS STRING * 1
        NumberOfImagePages AS STRING * 1
        Rsvd AS STRING * 1
        RedMaskSize AS STRING * 1
        RedFieldPosition AS STRING * 1
        GreenMaskSize AS STRING * 1
        GreenFieldPosition AS STRING * 1
        BlueMaskSize AS STRING * 1
        BlueFieldPosition AS STRING * 1
        RsvdMaskSize AS STRING * 1
        DirectColorModeInfo AS STRING * 1
        Reserved AS STRING * 216
    END TYPE

ModeAttributes - describes certain characteristics of the video mode. Bits are defined as follows.

                            0    - Mode supported in hardware
                                    0 - Mode not supported
                                    1 - Mode is supported
                            1    - 1 (Reserved)
                            2    - Output functions supported by BIOS
                                    0 - Output functions not supported
                                    1 - Output functions are supported
                            3    - Monochrome/colour mode
                                    0 - Monochrome mode
                                    1 - Colour mode
                            4    - Mode type
                                    0 - Text mode
                                    1 - Graphics mode
                            5-15 - Reserved

WinAAttributes - describe the characteristics of the CPU windowing scheme such as whether the windows exist and are read/writeable. Bits are as follows.
                            0   - Window supported
                                   0 - Window is not supported
                                   1 - Window is supported
                            1   - Window readable
                                   0 - Window is not readable
                                   1 - Window is readable
                            2   - Window writeable
                                   0 - Window is not writeable
                                   1 - Window is writeable
                            3-7 - Reserved

WinBAttributes - same as WinAAttributes.
WinGranularity - specifies the smallest boundary in KB on which the window can be placed in the video memory.
WinSize - specifies the size of the window in KB.
WinASegment - segment address at where the window is located in CPU address space.
WinBSegment - same as WinASegment
WinFuncPtr - specifies the address of the CPU video memory windowing function. This function is executed by VESA function &H05, calling the function with this pointer can improve performance.
BytesPerScanLine - specifies how many bytes each logical scanline consists of. The logical scanline could be equal to or larger than the displayed scanline.
XResolution - the width of the video mode. In graphics mode this is in pixels, in text modes it is in units of characters.
YResolution - the height of the video mode.
XCharCellSize - the width of the character cell in pixels.
YCharCellSize - the height of the character cell in pixels.
NumberOfPlanes - the number of memory planes available to software in that mode.
BitsPerPixel - specifies the total number of bits that define the colour of one pixel.
NumberOfBanks - specifies the number of banks in which the scan lines are grouped. The remainder from dividing the scan line number by the number of banks is the bank that contains the scan line and the quotient is the scan line number within the bank.
MemoryModel - specifies the general type of memory organization used by the mode, from one of the following.
                            &H00      - Text mode
                            &H01      - CGA graphics
                            &H02      - Hercules graphics
                            &H03      - 4-plane planar
                            &H04      - Packed pixel
                            &H05      - Non-chain 4, 256 colour
                            &H06      - Direct colour
                            &H07      - YUV
                            &H08-&H0F - Reserved, to be defined by VESA
                            &H10-&HFF - To be defined by OEM

BankSize - specifies the size of a bank in units of 1k.
NumberOfImagePages - specifies the number of additional complete display images that will fit into the VGA's memory in the mode.
Rsvd - defined to support a future VESA BIOS extension feature.
RedMaskSize - defines the size, in bits, of the red component in a direct colour pixel.
RedFieldPosition - defines the bit position within the direct colour pixel or YUV pixel of the least significant bit of the red colour component.
GreenMaskSize - same as RedMaskSize
GreenFieldPosition - same as RedFieldPosition
BlueMaskSize - same as RedMaskSize
BlueFieldPosition - same as RedFieldPosition
RsvdMaskSize - same as RedMaskSize for unused bits.
DirectColorModeInfo - describes characteristics of direct colour modes. Bits are defined as follows.
                            0 - Colour ramp is fixed/programmable
                                 0 - Colour ramp is fixed
                                 1 - Colour ramp is programmable
                            1 - Bits in Rsvd field are usable/reserved
                                 0 - Bits in Rsvd field are reserved
                                 1 - Bits in Rsvd field are usable

Appendix B - VESA defined screen modes
--------------------------------------

             GRAPHICS MODES                           TEXT MODES
  Mode number    Resolution    Colours      Mode number    Columns    Rows
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  &H100          640x400       256          &H108          80         60
  &H101          640x480       256          &H109          132        25
  &H102          800x600       16           &H10A          132        43
  &H103          800x600       256          &H10B          132        50
  &H104          1024x768      16           &H10C          132        60
  &H105          1024x768      256
  &H106          1280x1024     16
  &H107          1280x1024     256

  &H10D          320x200       32k   (1:5:5:5)
  &H10E          320x200       64k   (5:6:5)
  &H10F          320x200       16.8M (8:8:8)
  &H110          640x480       32k   (1:5:5:5)
  &H111          640x480       64k   (5:6:5)
  &H112          640x480       16.8M (8:8:8)
  &H113          800x600       32k   (1:5:5:5)
  &H114          800x600       64k   (5:6:5)
  &H115          800x600       16.8M (8:8:8)
  &H116          1024x768      32k   (1:5:5:5)
  &H117          1024x768      64k   (5:6:5)
  &H118          1024x768      16.8M (8:8:8)
  &H119          1280x1024     32k   (1:5:5:5)
  &H11A          1280x1024     64k   (5:6:5)
  &H11B          1280x1024     16.8M (8:8:8)

Appendix C - VESA VGA BIOS Extension function reference
-------------------------------------------------------

Function &H00 - Return Super VGA Information
Provides information to the calling program about the general capabilities of the SVGA environment. The function fills an information block of type VgaIngoBlock at the address specified by the caller.

      Input - AH = &H4F
              AL = &H00
              ES:DI = Pointer to buffer

      Output - AX = Status (&H4F if successful)
               (All other registers are preserved)

Function &H01 - Return Super VGA Mode Information
Returns information about a specific SVGA video mode. Fills a mode information block of type ModeInfoBlock at the address specified by the caller.


      Input - AH = &H4F
              AL = &H01
              CX = SVGA video mode
              ES:DI = Pointer to buffer

      Output - AX = Status (&H4F if successful)
               (All other registers are preserved)

Function &H02 - Set Super VGA Video Mode

Initializes a video mode.

Input - AH = &H4F
              AL = &H02
              BX = Video mode
                    Bits 0-14 - Video mode
                         15   - Clear memory flag
                                 0 - Clear video memory
                                 1 - Don't clear video memory

      Output - AX = Status (&H4F if successful)
               (All other registers are preserved)

Function &H03 - Return Current Video Mode
Returns the current video mode in BX. Not limited to SVGA modes, will also return any other video mode.

      Input - AH = &H4F
              AL = &H03

      Output - AX = Status (&H4F if successful)
               BX = Current video mode
               (All other registers are preserved)

Function &H04 - Save/Restore Super VGA Video State
Provides a mechanism to save and restore the SVGA video state.

      Input - AH = &H4F
              AL = &H04
              DL = &H00       Return save/restore state buffer size
              CX = Requested states
                    Bit 0 - Save/restore video hardware state
                        1 - Save/restore video BIOS state
                        2 - Save/restore video DAC state
                        3 - Save/restore SVGA state

      Output - AX = Status (&H4F if successful)
               BX = Number of 64 byte blocks to hold the state buffer
               (All other registers are preserved)

      Input - AH = &H4F
              AL = &H04
              DL = &H01       Save SVGA video state
              CX = Requested states (see above)
              ES:BX = Pointer to buffer

      Output - AX = Status (&H4F if successful)
               (All other registers are preserved)

      Input - AH = &H4F
              AL = &H04
              DL = &H02       Restore SVGA video state
              CX = Requested states (see above)
              ES:BX = Pointer to buffer

      Output - AX = Status (&H4F if successful)
               (All other registers are preserved)

Function &H05 - CPU Video Memory Window Control
Sets or gets the position of the specified window in the video memory. The function allows direct access to the hardware paging registers.

      Input - AH = &H4F
              AL = &H05
              BH = &H00       Select SVGA video memory window
              BL = Window number
                    0 - Window A
                    1 - Window B
              DX = Window position in video memory
                    (in window granularity units)

      Output - AX = Status (&H4F if successful)

      Input - AH = &H4F
              AL = &H05
              BH = &H01       Return SVGA video memory window
              BL = Window number (see above)

      Output - AX = Status (&H4F if successful)
               DX = Window position in video memory
                     (in window granularity units)

Function &H06 - Set/Get Logical Scan Line Length
Sets or gets the length of a logical scan line. This function allows an application to set up a logical video memory buffer that is wider than the displayed area.

      Input - AH = &H4F
              AL = &H06
              BL = &H00       Select scan line length
              CX = Desired width in pixels

      Output - AX = Status (&H4F if successful)
               BX = Bytes per scan line
               CX = Actual pixels per scan line
               DX = Maximum number of scan lines

      Input - AH = &H4F
              AL = &H06
              BL = &H01       Return scan line length

      Output - AX = Status (&H4F if successful)
               BX = Bytes per scan line
               CX = Actual pixels per scan line
               DX = Maximum number of scan lines

Function &H07 - Set/Get Display Start
Selects the pixel to be displayed in the upper left corner of the display from the logical page. This function can be used to pan and scroll around logical screens that are larger than the displayed screen. This function can also be used to rapidly switch between two different displayed screens for double buffered animation effects.

      Input - AH = &H4F
              AL = &H07
              BH = &H00
              BL = &H00       Select display start
              CX = First displayed pixel in scan line
              DX = First displayed scan line

      Output - AX = Status (&H4F if successful)

      Input - AH = &H4F
              AL = &H07
              BL = &H01       Return display start

      Output - AX = Status (&H4F if successful)
               BH = &H00 Reserved and will be 0
               CX = First displayed pixel in scan line
               DX = First displayed scan line

Function &H08 - Set/Get DAC Palette Control
Queries and selects the operating mode of the DAC palette. Some DACs are configurable to provide 6-bits, 8-bits, or more of colour definition per red, green, and blue primary colour. The DAC palette width is assumed to be reset to standard VGA 6-bits per primary during a standard or VESA Set SVGA mode call.

      Input - AH = &H4F
              AL = &H08
              BL = &H00       Set DAC palette width
              BH = Desired number of bits of colour per primary

      Output - AX = Status (&H4F if successful)
               BH = Current number of bits of colour per primary

      Input - AH = &H4F
              AL = &H08
              BL = &H01       Get DAC palette width

      Output - AX = Status (&H4F if successful)
               BH = Current number of bits of colour per primary

Appendix E - Suggested sources
------------------------------

The most useful source for programming VESA SVGA is probably the VESA specification. There are many places where you can find it, I have uploaded a copy on my website, use the address below.
http://www.geocities.com/SiliconValley/Peaks/9572/vesasp12.txt

Another good source on SVGA programming in the PC Game Programmers Encyclopedia. It includes the VESA specification listed above. You can get a copy from the following address.
www.qzx.com/pc-gpe

Appendix F - Contact info
-------------------------

If you have questions, I'd prefer that you post them on the www board at my website, rather than e-mail me.

Until September 1998, I can be reached by e-mail at rlsevern@idirect.com After September 1998 I will have a different e-mail, I don't know what it will be yet so I can't tell you.

I can always be reached by posting a message on the www board at my website, the address is www.geocities.com/SiliconValley/Peaks/9572/ Also go there for more demo code on using SVGA in QuickBasic as well as many other useful routines and fun games.

Appendix G - Works Cited
------------------------

Super VGA BIOS Extension, Standard #VS911022, October 22, 1991, Document Version 1.0, VBE Version 1.2.

The moment you've been waiting for!
------------------------

HERE IT IS! the svga library that does all the stuff Aaron has documented the last couple of months.

SVGAlib by Aaron Severn

Back to Top

By ZKman
Thank you for gandering at Issue 3 of Qbasic: The Magazine. We hope you liked it. Next issue, we'll have the first inductee to the QB Hall of Fame. Also, look for the beginning of a very secret new series as well as gobs of news. Coming in mid-November! Also, don't forget to register your QB company with the Visionaries Exchange. Till next time... END

Back to Top