#include <vectrex.h> //#include <stdio.h> //#include <stdlib.h> #define extern typedef int bit8; typedef long bit16; typedef long long bit32; typedef struct { bit32 pos[3]; bit16 expos[3]; bit16 view[9]; bit16 r; bit16 d; bit16 speed; bit16 *shape; } bodytype; typedef struct x { bit16 pos[3]; struct x *next; } startype; typedef struct { bit16 pos[3]; bit16 r; bit16 d; bit16 colour; bit16 type; } planettype; typedef struct { char type; bit16 x1,y1,x2,y2; } atomtype; #define mul16(x,y) ((bit16)((bit32)(x) * (bit32)(y))) #define div14(x) (bit16)((bit32)(x) / 16384LL) #define abs(x) (((x) < 0) ? -(x) : (x)) #define SCRX 320 #define SCRY 256 #define VPX1 64 #define VPY1 88 #define VPX2 256 #define VPY2 216 #define MAX_BODY 8 #define TOP 1 #define BOTTOM 2 #define LEFT 4 #define RIGHT 8 bit16 clipxl = VPX1; bit16 clipxr = VPX2; bit16 clipyt = VPY2; bit16 clipyb = VPY1; void code(bit16 x, bit16 y, bit16 *c) { *c = 0; if(x < clipxl) { *c = LEFT; } else { if(x > clipxr) { *c = RIGHT; } } if(y < clipyb) { *c += BOTTOM; } else { if(y > clipyt) { *c += TOP; } } } /* Cohen-Sutherland clipping algorithm */ bit16 clip(bit16 x1, bit16 y1, bit16 x2, bit16 y2, atomtype *ip) { bit16 c,c1,c2,x,y; code(x1,y1,&c1); code(x2,y2,&c2); while(c1 | c2) { if((c1 & c2) != 0) return 0; c = (c1 == 0) ? c2 : c1; if(LEFT & c) { /* crosses left edge */ y = mul16(y2-y1,clipxl-x1) / (x2 - x1) + y1; x = clipxl; } else { if(RIGHT & c) { /* crosses right edge */ y = mul16(y2-y1,clipxr-x1) / (x2 - x1) + y1; x = clipxr; } else { if(BOTTOM & c) { /* crosses bottom edge */ x = mul16(x2-x1,clipyb-y1) / (y2 - y1) + x1; y = clipyb; } else { if(TOP & c) { /* crosses top edge */ x = mul16(x2-x1,clipyt-y1) / (y2 - y1) + x1; y = clipyt; } } } } if(c == c1) { x1 = x; y1 = y; code(x,y,&c1); } else { x2 = x; y2 = y; code(x,y,&c2); } } /* here if line is visible */ ip->type = 'v'; ip->x1 = x1; ip->y1 = y1; ip->x2 = x2; ip->y2 = y2; return 1; } extern void vector(bit16 x1, bit16 y1, bit16 x2, bit16 y2, char mode, bit16 col); extern void plot(bit16 x, bit16 y); extern void draw_object(bodytype *body); extern void shit(void); extern bodytype bodies[]; #ifdef NEVER extern atomtype imbuf[256]; extern atomtype *ibase1,*ibase2; extern atomtype *iptr1,*iptr2; extern atomtype *imax1,*imax2; void init_atoms(void) { iptr1 = ibase1; } void plot_atoms(void) { char flag; imax1 = iptr1; iptr1 = ibase1; iptr2 = ibase2; do { flag = 0; if(iptr1 != imax1) { switch(iptr1->type) { case 'v': vector(iptr1->x1,iptr1->y1,iptr1->x2,iptr1->y2,'^',5); break; case 'p': plot(iptr1->x1,iptr1->y1); break; } iptr1++; flag = 1; } if(iptr2 != imax2) { switch(iptr2->type) { case 'v': vector(iptr2->x1,iptr2->y1,iptr2->x2,iptr2->y2,'^',5); break; case 'p': plot(iptr2->x1,iptr2->y1); break; } iptr2++; flag = 1; } } while(flag); iptr1 = ibase1; ibase1 = ibase2; ibase2 = iptr1; imax2 = imax1; } #endif void display(void/*bit16 dmode*/) { int i; register bodytype *p; //init_atoms(); for(i=0; i<MAX_BODY; i++) { p = &bodies[i]; if(p->r != 0) { draw_object(p); } } shit(); // plot_atoms(); } bit16 clip(bit16 x1, bit16 y1, bit16 x2, bit16 y2, atomtype *ip); bit32 divx(bit32 x); //atomtype imbuf[256]; //atomtype *ibase1,*ibase2; //atomtype *iptr1,*iptr2; //atomtype *imax1,*imax2; bit16 *pbase; struct ptype { char state; bit16 trans[3]; bit16 px,py; } points[20]; extern bit16 view_pos[3]; extern bit16 view_vec[9]; void clear_image(void) { // ibase1 = imbuf; // ibase2 = imbuf + 128; // imax2 = ibase2; } void genxyz(bit16 p, bit16 *v, bit16 *r, bit16 *o) { register struct ptype *pp = &points[p]; if(pp->state == '0') { bit16 *qq; pp->state = '1'; qq = &pbase[p * 3]; pp->trans[0]=div14(mul16(v[0],qq[0])+mul16(v[3],qq[1])+mul16(v[6],qq[2])) -view_pos[0]+o[0]; pp->trans[1]=div14(mul16(v[1],qq[0])+mul16(v[4],qq[1])+mul16(v[7],qq[2])) -view_pos[1]+o[1]; pp->trans[2]=div14(mul16(v[2],qq[0])+mul16(v[5],qq[1])+mul16(v[8],qq[2])) -view_pos[2]+o[2]; /* printf("qq %d,%d,%d\n",qq[0],qq[1],qq[2]); printf("ppt %d,%d,%d\n",pp->trans[0],pp->trans[1],pp->trans[2]); */ } r[0] = pp->trans[0]; r[1] = pp->trans[1]; r[2] = pp->trans[2]; } void gennorm(bit16 p, bit16 *v, bit16 *r) { bit16 *qq = &pbase[p * 3]; r[0]=div14(mul16(v[0],qq[0])+mul16(v[3],qq[1])+mul16(v[6],qq[2])); r[1]=div14(mul16(v[1],qq[0])+mul16(v[4],qq[1])+mul16(v[7],qq[2])); r[2]=div14(mul16(v[2],qq[0])+mul16(v[5],qq[1])+mul16(v[8],qq[2])); } bit32 scprod(bit16 *v1, bit16 *v2) { return mul16(v1[0],v2[0]) + mul16(v1[1],v2[1]) + mul16(v1[2],v2[2]); } void genxy(bit16 *v3, bit16 *v2) { bit16 d = div14(scprod(v3,view_vec+3)); v2[0] = (bit16)(divx(scprod(v3,view_vec)) / d) + (VPX1+VPX2)/2; v2[1] = (bit16)(divx(scprod(v3,view_vec+6)) / d) + (VPY1+VPY2)/2; } bit32 divx(bit32 x) { return (x >> 6); } void draw_body(bodytype *body) { bit16 *b_data = body->shape; bit16 *fbase = b_data + 1; bit16 nface = fbase[0]; bit16 *fptr = fbase + 1; bit16 *vbase = b_data + 1 + b_data[0]; bit16 maxvec = vbase[-1]; bit16 npoint; // bit16 flag; bit16 end_1[3],end_2[3]; bit16 p[2],q[2]; bit16 nvec,i,j; bit16 n_pos[3],n_vec[3]; // bit16 *fptr2; char vec_done[20]; pbase = vbase + vbase[-1]*2 + 1; npoint = pbase[-1]; for(i=0; i<maxvec; i++) vec_done[i] = 0; for(i=0; i<npoint; i++) points[i].state = '0'; for(i=nface; i != 0; i--) { nvec = *fptr++; gennorm(fptr[0],body->view,n_vec); genxyz(vbase[fptr[1]*2],body->view,n_pos,body->expos); if(scprod(n_pos,n_vec) < 0) { fptr++; for(j=0; j<nvec; j++) { if(!vec_done[fptr[0]]) { vec_done[fptr[0]] = 1; genxyz(vbase[fptr[0]*2],body->view,end_1,body->expos); genxyz(vbase[fptr[0]*2+1],body->view,end_2,body->expos); genxy(end_1,p); genxy(end_2,q); // if(clip(p[0],p[1],q[0],q[1],iptr1)) iptr1++; } fptr++; } /* for j */ } else { fptr += nvec + 1; } /* if(scprod..) */ } /* for i */ } void draw_object(bodytype *body) { bit16 d,x,y,pr; bit16 delta[3]; delta[0] = body->expos[0] - view_pos[0]; delta[1] = body->expos[1] - view_pos[1]; delta[2] = body->expos[2] - view_pos[2]; d = div14(scprod(&view_vec[3],delta)); if(d > body->r + 10) { x = (bit16)divx((bit32)scprod(&view_vec[0],delta) / (bit32)d); y = (bit16)divx((bit32)scprod(&view_vec[6],delta) / (bit32)d); pr = (bit16)divx(mul16(body->r,16384) / d); if((abs(x) < (VPX2-VPX1)/2 + pr) && (abs(y) < (VPY2-VPY1)/2 + pr)) { draw_body(body); } } } #define umod(x,y) ((unsigned)(x) % (unsigned)(y)) bit16 rnd(); //FILE *fpi; #define MAX_STARS 4 startype stars[MAX_STARS],*star_ptr; #define MAX_PLANETS 3 planettype planets[MAX_PLANETS],*planet_ptr; #define MAX_MOONS 2 planettype moons[MAX_MOONS],*moon_ptr; bit16 n_stars; bit16 n_suns; bit16 n_planets; bit16 n_moons; bit16 randseed; bit16 n_near,n_far; startype *far_root,*near_root; const bit16 cube[] = { 38,6, 4,8,0,9,4,8, 4,9,1,9,5,10, 4,10,2,10,6,11, 4,11,3,8,7,11, 4,12,0,1,2,3, 4,13,4,5,6,7, 12, 0,1, 1,2, 2,3, 3,0, 4,5, 5,6, 6,7, 7,4, 0,4, 1,5, 2,6, 3,7, 14, 20,-20,-20, 20,20,-20, -20,20,-20, -20,-20,-20, 20,-20,20, 20,20,20, -20,20,20, -20,-20,20, 1000,0,0, 0,1000,0, -1000,0,0, 0,-1000,0, 0,0,-1000, 0,0,1000 }; const bit16 kcf[] = { 46,8, 3,8,0,7,8, 3,9,1,8,9, 3,10,2,9,10, 3,11,3,10,11, 3,12,4,11,12, 3,13,5,12,13, 3,14,6,13,7, 7,15,0,1,2,3,4,5,6, 14, 1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,1, 1,0, 2,0, 3,0, 4,0, 5,0, 6,0, 7,0, 16, 0,35,0, -20,-15,0, -10,-15,-5, 10,-15,-5, 20,-15,0, 10,-15,5, 0,-15,8, -10,-15,5, -440,176,-880, 0,100,-995, 440,176,-880, 440,176,880, 284,151,947, -284,151,947, -440,176,880, 0,-1000,0 }; const bit16 icos[] = { 16384,16069,15137,13623,11585,9102,6270,3196, 0,-3196,-6270,-9102,-11585,-13623,-15137,-16069, -16384,-16069,-15137,-13623,-11585,-9102,-6270,-3196, 0,3196,6270,9102,11585,13623,15137,16069 }; const bit16 shit_data[] = { 32, -96,39,95,59,77,-108,-2,-11,-100,115,52,9,121,-45,117,111, 9,17,44,52,62,43,-11,-42,-87,61,11,-18,-113,69,4,17, 62,42,-68,-9,-94,-3,-113,-34,19,125,-53,41,112,-30,100,76, 114,-45,-22,-19,60,-71,-71,68,47,56,111,-60,5,-7,-92,-4, 28,-82,-43,-65,18,80,-95,-125,-108,-84,55,7,111,29,15,56, -16,-101,-40,86,106,-12,-78,82,19,90,-98,123,21,30,50,90 }; void make_planet(bit16 x, bit16 y, bit16 z, bit16 r, bit16 col, bit16 type) { planettype *p; p = &planets[n_planets++]; p->pos[0] = x; p->pos[1] = y; p->pos[2] = z; p->r = r; p->colour = col; p->type = type; // // // printf("planet type %d at %d,%d\n",type,x,y); } bit16 rand15(void) { return (((bit16)Random()<<8L) | (bit16)Random()) & 0x7fff; } void enter_galaxy(void) { register int i; //int t1,t2,t3; int x,y,z; #ifdef NEVER fpi = fopen("stars.dat","r"); if(fpi == NULL) exit(0); fscanf(fpi,"%d",&t1); n_stars = (bit16)t1; for(i=0; i<n_stars; i++) { stars[i].next = &stars[i+1]; fscanf(fpi,"%d,%d,%d",&t1,&t2,&t3); stars[i].pos[0]=t1; stars[i].pos[1]=t2;stars[i].pos[2]=t3; x = stars[i].pos[0] / 64; y = stars[i].pos[1] / 64; z = stars[i].pos[2] / 64; } #else n_stars = 4; for(i=0; i<n_stars; i++) { stars[i].next = &stars[i+1]; stars[i].pos[0]=rand15(); stars[i].pos[1]=rand15(); stars[i].pos[2]=rand15(); x = (int)(stars[i].pos[0] / 64L); y = (int)(stars[i].pos[1] / 64L); z = (int)(stars[i].pos[2] / 64L); } #endif stars[i-1].next = stars; far_root = stars; near_root = stars; n_far = n_stars; n_near = 0; } void enter_solar(void) { bit16 n_xp; bit16 i; bit16 r_ss,r; bit16 r_inc; randseed = (star_ptr - stars); r = 500 + (rnd() & 255); n_planets = 0; switch(rnd() & 3) { case 3: make_planet(-r*2,-r*2,0,r,7,0); case 2: make_planet(r*2,-r*2,0,r/2,6,0); case 0: case 1: make_planet(0,0,0,r,5,0); } n_suns = n_planets; n_xp = umod(rnd(),5) + 1; r *= 3; r_ss = 5000 + umod(rnd(),9000); r_inc = (r_ss - r) / n_xp; for(; r<r_ss-100; r += r_inc) { i = rnd(); make_planet(div14(mul16(icos[i & 31],r)),div14(mul16(icos[(i+8) & 31],r)) ,0,10,7,1); } } void enter_planet(void) { } bit16 rnd(void) { return (randseed = randseed * 3421 + 1); } bit16 mode,disp_mode; extern void display(void /*bit16 dmode*/); extern void combat_loop(void); extern void inigraf(void); extern void clear_image(void); extern void panel(void); extern void enter_galaxy(void); extern void enter_solar(void); extern void enter_planet(void); extern void make_pirates(void); void a_loop(void) { display(/*disp_mode*/); switch(mode) { case 0: combat_loop(); break; } } extern bit16 view_vec[9]; extern void steer_you(void); extern void move_you(void); extern void steer_opponents(void); extern void move_opponents(void); void solar_loop(void) { } void hyper_loop(void) { } void combat_loop(void) { steer_you(); move_you(); steer_opponents(); move_opponents(); } bodytype bodies[MAX_BODY]; bit32 ini_pos[3] = {0LL,200LL*16384LL,0LL}; bit16 ini_vec[9] = {16384L,0,0, 0,16384L,0, 0,0,16384L}; void copy16(bit16 *s, bit16 *d, bit16 c) { do { *d++ = *s++; c--; } while(c != 0); } void copy32(bit32 *s, bit32 *d, bit16 c) { do { *d++ = *s++; c--; } while(c != 0); } void update_pos(bodytype *b) { b->expos[0] = div14(b->pos[0]); b->expos[1] = div14(b->pos[1]); b->expos[2] = div14(b->pos[2]); } void clear_bodies(void) { register int i; for(i=0; i<MAX_BODY; i++) { bodies[i].r = 0; } } void make_pirates(void) { clear_bodies(); copy32(ini_pos,bodies[0].pos,3); copy16(ini_vec,bodies[0].view,9); bodies[0].r = 63; bodies[0].speed = 4;; bodies[0].shape = (bit16 *)kcf; update_pos(&bodies[0]); } extern bodytype bodies[]; extern bit16 view_vec[],view_pos[]; void distance(void) { int i; register bodytype *p = bodies; for(i=MAX_BODY; i != 0; i--,p++) { if(p->r != 0) { p->d = abs(p->expos[0] - view_pos[0]) + abs(p->expos[1] - view_pos[1]) + abs(p->expos[2] - view_pos[2]); } } } void move_opponents(void) { int i; register bodytype *p = bodies; for(i=MAX_BODY; i != 0; i--,p++) { if(p->r != 0) { p->expos[0] = div14(p->pos[0] += mul16(p->view[3],p->speed)); p->expos[1] = div14(p->pos[1] += mul16(p->view[4],p->speed)); p->expos[2] = div14(p->pos[2] += mul16(p->view[5],p->speed)); } } distance(); } extern void vector(bit16 x1, bit16 y1, bit16 x2, bit16 y2, char mode, bit16 col); void panel(void) { vector(1,1,1,SCRY-2,'|',7); vector(1,SCRY-2,SCRX-2,SCRY-2,'|',7); vector(SCRX-2,SCRY-2,SCRX-2,1,'|',7); vector(SCRX-2,1,1,1,'|',7); vector(VPX1-1,VPY1-1,VPX2,VPY1-1,'|',6); vector(VPX2,VPY1-1,VPX2,VPY2,'|',6); vector(VPX2,VPY2,VPX1-1,VPY2,'|',6); vector(VPX1-1,VPY2,VPX1-1,VPY1-1,'|',6); } bit32 scprod(); extern atomtype *iptr1; extern bit16 view_pos[3],view_vec[9]; extern bit16 divy(bit32 x); void shit(void) { register bit16 *p = (bit16 *)shit_data; bit16 i,x,y,d; bit16 shit_pos[3]; for(i=*p++; i != 0; i--,p+=3) { shit_pos[0] = (bit8)(p[0]-view_pos[0]); shit_pos[1] = (bit8)(p[1]-view_pos[1]); shit_pos[2] = (bit8)(p[2]-view_pos[2]); d = div14(scprod(shit_pos,view_vec+3)); if(d > 5) { x = divy(scprod(shit_pos,view_vec) / d) + (VPX1+VPX2)/2; if((x > VPX1) && (x < VPX2)) { y = divy(scprod(shit_pos,view_vec+6) / d) + (VPY1+VPY2)/2; if((y > VPY1) && (y < VPY2)) { iptr1->type = 'p'; iptr1->x1 = x; iptr1->y1 = y; iptr1++; } } } } } bit16 divy(bit32 x) { return (bit16)(x >> 8); } extern void xrotate(bit16 *v, bit16 x); extern bodytype bodies[]; void steer_opponents(void) { int i; register bodytype *p = bodies; for(i=MAX_BODY; i != 0; i--,p++) { if(p->r != 0) { xrotate(p->view,1000); } } } extern void norm(bit16 *a, bit16 *b); void xrotate(bit16 *v, bit16 x) { bit16 t[3]; t[0] = v[6]; t[1] = v[7]; t[2] = v[8]; v[6] -= div14(mul16(v[3],x)); v[7] -= div14(mul16(v[4],x)); v[8] -= div14(mul16(v[5],x)); v[3] += div14(mul16(t[0],x)); v[4] += div14(mul16(t[1],x)); v[5] += div14(mul16(t[2],x)); norm(v+3,v+3); norm(v+6,v+6); } void yrotate(bit16 *v, bit16 x) { bit16 t[3]; t[0] = v[6]; t[1] = v[7]; t[2] = v[8]; v[6] -= div14(mul16(v[0],x)); v[7] -= div14(mul16(v[1],x)); v[8] -= div14(mul16(v[2],x)); v[0] += div14(mul16(t[0],x)); v[1] += div14(mul16(t[1],x)); v[2] += div14(mul16(t[2],x)); norm(v,v); norm(v+3,v+3); } void norm(bit16 *a, bit16 *b) { register bit32 v = mul16(a[0],a[0])+mul16(a[1],a[1])+mul16(a[2],a[2]); bit16 g,m; if((v < 268304400l) || (v > 268566544l)) { g = 0; for(m=16384; m != 0; m /= 2) { g |= m; if(mul16(g,g) > v) { g ^= m; } } b[0] = mul16(a[0],16384) / g; b[1] = mul16(a[1],16384) / g; b[2] = mul16(a[2],16384) / g; } } char last_mode = '|'; bit16 last_col = 7; // white // static char hex_chars[] = "0123456789ABCDEF"; // BBC Micro-dependent void vdu(int code, int arg, int x, int y) { // low-level graphics calls on Beeb #ifdef NEVER putchar(code); putchar(arg); x = x*4; y = y*4; putchar(x & 255); putchar((x >> 8) & 255); putchar(y & 255); putchar((y >> 8) & 255); #endif // // // printf("Vdu %d,%d, %d, %d\n", code, arg, x, y); (void)code; (void)arg; (void)x; (void)y; } void inigraf(void) { // vdu(22,0,0,0); // CLS // // // printf("cls\n"); } void plot(bit16 x, bit16 y) { // // // printf("point %d,%d\n", x,y); //vdu(25,4,x,y); // moveto //vdu(25,5,x,y); // lineto same point Reset0Ref(); Dot_d((int)y,(int)x); } void vector(bit16 x1, bit16 y1, bit16 x2, bit16 y2, char mode, bit16 col) { if(col != last_col) last_col = col; (void)mode; #ifdef NEVER if(mode != last_mode) { last_mode = mode; switch(mode) { case '|': //vdu(18,0,1,0); // OR mode break; case '^': //vdu(18,4,1,0); // EXOR mode break; } } #endif // // // printf("line %d,%d, %d,%d\n", x1,y1, x2,y2); Reset0Ref(); Moveto_d_7F((int)y1,(int)x1); //vdu(25,4,x1,y1); // move to Draw_Line_d((int)(y2+y1),(int)(x2+x1)); //vdu(25,5,x2,y2); // line to } extern void xrotate(bit16 *v, bit16 x); bit16 view_speed = 3; bit32 view_big[3] = {0l,0l,0l}; bit16 view_pos[3] = {0,0,0}; bit16 view_vec[9] = {16384,0,0, 0,16384,0, 0,0,16384}; bit16 x_rot_val = 0; bit16 y_rot_val = 0; static char c; //extern void exit(int rc); // no stdlib :-( void steer_you(void) { // get68k(&c); // get an up/level/down command from the keyboard c = '5'; if (c == '\0') return; switch(c) { case '\033': /*exit(0)*/; case '8': x_rot_val = 200; break; case '2': x_rot_val = -200; break; case '5': x_rot_val = 0; y_rot_val = 0; break; } } void move_you(void) { if(x_rot_val != 0) xrotate(view_vec,x_rot_val); view_pos[0] = div14(view_big[0] += mul16(view_vec[3],view_speed)); view_pos[1] = div14(view_big[1] += mul16(view_vec[4],view_speed)); view_pos[2] = div14(view_big[2] += mul16(view_vec[5],view_speed)); } int main(void) { inigraf(); clear_image(); panel(); enter_galaxy(); star_ptr = stars; enter_solar(); planet_ptr = planets; enter_planet(); moon_ptr = moons; mode = 0; disp_mode = 0; make_pirates(); Intensity_7F(); VIA_t1_cnt_lo = (unsigned int)(0xFF); while(1) { Wait_Recal(); Print_Str_d(0, -70, "HELLO WORLD\x80"); Moveto_d_7F(-100,-100); Draw_Line_d(100,100); a_loop(); }; // if return value is <= 0, then a warm reset will be performed, // otherwise a cold reset will be performed return 0; } // *************************************************************************** // end of file // ***************************************************************************