.importzp ptr3, ptr4, sreg .import popeax, popax .export _ulong_to_big, _big_to_ulong .include "atari.inc" ;IFP = $d9aa fptemp = $a0 ; for now .rodata BIG_64K: .byte $42, $06, $55, $36, $00, $00 ;BIG_ULONG_MAX: ;.byte $44, $42, $94, $96, $72, $95 .code ; TODO: replace these *_to_* with OS calls fr0_to_fptemp: ldx #5 @l: lda FR0,x sta fptemp,x dex bpl @l rts fr0_to_fr1: ldx #5 @l: lda FR0,x sta FR1,x dex bpl @l rts fptemp_to_fr0: ldx #5 @l: lda fptemp,x sta FR0,x dex bpl @l rts fptemp_to_fr1: ldx #5 @l: lda fptemp,x sta FR1,x dex bpl @l rts fr0_to_ptr3: ldy #5 @l: lda FR0,y sta (ptr3),y dey bpl @l rts ptr4_to_fr1: ldy #5 @l: lda (ptr4),y sta FR1,y dey bpl @l rts ; truncate FR0 to integer (no rounding: 2.8 -> 2) trunc_fr0: lda FR0 and #$7f ; strip sign bit (we only care about exponent magnitude) sec sbc #$3f ; A now holds # of base-100 digits in integer part bcs @ok ; # of int digits > 0? jmp ZFR0 ; no, zero out FR0 and exit @ok: cmp #5 ; are there <= 5 int digits? bcs @done ; no, the number's already an integer. tax ; zero out digits: X is first one after decimal point lda #0 @zloop: sta FR0+1,x inx cpx #5 bne @zloop @done: rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; void __fastcall__ big_trunc(bignump b); sta FLPTR stx FLPTR+1 jsr FLD0P jsr trunc_fr0 jsr FST0P rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; void __fastcall__ ulong_to_big(const unsigned long l, bignum *b); _ulong_to_big: sta ptr3 stx ptr3+1 ; save b (destination) jsr popeax ; get low 16 bits of l in A/X (hi 16 bits in sreg) sta FR0 stx FR0+1 jsr IFP ; convert A/X to fp jsr fr0_to_fptemp ; stash it lda sreg ; now get high 16 bits of l in A/X sta FR0 ldx sreg+1 stx FR0+1 jsr IFP ; convert to fp lda #BIG_64K sta ptr4+1 jsr ptr4_to_fr1 jsr FMUL ; multiply... jsr fptemp_to_fr1 ; grab low value jsr FADD ; add to total jmp fr0_to_ptr3 ; store it in b and we're done. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; char __fastcall__ big_to_ulong(bignump b, unsigned long *l); ; ; This works, but it's not small, fast, or elegant... _big_to_ulong: sta ptr3 stx ptr3+1 ; save *l (dest) jsr popax ; get b sta FLPTR sta sreg stx FLPTR+1 stx sreg+1 jsr FLD0P ; there's a typo in atari.inc, should be FLD1P ldx #BIG_64K jsr FLD1R jsr FDIV ; FR0 = FR0 / FR1 jsr trunc_fr0 ; FR0 = INT(FR0) jsr fr0_to_fptemp ; stash for later... jsr FPI ; get integer form bcc @ok ; OS supposed to return with C set if range error ; failed, return 0 to caller lda #0 tax rts @ok: ldy #2 ; save top 16 bits of result where they belong lda FR0 sta (ptr3),y iny lda FR0+1 sta (ptr3),y jsr fptemp_to_fr0 ; this is int((*b)/65536) in FR0 now ldx #BIG_64K jsr FLD1R jsr FMUL ; FR0 now int((*b)/65536)*65536 jsr FMOVE ; FR1 = FR0 ldx sreg ; reload original *b in FR0 ldy sreg+1 jsr FLD0R jsr FSUB ; FR0 = FR0 - FR1 jsr FPI ldy #0 ; store low 16 bits where they belong lda FR0 sta (ptr3),y iny lda FR0+1 sta (ptr3),y ; success. return 1 to caller. tya ldx #0 rts