diff --git a/platform/libbasic64.oph b/platform/libbasic64.oph new file mode 100644 index 0000000..87d064a --- /dev/null +++ b/platform/libbasic64.oph @@ -0,0 +1,170 @@ +;;; LIBBASIC64.OPH + +;;; This is a collection of routines inside the BASIC ROM that can +;;; be repurposed to do floating-point math inside your machine +;;; language programs. It is currently VERY EXPERIMENTAL. The documentation +;;; available for this is spotty at best and disassembly confirms that +;;; a lot of hidden invariants may lurk. + +;;; There's a general TODO here to generate a relatively safe and +;;; easy to use set of macros that will do more or less what you want. + + ;; BASIC functions + .alias abs_fac1 $bc58 + .alias atn_fac1 $e30e + .alias cos_fac1 $e264 + .alias exp_fac1 $bfed + .alias int_fac1 $bccc + .alias log_fac1 $b9ea + .alias rnd_fac1 $e097 + .alias sgn_fac1 $bc39 + .alias sin_fac1 $e26b + .alias tan_fac1 $e2b4 + + ;; Getting data in and out of the FACs + .alias ld_fac1_a $bc3c + .alias ld_fac1_s16 $b391 + .alias ld_fac1_mem $bba2 + .alias ld_fac1_fac2 $bbfc + .alias fac1_to_string $bddd + .alias fac1_to_s32 $bc9b + .alias fac1_to_57 $bbca + .alias fac1_to_5c $bbc7 + + .alias ld_fac2_mem $ba8c + .alias ld_fac2_fac1 $bc0c + + ;; Unlike sgn_fac1, this returns the -1/0/1 in + ;; the accumulator + .alias fac1_sign $bc2b + + ;; FP operators. These are all FAC2 OP FAC1 + ;; with the result in FAC1. + .alias f_plus $b86a + .alias f_minus $b853 + .alias f_times $ba2b + .alias f_div $bb12 + .alias f_pow $bf7b + .alias f_and $afe9 + .alias f_or $afe6 + + ;; Memory-based FP operations. All are MEM OP FAC1. + ;; These seem safer; FAC2 seems to have some slippery + ;; invariants in it. + .alias f_add $b867 + .alias f_subtract $b850 + .alias f_multiply $ba28 + .alias f_divide $bb0f + + ;; Useful FP constants that live in the ROM. + ;; It's plausible that ld_fac1_a or ld_fac1_s16 + ;; would be more convenient than ld_fac1_mem + ;; with f_1 or f_10, but when doing memory-based + ;; generic stuff, these will still be useful + .alias f_0_5 $bf11 ; 0.5 + .alias f_1 $b9bc ; 1.0 + .alias f_pi $aea8 ; 3.1415926 + .alias f_10 $baf9 ; 10.0 + + ;; Macros to make our lives easier +.macro f_move + ldx #$00 +_fmvlp: lda _2,x + sta _1,x + inx + cpx #$05 + bne _fmvlp +.macend + +.macro print_str + lda #<_1 + ldy #>_1 + jsr strout +.macend + +.macro ld_fac1 + lda #<_1 + ldy #>_1 + jsr ld_fac1_mem +.macend + +.macro ld_fac2 + lda #<_1 + ldy #>_1 + jsr ld_fac2_mem +.macend + +.macro st_fac1 + lda #<_1 + ldy #>_1 + jsr fac1_to_mem +.macend + +.macro print_f + `ld_fac1 _1 + jsr fac1out +.macend + +ld_fac1_ti: + jsr $ffde ; RDTIM + sty $63 + stx $64 + sta $65 + ;; Once the requirements on .Y and $68 are better + ;; understood, this might be exportable as + ;; ld_fac1_s32, but there are still some dragons + ;; lurking + ldy #$00 ; Clear out intermediary values + sta $62 + sta $68 + jmp $bcd5 + +fac1_to_mem: + sta $fd + sty $fe + jsr fac1_to_5c + ldy #$00 +* lda $5c,y + sta ($fd),y + iny + cpy #$05 + bne - + rts + +fac1out: + ldy #$00 ; Clean out overflow + sty $68 + sty $70 + jsr fac1_to_string + ldy #$01 + ;; Skip the first character if it's not "-" + lda $100 + sec + sbc #$2d + beq strout + lda #$01 + ;; Fall through to strout + +;;; The BASIC ROM already has a STROUT routine - $ab1e - but +;;; it makes use of BASIC's own temporary string handling. We +;;; don't want it to ever touch its notion of temporary strings +;;; here, so we provide our own short routine to do this. +strout: sta $fd + sty $fe + ldy #$00 +* lda ($fd),y + beq + + jsr $ffd2 ; CHROUT + iny + bne - +* rts + +randomize: + jsr ld_fac1_ti + lda #$ff + sta $66 ; Force sign negative + jmp rnd_fac1 ; RND(-TI) + +rnd: lda #$01 + jsr ld_fac1_a + jmp rnd_fac1