Copy Link
Add to Bookmark
Report
The Basix Fanzine issue 12
-IMPORTANT NOTE----------------------------------------------------------------
NOTE: Issues 1-8 of the Basix Fanzine were edited by Peter Cooper.
Issues 9-13 of the Basix Fanzine were edited by Alex Warren.
The new editor of the Basix Fanzine is David Groulx and the addresses for the fanzine
are:
ARTICLES: Basix_Fanzine@yahoo.com
OTHER ENQUIRIES ETC.: Basix_Fanzine@yahoo.com
WWW ADDRESS: http://www.come.to/basixfanzine
Please use these addresses in place of the out-of-date addresses in the Fanzine
below.
David Groulx
April 1999
-------------------------------------------------------------------------------
The Basix Fanzine - TEXT VERSION
issue 12 · september/october 1998
email: basix@dewarr.globalnet.co.uk
www: http://come.to/basixfanzine
--------------------------------------------------------------------------------
[This is the text version of The Basix Fanzine, issue 12. It is a
copy-and-paste-over of the HTML version and as a result may contain a few
formatting errors]
Welcome to issue 12 of the Basix Fanzine! You'll notice that this is the
"September/October 1998" issue - I'm trying to release this thing more
regularly, and at first I'll be aiming for a bi-monthly issue. It would be nice
if I could release it monthly, but I'm not sure if I'll ever have the time or
get enough submissions for that to be possible. Anyway, on with the show.
In this issue: improve your programming skills... include data in an EXE file...
encrypt files... and relieve boredom!
--------------------------------------------------------------------------------
Levels are represented in bold by B, I or A for Beginner, Intermediate and
Advanced respectively, or a combination. They aren't clear-cut definitions
though, so you might find something useful labelled (B) even though you've been
programming for 10 years, for example. Unless otherwise stated, the articles
apply to all major breeds of BASIC.
Most of these links point to parts of this HTML document, although some may
point to other HTML files in the Basix Fanzine directory. Each article has a
link back to this contents section to save you the bother of scrolling back.
news
COMP.LANG.BASIC.POWERBASIC PASSES
The proposed comp.lang.basic.powerbasic newsgroup is a reality!
NEW ABC MIRROR
The ABC packets now have a mirror in the UK. Which is nice.
articles
GRAPHICS IN QBASIC TUTORIAL (PART 3) (I/A)
"Hacker" aka Damian Nikodem rounds off his graphics series with a look
at randomic algorithms.
INTERMEDIATE PROGRAMMING TIPS (PART 1) (I)
Alex Warren takes a look at variable types and screen-page swapping.
INCLUDING FILES IN EXEs (I/A)
Ollie Cook demonstrates a method of including data files within your EXE
file.
FONTS: AN ALTERNATIVE GRAPHIC
Regular contributor RudeJohn ponders upon the subject of fonts.
TEN ODD MOMENTS
RudeJohn's amazing list of "things to do", for bored programmers.
BACKUS-NAUR FORM (A)
RudeJohn presents an introduction to the Backus-Naur Form.
your programs
DETECTING THE PARALLEL PORT
by Juan F. Miguez
BINARY FILE ENCRYPTION
by Daniel Bolger
CONTROL+BREAK DISABLER
by Daniel Bolger
"A SCREENSAVER TYPE THING"
by Mike Anderson
letters
PROGRAMS, MIDI & INP
from Daniel Bolger
internet resources
final words
LAST WORDS, THANKS ETC.
NEXT ISSUE
(The "From the Newsgroups" section is on holiday...)
********************************************************************************
NEWS
the latest news in the BASIC world
*** COMP.LANG.BASIC.POWERBASIC PASSES
The proposed comp.lang.basic.powerbasic newsgroup passed its vote, with 149
"yes" votes to 14 "no" votes. 100 more "yes" than "no" votes were required, and
two thirds had to be in favour in order for the group to be created - and that
has happened, so comp.lang.basic.powerbasic should be hitting your news server
soon!
*** NEW ABC MIRROR
There is a new mirror for the ABC packets in the UK, available at
http://www.cvnet.co.uk/o.cook/abc. The site also includes several useful links
so is worth a look anyway, even if you don't need the packets.
********************************************************************************
Got a BASIC news article?
pleeease?
Opening a website? Want to announce a new product that will benefit BASIC
programmers? Want to reach hundreds of readers for free? Then send your press
release to basix@dewarr.globalnet.co.uk NOW!
[The editor reserves the right to edit or omit articles recieved for publication
- if you want an advert rather than a news article, read on.]
********************************************************************************
ARTICLES
enhance your programming - this is the place to learn BASIC tips, techniques and
tricks!
*** GRAPHICS IN QBASIC TUTORIAL (PART 3), by "Hacker" aka Damian Nikodem ·
Hacker@alphalink.com.au
Intro :
Today I will cover RANDOMIC ALGORITHMS. You will probably be asking yourself
what are they and how will they improve the graphics in my programs. Well
randomic algorythms add a twist of reality to your graphics. Take a look around
you is everything around you in total order is there NO light shining off
ANYTHING near you. If you notaice nearly everything has a random element. So
this is where I will base my tutorial on today.
Grass Routine:
Now lets just say that your writing a RPG and you have to write a graphics
routine. It most likeley looks kinda like this (asuming you are doing a 15x15
tileset)
'Start CODE
SCREEN 13
LINE (1,1)-(15,15),2 , BF
'END CODE
Well try this little program instead:
'Start CODE
SCREEN 13
RANDOMIZE TIMER
FOR x = 1 TO 15
FOR y = 1 TO 15
z = INT(RND * 2) + 1
IF z = 2 THEN z = 10
IF z = 1 THEN z = 2
PSET (x, y), z
NEXT y
NEXT x
'END code
Does that look a bit better? It should. But its still missing something isnt it,
it dosent have enough colors. Because we are using VGA mode 13h(Screen 13) we
have 255 colors to play with theres bound to be at least 1 GREEN! WAIT. there is
also dirt on the ground so we have to add BROWN and if you look almost always
there is about 2 browns before a green so here is a small EDIT of the program
above:
'Start CODE
SCREEN 13
RANDOMIZE TIMER
FOR x = 1 TO 15
FOR y = 1 TO 15
z2 = INT(RND * 8) + 1
z = z2 + 186
PSET (x, y), z
NEXT y
NEXT x
'End CODE
Now do you see the benifits of randomized graphics. If you downloaded quake2
unzip it and play it. While you are doing that take a look at some of the
graphics they look fuzzy (Unless you have a 3d card). If the graphics werent
fuzzy they would look hopeless. Because of the time that it would take to
"smooth" the graphic. So if you have some kind of graphic that dosent look quite
right try stuffing around with the colors for a bit if done properly it will
look ok if not good.
This is the end of what is going to be the last tutorial in this series because
I dont have enough time to write them. But eventually I might be able to write
another tutorial series on sound or even 3d calculations (pick up
where the other guys one left off)
- Hacker (Hacker@alphalink.com.au)
*** INTERMEDIATE PROGRAMMING TIPS (PART 1), by Alex Warren ·
alexwarren@writeme.com
I hope this will become a fairly regular feature of the fanzine, designed to
help those programmers who have only been programming in BASIC for a little
while to improve their programs.
The trouble with the term "intermediate" is that it is rather vague - in this
series I'll classify an "intermediate" programmer as one who can make a program
and knows the really basic things such as file I/O, simple graphics, etc., and
would like to make their programs better (faster, more user-friendly,
easier-to-read, or whatever else a "better" program is)
I'm not sure how many parts this series will have, nor what it exactly it will
cover - if anyone has any ideas or would like to donate a tip or two, please
feel free to send some in.
Anyway, are you sitting comfortably? Then I'll begin.
TIP 1: VARIABLES AND USER-DEFINED VARIABLE TYPES
This is two tips in one really...
We all know what a variable is (I hope) and we all know that they come in
several delicious flavours - strings, integers, long integers, and
floating-point variables, for example, which each have their own uses. As a
programmer, you should know the best circumstances in which to use each variable
type as there are differences between them in terms of speed and in what they
can store.
Obviously, a string is pretty much self-explanatory, and you would never (I
hope) use it to store a number (other than a phone number etc. which would need
formatting). It is up to you to decide when to use the other types of variable.
By default, BASIC will choose a floating-point variable if you don't specify
which type the variable is going to be, and this will really slow your program
down if it is doing a lot of calculations that don't require that kind of
precision. If your variable is never going to store anything with a decimal
point, declare it to be an integer and it will work more quickly.
If you're lazy, the easiest way to make BASIC use integers by default instead of
floating-point variables is to stick
DEFINT A-Z
at the beginning of your program. Better though, would be to explicitly state
the variable type, and you can do this in two ways:
integ% = 3
would set an integer variable called "integ%" to 3, as you should know. Or, you
could use:
DIM integ AS INTEGER
integ = 3
This would set an integer variable "integ", without a percent sign, to 3.
Which method you choose is up to you - if you have a large program it may be
better to use the second method as then you will be able to change the
variable's type by changing one word, without having to go all through the
program changing the % signs to # signs, or whatever.
Integers are the fastest variable types but they have disavantages. Apart from
the obvious fact that they can't contain anything with decimal places, they also
cannot store numbers greater than 32767 or less than -32768. (if you try to set
integ% to 40000 you get an "Overflow" error). If you need bigger integer
numbers, use a long integer. This can hold values from -2,147,483,648 to
+2,147,483,647 and takes up twice as many bytes of memory as a short integer,
and therefore will be a bit slower.
The various variable types, their limits and their memory requirements should be
discussed in more detail in the help file or manual for your particular flavour
of BASIC.
Visual Basic for Windows adds a few more flavours such as a Boolean one, which
can be either True or False, and a Variant, which can be just about anything. If
you have a BASIC compiler that is more modern than QuickBasic, you should have a
few more too, such as a currency type for example - have a look through the
types which are available, and see which types will suit your data best.
"User-defined" variable types are very useful. These are basically blocks of
other variables all stuck together. The following code shows an example of their
use:
TYPE persontype
thename AS STRING * 50
phonenumber AS STRING * 20
numberofhouses AS INTEGER
salary AS LONG
height AS SINGLE
END TYPE
DIM people(5) AS persontype
people(1).thename = "Bill Gates"
people(1).phonenumber = "1234-567-890"
people(1).numberofhouses = 353
people(1).salary = 500000000
people(1).height = 1.96
(All figures made up, in case you hadn't guessed... though maybe they aren't all
that far from the truth <g>)
As can be seen, a variable called "people" of type "persontype" is created, with
five elements. This only needs to be done once - so you don't need to DIM arrays
for thename, phonenumber, numberofhouses, etc., and it can be clearly seen from
the code that the phonenumber and salary are related to the same thing (in this
case, our old mate Bill). This is more readable than setting
phonenumber(1)="1234-567-890" and height(1)=1.96, etc., for example.
It also has the advantage that we can quickly, easily and efficiently copy all
the data to another person or record. If you add the line
people(2) = people(1)
and then read the value of people(2).salary, you will see that all five pieces
of data have been copied with this single statment. This is ever so much easier
than having five statements such as numhouses(2)=numhouses(1) which would have
been necessary had we not used user-defined types. So, as you can see,
user-defined types can make life a lot, lot easier, especially if you are
dealing with large amounts of data. They're also useful because you can pass
them to functions - much easier than passing each element to a function. In VB5
you can also declare functions to return user-defined data types, though I don't
think this is possible in QB. Anyway, as you can see, user-defined TYPEs are a
powerful tool which will make your code cleaner, easier to code and easier to
understand. Use them!
TIP 2: SCREEN PAGE SWAPPING
Ever tried making some graphics animation in your BASIC code only to find that
it flickered so much it gave you a migraine? No? Then you were one of the lucky
ones...
Seriously though, flickering doesn't look nice and it happens when you clear the
screen, draw a graphic, clear it again, draw it again, etc. - all that clearing
becomes really obvious and looks terrible. However, there is a way round it,
which is screen page swapping, as this program will show you.
' Screen swapping demo, by Alex Warren
' from the Basix Fanzine, Issue 12
RANDOMIZE TIMER
DEFINT A-Z
SCREEN 0: CLS : WIDTH 80
PRINT "Press any key to start the screen swapping demo..."
DO: LOOP WHILE INKEY$ = ""
SCREEN 7
PRINT "Pages are being drawn while this page is"
PRINT "being displayed..."
FOR i = 1 TO 7
SCREEN 7, , i, 0
FOR j = 0 TO 200 STEP i
LINE (0, j)-(320, j), i
NEXT j
FOR j = 0 TO 320 STEP i
LINE (j, 0)-(j, 200), i
NEXT j
FOR j = 1 TO i * 1000
PSET (RND * 320, RND * 200), RND * 15
NEXT j
LOCATE 2, 2
COLOR i + 1
PRINT "SCREEN PAGE"; i
NEXT i
BEEP
SCREEN 7, , 0, 0
LOCATE 4, 1
PRINT "Press the space bar to go to the next"
PRINT "page, and press [ESC] when done"
cpage = 1
DO
FOR cpage = 1 TO 7
DO
a$ = INKEY$
LOOP WHILE a$ <> CHR$(27) AND a$ <> " "
IF a$ = CHR$(27) THEN END
SCREEN 7, , , cpage
NEXT cpage
LOOP
What this code does is draw seven pages of spectacular graphics action (well,
lines and dots) into seven pages of video memory, completely hidden from view.
It then instantly switches between them - no flicker, no waiting for the screen
to draw - the page just pops into view.
If you examine the code you'll see the secret behind this trickery is some extra
numbers given to the SCREEN statement. The first number is the mode number which
you usually use with the screen statement. The third and fourth numbers control
the "apage" and the "vpage" respectively. The "apage" is the one that LINE
statements, PRINT statements and in fact any statements that draw to the screen
will be sent to. The "vpage" is the one the user will see while all this is
going on. (The second number in the SCREEN statement can be safely ignored -
just stick a space there instead). So, if you draw all the stuff to the apages
and then flick through the vpages, the pages that were drawn pop up instantly.
This technique is very useful for animation. The easiest way to use it for
animation is to use something like:
cpage% = 0
DO
SCREEN 7, , cpage%, 1 - cpage%
' insert code here to draw screen
cpage% = 1 - cpage%
LOOP
This will alternate between the pages; whenever page 0 is displayed, page 1 is
being drawn to, and then vice versa. The 1-cpage% bits are a useful shortcut -
because 1-0=1 and 1-1=0 - so they return whatever cpage% "isn't", without the
need for writing IF statements such as IF cpage% = 1 THEN cpage% = 0, etc.
Look in the help file for more information on screen pages. Screen 7, as used in
the demonstration program, can use up to 7 on a VGA or better monitor. Screen
13, unfortunately, only has room for one, so page swapping is not possible
directly from QB code, even though a modern SVGA monitor has several times the
256K memory that one screen 13 page will use. There are probably interrupts that
will let you do it... perhaps this could be the subject of a future article.
That's all for part 1 of my "Intermediate Programming Tips" series - if anybody
can think of anything they'd like me to cover in future parts, please let me
know - address at the top of the page.
*** INCLUDING FILES IN EXEs, by Ollie Cook · oliver.cook@bigfoot.com
This is the first programming article that I've ever written so I hope that I
make myself clear enough to be understood. This article is going to take the
form of a tutorial which will allow you to get this technique working, and will
give you scope to adapt and update the source included. We're going to make a
program which will play a WAV file, using only one executable.
Let's get started. Get the code below loaded up. It includes a lot of code
written by Mike Huff, and is simply to play the WAV were going to include, at a
decent quality.
' +---------------------------------+
' Ý This program is to accompany an Ý
' Ý article written by Ollie Cook Ý
' Ý about including files in EXEs. Ý
' Ý It makes use of DMA Play by Ý
' Ý Mike Huff (1996). Ý
' Ý oliver.cook@bigfoot.com - Ollie Ý
' +---------------------------------+
DECLARE FUNCTION SpeakerStatus% ()
DECLARE FUNCTION DMAStatus% ()
DECLARE FUNCTION DMADone% ()
DECLARE FUNCTION ResetDSP% ()
DECLARE SUB FMVolume (Right%, Left%, Getvol%)
DECLARE SUB VocVolume (Right%, Left%, Getvol%)
DECLARE SUB MasterVolume (Right%, Left%, Getvol%)
DECLARE SUB MicVolume (Gain%, Getvol%)
DECLARE SUB LineVolume (Right%, Left%, Getvol%)
DECLARE SUB CDVolume (Right%, Left%, Getvol%)
DECLARE SUB InputSource (InputSrc%, GetSrc%)
DECLARE SUB WriteDSP (byte%)
DECLARE SUB SetStereo (OnOff%)
DECLARE FUNCTION ReadDSP% ()
DECLARE SUB WriteDAC (byte%)
DECLARE SUB SpeakerState (OnOff%)
DECLARE SUB DMAState (StopGo%)
DECLARE FUNCTION ReadDAC% ()
DECLARE SUB DMAPlay (Segment&, offset&, Length&, Freq&)
DECLARE SUB DMARecord (Segment&, offset&, Length&, Freq&)
DECLARE SUB GetBLASTER (DMA%, BasePort%, IRQ%)
DECLARE FUNCTION DSPVersion! ()
COMMON SHARED BasePort%, LenPort%, Channel%, alarmtime$
GetBLASTER Channel%, BasePort%, IRQ% 'Parses BLASTER environment
SpeakerState 1 'turn the speaker on
MasterVolume Right%, Left%, -1 'this puts the mixer volumes in Right% and
Left%
MasterVolume 8, 8, 0 '15,15,0 cranks the master volume all the way
up.
DIM WavBuffer(1 TO 1) AS STRING * 32767 'Make a 32k buffer for file.
DIM RIFFsearch(1 TO 1) AS STRING * 4 'Make a search buffer
Filename$ = "exetute.exe"
Freq& = 8000
offset& = 1
OPEN Filename$ FOR BINARY AS #1
DO
GET #1, 44 + offset& + (32767 * CurrentPlay!), WavBuffer(1)'Get 32k from file
(skip header on WAV)
CurrentPlay! = CurrentPlay! + 1
Length& = LOF(1) - 44 - offset&
IF Length& > 32767 THEN Length& = 32767 'Adjust length if needed to
32k
DMAPlay VARSEG(WavBuffer(1)), VARPTR(WavBuffer(1)), Length&, Freq&
DO UNTIL a = 11500: a = a + 1: LOOP: a = 0
LOOP UNTIL EOF(1)
CLOSE
CLS
PRINT "Playing Sound and Waiting 5 Seconds for It to Finish"
SLEEP 5
PRINT "The END"
SUB CDVolume (Right%, Left%, Getvol%)
OUT BasePort% + 4, &H28
IF Getvol% THEN
Left% = INP(BasePort% + 5) \ 16
Right% = INP(BasePort% + 5) AND &HF
EXIT SUB
ELSE
OUT BasePort% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB
FUNCTION DMADone%
Count% = INP(LenPort%)
Count2% = INP(LenPort%)
Count& = CLNG(Count% + 1) * CLNG(Count2% + 1)
IF (Count& - 1) >= &HFFFF& THEN junk% = INP(DSPDataAvail%): DMADone% = -1
END FUNCTION
SUB DMAPlay (Segment&, offset&, Length&, Freq&)
' Transfers and plays the contents of the buffer.
Length& = Length& - 1
Page% = 0
MemLoc& = Segment& * 16 + offset&
SELECT CASE Channel%
CASE 0
PgPort% = &H87
AddPort% = &H0
LenPort% = &H1
ModeReg% = &H48
CASE 1
PgPort% = &H83
AddPort% = &H2
LenPort% = &H3
ModeReg% = &H49
CASE 2
PgPort% = &H81
AddPort% = &H4
LenPort% = &H5
ModeReg% = &H4A
CASE 3
PgPort% = &H82
AddPort% = &H6
LenPort% = &H7
ModeReg% = &H4B
CASE ELSE
PRINT "DMA channels 0-3 only are supported."
EXIT SUB
END SELECT
OUT &HA, &H4 + Channel%
OUT &HC, &H0
OUT &HB, ModeReg%
OUT AddPort%, MemLoc& AND &HFF
OUT AddPort%, (MemLoc& AND &HFFFF&) \ &H100
IF (MemLoc& AND 65536) THEN Page% = Page% + 1
IF (MemLoc& AND 131072) THEN Page% = Page% + 2
IF (MemLoc& AND 262144) THEN Page% = Page% + 4
IF (MemLoc& AND 524288) THEN Page% = Page% + 8
OUT PgPort%, Page%
OUT LenPort%, Length& AND &HFF
OUT LenPort%, (Length& AND &HFFFF&) \ &H100
OUT &HA, Channel%
IF Freq& < 23000 THEN
TimeConst% = 256 - 1000000 \ Freq&
WriteDSP &H40
WriteDSP TimeConst%
WriteDSP &H14
WriteDSP (Length& AND &HFF)
WriteDSP ((Length& AND &HFFFF&) \ &H100)
ELSE
IF DSPVersion! >= 3 THEN
TimeConst% = ((65536 - 256000000 \ Freq&) AND &HFFFF&) \ &H100
WriteDSP &H40
WriteDSP TimeConst%
WriteDSP (Length& AND &HFF)
WriteDSP ((Length& AND &HFFFF&) \ &H100)
WriteDSP &H91
ELSE
PRINT "You need a Sound Blaster with a DSP v3.x+ to play at high speed."
EXIT SUB
END IF
END IF
END SUB
SUB DMARecord (Segment&, offset&, Length&, Freq&)
Length& = Length& - 1
MemLoc& = Segment& * 16 + offset&
Page% = 0
SELECT CASE Channel%
CASE 0
PgPort% = &H87
AddPort% = &H0
LenPort% = &H1
ModeReg% = &H44
CASE 1
PgPort% = &H83
AddPort% = &H2
LenPort% = &H3
ModeReg% = &H45
CASE 2
PgPort% = &H81
AddPort% = &H4
LenPort% = &H5
ModeReg% = &H46
CASE 3
PgPort% = &H82
AddPort% = &H6
LenPort% = &H7
ModeReg% = &H47
CASE ELSE
EXIT SUB
END SELECT
OUT &HA, &H4 + Channel%
OUT &HC, &H0
OUT &HB, ModeReg%
OUT AddPort%, MemLoc& AND &HFF
OUT AddPort%, (MemLoc& AND &HFFFF&) \ &H100
IF (LongByte& AND 65536) THEN Page% = Page% + 1
IF (LongByte& AND 131072) THEN Page% = Page% + 2
IF (LongByte& AND 262144) THEN Page% = Page% + 4
IF (LongByte& AND 524288) THEN Page% = Page% + 8
OUT PgPort%, Page%
OUT LenPort%, Length& AND &HFF
OUT LenPort%, (Length& AND &HFFFF&) \ &H100
OUT &HA, Channel%
IF Freq& <= 23000 THEN
TimeConst% = 256 - 1000000 \ Freq&
WriteDSP &H40
WriteDSP TimeConst%
WriteDSP &H24
WriteDSP (Length& AND &HFF)
WriteDSP ((Length& AND &HFFFF&) \ &H100)
ELSE
IF DSPVersion! >= 3 THEN
TimeConst% = ((65536 - 256000000 / Freq&) AND &HFFFF&) \ &H100
WriteDSP &H40
WriteDSP TimeConst%
WriteDSP (Length& AND &HFF)
WriteDSP ((Length& AND &HFFFF&) \ &H100)
WriteDSP &H99
ELSE
PRINT "You need a Sound Blaster with a DSP 3.x+ to record at high speed."
EXIT SUB
END IF
END IF
END SUB
SUB DMAState (StopGo%)
' Stops or continues DMA play.
IF StopGo% THEN WriteDSP &HD4 ELSE WriteDSP &HD0
END SUB
FUNCTION DSPVersion!
' Gets the DSP version.
WriteDSP &HE1
Temp% = ReadDSP%
Temp2% = ReadDSP%
DSPVersion! = VAL(STR$(Temp%) + "." + STR$(Temp2%))
END FUNCTION
SUB FMVolume (Right%, Left%, Getvol%)
OUT BasePort% + 4, &H26
IF Getvol% THEN
Left% = INP(BasePort% + 5) \ 16
Right% = INP(BasePort% + 5) AND &HF
EXIT SUB
ELSE
OUT BasePort% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB
SUB GetBLASTER (DMA%, BasePort%, IRQ%)
' This subroutine parses the BLASTER environment string and returns settings.
IF LEN(ENVIRON$("BLASTER")) = 0 THEN PRINT "BLASTER environment variable not
set.": EXIT SUB
FOR Length% = 1 TO LEN(ENVIRON$("BLASTER"))
SELECT CASE MID$(ENVIRON$("BLASTER"), Length%, 1)
CASE "A"
BasePort% = VAL("&H" + MID$(ENVIRON$("BLASTER"), Length% + 1, 3))
CASE "I"
IRQ% = VAL(MID$(ENVIRON$("BLASTER"), Length% + 1, 1))
CASE "D"
DMA% = VAL(MID$(ENVIRON$("BLASTER"), Length% + 1, 1))
END SELECT
NEXT
END SUB
SUB InputSource (InputSrc%, GetSrc%)
OUT BasePort% + 4, &HC
IF GetSrc% THEN
InputSrc% = INP(BasePort% + 5) AND 2 + INP(BasePort% + 5) AND 4
ELSE
OUT BasePort% + 5, InputSrc% AND 7
END IF
END SUB
SUB LineVolume (Right%, Left%, Getvol%)
OUT BasePort% + 4, &H2E
IF Getvol% THEN
Left% = INP(BasePort% + 5) \ 16
Right% = INP(BasePort% + 5) AND &HF
EXIT SUB
ELSE
OUT BasePort% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB
SUB MasterVolume (Right%, Left%, Getvol%)
OUT BasePort% + 4, &H22
'PRINT BasePort%
IF Getvol% THEN
Left% = INP(BasePort% + 5) \ 16
Right% = INP(BasePort% + 5) AND &HF
EXIT SUB
ELSE
OUT BasePort% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB
SUB MicVolume (Volume%, Getvol%)
OUT BasePort% + 4, &HA
IF Getvol% THEN
Volume% = INP(BasePort% + 5) AND &HF
EXIT SUB
ELSE
OUT BasePort% + 5, Volume% AND &HF
END IF
END SUB
FUNCTION ReadDAC%
' Reads a byte from the DAC.
WriteDSP &H20
ReadDAC% = ReadDSP%
END FUNCTION
FUNCTION ReadDSP%
' Reads a byte from the DSP
DO
LOOP UNTIL INP(BasePort% + 14) AND &H80
ReadDSP% = INP(BasePort% + 10)
END FUNCTION
FUNCTION ResetDSP%
' Resets the DSP
OUT BasePort% + 6, 1
FOR Count% = 1 TO 4
junk% = INP(BasePort% + 6)
NEXT
OUT BasePort% + 6, 0
IF INP(BasePort% + 14) AND &H80 = &H80 AND INP(BasePort% + 10) = &HAA THEN
ResetDSP% = -1
ELSE
ResetDSP% = 0
END IF
END FUNCTION
SUB SetStereo (OnOff%)
OUT BasePort% + 4, &HE
IF OnOff% THEN OUT BasePort% + 5, 2 ELSE OUT BasePort% + 5, 0
END SUB
SUB SpeakerState (OnOff%)
' Turns speaker on or off.
IF OnOff% THEN WriteDSP &HD1 ELSE WriteDSP &HD3
END SUB
FUNCTION SpeakerStatus%
OUT BasePort% + 4, &HD8
IF INP(BasePort% + 5) = &HFF THEN SpeakerStatus% = -1 ELSE SpeakerStatus% = 0
END FUNCTION
SUB VocVolume (Right%, Left%, Getvol%)
OUT BasePort% + 4, &H4
IF Getvol% THEN
Left% = INP(BasePort% + 5) \ 16
Right% = INP(BasePort% + 5) AND &HF
EXIT SUB
ELSE
OUT BasePort% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB
SUB WriteDAC (byte%)
' Writes a byte to the DAC.
WriteDSP &H10
WriteDSP byte%
END SUB
SUB WriteDSP (byte%)
' Writes a byte to the DSP
DO
LOOP WHILE INP(BasePort% + 12) AND &H80
OUT BasePort% + 12, byte%
END SUB
Now. If we're going to append the WAV onto the end of the EXE, once compiled, we
are going to have to know where the EXE ends and the WAV begins. Luckily for us,
all WAV files begin with the same string: "RIFF". So, what we need to do is to
make the EXE scan itself until it finds that string. So to do that, replace
offset& = 1 with this:
stringmatch$ = CHR$(82) + CHR$(73) + CHR$(70) + CHR$(70)
OPEN Filename$ FOR BINARY AS #1
FOR loop1& = 1 TO LOF(1) - 4
GET #1, loop1&, RIFFsearch(1)
IF RIFFsearch(1) = stringmatch$ THEN offset& = loop1&: EXIT FOR
NEXT
CLOSE #1
IF offset& = 0 THEN CLS : PRINT "No WAV file detected": STOP
That will scan the file into a buffer, four bytes at a time, and check if what's
in the buffer matches the header we want. We use stringmatch$ = CHR$(82) +
CHR$(73) + CHR$(70) + CHR$(70) instead of stringmatch$ = "RIFF" because if we
did that the routine would pick up the wrong 'RIFF' in the file.
Now that the program knows where to find the WAV it's our job just to compile
the program and add the WAV onto the end. (To make the sound play correctly
replace 11000 in Freq& = 11000 with the actual frequency of the sound you want
to attach, in Hertz).
OK, now compile the code to 'exetute.exe', as that's what we referenced to in
the source. Now from a DOS prompt type the following:
copy /b exetute.exe + wavfile.wav
That will add on the WAV file to the EXE. The EXE knows where the WAV starts and
when run will play it, thanks to Mike Huff, and a little devious thinking.
Please pass on any comments you may have on this article to me at
oliver.cook@bigfoot.com - It's my first article, I hope you liked it.
*** FONTS: AN ALTERNATIVE GRAPHIC
NB: This article was originally in HTML and contained a lot of formatting, and a
list of useful font characters which would have been impossible to reproduce in
this text version. As a result, some of this article has been omitted.
Author's Forward
This article is not about programming , as such. However, it does suggest a
method for improving webpages or other HTML-ized documents related to
programming. IMHO, webpages and documentation both suffer a great deal from
clumsy, inadequate type. This article is my own humble(?) attempt to improve
upon this desperate situation.
Symbology 101
One thing is certain, if something is screwed up beyond all reason then human
beings have had a hand in it. So it is with the internet. I find it amazing that
with all of the man-hours which the internet commands, no organization has
(inadvertently) contributed more to standardizing how text is displayed to the
average web-head than -- I really hate to admit this -- Microsoft. If that
thought doesn't make you ralf, nothing will.
IMHO, the most important aspect of internet communication is text. To produce
text you need type. If two people are to communicate successfully over the
internet, then they need type which is well-suited to the task. This is not how
things have worked out. Webpages, for example, present a particularly bleak
landscape.
Fonts are very much OS specific. Needless to say, OS manufacturers are not
overly concerned with inter-system compatibility regardless of how much it might
benefit the user. Further confusion ensues due to the fact that almost anyone
can learn to author fonts for public distribution. People just love their chaos,
don't they?
That said, I'd like to suggest the following to prospective webpage authors:
Use the <FONT FACE="font-name,font-name,font-name,...">...</FONT> tag-pair for
special characters found in fonts common to the Windows operating system. It's
relatively simple and requires a lot less effort or storage than graphic
elements.
To anyone not running Windows all I can say is, "What in the blue blazes do you
expect me to do about it?"
According to Microsoft, the font styles common to Win 3.x and Win 95 are:
Arial
Courier New
Times New Roman
Wingdings
Symbol
The Symbol font offers a variety of math and logic related characters for the
programmer who lusts after a great looking website. The translation tables at
the end of this paper provide all of the information you will need to use
characters from the Symbol font in your webpages or other HTML-ized documents.
Obviously, anyone reading those pages will need to have symbol.ttf installed on
their system.
Some characters may be represented by either a numeric or character entity,
while others have only a numeric entity as an identifier. Using entities to
represent characters is very simple. All you need to specify is the name of the
font, and an identifier for each of the characters that you want to reproduce.
For example, joining the following lines
<FONT FACE="Symbol">
B Í A Û ("
bÎB)(bÎA)
</FONT>
will produce [the same as -ed]
<FONT FACE="Symbol">
B Í A Û ("bÎB)(bÎA)
</FONT>
And that's all there is to it. Now get out there and kick some serious butt!
[Symbol tables removed -ed]
C'ya,
RudeJohn
"I'm rude. It's a job."
*** TEN ODD MOMENTS
Disclaimer
The opinions expressed by RudeJohn do not necessarily reflect those of the Basix
Fanzine or its staff. In fact, they probably disagree with me entirely. Everyone
else does. <bfg>
Introduction
Below is a short list of exercises suitable for passing the odd moment or two
when you're bored silly and can't think of anything better to do. Then again, if
you're that bored maybe you should be looking for a job so that you can afford
to move out of your parent's basement. Think about it.
One
An automorphic number is a natural number which appears at the end of its
square, e.g.,
5² = 25
25² = 625
625² = 390625
Write a program to find more automorphic numbers.
Two
The Goldbach conjecture states that every even number can be represented as the
sum of two prime numbers. Show that this is true for the first 1000 even
numbers.
Three
A Mersenne prime is a prime number of the form
2^x - 1 [2 to the power of x - 1 -ed]
where x is also prime, e.g., 2³ - 1 = 7.
Write a program to find several more Mersenne primes.
Four
A perfect number is a natural number equal to the sum of all of its exact
divisors except itself, e.g.,
28 = 1 + 2 + 4 + 7 + 14
Write a program to find at least 3 more perfect numbers.
Five
Extend the notion of automorphism to higher integral powers, e.g.,
5³ = 125
25³ = 15625
625³ = 244140625
Write an efficient program to search for n-th power automorphic numbers.
Six
Let A and B be two unequal natural numbers. If A is the sum of all of the exact
divisors of B (excluding B itself), and if B is the sum of all of the exact
divisors of A (excluding A itself), then A and B are amicable. For example, the
sum of the exact divisors of 220 (excluding 220 itself) is equal to 284, and the
sum of the exact divisors of 284 (excluding 284 itself) is equal to 220. Thus,
220 and 284 are amicable. Isn't that nice?
Write a program to find more amicable numbers. Or else.
Seven
This exercise doesn't require a program, but you may want to write one anyway.
In fact, you may want to write several! <g>
Let's say that we are looking for a simple test for a random integer generator.
When do you think it would be reasonable to claim that each digit should occur
10% of the time? Less than 10%? More than 10%?
If we are generating random integers in the range of say, 0 to 999, then
shouldn't every number be considered as a string of digits of equal length? In
other words, shouldn't the number 2 be interpreted as 002? This approach will
certainly effect the frequency count for the digit zero. What do you think?
Eight
Write a program that will accept a simple arithmetical expression as a string
and check it for unmatched parentheses. And send me a case of scotch.
Nine
Write a program to determine whether a simple algebraic expression is
syntactically correct. This means that an expression such as X = 5 + Y / ( 3 - 3
) is acceptable because it is syntactically correct even though it is
mathematically invalid. Assume that variable names consist of a single letter,
and allow + and - to be used as unary operators, e.g., X * - Y is syntactically
correct but X - * Y is not. For now, restrict operations to +, -, *, and /.
Ten
Write a program that reads a simple arithmetical statement, checks it for
syntactical correctness, and then evaluates that statement using the following
rules of precedence:
both unary operators share equal precedence
both unary operators precede *
* precedes /
/ precedes binary +
binary + precedes binary -
The overall evaluation of an expression procedes from left to right. Parts of an
expression which are delimited by parentheses are evaluated before parts of the
expression which are not. If parentheses are nested, then evaluation procedes
from the innermost pair to the outermost pair. When confronted with two or more
sub-expressions of equal precedence, evaluation procedes from left to right. [[[
Do not depend upon your programming language-of-choice to automatically enforce
any of these rules. The point of the exercise is for you to define the
implementation of ( ), +, -, *, and /. ]]]
Accordingly, -5 + - -7 * - 4 / -2 + + 11 = 20.
C'ya,
RudeJohn
"I'm rude. It's a job."
*** BACKUS-NAUR FORM
Preface
Recently, I spotted a post enquiring about the existence of a BNF for some
flavour of BASIC. Since BASIC newsgroups seem to attract a lot of new and
inexperienced programming hobbyists, it's doubtful that any more than a handful
of the people who read that post understood the question. Not that you need an
advanced degree or anything, it's just that BNF doesn't come up much in
conversation with BASIC programmers. Which is unfortunate, because the BNF -- or
Backus-Naur form -- paints a wonderfully compact and powerful picture of a
language.
The purpose of this monograph is to introduce the reader to the Backus-Naur form
of notation through a series of easy-to-understand examples. This paper is by no
means an exhaustive treatment; it is meant to be nothing more than a bare-bones
introduction to the subject. Enjoy!
History <yawn>
Around 1959, John Backus -- one of the thirteen people on the Algol 60 committee
-- proposed what is today know as the Backus-Naur form of notation for
describing part of the syntax of Algol 60. Peter Naur, of the University of
Copenhagen, is associated with this notation because of his modifications and
extensive use of BNF as editor of the Algol 60 report.
The ideas behind BNF were advanced by Noam Chomsky, a linguist, in 1956. So why
isn't it called CBNF? I'll bet Noam would like to hear the answer to that one.
I Never Meta-Language I Didn't Like
We will begin by examining how BNF may be used to describe digits and integer
constants. In BNF, the fact that 1 is a digit is expressed by
(R1) <digit> ::= 1
"(R1)" is just a label. The term <digit> is delineated by angular brackets to
signify that it is a meta-linguistic entity, i.e., it is part of the language we
are using to describe the language under discussion. Meta-linguistic terms
delineated by angular brackets are typically referred to as nonterminal symbols,
or nonterminals. Characters of the language under discussion, such as the digit
1, are referred to as terminals.
The rule (R1) is called a production (or rewriting) rule. Its left part is a
nonterminal, and its right part is a nonempty, finite sequence of terminals and
nonterminals. The symbol "::=" is read "may be composed of" (or something
similar) so the rule (R1) is read
A digit may be composed of the sequence of symbols: 1
To allow the digits 0 and 1 we could write
<digit> ::= 0
<digit> ::= 1
We can combine these two rules using the symbol |, read as "or", to obtain
<digit> ::= 0 | 1
A more comprehensive set of rules might take the form
(R2.1) <constant> ::= <digit>
(R2.2) <constant> ::= <constant> <digit>
(R2.3) <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
The rules (R2.x) form a grammar for the language of <constant>s. The sentences
of the language are the sequences of terminals that can be derived from the
nonterminal <constant>. If we use the symbol => to indicate the process of
rewriting, the sentence 187 may be derived as follows:
<constant> => <constant> <digit> (R2.2)
=> <constant> 7 (R2.3)
=> <constant> <digit> 7 (R2.2)
=> <constant> 87 (R2.3)
=> <digit> 87 (R2.1)
=> 187 (R2.3)
Let " =>* " represent a sequence of zero or more single derivations (or
rewrites) using the production rules of our grammar. The previous derivation may
then be restated:
<constant> =>* 187.
A Grammar for Simple Arithmetic Expressions
The following grammar uses addition, subtraction, multiplication, parenthesized
expressions, and integer constants as operands.
(R3.1) <expression> ::= <expression> + <expression>
(R3.2) <expression> ::= <expression> - <expression>
(R3.3) <expression> ::= <expression> × <expression>
(R3.4) <expression> ::= ( <expression> )
(R3.5) <expression> ::= <constant>
According to this grammar, we derive <expression> =>* 3 × ( 4 - 7 ) as follows:
<expression> => <expression> × <expression> (R3.3)
=> <expression> × ( <expression> ) (R3.4)
=> <expression> × ( <expression> - <expression> ) (R3.2)
=> <constant> × ( <expression> - <expression> ) (R3.5)
=> <constant> × ( <constant> - <expression> ) (R3.5)
=> <constant> × ( <constant> - <constant> ) (R3.5)
=> <digit> × ( <constant> - <constant> ) (R2.1)
=> <digit> × ( <digit> - <constant> ) (R2.1)
=> <digit> × ( <digit> - <digit> ) (R2.1)
=> 3 × ( <digit> - <digit> ) (R2.3)
=> 3 × ( 4 - <digit> ) (R2.3)
=> 3 × ( 4 - 7 ) (R2.3)
The syntax tree for <expression> =>* 3 × ( 4 - 7 ) has the form:
<expression>
/ | \
<expression> × <expression>
| / | \
<constant> <expression> - <expression>
| | |
<digit> <constant> <constant>
| | |
3 <digit> <digit>
| |
4 7
The problem with syntax trees is that they don't specify the order in which some
production rules are applied. For instance, the syntax tree above doesn't
indicate whether <digit> ::= 4 precedes <digit> ::= 7, or vice versa.
Every derivation has a corresponding syntax tree, but more than one derivation
can correspond to the same tree. These derivations are considered to be
equivalent. For example,
<expression> => <expression> + <expression>
=> <constant> + <expression>
=> <constant> + <constant>
=> <digit> + <constant>
=> <digit> + <digit>
=> 2 + <digit>
=> 2 + 3
and
<expression> => <expression> + <expression>
=> <expression> + <constant>
=> <constant> + <constant>
=> <constant> + <digit>
=> <digit> + <digit>
=> <digit> + 3
=> 2 + 3
both correspond to the same syntax tree and are therefore considered to be
equivalent. <shrug>
Garden of Ambiguitiy
Consider <expression> =>* <expression> × <expression> - <expression>. This
sentence satisfies both of the syntax trees
<expression>
/ | \
<expression> × <expression>
/ | \
<expression> - <expression>
and
<expression>
/ | \
<expression> - <expression>
/ | \
<expression> × <expression>
Any grammar that allows more than one syntax tree for some sentence is called
ambiguous. The term is apt because if a sentence has two different syntax trees
then it can be parsed in two different ways. This can result in a particular
interpretation being assigned arbitrarily, or worse, inadvertently. Obviously,
whether 2 × 4 - 3 = 5 or 2 depends upon how we parse the sentence.
Dead Presidents
Fortunately, it isn't difficult to specify an unambiguous grammar for simple
arithmetic expressions. The solution does, however, require us to introduce a
few new nonterminals.
<expression> ::= <term> | <expression> + <term> | <expression> - <term>
<term> ::= <factor> | <term> × <factor>
<factor> ::= <constant> | ( <expression> )
<constant> ::= <digit>
<constant> ::= <constant> <digit>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
From this grammar, it's clear that multiplication takes precedence over addition
and subtraction. Thus, if you draw the syntax tree for <expression> =>* 2 + 3 ×
4 you'll find that the result is 14, not 20. We can, of course, use parentheses
to supercede precedence.
Extensions
As usual, people just can't leave well enough alone. In an effort to improve on
BNF, some smart-ass suggested using braces to indicate repetition, i.e., {xyz}
denotes zero or more occurrences of the sequence of symbols xyz.
Using this extension, we can rewrite our grammar for simple arithmetic
expressions as
<expression> ::= <term> { + <term> | - <term> }
<term> ::= <factor> { × <factor> }
<factor> ::= <constant> | ( <expression> )
<constant> ::= <digit> { <digit> }
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
The Last Word
I admire Harlan Ellison's work, but I'll never understand why he insists on
being such a monumental dickweed.
C'ya,
RudeJohn
"I'm rude. It's a job."
********************************************************************************
WANT TO SEE...
YOUR AD HERE AND ON THE BASIX FANZINE WEBSITE?
If so, please email basix@dewarr.globalnet.co.uk for details.
Advertising can be placed here in exchange for anything that would help the
fanzine - for example, webspace, a domain name, or the money to provide this -
in fact, if somebody could "sponsor" the fanzine and give us
www.basixfanzine.com with 10mb or more of webspace, that would be absolutely
fantastic! In return, your advertisements would be sprinkled liberally here and
there in the fanzine and on the website too.
********************************************************************************
YOUR PROGRAMS
useful programs demonstrating useful techniques
*** DETECTING THE PARALLEL PORT, from Juan F. Miguez ·
jfm7620@megahertz.njit.edu / miguez@andromeda.rutgers.edu / miguez@bifoot.com
(take your pick... I'm sure that last one should be miguez@bigfoot.com really,
but that's what it said in the code I recieved -ed)
This program demonstrates how to detect the parallel port automatically:
'###############################################
'### Juan F. Miguez 7-1-98 ###
'### Detects the Parallel Port Automatically ###
'### The condition here is that if the info ###
'### gathered from the port is 255, then the ###
'### parallel port does not exist. ###
'### Send all the comments to: ###
'### miguez@bifoot.com ###
'###############################################
'Basix Fanzine editor's note - perhaps the email address is really
' miguez@bigfoot.com ??
' #### Define the parallel ports as par1 and par2
par1 = &H378
par2 = &H3BC
' #### If the input from the port is 255 then the port does not exist
' #### INP sends acknowledges a bit from the specified port
' #### as INP(par1) gets a bit from the 378 parallel port and tests it.
IF (INP(par1) <> 255 AND INP(par2) <> 255) THEN
LOCATE 12, 12
PRINT "Both Parallel ports &H378 and &H3BC were found. "
INPUT "Which one would you like to use for the experiment?"; ParPort$
IF (ParPort$="&H378") then P=&H378
IF (ParPort$="&H3BC") then P=&H3BC
ELSE
IF (INP(par1) < 255) THEN
ParPort$ = "&H378" ' Parallel port is 3BC"
P = &H378
ELSEIF (INP(par2) < 255) THEN
ParPort$ = "&H3BC" ' Parallel port is 378
P = &H3BC
END IF
END IF
PRINT "Your parallel port is located at: "; ParPort$
END
*** BINARY FILE ENCRYPTION, from Daniel Bolger · daniel.bolger@ukonline.co.uk
Daniel Bolger writes:
"It works by adding the ascii numbers from each letter of the password together
and then dividing by the number of letters -- basically finding the average.
Then things get XORed etc. It originated as a copier - and a fast one at that,
but now it isn't very fast - perhaps you could change that. Anyway, I hope it is
of use."
'File encrypter Copyright Daniel Bolger 1998
DECLARE FUNCTION Encrypt$ (strenc AS STRING, pass AS STRING)
DIM tenner AS STRING * 10
DIM oneer AS STRING * 1
DIM hundreder AS STRING * 100
DIM thousander AS STRING * 1000
CLS
INPUT "Which file do you want to do today"; InFile$
INPUT "As what"; OutFile$
INPUT "Password"; pass$
OPEN InFile$ FOR BINARY AS #1
OPEN OutFile$ FOR BINARY AS #2
TotalSize = LOF(1)
RemainingSize = TotalSize
counter = 1
DO UNTIL RemainingSize = 0
buffer$ = ""
SELECT CASE RemainingSize
CASE IS >= 1000
choice$ = "thousander"
RemainingSize = RemainingSize - 1000
CASE IS >= 100
choice$ = "hundreder"
RemainingSize = RemainingSize - 100
CASE IS >= 10
choice$ = "tenner"
RemainingSize = RemainingSize - 10
CASE ELSE
choice$ = "oneer"
RemainingSize = RemainingSize - 1
END SELECT
IF choice$ = "oneer" THEN
GET #1, , oneer
oneer = Encrypt(oneer, pass$)
PUT #2, , oneer
ELSEIF choice$ = "tenner" THEN
GET #1, , tenner
tenner = Encrypt(tenner, pass$)
PUT #2, , tenner
ELSEIF choice$ = "hundreder" THEN
GET #1, , hundreder
hundreder = Encrypt(hundreder, pass$)
PUT #2, , hundreder
ELSEIF choice$ = "thousander" THEN
GET #1, , thousander
thousander = Encrypt(thousander, pass$)
PUT #2, , thousander
END IF
LOOP
PRINT
PRINT "Finished (wasn't that quick?)"
CLOSE
SYSTEM
FUNCTION Encrypt$ (strenc AS STRING, pass AS STRING)
FOR i = 1 TO LEN(pass)
cstring$ = MID$(pass, i, 1)
casc = ASC(cstring$)
tasc = tasc + casc
NEXT i
tasc = tasc / LEN(pass)
FOR i = 1 TO LEN(strenc)
cstring$ = MID$(strenc, i, 1)
casc = ASC(cstring$)
casc = casc XOR tasc
cstring$ = CHR$(casc)
MID$(strenc, i, 1) = cstring$
NEXT i
Encrypt$ = strenc
END FUNCTION
*** CONTROL+BREAK DISABLER, from Daniel Bolger · daniel.bolger@ukonline.co.uk
Daniel Bolger writes:
"This is a version of NoBreak (I call DazNoBreak). It disables the use of the
Cntrl + Break and the Cntrl + C keyboard shortcuts for exiting programs in
QBasic. I believe [the Basix Fanzine] had a program like this in the past... I
hope this is clearer. It isn't based on the previous version and any similarity
is purely coincedental.
Some disadvantages:
1. You cant use Num Lock or Caps, they stop it working, so they are turned off
at program startup. They are prevented from going back on. At program end, they
resume their status before the program was run.
2. Every time you use the two aforementioned shortcuts, the scroll lock toggles!
3. More seriously: you can't use INPUT, or LINE INPUT, although you can use
INKEY$, and INPUT$() as in the example. I hope you like it."
DECLARE SUB CLEARLOCKS ()
CLS
KEY 15, CHR$(0) + CHR$(29) 'Control (neccessary for DazNoBreak)
KEY 16, CHR$(0) + CHR$(69) 'NumLock
KEY 17, CHR$(0) + CHR$(58) 'CapsLock
KEY 18, CHR$(0) + CHR$(70) 'ScrollLock
ON KEY(15) GOSUB NOBREAK
ON KEY(16) GOSUB HandleLocks
ON KEY(17) GOSUB HandleLocks
ON KEY(18) GOSUB HandleLocks
KEY(15) ON
KEY(16) ON
KEY(17) ON
KEY(18) ON
DEF SEG = 0
OriginalStatus% = PEEK(&H417) 'Find original status of Lock keys
CLEARLOCKS
DO UNTIL I$ = chr$(27)
I$ = INPUT$(1)
IF ASC(I$) >= 32 THEN PRINT I$;
LOOP
POKE &H417, OriginalStatus% 'Restore original status of Lock keys
SYSTEM
NOBREAK:
RETURN
HandleLocks:
CLEARLOCKS
RETURN
SUB CLEARLOCKS
Status% = PEEK(&H417) 'Read keyboard status.
IF Status% <> 130 THEN POKE &H417, 130
END SUB
*** "A SCREENSAVER TYPE THING", from Mike Anderson · MikeAinIA@aol.com
His words, not mine :) "I've sent you this instead of a good article. :-)" he
says...
'---------------------------------------------------------------------
'| A Screensaver type thing |
'| Uses Screen 12 |
'| Runs until mouse moves, or key is pressed |
'| Has midnite rollover checking and should run about the |
'| same speed on any CPU. |
'| As a screensaver, it's pretty lame, but I actually use it! |
'| I hot-key into it from Win95, with properties set to give |
'| it priority. It keeps the hard-disk from thrashing while a |
'| real screensaver runs, because I set the properties |
'| to keep the real screen from starting! |
'---------------------------------------------------------------------
'Blankbox.BAS by Mike Anderson
'Draws a screen full of ellipses, erases them one at a time
' then draws a screen full of rectangles and erases them one
' at a time. Runs until mouse or keyboard action.
DEFINT A-Z
DECLARE SUB MIDNITE ()
DECLARE SUB Dlay (Sng!)
DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
DECLARE SUB Mousenow (leftbutton%, rightbutton%, xmouse%, ymouse%)
DECLARE FUNCTION MouseInstall% ()
DECLARE FUNCTION DrawBox ()
DECLARE FUNCTION DrawCirc ()
CONST TRUE = -1
CONST FALSE = NOT TRUE
' $INCLUDE: 'qb.bi'
RANDOMIZE TIMER
' The following structures are used to erase the randomly
' drawn figures.
TYPE Circs
R AS INTEGER 'R is horiz. pos of center
T AS INTEGER 'T is vert. " " "
L AS INTEGER 'L is Radius
A AS SINGLE 'A is aspect ratio (we're really drawing
END TYPE ' ellipses)
TYPE Boxes
R AS INTEGER 'R is Right edge
L AS INTEGER ' Left edge
T AS INTEGER ' Top
B AS INTEGER ' Bottom
END TYPE
DIM SHARED AllCircles(50) AS Circs 'Array of Ellipses drawn
DIM SHARED AllBoxes(50) AS Boxes 'Array of Boxes drawn
DIM SHARED ThisCirc AS Circs 'Ellipse buffer
DIM SHARED ThisBox AS Boxes 'Box buffer
SCREEN 12
CLS
x = MouseInstall 'check for mouse
IF x THEN 'If found,
xmouse% = 0 ' store the position
ymouse% = 0
Mousenow lbut, rbut, startx, starty
END IF
x = TRUE
DO
IF x THEN
x = DrawCirc 'DrawCirc is a function - returns TRUE
ELSE 'Until finished, then returns false
x = DrawBox 'DrawBox function returns false until
END IF 'finished, then returns true
'After each circle or box check the mouse position
'and quit if it has moved
Mousenow lbut, rbut, xnow, ynow
IF xnow <> startx AND ynow <> starty THEN SYSTEM
'If the mouse hasn't moved, check the keyboard
'and quit on any key.
R$ = INKEY$
IF LEN(R$) THEN SYSTEM
LOOP
SUB Dlay (Sng!)
Now! = TIMER
DO
TElapsed! = TIMER - Now!
IF TElapsed! < 0 THEN 'Midnite hath passed!
MIDNITE ' Announce it!
EXIT SUB ' Possible change - announce
END IF ' every hour, half-hour, or 1/4 hour
LOOP WHILE TElapsed! < Sng!
END SUB
FUNCTION DrawBox STATIC
DrawBox = FALSE
Dlay (.2)
L = INT(640 * RND): ThisBox.L = L
R = INT(640 * RND): ThisBox.R = R
T = INT(480 * RND): ThisBox.T = T
B = INT(480 * RND): ThisBox.B = B
C = INT(15 * RND) + 1
AllBoxes(count%) = ThisBox 'save characteristic of ThisBox
'to array of all boxes
Numbox = 50 ' 50 fills the screen nicely - if
' you change it, change the DIM statement
' for AllBoxes also.
IF count% >= Numbox THEN
IF erased% >= Numbox THEN 'If all are drawn, and all are erased
count% = 0 ' start over
erased% = 0
DrawBox = TRUE ' Return TRUE, to switch to ellipses
Dlay (.4)
ELSE '(keep erasing)
' Watch it - the next line is a long one!
LINE (AllBoxes(erased%).L, AllBoxes(erased%).T)-(AllBoxes(erased%).R,
AllBoxes(erased%).B), 0, B
erased% = erased% + 1
END IF
ELSE '(keep drawing)
LINE (L, T)-(R, B), C, B
count% = count% + 1
END IF
END FUNCTION
FUNCTION DrawCirc STATIC
DrawCirc = TRUE
Dlay (.2)
L = INT(240 * RND) 'set the "Radius"
A! = INT(10 * RND) + 1 'Set the aspect ratio
H = INT(2 * RND) + 1 ' Flip a coin
IF H = 1 THEN A! = 1 / A! ' If "heads" then invert the aspect ratio
'This next bit of gymnastics keeps the entire figure on the screen
IF A! < 1 THEN
R = INT(RND * (640 - (2 * L))) + L
T = INT(RND * (480 - (2 * A! * L))) + (A! * L)
ELSE
R = INT(RND * (640 - (2 * (1 / A!) * L))) + ((1 / A!) * L)
T = INT(RND * (480 - (2 * L))) + L
END IF
C = INT(15 * RND) + 1 'Pick a color, except black
ThisCirc.R = R
ThisCirc.T = T
ThisCirc.L = L
ThisCirc.A = A!
AllCircles(count%) = ThisCirc 'save the characteristics in the array
Numbox = 50 '50 is a nice number - if changed, be sure to change
'the DIM statement for AllCircles array
IF count% >= Numbox THEN 'Have we drawn all 50?
IF erased% >= Numbox THEN 'Yes. Have we erased all 50?
count% = 0 'Yes, so clean up
erased% = 0
DrawCirc = FALSE 'Return FALSE, to switch to boxes
Dlay (.4)
ELSE 'No - Keep erasing.
'Next line is a long one - watch for wrapping
CIRCLE (AllCircles(erased%).R, AllCircles(erased%).T),
AllCircles(erased).L, 0, , , AllCircles(erased%).A
erased% = erased% + 1
END IF
ELSE 'Not done drawing -
CIRCLE (R, T), L, C, , , A! 'Draw next one
count% = count% + 1
END IF
END FUNCTION
DEFSNG A-Z
SUB MIDNITE
CLS
'Announce that Midnite has passed
LOCATE 12, 36
COLOR 15
PRINT "MIDNITE"
' Play a tune
SOUND 1300, 12
SOUND 30000, 2
SOUND 1000, 12
SOUND 30000, 2
SOUND 1150, 12
SOUND 30000, 2
SOUND 760, 12
SOUND 30000, 2
SOUND 760, 12
SOUND 30000, 2
SOUND 1150, 12
SOUND 30000, 2
SOUND 1300, 12
SOUND 30000, 2
SOUND 1000, 16
COLOR 7
CLS
END SUB
DEFINT A-Z
SUB Mouse (m1%, m2%, m3%, m4%)
'Mouse interrupt handler
DIM InRegs AS RegType, OutRegs AS RegType
InRegs.ax = m1%
InRegs.bx = m2%
InRegs.cx = m3%
InRegs.dx = m4%
INTERRUPT &H33, InRegs, OutRegs
m1% = OutRegs.ax
m2% = OutRegs.bx
m3% = OutRegs.cx
m4% = OutRegs.dx
END SUB
FUNCTION MouseInstall%
'Checks for existance
mflag% = FALSE 'Assume it's not there
Mouse mflag%, 0, 0, 0
MouseInstall% = mflag%
END FUNCTION
SUB Mousenow (leftbutton%, rightbutton%, xmouse%, ymouse%)
Mouse 3, m2%, xmouse%, ymouse%
leftbutton% = ((m2% AND 1) <> 0)
rightbutton% = ((m2% AND 2) <> 0)
END SUB
********************************************************************************
LETTERS
your questions answered, your comments printed...
*** PROGRAMS, MIDI & INP, from Daniel Bolger · daniel.bolger@ukonline.co.uk
Hi
Below, I have included the source of my binary file encrypter... [included
above]
One more piece of code: This is a version of NoBreak (I call DazNoBreak). [also
included above]
Cheers, Daniel Bolger :-) (Age 12 - no kidding!) PS. Great fanzine, BTW is it
possible to play midi files in QB? Perhaps you could go over things like INP
which means nothing to me...
Thanks for the programs. It is indeed possible to play MIDI files from QB, but
not directly. It can be done using the QMIDI routines - the URL is in the
Internet Resources section of the fanzine, and you can download it directly by
clicking this link: http://members.tripod.com/~jdorland/qmidi/qmidi35.zip
INP is the opposite of OUT, and you use it for reading info from the ports. I
don't use it very much, probably the only time I need it is when reading/writing
the palette info (though this can be done in QB already using the PALETTE
command, but I find using OUT easier). Anyway, the following SUB uses OUT and
sets colour number n to the colours specified in r, g, and b. (The Red, Green,
and Blue values)
SUB pal (n AS INTEGER, r AS INTEGER, g AS INTEGER, b AS INTEGER)
OUT &H3C8, n
OUT &H3C9, r
OUT &H3C9, g
OUT &H3C9, b
END SUB
If you turn OUT to INP in the last three lines, they return the r, g and b
values rather than set them. So you can read the r, g and b values of colour 200
by using:
OUT &H3C8, 200
R = INP &H3C9
G = INP &H3C9
B = INP &H3C9
There are many other uses of INP and OUT - they're used in programming the
SoundBlaster for example. They can also control other things as well - just
about any piece of hardware connected to your computer can be controlled via INP
and OUT, if you know the various numbers. I have uploaded a file that I found
somewhere on the web to the Basix Fanzine website, it lists many of these ports
and the values they take. You can download it directly by clicking this link -
http://www.users.globalnet.co.uk/~dewarr/ports.txt
********************************************************************************
WANT TO SEE...
YOUR BASIC PRODUCT REVIEWED IN THE FANZINE?
If so, please email basix@dewarr.globalnet.co.uk for details.
If you market a compiler or other BASIC-related product and want the DOS BASIC
world to know about it, why not send in a review copy? It could be emailed to
the address above (please ask first though, before you plant a massive binary in
my mailbox) or, if you're kind enough, you could post a copy - email me for the
address.
********************************************************************************
INTERNET RESOURCES
GETTING THE FANZINE
Website
http://come.to/basixfanzine
From here, you can download all issues of the Basix Fanzine in text or HTML
format, download useful utilities and documentation, read issues online, and get
up-to-date news and information.
Newsgroups
The Basix Fanzine is posted when
it is released to alt.lang.basic,
alt.lang.powerbasic, comp.lang.basic.misc and microsoft.public.basic.dos, in a
zip file containing the HTML files for that issue. If you want it posted to any
other BASIC newsgroups then please let me know. You can download the
old-fashioned text format versions of the HTML issues at the Basix Fanzine
website, URL above.
Mailing List
To get the Fanzines as they are released, join Tony Relyea's mailing list by
sending an email to the new address of fanzine@vt.edu with subject "subscribe
basix-fanzine". This mailing list is completely separate from the Basix Fanzine
so I cannot accept responsibility for any emails you do - or don't - get when
you join the mailing list.
USEFUL BASIC WEBSITES
To read more information about a particular site, click the [info] link next to
the URL.
Compilers
-PowerBASIC (also FirstBasic, PB/DLL and PB/CC): http://www.powerbasic.com
-EMS (old MS compilers): http://www.wdn.com/ems/oldtools/ms.htm
-Provantage (old MS compilers): http://www.provantage.com
NEW URL: Old compilers: http://weber.u.washington.edu/~bpwilson
NEW URL: BASM: http://www.users.uswest.net/~sdiggins/basm.html
BASIC code
-The Beginners Basic Homepage: http://www.users.globalnet.co.uk/~basic/
-QBasic.com: http://www.qbasic.com
-The Programmer's Page: http://www.professionals.com/~peterp/
-ABC Packets (bi-monthly collections of useful BASIC code):
http://come.to/abcpackets
NEW MIRROR: There is a new UK mirror for the ABC Packets at
http://www.cvnet.co.uk/o.cook/abc
NEW URL: PowerBasic Archives: http://www.xs4all.nl/~excel/pb.html
-Tim's QuickBasic Page: http://www.geocities.com/SiliconValley/Heights/8967/
-QBasic Programming Corner: http://www.geocities.com/TheTropics/9964/qbasic.html
-The QBasic Site: http://hem.passagen.se/hedsen
-DMAPLAYH.BAS (WAV player): http://www.ocf.berkeley.edu/~horie/project.html
-The QuickBasic Enhanced Programming Page:
http://www.geocities.com/SiliconValley/Lakes/7303/
-Blood 225's BASIC stuff: ftp://users.aol.com/blood225
-Alex Warren's BASIC page: http://www.users.globalnet.co.uk/~dewarr/basic.htm
Libraries
-Zephyr Software (SVGA Library): http://www.zephyrsoftware.com
-MOD Library: http://www.fortunecity.com/millenium/celesteville/23/index.html
-QMIDI (MIDI player): http://members.tripod.com/~jdorland/qmidi/
Reference
NEW URL: Ralf Brown's Interrupts List:
http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html (also available at
http://www.ctyme.com/rbrown.htm)
NEW URL: Programmers' File Formats Collection: http://www.wotsit.org
-Basix Fanzine: http://come.to/basixfanzine
-X2FTP: ftp://x2ftp.oulu.fi/pub/msdos/programming/
-PCGPE (PC Games Programmers' Encyclopaedia):
ftp://x2ftp.oulu.fi/pub/msdos/programming/gpe
Add your site to this list by sending an email to basix@dewarr.globalnet.co.uk.
Also, if any of the sites disappear or move address, please send an email so I
can update this page when I release the next issue.
USEFUL BASIC NEWSGROUPS
alt.lang.basic
alt.lang.powerbasic
comp.lang.basic.misc
microsoft.public.basic.dos
NEW: comp.lang.basic.powerbasic
GETTING HOLD OF BASIC
QBasic:
QBasic is free and available on DOS disks (versions 5.0 and up), the Windows
95/98 CDROMs, and within http://www.microsoft.com/windows/download/olddos.exe.
QBasic supports a lot of what QuickBasic does, except that it does not compile
and has no built-in support for interrupts.
GW-BASIC:
Versions of DOS prior to 5.0 included GW-BASIC rather than QBasic. The last
version was v3.23. If you have any really old DOS disks, look on those, or you
can search for it on the web. I think there is a link to it at Ollie Cook's ABC
UK Mirror - address above. GW-BASIC is rather inferior to the likes of QBasic,
which is compatible with it, so I wouldn't bother with GW-BASIC, personally.
Unless you hate user-friendliness and have a bizarre fetish for line numbers, of
course.
Commercial Microsoft BASICs:
You can order new and used copies of QuickBASIC, PDS 7.x, VBDOS, etc. online at
http://www.wdn.com/ems/oldtools/ms.htm, http://www.provantage.com and
http://weber.u.washington.edu/~bpwilson.
These usually cost upwards of US$100. QuickBASIC is the "big older brother" of
QBasic. PDS is the "even bigger brother" and VBDOS is a BASIC flavour that
allows the easy creation of user interfaces (UIs). It is more-or-less compatible
with Visual Basic for Windows - you can port VBDOS code to VB5 if you have the
patience. It is worth noting that Microsoft is no longer supporting its DOS
versions of BASIC.
PowerBasic:
You can buy PowerBasic, FirstBasic, PB/DLL and PB/CC from
http://www.powerbasic.com.
PowerBasic (current version 3.5) is fairly compatible with Microsoft BASICs but
has no support for Screen 13, for some reason I've never bothered to find out
about. Libraries are available for this though. FirstBasic is a shareware
version of PowerBasic 2.1 and supports most of what QuickBasic does, though with
some syntax differences. PB/DLL and PB/CC work with Windows (PB/CC will soon
have versions for other operating systems). PowerBasic flavours all have the
advantage of the MS flavours that they are still being supported.
There are other freeware/shareware compilers available such as OmniBasic,
Liberty Basic (for Windows), and more. One day I'll even give you the links :)
If you want to compile very few programs which have been made using QBasic, and
don't want to shell out loads of money for a compiler, you can pay $5 a time for
compiling at http://members.aol.com/qbasicnow. Email qbasicnow@aol.com for more
information on this. NEW: "Simcop" tells me he will compile programs for free.
His email address is simcop2387@aol.com, and his homepage is at
http://members.aol.com/simcop2387/index.html.
QB4.5 and several other compilers can be also be downloaded illegally from
various websites. The Basix Fanzine does not accept responsibility for any
damage caused to your computer or your life through downloading illegal software
- you have been warned.
If you know of any other compilers or would like to advertise yours here, send
an email to basix@dewarr.globalnet.co.uk, or post a message on one of the BASIC
newsgroups and hope that I see it.
********************************************************************************
FINAL WORDS
Thanks to the following for contributing articles and source code for this
issue, in no particular order:
"Hacker" aka Damian Nikodem
RudeJohn (only one word - not "Rude John", as I wrote in the last issue, I'm
informed <g>), aka "The Tripods" or "When The Tripods Came", and now
"Sanctuary". Who knows, maybe he even has a real name.
Juan F. Miguez
Daniel Bolger
Ollie Cook
Finally, thanks to "Rembrandt Packaging" aka Jeroen and Marc van den Dikkenberg
for pointing out a few old links in the "Internet Resources" section.
NEXT ISSUE:
Well, hopefully I'll have the next issue - the last fanzine of 1998 - out by the
end of October. But, to do that, I need your contributions - so send something
in!
Alex Warren,
14th August 1998