diff --git a/gr-sim/tfv_multiply.c b/gr-sim/tfv_multiply.c index 9c45352e..8f337f0f 100644 --- a/gr-sim/tfv_multiply.c +++ b/gr-sim/tfv_multiply.c @@ -43,49 +43,50 @@ int fixed_mul(struct fixed_type *x, int result3; int result2,result1,result0; int aa,xx,cc=0,cc2,yy; - int negative=0; + int negate=0; num1h=x->i; num1l=x->f; - if (num1h&0x80) { - negative^=1; + if (!(num1h&0x80)) goto check_num2; // bpl check_num2 - num1l=~num1l; - num1h=~num1h; + negate++; // inc negate - num1l&=0xff; - num1h&=0xff; + num1l=~num1l; + num1h=~num1h; - num1l+=1; - cc=!!(num1l&0x100); - num1h+=cc; + num1l&=0xff; + num1h&=0xff; - num1l&=0xff; - num1h&=0xff; + num1l+=1; + cc=!!(num1l&0x100); + num1h+=cc; - } + num1l&=0xff; + num1h&=0xff; +check_num2: num2h=y->i; num2l=y->f; - if (num2h&0x80) { - negative^=1; + if (!(num2h&0x80)) goto unsigned_multiply; - num2l=~num2l; - num2h=~num2h; + negate++; - num2l&=0xff; - num2h&=0xff; + num2l=~num2l; + num2h=~num2h; - num2l+=1; - cc=!!(num2l&0x100); - num2h+=cc; + num2l&=0xff; + num2h&=0xff; - num2l&=0xff; - num2h&=0xff; + num2l+=1; + cc=!!(num2l&0x100); + num2h+=cc; - } + num2l&=0xff; + num2h&=0xff; + +unsigned_multiply: if (debug) { printf("Using %02x:%02x * %02x:%02x\n",num1h,num1l,num2h,num2l); @@ -165,7 +166,7 @@ label_l2: result3&0xff,result2&0xff,result1&0xff,result0&0xff); } - if (negative) { + if (negate&1) { // printf("NEGATING!\n"); cc=0; diff --git a/tfv/Makefile b/tfv/Makefile index 6bfa209e..1e794aaa 100644 --- a/tfv/Makefile +++ b/tfv/Makefile @@ -55,7 +55,7 @@ TFV: tfv.o ld65 -o TFV tfv.o -C ./apple2_1000.inc tfv.o: tfv.s \ - tfv_flying.s tfv_opener.s tfv_title.s \ + tfv_flying.s tfv_multiply.s tfv_opener.s tfv_title.s \ tfv_textentry.s tfv_utils.s \ tfv_backgrounds.inc tfv_sprites.inc tfv_zp.inc ca65 -o tfv.o tfv.s -l tfv.lst diff --git a/tfv/tfv_flying.s b/tfv/tfv_flying.s index c69ed496..b45f1787 100644 --- a/tfv/tfv_flying.s +++ b/tfv/tfv_flying.s @@ -52,6 +52,7 @@ flying_start: sta SHIPY lda #0 sta TURNING + sta ANGLE sta SPACEX_I sta SPACEY_I @@ -79,6 +80,7 @@ skipskip: bcc check_down ; bgt dec SHIPY dec SHIPY + inc SPACEZ_I check_down: cmp #('M') @@ -88,19 +90,26 @@ check_down: bcs check_left ; ble inc SHIPY inc SHIPY + dec SPACEZ_I check_left: cmp #('J') bne check_right inc TURNING + inc ANGLE check_right: cmp #('K') bne check_done dec TURNING + dec ANGLE check_done: + lda ANGLE + and #$f + sta ANGLE + ;==================== ; Draw the background ;==================== @@ -191,23 +200,38 @@ sky_loop: ; draw line across screen jsr hlin_double ; hlin 0,40 at 6 ; fixed_mul(&space_z,&BETA,&factor); + lda SPACEZ_I - sta NUM1+1 + sta NUM1H lda SPACEZ_F - sta NUM1 + sta NUM1L + lda #$ff ; BETA_I - sta NUM2+1 + sta NUM2H lda #$80 ; BETA_F - sta NUM2 + sta NUM2L + +;; TEST +;; lda #$0 +;; sta NUM1H +;; lda #$2 +;; sta NUM1L + +;; lda #$0 +;; sta NUM2H +;; lda #$3 +;; sta NUM2L + + jsr multiply - lda RESULT+1 - sta FACTOR_I lda RESULT+2 + sta FACTOR_I + lda RESULT+1 sta FACTOR_F -brk ;; SPACEZ=78 * ff80 = FACTOR=66 + ;; SPACEZ=78 * ff80 = FACTOR=66 ;; 4 80 * ff 80 = 83 81 @@ -215,7 +239,10 @@ brk ;; SPACEZ=78 * ff80 = FACTOR=66 ;; 4 80 * ffffffff 80 = fffffffd c0 ;; spacez*beta=factor - + ;; 00 40 02 00 + ;; 00000000 01000000 00000010 00000000 + ;; 11111111 10111111 11111110 00000000 + ;; ff Bf fe 00 ;; C ;; GOOD 4 80 * ffffffff 80 = fffffffd c0 @@ -256,17 +283,17 @@ screeny_loop: ; calculate the distance of the line we are drawing ; fixed_mul(&horizontal_scale,&scale,&distance); lda HORIZ_SCALE_I - sta NUM1 + sta NUM1H lda HORIZ_SCALE_F - sta NUM1+1 + sta NUM1L lda #$14 ; SCALE_I - sta NUM2 + sta NUM2H lda #$00 ; SCALE_F - sta NUM2+1 + sta NUM2L jsr multiply - lda RESULT+1 - sta DISTANCE_I lda RESULT+2 + sta DISTANCE_I + lda RESULT+1 sta DISTANCE_F ; calculate the dx and dy of points in space when we step @@ -285,17 +312,17 @@ screeny_loop: ; fixed_mul(&dx,&horizontal_scale,&dx); lda HORIZ_SCALE_I - sta NUM1 + sta NUM1H lda HORIZ_SCALE_F - sta NUM1+1 + sta NUM1L lda DX_I - sta NUM2 + sta NUM2H lda DX_F - sta NUM2+1 + sta NUM2L jsr multiply - lda RESULT+1 - sta DX_I lda RESULT+2 + sta DX_I + lda RESULT+1 sta DX_F @@ -312,17 +339,17 @@ screeny_loop: ; fixed_mul(&dy,&horizontal_scale,&dy); lda HORIZ_SCALE_I - sta NUM1 + sta NUM1H lda HORIZ_SCALE_F - sta NUM1+1 + sta NUM1L lda DY_I - sta NUM2 + sta NUM2H lda DY_F - sta NUM2+1 + sta NUM2L jsr multiply - lda RESULT+1 - sta DY_I lda RESULT+2 + sta DY_I + lda RESULT+1 sta DY_F ; calculate the starting position @@ -335,8 +362,8 @@ screeny_loop: sta SPACEX_F lda DISTANCE_I adc FACTOR_I - sta SPACEY_F - sta SPACEX_F + sta SPACEY_I + sta SPACEX_I lda ANGLE ; fixed_temp.i=fixed_sin[(angle+4)&0xf].i; // cos clc @@ -351,17 +378,17 @@ screeny_loop: ; fixed_mul(&space_x,&fixed_temp,&space_x); lda SPACEX_I - sta NUM1 + sta NUM1H lda SPACEX_F - sta NUM1+1 + sta NUM1L lda TEMP_I - sta NUM2 + sta NUM2H lda TEMP_F - sta NUM2+1 + sta NUM2L jsr multiply - lda RESULT+1 - sta SPACEX_I lda RESULT+2 + sta SPACEX_I + lda RESULT+1 sta SPACEY_F @@ -380,17 +407,17 @@ screeny_loop: ; fixed_mul(&fixed_temp,&dx,&fixed_temp); lda TEMP_I - sta NUM1 + sta NUM1H lda TEMP_F - sta NUM1+1 + sta NUM1L lda DX_I - sta NUM2 + sta NUM2H lda DX_F - sta NUM2+1 + sta NUM2L jsr multiply - lda RESULT+1 - sta TEMP_I lda RESULT+2 + sta TEMP_I + lda RESULT+1 sta TEMP_F @@ -414,17 +441,17 @@ screeny_loop: ; fixed_mul(&space_y,&fixed_temp,&space_y); lda SPACEY_I - sta NUM1 + sta NUM1H lda SPACEY_F - sta NUM1+1 + sta NUM1L lda TEMP_I - sta NUM2 + sta NUM2H lda TEMP_F - sta NUM2+1 + sta NUM2L jsr multiply - lda RESULT+1 - sta SPACEY_I lda RESULT+2 + sta SPACEY_I + lda RESULT+1 sta SPACEY_F @@ -443,17 +470,17 @@ screeny_loop: ; fixed_mul(&fixed_temp,&dy,&fixed_temp); lda TEMP_I - sta NUM1 + sta NUM1H lda TEMP_F - sta NUM1+1 + sta NUM1L lda DX_I - sta NUM2 + sta NUM2H lda DY_F - sta NUM2+1 + sta NUM2L jsr multiply - lda RESULT+1 - sta TEMP_I lda RESULT+2 + sta TEMP_I + lda RESULT+1 sta TEMP_F @@ -524,9 +551,9 @@ lookup_map: lda SPACEY_I and #MAP_MASK - lsr - lsr - lsr ; multiply by 8 + asl + asl + asl ; multiply by 8 clc adc TEMPY ; add in X value @@ -566,42 +593,8 @@ water_map: .byte $22,$22,$22,$22, $22,$22,$22,$22 .byte $22,$22,$22,$22, $ee,$22,$22,$22 +.include "tfv_multiply.s" -; http://www.llx.com/~nparker/a2/mult.html -; MULTIPLY NUM1H:NUM1L * NUM2H:NUM2L -; NUM2 is zero in end - -NUM1: .byte 0,0 -NUM2: .byte 0,0 -RESULT: .byte 0,0,0,0 - -; If we have 2k to spare we should check out -; http://codebase64.org/doku.php?id=base:seriously_fast_multiplication - -multiply: - lda #0 ; Initialize RESULT to 0 - sta RESULT+2 - ldx #16 ; There are 16 bits in NUM2 -L1: - lsr NUM2+1 ; Get low bit of NUM2 - ror NUM2 - bcc L2 ; 0 or 1? - tay ; If 1, add NUM1 (hi byte of RESULT is in A) - clc - lda NUM1 - adc RESULT+2 - sta RESULT+2 - tya - adc NUM1+1 -L2: - ror A ; "Stairstep" shift - ror RESULT+2 - ror RESULT+1 - ror RESULT - dex - bne L1 - sta RESULT+3 - rts ; 8.8 fixed point ; should we store as two arrays, one I one F? diff --git a/tfv/tfv_multiply.s b/tfv/tfv_multiply.s new file mode 100644 index 00000000..ab6bd80c --- /dev/null +++ b/tfv/tfv_multiply.s @@ -0,0 +1,109 @@ +; http://www.llx.com/~nparker/a2/mult.html +; MULTIPLY NUM1H:NUM1L * NUM2H:NUM2L +; NUM2 is zero in end + +NUM1L: .byte 0 +NUM1H: .byte 0 +NUM2L: .byte 0 +NUM2H: .byte 0 +RESULT: .byte 0,0,0,0 +NEGATE: .byte 0 + +; If we have 2k to spare we should check out +; http://codebase64.org/doku.php?id=base:seriously_fast_multiplication + +multiply: + + lda #$0 + sta NEGATE + + ; Handle Signed + lda NUM1H + bpl check_num2 + + inc NEGATE + + clc + lda NUM1L + eor #$ff + adc #$1 + sta NUM1L + + lda NUM1H + eor #$ff + adc #$0 + sta NUM1H + +check_num2: + lda NUM2H + bpl unsigned_multiply + + inc NEGATE + + clc + lda NUM2L + eor #$ff + adc #$1 + sta NUM2L + + lda NUM2H + eor #$ff + adc #$0 + sta NUM2H + +unsigned_multiply: + + lda #0 ; Initialize RESULT to 0 + sta RESULT+2 + ldx #16 ; 16x16 multiply +multiply_mainloop: + lsr NUM2H ; Shift right 16-bit NUM2 + ror NUM2L ; low bit goes into carry + bcc shift_output ; 0 or 1? + tay ; If 1, add NUM1 (hi byte of RESULT is in A) + clc + lda NUM1L + adc RESULT+2 + sta RESULT+2 + tya + adc NUM1H +shift_output: + ror A ; "Stairstep" shift + ror RESULT+2 + ror RESULT+1 + ror RESULT + dex + bne multiply_mainloop + sta RESULT+3 + + ;; Negate if necessary + + lda NEGATE + and #$1 + beq positive + + clc + lda RESULT+0 + eor #$ff + adc #$1 + sta RESULT+0 + + lda RESULT+1 + eor #$ff + adc #$0 + sta RESULT+1 + + lda RESULT+2 + eor #$ff + adc #$0 + sta RESULT+2 + + lda RESULT+3 + eor #$ff + adc #$0 + sta RESULT+3 + +positive: + + rts +