tfv: wasted a lot of time trying to get signed 16x16 multiply working

This commit is contained in:
Vince Weaver 2017-09-06 23:17:39 -04:00
parent efb63f57b7
commit 621f808531
5 changed files with 354 additions and 35 deletions

View File

@ -93,6 +93,9 @@ tfv_flying.o: tfv_flying.c
tfv_info.o: tfv_info.c
$(CC) $(CFLAGS) -c tfv_info.c
tfv_multiply.o: tfv_multiply.c
$(CC) $(CFLAGS) -c tfv_multiply.c
tfv_opener.o: tfv_opener.c tfv_utils.h
$(CC) $(CFLAGS) -c tfv_opener.c
@ -114,8 +117,8 @@ tfv_worldmap.o: tfv_worldmap.c
tfv.o: tfv.c gr-sim.h tfv_backgrounds.h tfv_sprites.h
$(CC) $(CFLAGS) -c tfv.c
tfv: tfv.o tfv_backgrounds.o tfv_battle.o tfv_flying.o tfv_info.o tfv_opener.o tfv_sprites.o tfv_textentry.o tfv_title.o tfv_utils.o tfv_worldmap.o gr-sim.o
$(CC) $(LFLAGS) $(SDL_LIBS) -o tfv tfv.o tfv_backgrounds.o tfv_battle.o tfv_flying.o tfv_info.o tfv_opener.o tfv_sprites.o tfv_textentry.o tfv_title.o tfv_utils.o tfv_worldmap.o gr-sim.o
tfv: tfv.o tfv_backgrounds.o tfv_battle.o tfv_flying.o tfv_info.o tfv_multiply.o tfv_opener.o tfv_sprites.o tfv_textentry.o tfv_title.o tfv_utils.o tfv_worldmap.o gr-sim.o
$(CC) $(LFLAGS) $(SDL_LIBS) -o tfv tfv.o tfv_backgrounds.o tfv_battle.o tfv_flying.o tfv_info.o tfv_multiply.o tfv_opener.o tfv_sprites.o tfv_textentry.o tfv_title.o tfv_utils.o tfv_worldmap.o gr-sim.o
###

View File

