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 | )