HANDY USR ROUTINESMachine language power from BASIC
by ERNIE NEGUS
A collection of short but powerful USR machine language routines that can be usefully plugged into your your BASIC programs for any Atari computer. Antic Disk subscribers ENTER "D:USERCALL.LST" and follow the instructions in the article.
BASIC's USR command lets you use speedy, memory-efficient machine language
subroutines from the comfort of BASIC. Although these subroutines are tricky
to type, they let your BASIC programs access a wider variety of functions,
run faster and occupy less memory.
Simply put, machine code is a series of numbers stored in memory. Each number stands for an instruction to the computer. Once you have the address of this code, the USR function lets you run it from BASIC.
Machine code can be stored in several ways. Here, the code is stored in character strings. We can now use BASIC's ADR function to find the beginning address of the character string, and put this value into our USR call.
Since the computer interprets each character as a machine code instruction, a single mistyped character could cause your computer to lock up when you RUN the program.
You must type in each character string exactly as it appears, checking each line with TYPO II. Refer to the Special Atari Character charts in the Antic listings section if you need additional help.
Also, please note that you only need to type the dot-matrix listing printouts marked with TYPO II codes. The typeset example lines below each listing simply indicate how these listings should be called up in these demonstrations or in your own BASIC programs.
All USR calls have the general form: X = USR(z, p1, p2, p3) where z is the decimal address of the machine language routine, and p1, p2 and p3 are input values (parameters) which the machine language routine will use. While some USR calls do not need parameters, others demand several. Any parameters you use must be numbers between 0 and 65,535.
Here are some short USR routines which use machine language to manipulate bits, perform multiple PEEKs and POKEs, evaluate Boolean expressions, and even play music.
Let's examine our USR routines and see how they work:
This routine converts binary numbers to decimal. In our example, the
mysterious-looking character string is the machine language subroutine.
The ADR function determines the decimal address of the subroutine. This
address is stored in the Variable BBYT. Our final result will be stored
We'll use this routine to convert 00001111 to decimal:
First, type in the machine language string as shown in
17 PRINT ANS
When you RUN this demonstration, ANS will be equal to 15,
the decimal equivalent of 00001111.
USR routines which do not return values to your BASIC program, such as MPOK, must also be equated to a BASIC variable. Programmers often call these "dummy" variables because they aren't used in any calculations, but are required by BASIC syntax rules.
25 ANS = USR(DPEK,<address>)
This routine performs a double PEEK at any given decimal address. Its BASIC equivalent is:
ANS = PEEK (<address>) + PEEK (<address + 1>) * 256
Please note that items within angle brackets, such as <address>, tell you what type of data the USR routine requires. If you wanted to perform a double PEEK at address 1536, for example, you would type:
25 ANS = USR(DPEK,15 36)
35 DUMMY= USR(MPOK,<address>,<bytel>, <byte2>...)
MPOK will POKE any number of bytes into successive memory
locations, beginning at the specified decimal address.
45 DUMMY= USR(DPOK,<address>,<wordl>, <word2>...)
DPOK works just like MPOK, except DPOK will POKE any number
of words into successive memory locations.
55 ANS = USR(HI,<word>)
HI returns the high byte of any word. Its BASIC equivalent
65 ANS = USR(LOW,<word>)
LOW returns the low byte of any word. Its BASIC equivalent is:
ANS =WORD-INT(WORD/256)* 256
BAND performs a logical "AND" on the bits of any number
of parameters. BAND can be used to separate missiles and test the direction
bits of the joystick ports.
BOR performs a logical "OR" on the bits of any number of
parameters. BOR can be used to set bits and alter display list options.
BXOR performs a logical "Exclusive OR" on the bits of any
number of parameters. The routine can be used to control blinking characters
and flashing colors.
105 ANS = USR(BROT,<address>,<direction>,<carry>)
BROT will rotate the bits of a byte in RAM. In line 75,
<address> is the decimal address of this byte, <direction>, is the
direction of rotation (use 0 for right rotation, 1 for left rotation),
and <carry> initializes the carry bit. ANS will contain the carry condition
after the rotation.
BROT can be used to rotate characters and players, and convert decimal numbers to binary numbers.
115 DUMMY= USR(RORB,<start>,<end>,<skip>)
125 DUMMY= USR(ROLB,<start>,<end>,<skip>)
RORB and ROLB will rotate bytes from decimal address <start>
to address <end>, while skipping every <skip> bytes. Of course, the
difference between <start> and <end> should be evenly divisible by
<skip>. Otherwise, your program may lock up.
These routines can be used for coarse scrolling, animating characters, moving players and missiles vertically, and changing display lists.
This routine lets the computer play simple tunes from data
stored in MUSDAT$. Each note in MUSDAT$ is represented by two bytes. The
first byte of each pair is the pitch value of the note. Consult your BASIC
reference manual for appropriate pitch values. The second byte is the duration
of the note, in jiffies.
Whole notes require approximately 60 jiffies, quarter notes use approximately 15 jiffies. In our example, MUSDAT $ holds the data for the last two bars of "Mary Had A Little Lamb."
USR routines are easy to use and can breathe new life into tired BASIC programs.
Listing: USERCALL.BAS Download
Ernie Negus is a computer engineer for Intel in Oregon, working mainly
on state-of the-art hard disks, 32-bit microprocessors and quad density