After you have read this part of the QB Times, please rate it here!
Well I hope that with this new cooperation we can bring you an even better QB Times. I also hope that you like the new lay-out as I think this is much better than the old one! The HTML build is done because it's easier to read. I hope you enjoy reading this issue!
WisdomDude is working on CyberChick. CyberChick is a platform game that is a lot like Metroid from Nintendo. There are several demos available already. Just pick the newest and experience the nice playability, neat graphics, and speed of this game.
Another Nes-Emulator is being developed in QB! The name is BXNes. BX Software is working on it, saying they have completed it for 2% already :)
Adam Kewley aka Fishstix, Rancid, and John Hoffman aka qbasic man are working on QMod. QMod will be a replacement for bwsb. BWSB eats up array memmory, they are hoping to make qmod into a tsr that will be used by poking commands into memory. The project page is here!
The first part of the source of the RapidBasic compiler has been released by JQB45.
Nightwolf (from the Programming Oasis & the QB Times) is working on a graphics/sprite-editor in QB. It will feature import and export of the following graphics formats: BMP, GIF, PCX, and maybe JPEG. You can save/load in all the QB's general formats (BSAVE, JSprite). You can have multiple tiles in one file and your tile's size can be up to 200 pixels each side. Further it includes a lot of filters and 6 different zoom levels.
Jorden from Future Software is working on making BomberZone Online! The programs uses the windows clipboard and files to send dat to a VB5 programs, which sends it over the internet using a TCP/IP connection with someone else. The first small steps have been done, so we know it works!
Another new IDE for QB 4.5 is being written. Looks like this is gonna be the year of the QB IDEs/GUIs!!!
It's being written in VB3, though a switch to VB 5 might be made soon. It does NOT use BC.EXE as its compiler however. It uses PBC! Yeah! For the first time ever, PowerBasic will have a proper IDE. The beauty of this new project (called QuickPower) is that unlike the 90% compatability rate between PB and QB, it will have a MINIMUM of 99% compatability! Imagine doing QB code with inline assembly! No CALL ABSOLUTE crap required!
QuickPower has a preparser which converts QB code to PB code, and takes advantage of certain QB "quirks" (like psuedo-unsigned integers as a result of a calculation). It will have several library modules built-in to it, including a custom 13h lib (did you all know PB doesnt have 13h support natively??). Nekrophidius is working on it, by the way!
If you want to know more about the projects in the the QB Times, we suggest you visit NeoBasic, which has a big list of projects...Be sure to submit YOUR project also!
|The QB.Scene and the QB Times have merged! NightWolf (from the Programming Oasis) & Jorden (from Future Software) are now co-operating on the magazine, which means you'll get the best of both worlds.|
|V Planet! is starting the QB Expo soon. The QB Expo will be a chance for QB programmers of all skill levels to show off their newest material. It's still in the planning-stages, so nothing is sure yet.|
|Welcome to the QB Cult Magazine! It looks like 2000 is becoming the year of QB Magazines! After the amazing popularity of QBasic: The Magazine, we've had QB Times, QB On Acid, QB.Scene, QBSI and now the QB Cult magazine! It's got a little news but a ton of tutorials. Take a look at it by clicking the link that will take you to Xybertech.|
|There is a whole new site going up right now at the Programmers Top 500! It's currently up and in preliminary testing. The new site will eliminate all the previous bugs and include an expansion that will blow you waat. It's release date is approxametly 2 months from now. Get ready for the new Developers Index!!!|
Neozones is back online...the new address is http://www.neozones.cjb.net/. Rest assured that the Qlympics won't be moving for a while, though.|
NeoBASIC/Neozones.com has a new people/profile-directory called Neo Marcade Profiles (NMP, for short). Worth to check out, be sure to register your name too! Marcade is working on a projects-system, all NMP members can get their projects in there, and update them theirselves so the page is never outdated. That's probably one of the best new parts of NeoBasic!!!
DarkDread has just uploaded the Vault, with 8 old games done by Darkdread! Don't miss this one!
Ampleworks.com has had a server change recently. Because of that, the Elite top 50 wasn't online for a few days, same for the QB News. It's back now though, so visit now by clicking the link!
Jorden also gave Future Software a redesign! New backgrounds and navigation bars give the page an 'assimulated' look...
Messageboards can be boring, except when it's february 29th...The two best visited boards, those from Future Software and Neozones.com, went crazy for one day...The Future Software board allowed people to get their name on the board in orange, which caused tons of additional orange posts... The NeoBoard replaced all a's with e's and e's with a's... Soma paopla want crezy thara!
' text$ is the text to save DIM txtmatrix(LEN(textin$) * 9, 13) ' we must dim the matrix to keep it in memory LOCATE 1, 1: PRINT text$ ' the text is printed on the screen so that it can be saved. If the text you want to save ' is already there, you can remove this line ! FOR i = 0 TO LEN(textin$) * 8 ' in screen 9, the characters width is 8 FOR j = 1 TO 13 ' in screen 9, the characters height is a little less than 13, ' but if the text is ' already modified (with underlining, for example), the best thing to do is to reserve ' more memory for the matrix txtmatrix(i, j) = POINT(i, j) ' here is the way to save each dot of the text in the matrix. NEXT j, iNow that your text is saved, you can modify it ! For example, to flip the text horizontaly, add this code after saving the text matrix :
FOR i = 630 TO 630 - (LEN(textin$) * 8) STEP -1 ' we must start from the right of the screen (640*350 in screen 9) FOR j = 1 TO 13 IF txtmatrix((630 - i), j) <> 0 THEN PSET (i, j), txtmatrix((630 - i), j) ' I add the test because on slow computers, the program printed the black dots too and it ' was a waste of time ! NEXT j, iTo flip the text vertically, you can draw a separation line using this line of code :
LINE (0, 14)-(LEN(textin$) * 8, 14)To flip the text, that's the same sub as previously but now J is reversed, not I. So you must use that sub :
FOR i = 1 TO LEN(textin$) * 8 FOR j = 14 TO 1 STEP -1 IF txtmatrix(i, 14 - j) <> 0 THEN PSET (i, j + 14), txtmatrix(i, 14 - j) NEXT j, iAnd if you want to create a nice effect on the vertical flipping, transform the third line of code to the following :
IF txtmatrix(i, 14 - j) <> 0 THEN PSET (i + j, j + 14), txtmatrix(i, 14 - j)so that the text is inclined.
That is all very interesting, you say, but how do I do it in Qbasic? Well, that is very simple. There are just 4 commands you are going to need to do some modem communications! They are as follows:
OPEN COM.........Open up the modem for use by Qbasic. INPUT$...........Get data from the modem. LOC..............Tells you if the modem has any data from an outside source. PRINT #..........Send data to the modem.To start work with the modem, you have to open a "path" to it. This is just like opening a file, except you use the "OPEN COM" statement. Here is a sample:
OPEN "COM2:2400,N,8,1,RB2048,TB2048" FOR RANDOM AS #1Now, you wonder what that all means, but it really is quite simple, you just must remember this little secret: opened devices (like the modem) act just like opened files! Now back to the example code above. I know it looks confusing at first, but dont worry, the only thing you need to concern your- self with is the number between "COM" and ":" and the number between ":" and ",N". All the other stuff deals with transmition settings and the RB TB things deal with uploading and downloading. The first value is the COM port number that your modem is on. Because Qbasic was made a long time ago, you only have access to ports 1 and 2. If your modem is on another port, dont worry, there is a way around that which involves switching the memory addresses on the COM ports. Dont worry about that now though, I'll go into that in another article some time.
The 2nd number is the Baud. BAUD is the speed of the modem. Qbasic cant access COM ports at any higher speed than 9600, so if you have a 56K modem, Qbasic can still use it, but it wont go any faster than 9600. Dont worry about this too much though, I am busy writing a library that gives you access to the modem at any speed.
To send data to your modem you use the PRINT #n statement, where n is the file number (in the example, 1.) But there is no point sending stuff like "Hello world" to your modem right now, because you are not connected to anything. All you have done with the "OPEN COM" statement, is made a path from your modem to your program so they can talk to each other.
Hmmm, this is quite a problem. So how do we get connected to something then? Well, when you want your modem to talk to an outside source, like a BBS, you have to tell the modem to dial a number. To do this you must know that all modems have a set of commands eched in their read-only-memory chips that allow them to do different things. You cant just say "Hey modem, dial 555-314-545", you gotta talk in the modems lingo! This is alot easier than it sounds. All of these commands begin with "AT". Here are the most used ones:
|---------------------------------------------------------------------------| | MODEM LANGUAGE | TRANSLATION TO ENGLISH | |---------------------------------------------------------------------------| | "ATDT###-###-####" | "Hey modem, dial ###-###-####" | | "ATZ" | "Hang up the phone!" | | "ATS0=#" | "Wait until you someone calls and the phone rings | | | # number of times, then try to connect modems." | | "ATM2H1L#" | "Set your speaker volume at # (1-3)" | |---------------------------------------------------------------------------|So, if you wanted to call someone with the modem, you would first use an OPEN COM statement, to get the path between your modem and your prog set up, then you would use an INPUT statement to get the phone number to dial as a string, then use PRINT #n to talk to the modem. I think now is a pretty good time for an example! Here is a simple phone dialer:
(Replace COM# with the COM port your modem is on.)
CLS PRINT "Openning a path to your modem..." OPEN "COM2:2400,N,8,1,RB7048,TB7048" FOR RANDOM AS #1 PRINT "Please enter the phone number you wish to call" INPUT PhoneNumber$ PRINT "Talking to your modem..." PRINT #1, "ATDT"; PhoneNumber$ PRINT "There you go, pick up the phone and talk!" PRINT "Press the ESC key to hang up!" DO LOOP UNTIL INKEY$ = CHR$(27) PRINT #1, "ATZ"Now that wasnt so hard was it? But here comes the biggest problem of modem control in Qbasic, HOW DO I READ WHAT COMES FROM THE MODEM? Well there is a little function called LOC that does this. The syntax is:
LOC(n) where n is the file number, which if you used my sample, would be 1.
LOC tells you where in a file you are. File? But I am trying to access the modem! As I said before, files and devices work the same way. But with a modem, LOC tells if it has received anything. Fine, now you know if the modem is getting stuff, but how do you know what it is getting? For that you use the INPUT$(x,y) statement. x is the number of bytes to get from a file/device and y is the number of the opened file/device.
x should ALWAYS be 1. I know this means that only 1 character can be read on each pass, but this way EVERY character is read, and none are skipped. If you were getting an 11 byte transmittion, and x was 2, only the first 10 characters would be read (because it is a multiple of 2.) The last part would be skipped. This is the way for NORMAL communications. Keep x as 1!
There is just one more modem command to talk about, namely, the "ATSO=#" command, which you use to wait for a call. But I think it is best explained with an example. Oh, what the heck, lets just put everything we have learned here together into a fully commented communications program. You can use this to call up any BBS and interact with it. Note that it has no uploading or downloading capabilities, though. I will have to cover this, along with some other stuff, in another tutorial some time.
CLS PRINT "HORIZONS Interactive Entertainment - BasHack v1." PRINT "What COM port does your modem use?" INPUT ">", port$ baud$ = "9600" '9600 should work fine with most modems. If you have 'an older one use 2400. 'Open up that com port. OPEN "COM" + port$ + ":" + baud$ + ",N,8,1,RB2048,TB2048" FOR RANDOM AS #1 PRINT "OPTIONS:" PRINT "1-Dial up to another computer" PRINT "2-Wait for a call" PRINT "3-Quit" DO a = VAL(INKEY$) LOOP UNTIL a >= 1 AND a <= 3 IF a = 3 THEN CLOSE : SYSTEM IF a = 2 THEN GOTO wait PRINT "Number to call?" INPUT ">", number$ PRINT #1, "ATDT" + number 'Tell the modem to dail the number. GOTO chat wait: PRINT #1, "ATS0=1" 'Tell modem to conect after 1 ring. 'When a modem connects it returns "CONNECT ####" 'The next hunk of code waits until the modem connects before moving on a$ = "" DO IF LOC(1) THEN a$ = a$ + INPUT$(1, 1) 'if anything in modem add it to a$ LOOP UNTIL INSTR(a$, "CONNECT") 'Wait until modem have connected. chat: 'If you where waiting for a call, alot of ASCII characters will be printed 'on the screen. Dont worry, that just the computers getting in sync and 'talking. You also will not see what you type. CLS PRINT "You are now ready to chat, press ESC to quit." DO t$ = INKEY$ IF LEN(t$) THEN PRINT #1, t$ 'if you typed something send it to the modem 'this will be send by the modem to the other 'computer IF LOC(1) THEN r$ = INPUT$(1, 1)'if the is something to get, get it and save 'it as r$ IF LEN(r$) THEN PRINT r$; 'if r$ <> "" then print it. the ";" means a 'line is not started LOOP UNTIL t$ = CHR$(27) 'keep doing this until ESC is pressed PRINT #1, "ATZ" 'tell the modem to hang up CLOSE 'close the open com statmentAnd thats it! Simple huh? Now you have a cool program that you can use to talk with your friends over the modem in Qbasic! Before I leave you to experiment with your newly aquired knowledge, I would like to extend my thanks to the following people who have helped me some way along the line with my programming in general: LordAcidus, Petter Holmberg, Tek, ZKman, and last but not least, Christian Garms. You guys have helped me alot.
Happy hacking everyone!
learn asm in 1 hour flat
Register Use ======== ==== AX Calculation and Main register |__AL Low byte and Int function index (Lower AX) 8-bit register |__AH High byte (Higher AX) 8-bit register BX Calculation and basic Pointer |__BL Lower bit (Lower BX) 8-bit register |__BH High bit (Higher BX) 8-bit register CX Calculation and counter |__CL Lower bit (Lower CX) 8-bit register |__CH High bit (Higher CX) 8-bit register DX Calculation and Data |__DL Lower bit (Lower DX) 8-bit register |__DH High bit (Higher DX) 8-bit register SI Pointer DI Another pointer BP "Byte Pointer" mainly used to access stack and preform data movement SP "Stack Pointer" Points to first byte to the stack IP Code pointer points to current byte of code CS "Code Segment" Points to segment of current code cannot be changed, and even if it can would crash your system. DS "Data Segment" Points to segment of data area ES Extra segment, for use in misc. function FS Same as above GS Same as aboveWe all know what is AX and how AX is used. We all also know it's a 16-bit register (like an integer). But what in a blue moon is AL and AH? Quite simple, really. AH and AL are respectably the higher and lower bytes of AX.
Here's an example:
AX= 0 0 0 0 0 0 1 1 1 1 1 0 1 1 0 0 | | | | | | | | | | | | | | | | \-------------/ \-------------/ Higher Byte Lower ByteWell we have a number in AX (1004), when writen in binary it equals 0000001111101100. But what if we split it into two bytes? One we'll call the Higher Byte AH and we'll call the Lower Bit AL. So, if AX=1004 then,
AX= 0 0 0 0 0 0 1 1 1 1 1 0 1 1 0 0 | | | | | | | | | | | | | | | | \-------------/ \-------------/ Higher Byte Lower Byte = AH = ALAH = 00000011 = 3
It is also interesting to know that thanks to AH and AL, you could manipulate AX in many ways. Here's a formula you really might find handy:
Now that you know how AX, AL and AH behave, I can safely tell you that (as you have probably assumed) this counts to BX, CX and DX as well.
Lesson no.7 Segment Registers and memory
There are techniques around this for example:
mov ax,segment mov ds,axYou can use segments to address parts of the memory, much like POKE and PEEK. But you also need an offset (if you have'nt already,which you should by now, read the segment tutorial). To use an offset is rather simple, you can put your offset in di,si,bx or dx (which ever one picks your fancy) and you put square brackets around it. That is practically an offset pointer. Here's an example:
MOV BX,140h ;Offset MOV AX,3h ;Value to poke MOV [BX],AL ;why AL? because we only want to poke 1 byte (8-bit)This basically goes pokes 3 into the memory location 140h. But what segment you might ask? As QB has DEF SEG to address the default data segment, your processor uses the DS register for that job. So really you are writing 3h to DS:0140. Here's an example using a diffrent segment.
MOV BX,140h ;offset MOV AX,3h ;value to poke MOV CX,0A000h ;new segment MOV DS,CX ;our little trick to change the segment = ) MOV [BX],AL ;writes 3 to DS:BXThis would write 3 to A000:0140. The same code could have been writen like this:
MOV BX,140h ;offset MOV AX,3h ;value to poke MOV CX,0A000h ;new segment MOV DS,CX ;our little trick to change the segment = ) MOV DS:[BX],AL ;writes 3 to DS:BXWhich specifies that we want to use DS as the segment. This just makes things look clearer, but is not needed as DS is the default data segment. But what if you don't want to use DS? maybe you want to use CS or ES... You'd simply do this:
MOV BX,140h MOV AX,3h MOV CX,0A000h MOV ES,CX MOV ES:[BX],AL ;writes 3 to ES:BXPretty simple is'nt it? Well, since you've loyally finished this course you will find the next one more interesting as we get into new and exciting opcodes. These should make your life easier. Also we might be getting on on how to make your own library. All that coming next month!
Before I continue, I'd like to make 2 correction to previous articals.
*****Correction 1: In the segment tutorial I said 2 byte pointers for 32-bit, what I meant to say was 4 byte pointers. Thank god I picked it up while proof-reading it agian!*****
*****Correction 2: In issue#2 I said retf to exit the program. I don't know what I was thinking, but I'm sorry if it crashed your computer. Infact if we meet one day, you can hit me over the head with a stick = P Use retn or better still function 4C like in issue#3*****
Lesson no.8 Basics of The Stack
After coding a while, you'll probably think it gets pretty cramed with the small amount of registers you can use. It gets tacky and some times you might want to "backup" a value a register has. There is a way to do this and obviously it involves the stack or I would'nt be mentioning it (hehehe = P). The two fundimental commands to use the stack are:
PUSH POPPUSH saves a value of a register (or a memory location but lets not get on to that yet) on the stack, and POP basically takes this value which was saved out of the stack and in the register.
MOV AX,3 ;Give AX a value of 3 PUSH AX ;PUSH AX (3) onto the stack MOV AX,5 ;Give AX a value of 5 POP AX ;POP AX off the stackWell, lets take this simple code step by step. First AX is given a value of 3: "MOV AX,3". Then AX is push on the stack: "PUSH AX", after this AX is given a value of 5: "MOV AX,5". To finish it all AX is pulled out of the stack: "POP AX". As you probably (or hopefully as my maths teacher used to say = )) have figured out AX ends up having a value of 3. The reason for this is PUSH AX, pushed the value of AX (which was 3 at the time) onto the stack then at the end, even after AX was given 5, POP AX pops 3 out of the stack and puts it into AX agian.
Now, you might find this handy later on, but you don't have to give AX a register. You can also give it a immediate value! The above code could have been writen like this:
PUSH 3 ;PUSH 3 on the stack MOV AX,5 ;Give AX a value of 5 POP AX ;POP AX off the stackReading that, you'd relise it's not important what register you pop the value of the stack onto, infact you can re-write the code before the one above like this:
MOV AX,3 ;Give AX a value of 3 PUSH AX ;PUSH AX (3) onto the stack MOV AX,5 ;Give AX a value of 5 POP DX ;POP DX off the stack MOV AX,DX ;Put the value of DX into AXSo you pushed the value of AX, being 3, onto the stack and poped it out as DX! And at the end you moved DX into AX (MOV AX,DX). If you run that code, both AX and DX would end up being 3! As you'd realise the stack is very easy to use, but there is one more thing you have to learn. What if you want to push more than 1 register? Would you do something like this
PUSH AX ;PUSH AX onto the stack PUSH BX ;PUSH BX onto the stack POP AX ;POP AX off the stack POP BX ;POP BX off the stackSounds right does'nt it? We push AX, then BX then we POP AX then BX. Sad to say, but it does'nt work like this. Think of the stack, as a stack of papers. You put one paper labeled A on the floor and then put another paper labeled B down on the floor. When you go to pick up the one on the top you don't pick up A but you pick up B! Here's a simple diagram:
First we PUSH AX (put AX on the stack)
The Stack | | | | |===============| <-- AX |_______________|Then we PUSH BX (put BX on the stack)
The Stack | | |===============| <-- BX |===============| <-- AX |_______________|What's at the top of the stack? BX! This is why you can PUSH one register and POP out another one, because the stack does'nt keep track of what you pushed and where you pushed it, it simply pops out the one on the top! If you are ever confused think of "first in last serve", but for now here is another example:
MOV AX,3 ;Give AX a value of 3 MOV DX,5 ;Give DX a value of 5 PUSH AX ;PUSHs AX (3) on the stack PUSH DX ;PUSHs DX (5) on the stack ADD AX,DX ;ADDs DX into AX (3+5=8) PUSH AX ;PUSHs DX (8) on the stack POP CX ;POPs 8 off the stack and into CX POP DX ;POPs 5 off the stack and into DX POP AX ;POPs 3 off the stack and into AXSo AX has a value of 3 and DX has a value of 5. We then push AX then DX onto the stack so it'll look like this:
The Stack | | | | |===============| <-- DX (5) |===============| <-- AX (3) |_______________|When the add DX into AX which gives the value of 8. After this we push AX (which has the value of 8 now) onto the stack agian, so it should look like this:
The Stack | | |===============| <-- AX (8) |===============| <-- DX (5) |===============| <-- AX (3) |_______________|The operations to flow are:
POP CX ;POPs 8 off the stack and into CX POP DX ;POPs 5 off the stack and into DX POP AX ;POPs 3 off the stack and into AXWhen then pop out 8 and put it in CX, then pop 5 out for DX, and finnally 3 out for AX. So it's going to do this:
The Stack | | |===============| <-- AX (8) ==> CX |===============| <-- DX (5) ==> DX |===============| <-- AX (3) ==> AX |_______________|So CX=8, DX=5 and AX=3. Pretty simple if taken step by step, and I promise this will be very very handy to you when you start programming biggies. Now, should I make another chapter? Should I? Ah what the heck, it's 1999 (is it? Don't tell me it's over already = P) so lets go have some fun!
Lesson no.9 Procedures 2
Here's an example from Lesson 4 (edited because of retf ... hit me)
1E7D:0100 CALL 200 RETN ... 1E7D:0200 MOV AX,1 INT 33h RETNWell so we did'nt complicate things, I did'nt explain what the heck 1E7D was. Basically, 1E7D is the current segment the program resides. Now, we already know what CALL does (it's like a SUB) and retn (like END SUB) so in QB it would have looked like this:
CALL asub EXIT SUB asub ... 'Show the mouse END SUB asubYou would probably think that the way above there is quite messy. There is another way however, a diffrent approach. I'll be honest with you though, you'll end up with nearly exactly the same compiled code but the source code will look better. Lets look at the previous example in a diffrent way (and it gives me a chance to further explain the stack):
.STACK 100h ;This gives us 256 (100h) bytes worth ;of stack space, where we can push and ;pop .CODE ;This is the code segment (CS) CALL showmouse ;CALL the procedure "showmouse" mov ax,4C00h ;the prefered way to exit a program int 21h ;Use the function 4C to exit showmouse PROC ;like saying SUB showmouse mov ax,1 ;Use function 1 int 33h ;of int 33h retn ;return showmouse ENDPROCHey, this kinda looks like a .BAS file in a text editor eh? PROC is like SUB and ENDPROC is like END SUB. But remeber, you always have to have the retn at the end it's what gets you back to the main section. Without the retn, your program will most definatly crash, and if you got complex routines that mess with the hard drive to come, you can kiss your computer goodbye. I can't stress enough how important it is to return to the main code section because when you make libraries for QB, you'll probably want control back to your program, not what ever garbage is after your little routine.
Now, on to a part which you've probably been waiting ages for. How to implement such functions in QB. It's all rather simple really, but it does require a linker and a library creator (which ussally come with QB) and a little bit of patience. Compiling and Linking can be a hassel sometimes, but there are make utilities out there to make life just that little bit easier so I suggest you grab one.
First you'd make a assembler file which looks like this:
.model medium,basic .stack 100h ;enough for us and BASIC .data ;Where you would place all your variables ;(explained later,data segment) .code ;the code segment begins here PUBLIC showmouse ;Declare "showmouse" to QB showmouse PROC ;Like SUB showmouse mov ax, 1 ;Function 1 of int 33h ;Int 33 ret ;Return to BASIC showmouse ENDP ;Like END SUB showmouse END ;END the whole thingNotice the PUBLIC up there? Well, that's needed for QB to access the procedure (showmouse) we've made. It's like DECLARE SUB if you think about it. Anyway, from here you'd compile the code as a .obj file then link as a .QLB file like this:
C:\PROJECT\MOUSE>tasm32 mouse.asm mouse.obj Turbo Assembler Version 5.0 Copyright (c) 1988, 1996 Borland International Assembling file: mouse.asm Error messages: None Warning messages: None Passes: 1 C:\PROJECT\MOUSE>link /qu mouse.obj Microsoft (R) Overlay Linker Version 3.69 Copyright (C) Microsoft Corp 1983-1988. All rights reserved. Run File [MOUSE.QLB]: List File [NUL.MAP]: Libraries [.LIB]: bqlb45.libTASM is used here, but any other compiler would do just fine, if it can generate .obj files (But I recommend the Borland TASM compiler). Now, you would load up QB using the library like so:
QB /L mouseWhen inside QB, you'd make a statment like this:
DECLARE SUB showmouseThat's all there is to it! Well, not quite but we'll learn more later on! I hope your busting with ideas for stuff to put into QB! I'll be back next issue with stuff on linking ASM with QB. Hey that's what this whole thing is about is'nt it? = )
|# Rating (1-100)||Description|
|Content||25/30||Info about their products, daily updated news on several topics, a top 10 for links, games, and utilities, and more!|
|Program count||18/20||Only the best games (10) and utilities (another 10), and ofcourse, the best (in my opinion) QB RPG: Shadow of Power!|
|Links count||14/20||Only 10 links, ranked by quality, not votes! All the sites are worth to check, so I still gave it 14/20 even though there aren't many links...|
|Unique||8/10||The top 10s, daily updated news, and Shadow of Power, ofcourse!|
Download the complete top10s and Shadow of power, check the top 10 links, and come back often to read the latest news!
|# Rating (1-100)||Description|
|Content||12/30||A big load of files, some tutorials, some links, a little info on their projects, but not much more.|
|Program count||13/20||100+ programs, but again, there is some thrash in it...|
|Links count||5/20||A few links, most are a little old too.|
|Quality of design||6/20||Not that good...the whole text is Times New Roman, which doesn't look that good...It's bold, which makes it even more ugly, the background image of the mainpage is missing so you can't read the text because it's thesame color as the background, and the buttons are too big and hard to read.|
Needs to get a better layout, and more content.
Nightwolf & Jorden