@ -76,11 +76,6 @@ static int screen_x, screen_y;
static char angle=0;
struct fixed_type {
char i;
unsigned char f;
};
// 1 = use reduced fixed point
// 0 = use fancy hi-res floating point
#if 1
@ -204,28 +199,14 @@ static void fixed_add(struct fixed_type *x, struct fixed_type *y, struct fixed_t
// f->f=temp&0xff;
//}
static void fixed_mul(struct fixed_type *x, struct fixed_type *y, struct fixed_type *z) {
int a,b,c;
a=((x->i)<<8)+(x->f);
b=((y->i)<<8)+(y->f);
c=a*b;
c>>=8;
z->i=(c>>8);
z->f=(c&0xff);
}
//
// Non-detailed version
//
//
static int displayed=0;
void draw_background_mode7(void) {
@ -247,7 +228,13 @@ void draw_background_mode7(void) {
// fixed_to_double(&space_z,&double_space_z);
// double_factor=double_space_z*double_BETA;
fixed_mul(&space_z,&BETA,&factor);
fixed_mul(&space_z,&BETA,&factor,0);
if (!displayed) {
printf("%x %x * %x %x = %x %x\n",
space_z.i,space_z.f,BETA.i,BETA.f,factor.i,factor.f);
displayed=1;
}
// printf("spacez=%lf beta=%lf factor=%lf\n",
// fixed_to_double(&space_z),
@ -265,7 +252,7 @@ void draw_background_mode7(void) {
horizontal_lookup[space_z.i&0xf][(screen_y-8)/2];
// calculate the distance of the line we are drawing
fixed_mul(&horizontal_scale,&scale,&distance);
fixed_mul(&horizontal_scale,&scale,&distance,0);
//fixed_to_double(&distance,&double_distance);
// printf("Distance=%lf, horizontal-scale=%lf\n",
@ -275,11 +262,11 @@ void draw_background_mode7(void) {
// through all points on this line
dx.i=fixed_sin[(angle+8)&0xf].i; // -sin()
dx.f=fixed_sin[(angle+8)&0xf].f; // -sin()
fixed_mul(&dx,&horizontal_scale,&dx);
fixed_mul(&dx,&horizontal_scale,&dx,0);
dy.i=fixed_sin[(angle+4)&0xf].i; // cos()
dy.f=fixed_sin[(angle+4)&0xf].f; // cos()
fixed_mul(&dy,&horizontal_scale,&dy);
fixed_mul(&dy,&horizontal_scale,&dy,0);
// calculate the starting position
//double_space_x =(double_distance+double_factor);
@ -287,11 +274,11 @@ void draw_background_mode7(void) {
// double_to_fixed(double_space_x,&space_x);
fixed_temp.i=fixed_sin[(angle+4)&0xf].i; // cos
fixed_temp.f=fixed_sin[(angle+4)&0xf].f; // cos
fixed_mul(&space_x,&fixed_temp,&space_x);
fixed_mul(&space_x,&fixed_temp,&space_x,0);
fixed_add(&space_x,&cx,&space_x);
fixed_temp.i=0xec; // -20 (LOWRES_W/2)
fixed_temp.f=0;
fixed_mul(&fixed_temp,&dx,&fixed_temp);
fixed_mul(&fixed_temp,&dx,&fixed_temp,0);
fixed_add(&space_x,&fixed_temp,&space_x);
fixed_add(&distance,&factor,&space_y);
@ -299,11 +286,11 @@ void draw_background_mode7(void) {
// double_to_fixed(double_space_y,&space_y);
fixed_temp.i=fixed_sin[angle&0xf].i;
fixed_temp.f=fixed_sin[angle&0xf].f;
fixed_mul(&space_y,&fixed_temp,&space_y);
fixed_mul(&space_y,&fixed_temp,&space_y,0);
fixed_add(&space_y,&cy,&space_y);
fixed_temp.i=0xec; // -20 (LOWRES_W/2)
fixed_temp.f=0;
fixed_mul(&fixed_temp,&dy,&fixed_temp);
fixed_mul(&fixed_temp,&dy,&fixed_temp,0);
fixed_add(&space_y,&fixed_temp,&space_y);
// go through all points in this screen line

295
gr-sim/tfv_multiply.c Normal file
View File

@ -0,0 +1,295 @@
#include <stdio.h>
#include <stdlib.h>
#include "tfv_zp.h"
#if 0
int fixed_mul(struct fixed_type *x,
struct fixed_type *y,
struct fixed_type *z, int debug) {
int a,b,c;
a=((x->i)<<8)+(x->f);
b=((y->i)<<8)+(y->f);
c=a*b;
if (debug) {
printf("%x:%x (%d) * %x:%x (%d) = %x (%d)\n",
x->i,x->f,a,
y->i,y->f,b,
c,c);
}
c>>=8;
z->i=(c>>8);
z->f=(c&0xff);
return a*b;
}
#else
int fixed_mul(struct fixed_type *x,
struct fixed_type *y,
struct fixed_type *z,
int debug) {
int num1h,num1l;
int num2h,num2l;
int result3;
int result2,result1,result0;
int aa,xx,cc=0,cc2,yy;
int negative=0;
num1h=x->i;
num1l=x->f;
if (num1h&0x80) {
negative^=1;
num1l=~num1l;
num1h=~num1h;
num1l&=0xff;
num1h&=0xff;
num1l+=1;
cc=!!(num1l&0x100);
num1h+=cc;
num1l&=0xff;
num1h&=0xff;
}
num2h=y->i;
num2l=y->f;
if (num2h&0x80) {
negative^=1;
num2l=~num2l;
num2h=~num2h;
num2l&=0xff;
num2h&=0xff;
num2l+=1;
cc=!!(num2l&0x100);
num2h+=cc;
num2l&=0xff;
num2h&=0xff;
}
if (debug) {
printf("Using %02x:%02x * %02x:%02x\n",num1h,num1l,num2h,num2l);
}
result0=0;
result1=0;
//label_multiply:
aa=0; // lda #0 (sz)
result2=aa; // sta result+2
xx=16; // ldx #16 (sz)
label_l1:
cc=(num2h&1); //lsr NUM2+1 (szc)
num2h>>=1;
num2h&=0x7f;
// if (num2_neg) {
// num2h|=0x80;
// }
cc2=(num2l&1); // ror NUM2 (szc)
num2l>>=1;
num2l&=0x7f;
num2l|=(cc<<7);
cc=cc2;
if (cc==0) goto label_l2; // bcc L2
yy=aa; // tay (sz)
cc=0; // clc
aa=num1l; // lda NUM1 (sz)
aa=aa+cc+result2; // adc RESULT+2 (svzc)
cc=!!(aa&0x100);
aa&=0xff;
result2=aa; // sta RESULT+2
aa=yy; // tya
aa=aa+cc+num1h; // adc NUM1+1
cc=!!(aa&0x100);
aa=aa&0xff;
label_l2:
cc2=aa&1;
aa=aa>>1;
aa&=0x7f;
aa|=cc<<7;
cc=cc2; // ror A
cc2=result2&1;
result2=result2>>1;
result2&=0x7f;
result2|=(cc<<7);
cc=cc2; // ror result+2
cc2=result1&1;
result1=result1>>1;
result1&=0x7f;
result1|=cc<<7;
cc=cc2; // ror result+1
cc2=result0&1;
result0=result0>>1;
result0&=0x7f;
result0|=cc<<7;
cc=cc2; // ror result+0
xx--; // dex
if (xx!=0) goto label_l1; // bne L1
result3=aa&0xff; // sta result+3
if (debug) {
printf("RAW RESULT = %02x:%02x:%02x:%02x\n",
result3&0xff,result2&0xff,result1&0xff,result0&0xff);
}
if (negative) {
// printf("NEGATING!\n");
cc=0;
aa=0;
aa-=result0+cc;
cc=!!(aa&0x100);
result0=aa;
aa=0;
aa-=result1+cc;
cc=!!(aa&0x100);
result1=aa;
aa=0;
aa-=result2+cc;
cc=!!(aa&0x100);
result2=aa;
aa=0;
aa-=result3+cc;
cc=!!(aa&0x100);
result3=aa;
}
z->i=result2&0xff;
z->f=result1&0xff;
result3&=0xff;
result2&=0xff;
result1&=0xff;
result0&=0xff;
if (debug) {
printf("%02x:%02x * %02x:%02x = %02x:%02x:%02x:%02x\n",
num1h,num1l,y->i,y->f,
result3&0xff,result2&0xff,result1&0xff,result0&0xff);
// printf("%02x%02x * %02x%02x = %02x%02x%02x%02x\n",
// num1h,num1l,y->i,y->f,
// result3,result2,result1,result0);
}
int a2;
// int s1,s2;
// s1=(num1h<<8)|(num1l);
// s2=(y->i<<8)|(y->f);
a2=(result3<<24)|(result2<<16)|(result1<<8)|result0;
// printf("%d * %d = %d (0x%x)\n",s1,s2,a2,a2);
return a2;
}
#endif
#if 0
int main(int argc, char **argv) {
struct fixed_type a,b,c;
int i,j,k;
i=-32768;
j=3;
a.i=i>>8;
a.f=i&0xff;
b.i=j>>8;
b.f=j&0xff;
k=fixed_mul(&a,&b,&c,1);
if (k!=i*j) {
printf("Error! %d*%d=%d, %d\n",i,j,i*j,k);
}
a.i=0x0;
a.f=0x2;
b.i=0x0;
b.f=0x3;
fixed_mul(&a,&b,&c,0);
a.i=0xff;
a.f=0xff;
b.i=0xff;
b.f=0xff;
fixed_mul(&a,&b,&c,0);
a.i=0xff;
a.f=0xff;
b.i=0x00;
b.f=0x01;
fixed_mul(&a,&b,&c,0);
for(i=-32768;i<32768;i++) {
for(j=-32768;j<32768;j++) {
a.i=i>>8;
a.f=i&0xff;
b.i=j>>8;
b.f=j&0xff;
k=fixed_mul(&a,&b,&c,0);
if (k!=i*j) {
printf("WRONG! %x*%x = %x not %x\n",
i,j,i*j,k);
printf("%d * %d = %d not %d\n",i,j,i*j,k);
exit(1);
}
}
if (i%256==0) printf("%x\n",i);
}
return 0;
}
#endif

View File

@ -56,6 +56,15 @@ extern unsigned char ground_color;
extern char nameo[9];
struct fixed_type {
char i;
unsigned char f;
};
int fixed_mul(struct fixed_type *x,
struct fixed_type *y,
struct fixed_type *z, int debug);
int opening(void);
int title(void);

View File

@ -55,6 +55,11 @@ flying_start:
sta SPACEX_I
sta SPACEY_I
lda #4
sta SPACEZ_I
lda #$80
sta SPACEZ_F
flying_loop:
@ -187,19 +192,35 @@ sky_loop: ; draw line across screen
; fixed_mul(&space_z,&BETA,&factor);
lda SPACEZ_I
sta NUM1
lda SPACEZ_F
sta NUM1+1
lda SPACEZ_F
sta NUM1
lda #$ff ; BETA_I
sta NUM2
lda #$80 ; BETA_F
sta NUM2+1
lda #$80 ; BETA_F
sta NUM2
jsr multiply
lda RESULT+1
sta FACTOR_I
lda RESULT+2
sta FACTOR_F
brk ;; SPACEZ=78 * ff80 = FACTOR=66
;; 4 80 * ff 80 = 83 81
;; 4 80 * 00 00 = fc 83 81 40
;; 4 80 * ffffffff 80 = fffffffd c0
;; spacez*beta=factor
;; C
;; GOOD 4 80 * ffffffff 80 = fffffffd c0
;; BAD 4 80 * ffffffff 80 = 42 40
lda #8
sta SCREEN_Y
@ -548,11 +569,15 @@ water_map:
; 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