M/C Part 5
ROM Routines
==============
If you were tuned into last issue's column, you'll know how ROM0
and ROM1 can be paged into memory. And if you don't know... tuf!
Well, as I'm sure you all know, there are ROM routines which we
can use in our own machine code programs. This has 2 uses:-
1- To save us from writing long and complicated routines of our
own. (ie, let us be lazy)
2- To let us see how Dr. Andy Wright (genius extrodinaire)
solved some (very!) tough problems. (ie, to pinch his ideas)9
Again, I will reiterate that budding coders should get SAMCO's
Advanced Technical Manual. It retails around `17 (I think) but
is certainly more than worth its weight in gold if you are doing
any coding. Anyway, the manual gives you a full list of routines
and entry conditions, as well as floating point calculator codes
(see later).
Meanwhile, I'll give you a rough idea of some of the more useful
routines and how to use them:
Well, basically there is a jump table in ROM0 at 0100H which
contains instructions to run certain subroutines. It is worth
noting that before one of the addresses in the table is called,
you should switch in ROM0, which expects page 0 to be in section
4000-7FFF. Your simple routine would be something like:
IN a,(LMPR) ; LMPR=250 dec.
LD (LMPRSTORE),a ; store original status
LD a,%00111111 ; switch in ROM0 and necessary RAM
OUT (LMPR),a ;
. ;
. ; rest of routine, including CALL to
. ; jump table
. ;
LD a,(LMPRSTORE) ; reset LMPR's status
OUT (LMPR),a ;
The important thing to remember is that you MUST set every
parameter and entry condition the routine needs. If anything
goes wrong you should return to BASIC, but you can never be too
careful when using other people's routines. However, you don't
have to worry about switching in ROM1 as well - if the routine
uses it the jump table will sort it all out for you, including
the restoration of HMPR.
So, what about the routines themselves, eh? Well here's a sample
of the ones you are most likely to use ( most of them
graphical), with all the entry conditions:
JPLOT Plot pixel. B= y coordinate (0 at top, 191 at bottom),
0139H C= x coordinate. [If mode=3, and fatpix=0, then HL= x
coordinate (0-511)]
JDRAW Draw line from current coords, going C pixels
013CH horizontally (or HL if fatpix=0 & mode=3), and B pixels
vertically. E= 1 to go right, FF to go left. D= 1 to go
down, FF to go up. Colour, inverse etc are all governed
by syatem variables as is the screen to use.
JDRAWTO Like JDRAW, except that the line is drawn to C,B (or
013FH HL, as above).
JCIRCLE Draw circle at C,B radius A. Colours etc come from
0142H temporary colour SVARs.
JFILL Modes 3,4 only. Fills a pattern into the space from
01455H C,B, with the address of the 16*16 pixel pattern held
in DE (0 for solid fill of current pen). A=0 to use 6k
scratchpad immediately after the 24k screen. A<>0 to
use previous scratchpad for new colour/pattern.
Pattern data for DE has 8 bytes for each row, makes 128
bytes in total.
JCLSBL If A=0 clear entire screen.
0143H If A<>0 clear upper screen.
JGETINT Unstack rounded number from FPCS (see later) and put it
0121H in HL. BC=HL. A=L
JSTKFETCH Unstack top number of FPCS into AEDCB.
0124H
JSTKSTORE Stack AEDCB onto FPCS.
0127H
JBUFFET Unstack the details of a string from the FPCS, copy
012AH text to a buffer in the system variables page. On exit,
DE points to the start of the buffer, BC holds the
string length. A=C.
Phew! And that's just a sample! There are plenty more, with more
detailed descriptions then those listed above, in the Advanced
Technical Manual.
And after that heavy dose of information...
The Floating Point Calculator
===============================
Ha ha! This one's a nightmare! zillions of control codes with a
second stack and 2 different ways of storing numbers. And you
thought assembly language was tough!.
Anyway, the floating point calcultor (FPC for short and typist's
cramp avoidment) is the bit of the ROM that does all the SAM's
complicated maths work, and most of the string functions too
just for good measure.
It has its own stack where numbers and string information are
stored as 5-byte long codes. These are stored in three different
ways, as is described below:-
i> Integers between -65535 and +65535 are stored as -
0, sign (0 for positive, FF for negative), least
significant byte, most significant byte, 0.
ii> Other numbers between around 1E38 and 1.7E-39 are held in
the same way as with the Spectrum : ie, as 2 raised to a
power (called the exponent) times another bit called the
mantissa. The first byte is the exponent+80H, the other
four are the mantissa. The exponent can be negative of
course, but you should note than this scheme does not allow
some numbers like 1/10 being stored acurately, just like
1/3 cannot be represented accurately in decimal.
iii> Strings are held in the 5-byte code thus -
16k page of text, offset of text start within page (8000H -
BFFFH, LSB/MSB), string length (LSB/MSB).
The calculator itself is used in a very simple way. Making sure
ROM0 is switched in, do a RST08. Follow this by the list of
control codes to command it. The codes themselves are like a
sort of mini-language, but it is not necessary to learn them -
they are all listed in the ATM. Because there are so many, I
will give you a selection with their 'labels'. Please note - N2
refers to the top number on the FPCS, N1 is the number below it.
Hex Label Function
00 MULT N1*N2
01 ADDN N1+N2
03 SUBN N1-N2
05 DIVN N1/N2
06 SWOP Swop round top two numbers or strings
23 STKBREG Stack whatever B was on entry as a 5-byte integer
25 DUP Duplicate top FPCS entry
26 ONELIT Stack next byte on FPCS as a 5-byte number.
27 FIVELIT Stack next 5 bytes.
30 TRUNC Chop off any part after the decimal point.
33 EXIT Finish using calculator.
34 EXIT2 Finish using calculator and do a RET.
E0 STKHALF Stack 0.5
E1 STKZERO Stack zero
E2 STK16k Surprise, surprise - stack 16384
E6 STKFONE Stack five byte version of 1
E9 STKONE Stack integer version of 1
EC STKTEN Guess
F0 STKHALFPI Stack PI/2
And there's more... but I'll save that for the next time.
To round off today, though I'll show you how to use these codes
in any proggies you might have. For example, let's use the
calculator to work out what the circumference of a circle is,
when we know the diameter.
CALL ROM_IN ; Routine to do ROM switching
LD a,(DIAMETER)
LD b,a
RST #08
DB STKBREG ; Stack on the diameter
DB STKHALFPI ; Stack PI/2
DB ONELIT,2 ; Stack 2
DB MULT ; Multiply to get PI on the FPCS
DB MULT ; Circumference= diameter*PI
DB STKHALF ; We'll round off by adding a half
DB ADDN ; and chopping off fractions
DB TRUNC ; Making sure the number is stored as
DB RESTACK ; an integer
DB EXIT ; Leave calculator
CALL JGETINT ; ROM routine listed above that gets
; the top value in the FPCS and,
; providing its an integer, puts it
; into HL, BC and the LSB into A.
LD (CIRCUM),HL ; Store result
CALL ROM_OUT ; Restore LMPR
RET ; Go bye-bye
All the labels named above are listed earlier on; you will need
to EQU them elsewhere. ROM_IN and ROM_OUT were subroutines I
gave you in the last column, but I'm sure you can write your own
if you want.