Path: news.uiowa.edu!news.physics.uiowa.edu!math.ohio-state.edu!usc!elroy.jpl.nasa.gov!decwrl!waikato!comp.vuw.ac.nz!asgard.actrix.gen.nz!atlantis.actrix.gen.nz!not-for-mail
From: dempson@atlantis.actrix.gen.nz (David Empson)
Newsgroups: comp.sys.apple2.programmer
Subject: Re: FAC to 3 byte integer
Date: 21 Apr 1996 16:56:08 +1200
Organization: Actrix - Internet Services
Lines: 93
Message-ID: <4lcf58$lb9@atlantis.atlantis.actrix.gen.nz>
References: <4kudq8$1on@apollo.is.co.za>
NNTP-Posting-Host: atlantis.actrix.gen.nz
In article <4kudq8$1on@apollo.is.co.za>,
Greg Wildman wrote:
> I am writing an ampersand addon to Applesoft that will convert a floating
> point number to a three byte integer. (ie. file offset under ProDOS 8)
>
> The format is as follows: & XI,OF
> where OF is the file OFfset, 0 to XXXXXXXXXX.
>
> I use FRMEVL ($DD7B) to place the value into the FAC. Now my problem is
> converting the 5 byte FAC into a 3 byte unsigned integer value (ProDOS 8
> file offset value)
>
> Any Ideas!
Yep. The Sourceror's Apprentice (V1N1 and V1N3) to the rescue. It
provides routines to get a three-byte integer into and out of the FAC.
In fact, this is probably all you need for your code.
* The Applesoft Connection
* Three-Byte Integers
*
* Routines by Jerry Kindall
* Zero page locations:
VARNAM = $81 ; variable name
VARPNT = $83 ; variable pointer
FAC = $9D ; floating-point accumulator
* Applesoft routines:
CHKNUM = $DD6A ; check for numeric
TYPERR = $DD76 ; TYPE MISMATCH error
CHKCOM = $DEBE ; check for a comma
PTRGET = $DFE3 ; get pointer to variable
IQUERR = $E199 ; ILLEGAL QUANTITY error
MOVMF = $EB2B ; move FAC to variable
FLO3 = $EBA6 ; convert integer to FAC
QINT = $EBF2 ; convert FAC to integer (INT function)
* GETNUM3 routine
*
* Evaluates Applesoft expression and returns a three-byte in
* Acc, X-reg, Y-reg (lo/mid/hi)
GETNUM3 JSR CHKCOM ; we must have a comma
JSR FRMNUM ; evaluate numeric formula
JSR QINT ; get integer value
LDA FAC+1 ; check highest byte (#4)
BEQ :OK ; If number < 16777215 it's OK
CMP #$FF ; negative equivalent?
BEQ :OK
JMP IQERR
:OK LDA FAC+4 ; get number: lo
LDX FAC+3 ; mid
LDY FAC+2 ; hi
RTS
* PUTNUM3 routine
*
* Pass a 3-byte integer back to an Applesoft real variable; value in
* Acc, X-reg, Y-reg (lo/mid/hi)
PUTNUM3 STA FAC+3 ; store number: lo
STX FAC+2 ; mid
STY FAC+1 ; hi
LDA #0
STA FAC+4 ; zero fractional part
JSR CHKCOM ; comma check
JSR PTRGET ; find variable
JSR CHKNUM ; make sure its numeric
LDA VARNUM ; must be real
BMI :TM ; reject integer
LDX #$98 ; convert integer to FAC
SEC
JSR FLO3
LDX VARPNT ; move value to variable
LDY VARPNT+1
JMP MOVMF
:TM JMP TYPERR ; TYPE MISMATCH
--
David Empson
dempson@actrix.gen.nz
Snail mail: P.O. Box 27-103, Wellington, New Zealand
Path: news.uiowa.edu!news.physics.uiowa.edu!newsrelay.iastate.edu!vixen.cso.uiuc.edu!newsfeed.internetmci.com!netnews2.nwnet.net!news.u.washington.edu!news.uoregon.edu!cie-2.uoregon.edu!nparker
From: nparker@cie-2.uoregon.edu (Neil Parker)
Newsgroups: comp.sys.apple2.programmer
Subject: Re: FAC to 3 byte integer
Date: 21 Apr 1996 11:44:48 GMT
Organization: University of Oregon Campus Information Exchange
Lines: 92
Message-ID: <4ld73g$ouu@pith.uoregon.edu>
References: <4kudq8$1on@apollo.is.co.za>
NNTP-Posting-Host: cie-2.uoregon.edu
In article <4kudq8$1on@apollo.is.co.za> Greg Wildman writes:
>I am writing an ampersand addon to Applesoft that will convert a floating
>point number to a three byte integer. (ie. file offset under ProDOS 8)
>
>The format is as follows: & XI,OF
>where OF is the file OFfset, 0 to XXXXXXXXXX.
>
>I use FRMEVL ($DD7B) to place the value into the FAC. Now my problem is
>converting the 5 byte FAC into a 3 byte unsigned integer value (ProDOS 8
>file offset value)
First, you might want to call FRMNUM ($DD67) instead of FRMEVL. This works
just like FRMEVL, but it guarantees that the thing that ends up in the FAC
is a number, not a string.
The best FAC-to-integer routine I can find is QINT ($EBF2), but it only
works for numbers less than 2^23, whereas you need to handle up to 2^24
for your ProDOS file offsets. This means you'll need to do the conversion
yourself. This isn't too hard, once you know the layout of the FAC:
FACEXP EQU $9D ;Exponent
FACHO EQU $9E ;Mantissa (high byte)
FACMOH EQU $9F ;Mantissa
FACMO EQU $A0 ;Mantissa
FACLO EQU $A1 ;Mantissa (low byte)
FACSGN EQU $A2 ;Sign
If the exponent is zero, the number is zero.
If the exponent is not zero, then the number is 2^(exponent-$80)*manitssa
(i.e. the exponent has $80 added to it, so that an exponent of $80 means
2^0).
The decimal point in the mantissa is assumed to be to the left of the high-
order bit. The high-order bit is always 1 (i.e. denormalized numbers are
not allowed).
Only bit 7 of the sign is significant--0 means a positive number, and 1
means negative.
Examples: The number 1 is stored as $81 80 00 00 00 00. This is
interpreted as 2^1*.5.
The number -10 is stored as $84 A0 00 00 00 FF. This is interpreted as
2^4*(.5+.125)*(-1).
The number 0.375 is stored as $7F C0 00 00 00 00. This is interpreted as
2^(-1)*(.5+.25).
Thus, you'll probably want to program something like this:
FACEXP EQU $9D
FACHO EQU $9E
FACMOH EQU $9F
FACMO EQU $A0
FACLO EQU $A1
FACSGN EQU $A2
ERROR EQU $D412
;
FAC2INT LDA FACSGN
BMI BADNUM ; Reject negative numbers
LDX FACEXP
CPX #$80
BCC ZERO ; Numbers < 1 become 0
CPX #$99
BCS BADNUM ; Reject numbers >= 2^24
L1 CPX #$A0 ; Shifted enough times yet?
BEQ DONE ; If so, quit...
LSR FACHO ; ...else shift FAC down
ROR FACMOH
ROR FACMO
ROR FACLO
INX
BNE L1 ; (branch always taken)
ZERO LDA #0
STA FACHO
STA FACMOH
STA FACMO
STA FACLO
DONE RTS
BADNUM LDX #53 ; ILLEGAL QUANTITY ERROR
JMP ERROR
This leaves the result in FACMOH (high byte), FACMO (middle byte), and FACLO
(low byte). It can be generalized for numbers up to 2^32 by replacing the
"CPX #$99" line with "CPX #$A1" (in which case the high-order byte will be
in FACHO). But trying to go beyond 2^32 isn't very useful, since beyond
that point you start running into integers that Applesoft can't represent
precisely.
- Neil Parker
--
Neil Parker | No cute quote, no cute ASCII art, no cute
nparker@cie-2.uoregon.edu | disclaimer, no deposit, no return....
nparker@cie.uoregon.edu | (This space intentionally left blank:
http://cie-2.uoregon.edu/~nparker | )