tfv: multiply finally working

This commit is contained in:
Vince Weaver 2017-09-07 01:32:31 -04:00
parent 621f808531
commit 20b070a413
4 changed files with 220 additions and 117 deletions

View File

@ -43,49 +43,50 @@ int fixed_mul(struct fixed_type *x,
int result3; int result3;
int result2,result1,result0; int result2,result1,result0;
int aa,xx,cc=0,cc2,yy; int aa,xx,cc=0,cc2,yy;
int negative=0; int negate=0;
num1h=x->i; num1h=x->i;
num1l=x->f; num1l=x->f;
if (num1h&0x80) { if (!(num1h&0x80)) goto check_num2; // bpl check_num2
negative^=1;
num1l=~num1l; negate++; // inc negate
num1h=~num1h;
num1l&=0xff; num1l=~num1l;
num1h&=0xff; num1h=~num1h;
num1l+=1; num1l&=0xff;
cc=!!(num1l&0x100); num1h&=0xff;
num1h+=cc;
num1l&=0xff; num1l+=1;
num1h&=0xff; cc=!!(num1l&0x100);
num1h+=cc;
} num1l&=0xff;
num1h&=0xff;
check_num2:
num2h=y->i; num2h=y->i;
num2l=y->f; num2l=y->f;
if (num2h&0x80) { if (!(num2h&0x80)) goto unsigned_multiply;
negative^=1;
num2l=~num2l; negate++;
num2h=~num2h;
num2l&=0xff; num2l=~num2l;
num2h&=0xff; num2h=~num2h;
num2l+=1; num2l&=0xff;
cc=!!(num2l&0x100); num2h&=0xff;
num2h+=cc;
num2l&=0xff; num2l+=1;
num2h&=0xff; cc=!!(num2l&0x100);
num2h+=cc;
} num2l&=0xff;
num2h&=0xff;
unsigned_multiply:
if (debug) { if (debug) {
printf("Using %02x:%02x * %02x:%02x\n",num1h,num1l,num2h,num2l); 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); result3&0xff,result2&0xff,result1&0xff,result0&0xff);
} }
if (negative) { if (negate&1) {
// printf("NEGATING!\n"); // printf("NEGATING!\n");
cc=0; cc=0;

View File

@ -55,7 +55,7 @@ TFV: tfv.o
ld65 -o TFV tfv.o -C ./apple2_1000.inc ld65 -o TFV tfv.o -C ./apple2_1000.inc
tfv.o: tfv.s \ 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_textentry.s tfv_utils.s \
tfv_backgrounds.inc tfv_sprites.inc tfv_zp.inc tfv_backgrounds.inc tfv_sprites.inc tfv_zp.inc
ca65 -o tfv.o tfv.s -l tfv.lst ca65 -o tfv.o tfv.s -l tfv.lst

View File

@ -52,6 +52,7 @@ flying_start:
sta SHIPY sta SHIPY
lda #0 lda #0
sta TURNING sta TURNING
sta ANGLE
sta SPACEX_I sta SPACEX_I
sta SPACEY_I sta SPACEY_I
@ -79,6 +80,7 @@ skipskip:
bcc check_down ; bgt bcc check_down ; bgt
dec SHIPY dec SHIPY
dec SHIPY dec SHIPY
inc SPACEZ_I
check_down: check_down:
cmp #('M') cmp #('M')
@ -88,19 +90,26 @@ check_down:
bcs check_left ; ble bcs check_left ; ble
inc SHIPY inc SHIPY
inc SHIPY inc SHIPY
dec SPACEZ_I
check_left: check_left:
cmp #('J') cmp #('J')
bne check_right bne check_right
inc TURNING inc TURNING
inc ANGLE
check_right: check_right:
cmp #('K') cmp #('K')
bne check_done bne check_done
dec TURNING dec TURNING
dec ANGLE
check_done: check_done:
lda ANGLE
and #$f
sta ANGLE
;==================== ;====================
; Draw the background ; Draw the background
;==================== ;====================
@ -191,23 +200,38 @@ sky_loop: ; draw line across screen
jsr hlin_double ; hlin 0,40 at 6 jsr hlin_double ; hlin 0,40 at 6
; fixed_mul(&space_z,&BETA,&factor); ; fixed_mul(&space_z,&BETA,&factor);
lda SPACEZ_I lda SPACEZ_I
sta NUM1+1 sta NUM1H
lda SPACEZ_F lda SPACEZ_F
sta NUM1 sta NUM1L
lda #$ff ; BETA_I lda #$ff ; BETA_I
sta NUM2+1 sta NUM2H
lda #$80 ; BETA_F 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 jsr multiply
lda RESULT+1
sta FACTOR_I
lda RESULT+2 lda RESULT+2
sta FACTOR_I
lda RESULT+1
sta FACTOR_F sta FACTOR_F
brk ;; SPACEZ=78 * ff80 = FACTOR=66 ;; SPACEZ=78 * ff80 = FACTOR=66
;; 4 80 * ff 80 = 83 81 ;; 4 80 * ff 80 = 83 81
@ -215,7 +239,10 @@ brk ;; SPACEZ=78 * ff80 = FACTOR=66
;; 4 80 * ffffffff 80 = fffffffd c0 ;; 4 80 * ffffffff 80 = fffffffd c0
;; spacez*beta=factor ;; spacez*beta=factor
;; 00 40 02 00
;; 00000000 01000000 00000010 00000000
;; 11111111 10111111 11111110 00000000
;; ff Bf fe 00
;; C ;; C
;; GOOD 4 80 * ffffffff 80 = fffffffd c0 ;; GOOD 4 80 * ffffffff 80 = fffffffd c0
@ -256,17 +283,17 @@ screeny_loop:
; calculate the distance of the line we are drawing ; calculate the distance of the line we are drawing
; fixed_mul(&horizontal_scale,&scale,&distance); ; fixed_mul(&horizontal_scale,&scale,&distance);
lda HORIZ_SCALE_I lda HORIZ_SCALE_I
sta NUM1 sta NUM1H
lda HORIZ_SCALE_F lda HORIZ_SCALE_F
sta NUM1+1 sta NUM1L
lda #$14 ; SCALE_I lda #$14 ; SCALE_I
sta NUM2 sta NUM2H
lda #$00 ; SCALE_F lda #$00 ; SCALE_F
sta NUM2+1 sta NUM2L
jsr multiply jsr multiply
lda RESULT+1
sta DISTANCE_I
lda RESULT+2 lda RESULT+2
sta DISTANCE_I
lda RESULT+1
sta DISTANCE_F sta DISTANCE_F
; calculate the dx and dy of points in space when we step ; calculate the dx and dy of points in space when we step
@ -285,17 +312,17 @@ screeny_loop:
; fixed_mul(&dx,&horizontal_scale,&dx); ; fixed_mul(&dx,&horizontal_scale,&dx);
lda HORIZ_SCALE_I lda HORIZ_SCALE_I
sta NUM1 sta NUM1H
lda HORIZ_SCALE_F lda HORIZ_SCALE_F
sta NUM1+1 sta NUM1L
lda DX_I lda DX_I
sta NUM2 sta NUM2H
lda DX_F lda DX_F
sta NUM2+1 sta NUM2L
jsr multiply jsr multiply
lda RESULT+1
sta DX_I
lda RESULT+2 lda RESULT+2
sta DX_I
lda RESULT+1
sta DX_F sta DX_F
@ -312,17 +339,17 @@ screeny_loop:
; fixed_mul(&dy,&horizontal_scale,&dy); ; fixed_mul(&dy,&horizontal_scale,&dy);
lda HORIZ_SCALE_I lda HORIZ_SCALE_I
sta NUM1 sta NUM1H
lda HORIZ_SCALE_F lda HORIZ_SCALE_F
sta NUM1+1 sta NUM1L
lda DY_I lda DY_I
sta NUM2 sta NUM2H
lda DY_F lda DY_F
sta NUM2+1 sta NUM2L
jsr multiply jsr multiply
lda RESULT+1
sta DY_I
lda RESULT+2 lda RESULT+2
sta DY_I
lda RESULT+1
sta DY_F sta DY_F
; calculate the starting position ; calculate the starting position
@ -335,8 +362,8 @@ screeny_loop:
sta SPACEX_F sta SPACEX_F
lda DISTANCE_I lda DISTANCE_I
adc FACTOR_I adc FACTOR_I
sta SPACEY_F sta SPACEY_I
sta SPACEX_F sta SPACEX_I
lda ANGLE ; fixed_temp.i=fixed_sin[(angle+4)&0xf].i; // cos lda ANGLE ; fixed_temp.i=fixed_sin[(angle+4)&0xf].i; // cos
clc clc
@ -351,17 +378,17 @@ screeny_loop:
; fixed_mul(&space_x,&fixed_temp,&space_x); ; fixed_mul(&space_x,&fixed_temp,&space_x);
lda SPACEX_I lda SPACEX_I
sta NUM1 sta NUM1H
lda SPACEX_F lda SPACEX_F
sta NUM1+1 sta NUM1L
lda TEMP_I lda TEMP_I
sta NUM2 sta NUM2H
lda TEMP_F lda TEMP_F
sta NUM2+1 sta NUM2L
jsr multiply jsr multiply
lda RESULT+1
sta SPACEX_I
lda RESULT+2 lda RESULT+2
sta SPACEX_I
lda RESULT+1
sta SPACEY_F sta SPACEY_F
@ -380,17 +407,17 @@ screeny_loop:
; fixed_mul(&fixed_temp,&dx,&fixed_temp); ; fixed_mul(&fixed_temp,&dx,&fixed_temp);
lda TEMP_I lda TEMP_I
sta NUM1 sta NUM1H
lda TEMP_F lda TEMP_F
sta NUM1+1 sta NUM1L
lda DX_I lda DX_I
sta NUM2 sta NUM2H
lda DX_F lda DX_F
sta NUM2+1 sta NUM2L
jsr multiply jsr multiply
lda RESULT+1
sta TEMP_I
lda RESULT+2 lda RESULT+2
sta TEMP_I
lda RESULT+1
sta TEMP_F sta TEMP_F
@ -414,17 +441,17 @@ screeny_loop:
; fixed_mul(&space_y,&fixed_temp,&space_y); ; fixed_mul(&space_y,&fixed_temp,&space_y);
lda SPACEY_I lda SPACEY_I
sta NUM1 sta NUM1H
lda SPACEY_F lda SPACEY_F
sta NUM1+1 sta NUM1L
lda TEMP_I lda TEMP_I
sta NUM2 sta NUM2H
lda TEMP_F lda TEMP_F
sta NUM2+1 sta NUM2L
jsr multiply jsr multiply
lda RESULT+1
sta SPACEY_I
lda RESULT+2 lda RESULT+2
sta SPACEY_I
lda RESULT+1
sta SPACEY_F sta SPACEY_F
@ -443,17 +470,17 @@ screeny_loop:
; fixed_mul(&fixed_temp,&dy,&fixed_temp); ; fixed_mul(&fixed_temp,&dy,&fixed_temp);
lda TEMP_I lda TEMP_I
sta NUM1 sta NUM1H
lda TEMP_F lda TEMP_F
sta NUM1+1 sta NUM1L
lda DX_I lda DX_I
sta NUM2 sta NUM2H
lda DY_F lda DY_F
sta NUM2+1 sta NUM2L
jsr multiply jsr multiply
lda RESULT+1
sta TEMP_I
lda RESULT+2 lda RESULT+2
sta TEMP_I
lda RESULT+1
sta TEMP_F sta TEMP_F
@ -524,9 +551,9 @@ lookup_map:
lda SPACEY_I lda SPACEY_I
and #MAP_MASK and #MAP_MASK
lsr asl
lsr asl
lsr ; multiply by 8 asl ; multiply by 8
clc clc
adc TEMPY ; add in X value 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, $22,$22,$22,$22
.byte $22,$22,$22,$22, $ee,$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 ; 8.8 fixed point
; should we store as two arrays, one I one F? ; should we store as two arrays, one I one F?

109
tfv/tfv_multiply.s Normal file
View File

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