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

View File

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

View File

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

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