| Want to print? Use this version|
Back issues are in the Archive
Go back to the main site
REM 'Letter from the Editor
qb:tm hits the half-year mark with the super-fab Issue 6!
Heya! Qbasic: the Magazine hits the half year mark with the super-fab Issue 6 and a brand new look! Hope everyone likes our newer and easier to read format! For articles this month, Hal_8900, Ma Snart, Petter Holmberg, Enigma and myself tell ya ev'rything ya need to know in the qb world. Petter has the 3rd installment of his great asm series...this month we'll learn arithmetic, logic operators and much more! Hal_8900 tells ya how to buy a "test machine". What's that, ya ask? Well, how else are ya gonna make sure your game you've been dev'ing on a P-II will operate right on a p-100? Enigma rants on about the subject he knows most about: Art. This month he's talking about cutscenes. Everyone loves 'em in FFVII and others...so why not put them in your game? Ma Snart starts what will become a great 3d series by explaining polys vs. Voxels, camera, scenes, objects and more! But what about his RPG Script article? We're going to delay the rest of this series for now, but be assured it will be finished at some point in the future.
Is a .zip version coming in your future?
Speakin' of the Future, we've talked with some of the leaders in qb development and are here to tell ya what you can expect from the future of qbasic. What trends are developing? What will we see in the future? It's all right here. Who loves ya, baby?
We've had a lot of questions asking about a possible .zip version of the mag, or an email version. How many of you are up for this? **watches Lynx users hands raise**. Right now, we're sticking with the printable version of the issue (which I encourage all of you to use...tis a great reference!), but if you all bombard me with email concerning this, umm, we might change our minds. ^_^
So, hope everyone got what they wanted for the holidays (I'm enjoyin' my new Voodoo very much, thank you ^_^), and let's make this year the best year for qbasic ever!
See ya' next month!
Compiled by ZKman
What da ya MEAN "for sale"?
You can contact Steve at this address
quickbasic.com, the qbt50 sale, lib updates, and more
TMJ at the drawing board
Why has this sudden change of heart occured? According to a report on his web page, Danny felt that the engine (which did have a slightly antiquated graphical style) was not competitive with such newer games as "Wrath of Sona and Sypharage". Check out the progress of the new TMJ at VirtuaSoft.
Codex: December Winners
If you're interested in seeing the other winners, or gaining more information about this month's challenge, surf on over to Neozones and click on "codex" in the sidebar.
DarkDread != RavenNight
Another Month...another dqb version
Meanwhile, over with Dash
In even more! library news
Wrath of Sona: The Revenge
It was NINE separate zips for a total of an almost TEN megabyte download! The game unzipped was THIRTEEN MEGABYTES!!!.
Somewhere around this point, after having unzipped the demo's fifth megabyte of .mod's, I started thinking, "hmm....lotsa stuff, this game must be good now! It must be GODLY!" I was only fooling myself.
Ludicrously bad graphics, an increase in the amount of porno, and an ok backstory were brought together into a 13mb mess. I must admit, though, the sound was the best qb sound I'd ever heard (although methinks it wasn't 6 megabytes good ^_^), and the engine promises a couple of original npc ideas. Better luck next time, I guess...
Toshi does 18-bit style
Anyway, this demo does 18-bit color (which, if I'm not mistaken, is the same that comes out of your tv) and it looks REALLY nice, not to mention that it uses little memory. A major drawback is it's lack of speed, though. Check it out.
Xeno, Project RT, DA2, the universe, and everything!
Latest Game updates:
A clone of Zelda I from the Nintendo Entertainment System is in the works! Killian and the people over at Future Software are working on the project, which will be an exact reproduction in full qb of one of the greatest action/adventure games of all time. Based on early screenshots, the game looks to be coming out very well. It looks like the shots we're taken off of the emulated version! Pay attention to this game...it's gonna be hot!
Hmmm....what's this game? Oh...Charter Magica. Yay. Anyways, this action/adventure in development by...errr...me, is coming along well and should have a demo out around the time of the next issue. The game already features 144 maps complete with 7 enemies, full enemy AI, sword swings, and a rotating palette! Super-cool! Anyways, you can get more on the game by clicking the little "Grand Scimitar" button in the frame to your left.
Entropy has quite a few projects in the works. A demo has been released for his major project called "THEM". This project has been put on hold for a little bit, but looks to have quite a good look to it as of now. We anticipate this title fairly highly.
Wow! Have I heard a lot of speculation about Project RT! Angelo and company must be doing a good job keepin' their secret because no one has guessed right as to what Project RT will be. ^_^ Anyways, we'll continue to pester Angelo and Petter until they're forced into submission. Hopefully, more in this section next month.
Here are this month's sound bites: Dark Ages 2, our feature from last month, is coming along well. The game packs it's wicked scrolling engine, and great graphics by Gavan. Sometime near when you're reading this, expect a technology demo to show off the basic engine (although it is stressed that this is NOT the "real" demo!). New screen shots, such as one of a beach scene, are up now at The DA2 homepage... Looking for a way to save memory with EMS but don't want to become a "lib person"? In addition to Entro's work, you can try the trusted and true QBV by Pasco, and get the glory without the disgrace ^_^. Pick up QBV at Pasco's Page... FrozenEmu has a great project in the works in his game "Untitled RPG". The title may not be the best, but the game has a cool anime look to it, and even some gameplay already (although it's still demo form)! The game promises to play like Final Fantasy Tactics ... finally, Jaws-V is the man! If you haven't played Cookie Delivery, go get it now. It's not an epic quest of a young hero; it's the story of a ghost-smashing cookie delivery girl. And it rules.
That's all the latest news for this month. Remember, if you have any news or rumours, send them along to Qbasic: The Magazine
Here's what you had to say about last month. Be sure and send us more letters soon!
Contrary to something mentioned in your article, many games have already been released in SVGA, such as Zoltrax, and non-RPG games like the completed Meteor Attack.
Correct you are! Dark Ages 2 won't be the first qbasic game to be done in svga and completed. However, it will definitely be the first to have widespread distribution.
After reading your latest issue, I have a few things to say. First off, some of your info
seems a little... well... incorrect. I may just have been misinformed, but I don't think
synnine's RPG, vampira, uses voxels. It's just a 3/4 perspective game. When I think of
voxels, I think of real-time 3-D landscapes. As you said, a voxel is a volumetric pixel, which
is used to quickly draw an area of a 3D landscape (at least, that's what I've heard). Also, as
far as I know, vampira uses tiles. So, there's no reason for synnine to plot voxels when he
an just PUT tiles. Another error on your part is about The Labyrinth, by SEAV. It is not DD's
engine! If you had read SEAV's awesome site, you would have known that he is writing all
of his own ASM routines so it runs much smoother and faster. I know you never actually said
the two engines were the same, that is easily implied. Plus, SEAV's engine is much more advanced,
and uncomparable to DD's.The rest of the info in the issue seemed valid, but unfairly distributed.
You're message that Eldim had been delayed was hard to see, while it should have stuck out,
and I would hardly consider it breaking news, as Enigma announced it close to a week ago.
And regarding Pasco's projects, you didn't mention QBV, his graphic routines that allow
virtual pages without the use of libraries. Iwould consider this to be bigger news than yet
another "secret project" that will probably never be finished or revealed. Now, I just have a few
things to say about your layout. To be frank, I hate it. Four frames?! And the latest news gets
about 4 squareinches. I would suggest leaving the top-left frame as is. Either removing the
articles list and linking to it from the left frame, or moving it to the right of the main portion.
And putting the news inthe main portion. So you'd end up with two or three frames: left, main,
and possible right.Also, I suggest changing the text color from grey to white, and changing the
font to Verdana or Arial. Just my opinions.
hmm....some valid concerns. First, about syn nine's rpg Vampira. We mentioned it uses voxels, but neglected to say that it uses them ONLY in the battle screen (as far as we've been informed). Sorry about the oversight. As for Seav's routines, we know they are much smoother than DD's, but they are still a first-person, tile-based engine, which is what DD wrote. Although I look forward greatly to labyrinth, as the gameplay of course is not comparable to a DarkDread game; it's better.
About our web site layout, we hope you like the "new" look. It's a bit cleaner than the admittantly somewhat cluttered old layout. As you may have noticed, we do use White Arial for the issue, but for the other pages, which involve less "reading", we are keeping the old colors.
ZKMan, Wow ! QB:tm was damn good this issue. Well done for a great publication. Now here's the question: Can I mirror the mag on my site QBNews qbnews.8m.com please ? I need the hits and can provide it over 8m's fast servers. I think this would benefit both of us in the future.Oh yeh. Can I just write an article and send it in ? I have some cool ideas for one Cheers,
We've had a couple requests for mirror sites. Unforunately, we're not very interested at this time. However, if anyone out there wants to do a translation, that would of course be encouraged! About articles: we tend to take solicited articles only now. However, if you have a good idea and good writing talent, send me your idea and I'll take a look.
I think qbasic magazine is one of the best qb publications out there. It covers EVERYTHING!!!!! I had questions about qb and since reading Qbasic Magazine for the first time and all my questions have been answered. I was just wondering: could I please add a link to your site from my site? In case you want to, click on here to visit my site. Well, thanks for considering and keep up the good work!
Of Course! Feel free to link us. Right now, you'd have to use a text link, but I should have banners up within the week that this issue is released in 3 sizes. Check ya later.
I think you should have downloadable zip files that contain the html file and all the images. That way, you could download them for 'offline viewing'.
hmm...we did do a downloadable version of qb:tm in Issue 3. However, we've dropped that in favor of printable versions. However, as I said in the Letter from the Editor, if you bombard me with mail, I might change my mind ^_^
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 fourth survey from Qbasic: The Magazine! We need more people to Vote! So do it!
Favourite Game | Last Month | Change 1. Wetspot 2 1 <> 2. Dark Ages 2 <> 3. SFB2 (t) 3(t) <> 3. Mystic. Journey (t) -- -- 3. Soccer (t) -- -- Comments: Best game list stays pretty much the same. Monospace Shooter and Groov Buggies were replaced by The Mystical Journey and Pasco Soccer. Favourite Utility | Last Month | Change 1. DirectQB 1 <> 2. DashX (t) 2(t) <> 2. Qmidi (t) - -- 2. PP256 (t) - -- Comments: Also, very little change on this list, although dqb pulled WAY ahead of Dash. Dash supporters, where are you? PP256 makes the list for the first time this month. Best Upcoming | Last Month | Change 1. Dark Ages 2 1 <> 2. "Project RT" 2(t) <> 3. Labyrinth (t) - -- 3. VSPaint (t) - -- Comments: DA2 and Project RT controlled the voting this month, and we finally have stability in the Best Upcoming list ^_^! Some surprises not making the list include Wrath of Sona, Groov 2, Soccer and Mario Clone.
Vote today by emailing your votes for:
You need this stuff!
Must Downloads returns for another showing. This month, no changes were made
to the list, although the demo and source of "Xeno" was very close to being
included. 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
Petter Holmberg of Enhanced Creations's assembly converter. By typing in normal asm, this proggy will convert the asm into goods that qb will understand. Super-spiffy!
Lianne...in the Dark Crown
Wetspot & Wetspot 2
This month's site of the Month is probably the biggest collection of qbasic source in existence. More than 1200! programs are housed here, released in "packets" every few months. Whatever you need can be found here: dqb, Huffman Compression, AI routines. And all qbasic.
The site I'm talking about is All Basic Code Homepage. This hugely popular site in some circles is a fantastic resource and the qb:tm Site of the Month for Issue 6. Congratulations!
ABC Packets Rules. End Story.
By Petter Holmberg
More assembly: Served Fresh every month...
In the previous part of this tutorial, I showed you how to use my program Absolute Assembly - with a little help from Microsoft's DEBUG - to make an assembly routine run in QBASIC. Using that knowledge, we can now start writing assembly pre and see it run. In order to do that we need to know more assembly instructions, so that's what this part mainly is about. When you've read through it you will have enough knowledge to start making your own experiments. But first, let's repeat the important parts from the last time!
I also introduced a sequence of four assembly instructions that you will use a lot in the future:
PUSH BP MOV BP, SP POP BP RETF
They will be the base for many of the assembly routines that you will write,
and you will soon understand why.
ADD Destination, source
SUB destination, source
Just like with MOV, the destination is where the result of the operation is placed. It can be a register or a pointer to a memory address. The source can be a register, a memory pointer or a direct value. Let's consider an example: If you would like to see the result of a subtraction of 4 from the value 5 in the AX register, you could test it like this:
MOV AX, 5 SUB AX, 4
The number 5 gets into the AX register with MOV, and then it's subtracted by 4 using SUB. The result, 1, will be in the AX register. Another example: Let's imagine you want to add 2 to the byte value at memory address 3:3, and put the answer in the CH register. Then you could write:
MOV BX, 3 MOV DS, BX MOV SI, 3 MOV CH, (SI) ADD CH, 2As explained in the last part of this tutorial, the first four lines are an example of reading a byte from the memory and putting it into a register. The ADD instruction then adds 2 to the value located in CH.
There are also two special case instructions for additions and subtractions. If you only want to add or subtract the number 1 from a value, you can use the instructions INC or DEC (short for Increase and Decrease). These instructions are performed faster by the processor than ADD and SUB, at least by older processors. They are also very easy to use. They only take one argument: The destination. It's recommended that you use INC X/DEC X instead of ADD X, 1/DEC X, 1. An example: You want to increase the value in the AL register with 1. The you just type:
INC AXCould it be any easier?
There are more things you probably want to do. How about multiplications and divisions? Well, you can certainly do that too, using the instructions MUL and DIV. They are a little harder to use though. The MUL instruction only takes one operand, like this:
The source cannot be a direct number, it has to be either a register or a memory pointer. If the source value is an 8 bit number, it will be multiplied with the value in the AL register, and the answer gets into the AX register. This is because the product of two 8 bit numbers can be 16 bits long. For example, suppose we want to multiply 100 with 200. We can do that like this:
MOV AL, 100 MOV DL, 200 MUL DL
The result, 20000, will fill up the whole AX register since it wouldn't fit into one byte. What about 16 bit numbers then? Well, since DEBUG cannot handle 32 bit registers, the solution looks somewhat different. If we use a 16 bit number as source, it is multiplied with the whole AX register and the result goes into DX:AX. That means that the high 16 bits goes into DX and the low 16 bits goes into AX. In many cases you, the programmer, knows that a multiplication won't have a product that exceeds 16 bits, so you can ignore the DX register. But if you have an important number in the DX register before the multiplication it will be lost anyway. Division is similar to multiplication. The syntax for DIV is:
Like with MUL, the source must be a register or a memory pointer, not a direct value. If the value is 8 bits, the whole 16 bit number in AX is divided by the source. The quotient of the division goes into AL and the remainder into AH. If the value is 16 bits, the number in the DX:AX register pair is divided by the source and the quotient goes into AX and the remainder into DX. This tells us that DIV can only perform integer division, like the \ sign in QBASIC, which is unfortunately true. For the sake of clarity, let's make an example: We want to divide 5 by 2, which would result in a quotinent of 2 and a remainder of 1. Let's try it:
MOV AL, 5 MOV DL, 2 DIV DL
Now the number 2 would be in AL and the number 1 in AH. As you can see, multiplications and divisions are trickier than additions and subtractions. Multiplications and divisions are also very slow compared to additions and subtractions. If you want to make a really fast assembly routine, try to avoid MUL and DIV as much as possible. One of the tricks to do that will be showed later.
There's also another thing about multiplications and divisions I have to tell you about. The MUL and DIV instruction only works with unsigned values, which means values that are positive. If you want to do multiplications or divisions with signed values, values that are negative, you must instead use the instructions IMUL and IDIV. They work with both positive and negative numbers, and works in the same way as MUL and DIV. But if you know that you only have positive values, use MUL and DIV for clarity purposes. That was the important stuff about arithmetic operations in assembler.
There are four arithmetic instructions in assembler: AND, OR, XOR and NOT. They have the same names in QBASIC. The processor has no problems executing these instructions, because it works with logical instructions for almost everything it does. Basic operations like additions and subtractions are performed as a series of logical instructions within the small semiconductive transistors in the CPU. Executing logical assembly instructions are therefore also one of the fastest operations the CPU can perform. Let's begin exploring These instructions!
Logical instructions doesn't treat the numbers in the computer as numbers, they operate on the individual bits in the number. So you won't understand the logical instructions if you look at what happens to the numbers you pass to them. You must study the individual bits.
The first logical instruction we will look at is NOT. It's a little different from the other three, and it's also the easiest to understand. NOT inverts all the bits in a number. So if you perform a NOT on the binary 8 bit number 00001111, you will get the result 11110000. If you NOT the number 10101100, you get 01010011 and so forth. The NOT instruction only takes one argument:
The destination can be a register or a memory pointer. The other three instructions, AND, OR and XOR, takes two arguments:
AND destination, source OR destination, source XOR destination, source
AND works like this: The destination value is compared bitwise against the source value, and only in the case where both corresponding bits are 1, the result will be 1. Otherwise it will be 0. So if you AND the value 11110000 with 10101010, you will get the result 10100000. 11001100 AND 10101010 will give the result 10001000 and so forth. The name of the instruction can be used as a remainder of its use: If bit A AND bit B is a 1, the result will be 1. Otherwise it will be 0.
OR is similar to AND, but it works in the opposite way. If both bits are 0, the result will be 0. Otherwise it will be 1. Or you can also say that if at least one of the bits is 1, the result will be 1. 11110000 OR 10101010 is therefore 11111010, and 11001100 OR 10101010 is 11101110. If you want to use the name as a remainder, you can say that if bit a OR bit b is a 1, the result will be 1. Otherwise it will be 0.
XOR is perhaps the most interesting logical instruction. The names stands for eXclusive OR. It works like OR except for one detail: If both bits are 1, the result is 0. You can also say that the two compared bits must be different if the result should be a 1. 11110000 XOR 10101010 is therefore 01011010, and 11001100 XOR 10101010 is 01100110. If this has made you dizzy, we better summarize the four logical instructions in a table:
AND: ----------- 0 AND 0 = 0 0 AND 1 = 0 1 AND 0 = 0 1 AND 1 = 1 OR: ----------- 0 OR 0 = 0 O OR 1 = 1 1 OR 0 = 1 1 OR 1 = 1 XOR: ----------- 0 XOR 0 = 0 O XOR 1 = 1 1 XOR 0 = 1 1 XOR 1 = 0 NOT: ----------- NOT 0 = 1 NOT 1 = 0
Now, what use can we have for logical instructions then? Well, there are several neat things you can do with them. AND can be used as a filter if you only want to read special bits in a number. For example, if you have a number in the AL register and you want to take away the four highest bits in the number. Then you only AND it with the binary number 00001111. Let's suppose the number in AL was 10010011. The result will then be 00000011. Notice how the four high bits have been filtered away. If you check the table above you can probably figure out why this works.
We covered the binary numbering system in part 1 of this tutorial, and if you remember it, you know that the bits in a binary number are "worth" 1, 2, 4, 8, 16, 32, 64, 128 and so forth if you count from right to left. Notice how only one of these numbers are odd? That's right: the first one. This implies that if a number is odd, it MUST have the binary digit worth 1 set. With a little help from AND, you can then test if any number is odd. Let's test the number 5. 5 in binary is 00000101. If we AND this with 00001111, we get the result 00000001. The result is 1, so 5 must be odd. If we test 10 instead, we get: 00001010 AND 00000001 = 00000000. The result is 0, so 10 must be an even number. Test this in QBASIC!
XOR also have some nice uses. One of the most common ones uses the fact that if both bits compared with XOR are the same, the resulting bit is 0. This means that if you compare a number against itself, the result must always be 0 no matter what the number is, because all bits always are the same. For example, 11001100 XOR 11000011 = 00000000. This works no matter what number you use. Remember what I said about the speed of logical instructions? These two facts together suggests that:
XOR AL, AL
is faster than:
MOV AL, 0
And that is certainly true! At least with older processors. This trick is often used by assembly programmers. Rather than just setting a register to 0, you XOR the register with itself, thus getting the same result faster. XOR can also be used for very simple data encryption. Take any number and XOR it with a number X. You will probably get a result that makes no sence. If you then XOR it again with the same number X, you get the original number back! Cool, huh? Let's test it: We have the top secret number 10011011. Now we use the secret pre key 10110110 to encrypt it, using XOR. The result is 00101101. you can't se any connection to the original number, can you? Then we "unlock" the number with our pre key and XOR again. The result is now 10011011. Wow! Our secret number is back! Of course you won't see Pentagon using this not too sophisticated encryption scheme for their secret documents, but maybe you'll have some private use for it? Test this in QBASIC too and make sure I'm not lying to you!
Shift and rotation opertations:
I'll begin by explaining shifts. Shift instructions are not too hard to understand. Their purpose is to move all the bits in a number a certain amount of bit positions in a certain direction. There are two basic shift instructions SHL and SHR, short for Shift Left and Shift Right. If you have the binary number 00111001 and shift it left one position, you get the number 01110010. If you shift it right one position, you get the number 00011100. Get it? It's like taking away one bit at one end of the number, move all the others one step to fill up the hole, and put a 0 in the empty place at the other end.
The shift instructions are not too hard to use. The basic syntax for the two shift instructions are:
SHL source, count SHR source, count
The source can be a register or a memory pointer. The count value tells the CPU the amount of bits to shift. Here comes a little quirk though: The 8086 processor only allowed the count to be the number 1 or the contents of the CL register. The instruction SHL AL, 2 was therefore not valid. Later Intel processors can use any direct number. BEBUG however, only supports the basic 8086/8088 assembly instructions, so we must use the CL register if we want to shift a number more than one bit position. If we want to shift the contents of the BH register four steps to the right, we must then type:
MOV CL, 4 SHR BH, CL
What can we use shift instructions to then? Well, there's a very neat use for it that often comes in handy. Remember what I said about the slowness of multiplications and divisions? Well, certain multiplications and divisions can be done with shift instructions, making them even faster than additions and subtractions! In the binary world, you double the value of a bit if you move it one step to the left. The binary number 100 is two times as big as the number 10 and so forth. Therefore, shifting a number one step to the left is the same as multiplying it by two. If you shift it two steps you multilply it by four and so on. So if you want to multiply a number with 2^x, for example 128, you can use a SHL instruction instead. Let's try it! Suppose we want to multiply the number 10 with 8, you can either type the slow:
MOV AL, 10 MOV DL, 8 MUL DL
Or, you could type the much faster:
MOV AL, 10 MOV CL, 3 SHL AL, CL
Get it? The same goes for division, but then you use SHR instead. The only thing you have to watch out for is that the shift instructions may push some ones over "the edge" of the register, and then you will get an incorrect answer. So make sure the numbers you want to multiply doesn't get bigger than 8 bits. Or 16 bits if you're dealing with bigger numbers.
Rotations works like shifts, but they don't throw away any bits. The bits that disappears on one side of the number, are put on the other side. So if you rotate the number 10100110 two steps to the left, the result will be 10011010. The 10 that was pushed away at the left edge, are moved to the new, empty spaces at the right edge. A rotation of a byte eight steps in any direction would not modify the byte at all because all the bits would be rotated to the same positions that they were at from the beginning. The two instructions needed are ROL and ROR, short for Rotate Left and Rotate Right. The basic syntax is exactly the same as for SHL and SHR, and the count value can be either 1 or the contents of the CL register. If you want to rotate the byte in AL four steps to the right, you simply type:
MOV CL, 4 ROR AL
Passing values between QBASIC and the assembly program:
Okay: Now We've been going through 16 basic assembly instructions: ADD, SUB, INC, DEC, MUL, IMUL, DIV, IDIV, AND, OR, XOR, NOT, SHL, SHR, ROL and ROR. With these at your hand you can do many things. Now you probably want to test this in reality, using QBASIC. But there's no way you can watch the results of these calculations in QBASIC yet. Therefore, we must learn how to pass variables between QBASIC and assembly routines.
Last time, you saw how an assembly routine could be called with the CALL ABSOLUTE keyword. The syntax for CALL ABSOLUTE is:
Where offset is the offset address of the string/array that contains the machine pre you want to execute. The segment address must be set with a DEF SEG before the call. If you want to pass variables to the routine, you do so by putting them before the offset specification. This is what I mean: Suppose you want to pass the integer variables a% and b% to the assembly routine. You then type:
CALL ABSOLUTE(a%, b%, offset%)
This will ensure that the a% and b% variables are passed to the assembly routine. Exactly how this works will be explained in just a minute. First I must point out that CALL ABSOLUTE can only pass variables of the type INTEGER. LONG variables, SINGLE and DOUBLE variables, strings, user data type variables and arrays can NOT be passed to your assembly routines. If you have the need to do that you must instead pass two integer variables, describing the segment and offset address of the variable you really want to send.
How can you read the variables in your assembly pre then? Now it's time to look back on the four golden lines that were presented in the last part:
PUSH BP MOV BP, SP POP BP RETFWhen QBASIC executes a CALL ABSOLUTE instruction, the segment and offset address of the next QBASIC instruction is pushed onto the stack. That is 4 bytes. If you add variables to the CALL ABSOLUTE line, these are also pushed onto the stack, BEFORE the BASIC segment/offset pair. They are pushed in the order they appear inside the parantheses after the CALL ABSOLUTE statement. Now, the first assembly instruction above pushes the BP register onto the stack. BP tells the program on what offset the bottom of the stack is located. Then, the contents of SP is copied into BP. SP tells the program where the top of the stack is. Now the computer thinks that the stack starts in the end. This comes in handy, because it is possible to fetch a byte from the memory like this:
MOV BX, (BP)
If we use the BX register as destination, we can get the two bytes located at the memory position SS:BP. The SS register is a new register to you. It contains the segment address of the stack. It's rarely used by assembly programmers though. Anyway, it is also possible to get the two bytes at a position RELATIVE to SS:BP. Let's say we want the word (a two byte number is called a word in assembler) 5 bytes above SS:BP. We then type:
MOV BX, (BP + 5)
If we want the word 8 bytes below SS:BP, we type:
MOV BX, (BP - 8)
Now, remember that I said last time that the stack is like a stack of plates turned upside-down, i.e. the stack grows DOWNWARDS as you push values onto it. The values already pushed on the stack are thus at higher memory adresses than the current SP value. Since we put the contents of the SP register in BP, we can now find our variables by searching at memory addresses above SP:BP. The current value of BP points at the value that was last pushed onto the stack. We just pushed the original BP value, so that's what We'll find that. At BP+2, we'll find the next value. Before QBASIC gave our assembly routine the control of the program flow, CALL ABSOLUTE pushed the segment and offset of the next QBASIC instruction onto the stack, so on BP+2 and BP+4 you'll find these values, numbers that are of no interest to us. It is after that, at BP+6 and above, that we'll find our variables. If you wrote:
CALL ABSOLUTE(myvariable%, offset%)
myvariable% would be located at BP+6. If you wrote:
CALL ABSOLUTE(x%, Y%, z%, offset%)
x% would be at BP+10, y% at BP+8 and z% at BP+6. This may sound confusing, but QBASIC pushes the variables in the order they appear inside the parantheses. x% will therefore have the highest memory address in the stack. The last variable will always be the closest one to BP. If you use PUSH in your own assembly pre, you can read them without using POP in the same way you read the QBASIC variables. The first value you push will be at BP-2, the second one at BP-4 and so on.
Let's suppose you want to get the value of the variable x% into the AX register. Then you only type:
PUSH BP MOV BP, SP MOV BX, (BP + 6) MOV AX, BX
As if our problems weren't enough, QBASIC hasn't passed the value of x% to the stack. The number at BP+6 is the OFFSET addres of the x% variable in the memory. This makes things a little harder to grasp, but as you'll see, this can be very useful.
But first, let's solve this new problem in QBASIC. If you use the QBASIC BYVAL clause before the variable, your problems will be solved. This is what I mean:
CALL ABSOLUTE(BYVAL x%, offset%)
Now, QBASIC won't push the offset of the variable x% on the stack. It now pushes the actual value of x%. Now you can use these lines to get the value of x% in the AX register:
PUSH BP MOV BP, SP MOV BX, (BP + 6) MOV AX, BX
Wow! Now we can pass variables from QBASIC to an assembly routine. Now we can
use ADD, OR, SHL or any other instruction to modify the values in cool ways.
Well, even if that's certainly true, we won't have much use for it if we
couldn't pass the modified values back to QBASIC again. How can we do that
then? Well, we need to know the memory addresses of the QBASIC variables
from within our assembly routine in order to change them. If we just let
QBASIC push the values of some variables onto the stack, we can read them,
but we cannot return any values, because we don't know where the variables
reside. This is the reason QBASIC as default pushes the offset of the
variables instead of their values. Let's try to solve the problem without
PUSH BP MOV BP, SP MOV BX, (BP + 6) MOV AX, (BX)
Now, the third line won't get the actual value of x%, but the offset address where x% can be found. BX now knows where the variable is. The last line doesn't just copy the value of BX like before. Now it gets the word located at the MEMORY POSITION pointed out by BX. Wow! That's the value that was in x% from the beginning! Are you getting dizzy yet? ;-) If you're confused, just read the last lines again and again until you get it.
Now you know how to get values of QBASIC variables into a registers both with and without BYVAL. When your assembly routine only needs to read values from QBASIC, you can use any of these two methods. I usually use BYVAL, Because it's easier to read the values from the assembly pre then. When you want to pass values back to QBASIC, you don't have any option: You cannot use BYVAL. Passing values to QBASIC is not any harder than to read them though. Let's imagine we want to do the opposite of the previous example of getting the value of the x% variable into AX: Getting the value of AX into x%, readable by QBASIC: You call the routine like before, but without BYVAL:
CALL ABSOLUTE(x%, offset%)
Then, you only need to type this in assembler:
PUSH BP MOV BP, SP MOV BX, (BP + 6) MOV (BX), AX
The only line that has been changed from the last example is the last one. Instead of getting the value at the offset of BX into AX, we now put the value of AX at the offset of BX. When the control has been returned to QBASIC again, you'll find that the x% variable has changed! Now the topic of variable passing is almost completed. Just a few more things:
First, let's return to the last two lines in the set of four lines that I showed you already in the last part of this tutorial:
POP BP RETF
When you've done what you wanted in your assembly routine, you must return to QBASIC properly. As we pushed the original value of BP before and changed it, we must change it back before we get back to QBASIC. The POP instruction ressurects the old value. Then comes the RETF instruction. RETF, short for Return Far, will POP back the segment and offset that CALL ABSOLUTE pushed onto the stack, and jump to that memory position. The control has returned to QBASIC! But when you passed variables to your assembly routine, CALL ABSOLUTE pushed them on the stack also. RETF alone won't clean up the mess you left in the stack and QBASIC will lock up your computer when it gets the wrong values from the stack. In order to fix things up, you must tell RETF to POP away the extra words that you put there by passing variables to your assembly pre. This is easy to do. Let's say you only passed one variable. One integer variable takes two bytes, so you change the RETF to RETF 2, and two extra bytes will be popped away into cyberspace! If you passed four variables, you must take away 2 * 4 = 8 bytes. RETF 8 fixes it! And finally: Remember that you can ONLY use BX when reading values relative to the offset of BP!
An example program:
CLS PRINT "This program adds two numbers together through an assembly routine." PRINT INPUT "Type the value of number 1: "; a% INPUT "Type the value of number 2: "; b% ' We'll put some assembly pre here later! CALL ABSOLUTE(a%, b%, c%, offset%) PRINT PRINT "The result of the addition is"; c%
Now we have the skeleton pre for our program. Let's start a text editor and write the assembly pre:
PUSH BP MOV BP, SP MOV BX, [BP+0A] MOV AX, (BX) MOV BX, (BP + 8) MOV CX, (BX) ADD AX, CX MOV BX, (BP + 6) MOV (BX), AX POP BP RETF 6
If you feel confused, here's some explanations:
In order to make this program run, you must now use Absolute Assembly like I showed you in the last part of this tutorial. Call the pre string add$, answer yes to the question about appending the destination file and answer no to the question about adding call absolute pre to the program, and then you'll get the following QBASIC program:
CLS PRINT "This program adds two numbers together through an assembly routine." PRINT INPUT "Type the value of number 1: "; a% INPUT "Type the value of number 2: "; b% ' We'll put some assembly pre here later! CALL ABSOLUTE(a%, b%, c%, offset%) PRINT PRINT "The result of the addition is"; c% ' ------ Created with Absolute Assembly 2.1 by Petter Holmberg, -97. ------- ' add$ = "" add$ = add$ + CHR$(&H55) ' PUSH BP add$ = add$ + CHR$(&H89) + CHR$(&HE5) ' MOV BP,SP add$ = add$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) ' MOV BX,[BP+0A] add$ = add$ + CHR$(&H8B) + CHR$(&H7) ' MOV AX,[BX] add$ = add$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) ' MOV BX,[BP+08] add$ = add$ + CHR$(&H8B) + CHR$(&HF) ' MOV CX,[BX] add$ = add$ + CHR$(&H1) + CHR$(&HC8) ' ADD AX,CX add$ = add$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) ' MOV BX,[BP+06] add$ = add$ + CHR$(&H89) + CHR$(&H7) ' MOV [BX],AX add$ = add$ + CHR$(&H5D) ' POP BP add$ = add$ + CHR$(&HCA) + CHR$(&H6) + CHR$(&H0) ' RETF 0006 ' ------ Created with Absolute Assembly 2.1 by Petter Holmberg, -97. ------- '
Now, move up the pre declaration above the CALL ABSOLUTE line and add a DEF SEG to set the segment address of the string before the call, and you'll end up with this program:
CLS PRINT "This program adds two numbers together through an assembly routine." PRINT INPUT "Type the value of number 1: "; a% INPUT "Type the value of number 2: "; b% add$ = "" add$ = add$ + CHR$(&H55) ' PUSH BP add$ = add$ + CHR$(&H89) + CHR$(&HE5) ' MOV BP,SP add$ = add$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) ' MOV BX,[BP+0A] add$ = add$ + CHR$(&H8B) + CHR$(&H7) ' MOV AX,[BX] add$ = add$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) ' MOV BX,[BP+08] add$ = add$ + CHR$(&H8B) + CHR$(&HF) ' MOV CX,[BX] add$ = add$ + CHR$(&H1) + CHR$(&HC8) ' ADD AX,CX add$ = add$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) ' MOV BX,[BP+06] add$ = add$ + CHR$(&H89) + CHR$(&H7) ' MOV [BX],AX add$ = add$ + CHR$(&H5D) ' POP BP add$ = add$ + CHR$(&HCA) + CHR$(&H6) + CHR$(&H0) ' RETF 0006 DEF SEG = VARSEG(add$) CALL ABSOLUTE(a%, b%, c%, SADD(add$)) DEF SEG PRINT PRINT "The result of the addition is"; c%
Notice how I exchanged the offset% variable in the CALL ABSOLUTE line with SADD directly. It's not necessary to put the offset in a variable before using it with CALL ABSOLUTE.
Test this program and you'll see that it works, at least when the numbers you add won't give a result that is above the 16 bit limit. This program can now serve as a base for more experiments. You can test all the instructions I've been presenting in this part of the tutorial with only small modifications of the assembly pre in this example. I encourage you to do so. It's the best way to learn how to use them.
Phew! That was all for this part of my assembly tutorial, the longest one so far. Now you know 20 assembly instructions: MOV, PUSH, POP, RETF, ADD, SUB, INC, DEC, MUL, IMUL, DIV, IDIV, AND, OR, XOR, NOT, SHL, SHR, ROL and ROR. You also know of 10 registers: AX, BX, CX, DX, DS, SI, DI, SS, BP and SP. There are more assembly instructions and registers to cover, but with the ones you master now, together with the knowledge on how to use CALL ABSOLUTE, you know enough to start writing some basic assembly routines yourself. There are many more things to know about assembly programming though. In the next part of this tutorial, we'll look at the possibilities to control the program flow, learn more about memory access, discover the extra features of Absolute Assembly, and finally, open the door into one of the most interesting parts of assembly programming in QBASIC, using an assembly instruction that will make you sit up for whole nights programming!
Until the next time, experiment with the new things I've presented in this part until you feel familiar with them. Now we're really getting somewhere!
They took up nearly 2/3rds of the 3 Final Fantasy 7 CDs. They're jam packed onto every Playstation game existing. And people were shocked when they appeared for over an hour in Zelda: The Ocarina of Time.
I cannot be talking about anything other than cutscenes. They can either be showy CGI cinematics, or real-time movement coupled with some impresive camera positions. But, are they really necessary, you question?
Hell yeah. Do all you Zelda owners remember when you walked into
Kakariko Village and then saw the cutscene involvnig Shiek and a nasty
little shadow enemy? Was I the only one that was duely impressed by that?
I mean, what better way to reward your players after hours of strenouous gameplay than with a long, involving cutscene? I personally, think it's the best way.
I dunno, this article is on a swerving track to oblivion. Maybe it wouldn't be so crappy if I wasn't in a big rush to finish this article before the deadline because I'm a procrastinating bastard child of Satan. Or maybe the topic's too vague for a loser such as moi to go into detail. Or maybe I need a shot of bourbon...oh wait, I don't drink.
-Enigma, signing off of a really lame-ass article that never should have been published (^_^...editor)
Enigma rants again... "on a swerving track to oblivion."
By MA SNART
See! 3d's not that hard after all...umm...no, really!
Almost every video game you can buy today is presented in 'Incredible NEW!' 3D graphics. However the basics of 3D graphics have been with us long before the computer was invented. Not until recently has the processing speed been fast enough to draw the graphics in real time. In this series of articles I will show you the basics of how 3D is done in games, the concepts involved, and the limitations that have yet to be overcome.
First off there are currently two distinctly different ways for game developers to implement 3D: the extremely popular polygonal way...and the voxel way. The polygonal way is obviously used the most. Because 3D polygon objects in games don't take up a lot of PC memory, Objects can have very few polygons and as such take less time to RENDER, To get realistic results depends more on the 2D textures that cover objects. These 2D textures are easier for artists to make because they are similar in design to the 2D tiles they have made for years. There are also many ways to optimize these 3D engines by using BSP-tree techniques or 3D accelerator cards. However with many developers depending on many large texture-maps and intricate mesh designs you need quite a bit of memory to run some of the latest games...Also with the large burden on texture-mapping related techniques today's 3D game engines are still limited to how many polygons can be viewed...Also the reliance on polygons ultimately limits the ability to render organic forms... With voxels on the other hand organic forms are very easy to render. Also a 'scene' can be much more complex than a comparable polygon environment. Rendering such a scene isn't anymore of a time consuming burden than rendering a simple object [ideally]. However, a voxel model takes up a LOT of memory, in fact this is a primary reason why this form of 3D hasn't been implemented as much. But it has been used [in a limited form] as a 'landscape' render for some games, and as '3D sprites' in such games as SHADOW WARRIOR and TOTAL ANNHIALATION. And a upcoming game called OUTCASTS will use voxels in ways yet unseen in games...[sorry I'm a bit bias, I prefer voxels to polygons :)] Anyhow the concepts that follow are used by both rendering techniques.
Remember this: two points define a line [or vector] three points define a plane and three or more points on the same plane define a polygon. A Verticy is one of a number of points that define a polygon [or in Voxel graphics: it could just be considered a voxel]. Also any number of polygons can use the same verticy [this is important]. A vector is a point that is used to move [or translate and rotate] vertices [and points] from one place to another. That is, 'basically' what thay are used for. Example: [on a tile-engine] to get the player from point A [say x=10, Y=10] to point B [say X=11, Y=10) you find the difference of point A from point B [B'sX=11 minus A'sX=10 which equals 1...and B'sY=10 minus A'sY=10 equaling 0] this difference is the VECTOR. To use the VECTOR you add it to the the current point to transform it to the desired point [point A [X=10,Y=10] plus the vector [X=1,Y=0] equals point B [X=11,Y=10]]. This may seem overly obvious [and simple] but it is a very important concept to understand.
The object space is simply an area that contains a unique object. An object being a 3D model of a unique game element [like the unique models for the player character, or a particular monster, and even the level itself]. Every point [be it a verticy of a polygon or a single voxel] of the object is measured, just like a vector, from the OBJECT space reference point [x=0;y=0;z=0]. None of these points HAVE to be located at 0,0,0; in fact the whole object doesn't HAVE to be anywhere near the reference point [the models in QUAKE are located above it, appearing to 'stand' on it].
The world space is the area where ENTITIES preside. Everything in WORLD space is [just like OBJECT space] a measurement from the WORLD reference point [also 0,0,0]. An ENTITY is actually what players control and interact with during a game. Each ENTITY has variables attached to it for things like location, facing vector, movement vector, rotation angles for the x/y/z axis and a POINTER to whatever object represents it [think of OBJECTS as sprites for your game. ENTITIES are then the specific monsters, creatures and effects that inhabit the world. Even if two monsters use the same set of sprites they would be considered different]. With that understanding then the first step of RENDERing: [in order to view any OBJECT that an ENTITY represents] The object [actually a copy of it residing in OBJECT space] must be transformed to WORLD space by using the attributes of the particular ENTITY. [just remember that ENTITIES have world coordinates, just like, in a tile-engine, the player has map coordinates]
Even though the camera is in essence just another ENTITY [it uses WORLD coordinates] in order for it to be used [for you to 'see the world'] the WORLD space must be transformed into CAMERA space. This is the second step of rendering [after the OBJECTS are transformed to WORLD space]. In CAMERA space [just like OBJECT and WORLD spaces] every point of every polygon and voxel is just a measurement from the CAMERA reference point [again 0,0,0]. At this step in the rendering process the third and final step can be performed...PROJECTION.
SUB-STEP 1: This step takes all the listed [CAMERA space transformed] polygons and removes the ones that wouldn't be visible. Like those that are behind the camera or that are considered to far away. It is also at this point that polygons that are in direct contact with the camera or are partially visible are 'clipped'. In 'clipping' the engine takes the regular full size polygon and 'removes' the unwanted portion. This 'visible' polygon list is then sent to SUB-STEP 2[the 'Z-buffer']
SUB-STEP 2: This is commonly called a z-buffer [NOTE: by doing some pre-runtime calculations and other tricks [this step may not be needed]. Basically what happens is that the polygon list that ends up here gets sorted into a list that re-orders the polygons from those farthest away from the CAMERA to those nearest to the CAMERA [along the Z dimension]. This is done so that, when they are drawn, those farthest away are first followed, in order, by those that are closer [the close ones are usually larger and need to be drawn over portions of those farther away]. At last, this new list of polygons is ready for PROJECTION.
DRAWING THE POLYGONS
And when it's done it can start all over again transforming the OBJECT space to WORLD space and so on for frame number two... As, you can imagine, 3D is a very math intensive format. A lot has to happen between frames in order to 'see' what is happening in the game 'world'. However the math isn't all that complicated once broken down into it's basic concepts: rotation and translation. Next time I'll cover these core math concepts in depth.
| ||The future of qbasic. No one can quite put a finger on exactly what the future holds. However, based on discussions with top developers and current trends in upcoming games, we can come pretty friggin' close. Here, we've identified the top 5 trends we see affecting qbasic, and also 5 things that are on their way out (or perhaps already gone). Read on...||
what is the future? can qbasic survive Win2000?
TREND #1:The third dimension. No one doubts that 3d will have the biggest impact on qbasic programs in coming years. Whether it comes in the forms of voxels (which is doubtful, because of the low amount of memory qbasic has) or polygons, 3d will shape future games. Only minimalistic flat-shaded (Lambert Shaded) games currently exist, but in the next year or two, you WILL see games with full 3d levels, gourard shading, and high-quality texture-mapping.
Where does this sudden revelation come from? As it was reported in the Hot List this month, 3d libraries are going to be coming within the year. They'll do for 3d apps what directqb did for side-scrollers. It makes them accessible to those without the years of experience required for a fast mapping loop or something of that sort. In addition, the controls for Glide can most certainly be accessed from qbasic (because they do work on DOS-based applications) and we will possibly see 3d-acceleration in some of these future games.
So whether the "breakthrough" lies in Xeno, Groov Buggies 2, or a 3d prog still in pre-coding, one game will do for 3d what DarkDread did for roleplaying. End Story.
TREND #2:More and more libraries! So, ya think Blast, Dash, DashX, and dqb are enough and that qbasic won't be able to support more? Think again. The next 2 years will bring, at our estimate, another 3-5 library sets. From the already planned "Nemesis" and 3-d libraries to "all-inclusives" (i.e., those libraries which include graphical, text, sound, and loading functions), and even specialized libraries like a "graphical-effects" set (i.e., fire and starfields), you'll be overwhelmed by the choice in the coming years.
Although many may be against the idea of libraries (because they essentially allow newbies to do many things that would normally takes years to learn), qb:tm thinks that anything which will keep programmers in qbasic and bring new coders to this somewhat antiquating, but fun, languague, is a good thing.
So, if you're one who is in the "anti-library" league, your number will soon be degrading. "Professional" coders use many different libs, whether thru Win32 API's or console dev systems. These qlb's will allow qbasic to survive longer and make it possible for qbasic games to increase their quality at an ever increasing rate.
TREND #3:Svga! This one word will affect qbasic more and more, starting with this year. Dark Ages 2 will be the first major title to use svga, although it (and, I believe, Sypharage) are running at 640x480x256, which means we're still limited to 256 colors. This will change VERY quickly, however.
16-bit, 18-bit, and possibly 24-bit color have been proven able to be done in qbasic (with 16-bit routines fairly easy to find). Right now, only veteran programmers will use high-color svga in their games, and these "hi-color" titles could begin appearing by 3rd or 4th quarter of this year. Around that time, I believe the first fast svga library set will appear; one that is accessible to the main part of the qbasic community (the current 16-bit routines are somewhat complicated to navigate for beginner/intermediates). So, the first "wave" of svga games will appear in early 2000. By 2001, Vga will be used as much as SCREEN 9 or SCREEN 7 is used today; that is, not much.
TREND #4:EMS/XMS. No one can doubt that this will be hugely important to the future of qbasic. To put it lightly, the amount of memory qbasic "normally" has access to is VERY small. Current RPG's are barely getting by with the amount of memory they have right now. Memory is at a premium. EMS and XMS routines get by this premium by accessing megabytes of storage (mostly used for graphical arrays or (in 3d games) division and sin/cos tables) that qbasic normally can't.
Unfortunately, EMS and (especially) XMS routines are VERY difficult to write, especially for newbies. So, once again, libraries will become a greater and greater force. Hopefully, the use of these EMS libs and virtual screens will bring an end of flicker by the end of 1999. Any game released at that time with flicker will be inexcusable.
TREND #5:Multiplay. Wetspot II across a modem? Of course not. Internet-based multiplayer Dark Ages? No way! Right now, qbasic games that are playable (and fun!) across a modem do not exist. Why is this if multiplay is so common in "mainstream" games? Because TCP/IP routines that were capable of sending/recieving packets across the internet did not used to exist! Although there were tons of LAN routines and IPX routines, TCP/IP (which is the main way of communication between modems across the internet) has not existed prior in qbasic.
That will change. Qb:tm has heard that early, working TCP/IP routines are being developed. It is predicted that modem qbasic games could show up by the middle of this year, and will be fairly common, once again, when they are incorporated into a library. The year 2000 could bring modem-play to the forefront of future qbasic projects.
So, the future of qbasic looks pretty bright, eh? Maybe not. Rumours are circulating that Windows2000 (formerly known as nt5.0) will not support DOS Real-mode and also will not include qbasic1.1. What does this mean? A MUCH smaller qbasic community. Most qb coders were introduced to qbasic at school or have been using it since the days of DOS. I don't think that, if it is not included on the Win2000 cd, schools will be willing to teach the language anymore. This could potentially be a bad thing for our favourite language.
But we certainly hope not! Happy coding!
5 qbasic trends soon to be gone:
#1: The RPG Crusades will slow. Although RPG's will continue to be much used, they won't dominate qbasic like they do today
#2: VGA. This will take a couple of years, but rising svga libraries will eventually relegate vga to the way it is currently used in mainstream games: Very rarely.
#3: The Lone Wolf. Solitary programmers will still be around, but their numbers will dwindle as teams from 2 (an artist and a programmer) to more start to increase in amount.
#4: All qb code. In order to "keep up", qb programmers will begin to boost their code with more and more assembly, especially for 3d applications.
#5: Regular Text. Screen 13 text is almost gone now, and will dissapear totally soon. It looks SOOOOO bad. ^_^
Everyone playtests. What about Machine Testing?
So, have you made the next Mortal Kombat game.. in QB? Incredible! Fantastic! SLOW!!!! Uh-oh, looks like you have a problem, considering the fact that your game runs at 70 FPS on your CRAY XMP. How were you supposed to know that it was slower than the 7 year itch on everyone else's machine? Sure, you could send every new version of your game to your best friend, Bob, the 486-100 guy, but that takes a lot of time, considering Bob only has a 2400 baud modem. What else can you do to insure that your game runs fine on all systems, not just your supercomputer? Well, you can build your own system!
Now, I know what you're thinking.... "build my own system? This guy is crazy!" but, really, it's not as hard as you may think. You can get a 486 motherboard nowadays for $5, and hard drives and RAM are the cheapest that they've ever been! There are also a lot of advantages to having a second computer in the house. Got a brother or sister (or spouse) that is busy typing something up on your machine? Well, you can get on your second computer, to make sure you dont miss that important email. Ever wanted to run Linux, but didn't want to screw up your good computer? Put it on your home-built! Remember, you dont need a fancy p2/450, a p-100 should be fine. You dont need a CD-ROM drive (although it would be useful), and you dont need a 19" 1024x768 res monitor! Just get the basics!
Well, heres a list of resources you can check out: Web Sites:
Always get printed catalogs from places, and look for electronics surplus, and robotics shops, they usually carry support for older systems. You should be able to find a good test machine (something around a p-100, 8 or 16mb ram) for only about 199 american dollars. Remember, this is just another way of playtesting and a good way to make sure your game will handle "lesser" systems.
Thanks for reading Issue 6! Next issue is coming on 13 January, so mark your calenders! We should have the next asm article, another part of the 3d series, a review and the second ever entry into the qbasic Hall of Fame! Who will join DarkDread? Will it be Mallard? Angelo Mottola? Danny Gump? Mike Hoopman? Class-? Also, don't forget to register your QB company with the Visionaries Exchange. Till next time... END