// ------------------------------------------------------------------------ // Net Yaroze Development Template // High performance macros & functions for 2D & 3D // Second version (25/02/99) // // A collection of functions designed to speed up development time. // Please note, everything in this library is written for speed not size. // If you wish to optimize for space, you can rewrite the macros as // functions. // // Use and abuse as you see fit. This library will expand over time! // If you do use any of this code, please give me a mention in your readme. // // Written by Harvey Cotton (hc054@mdx.ac.uk) // http://www.netyaroze-europe.com/~harveyc // ------------------------------------------------------------------------ // **************************************************************************************************************** Constants // Alter these to match your screen resolution #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 #define HALF_WIDTH 160 #define HALF_HEIGHT 120 // ************************************************************************************************ Billboarding (3d sprites) typedef struct { GsSPRITE *sprite; // Pointer to sprite VECTOR position; // Position in 3d world long distance; // Maximum draw distance long precision; // 3d precision } Object2; // Initialise a 3d sprite // x,y,z = position in 3d world // distance = maximum draw distance from camera // precision = same as 3d object void initialise_3dsprite (Object2 *object2,GsSPRITE *sprite,long x,long y,long z,long distance,char precision) { object2->sprite=sprite; object2->position.vx=x; object2->position.vy=y; object2->position.vz=z; object2->distance=distance; object2->precision=precision; } // Send &object to ordering table void draw_3dsprite (Object2 *object) { register VECTOR *transformedPosition=(VECTOR *)0x1f800000; ApplyMatrixLV(&GsWSMATRIX,&object->position,transformedPosition); transformedPosition->vz+=GsWSMATRIX.t[2]; if (transformedPosition->vz>0 && transformedPosition->vzdistance) { transformedPosition->vx+=GsWSMATRIX.t[0]; transformedPosition->vy+=GsWSMATRIX.t[1]; object->sprite->scalex=object->sprite->scaley=16777216/transformedPosition->vz; object->sprite->x=(transformedPosition->vx<<8)/transformedPosition->vz; object->sprite->y=(transformedPosition->vy<<8)/transformedPosition->vz; GsSortSprite(object->sprite,&OTable_Header[CurrentBuffer],transformedPosition->vz>>object->precision); } } // *********************************************************************************************************************** 3d // Sets the position of a matrix in 3d space // Object_Coord = Pointer to coordinates to rotate (e.g. &player.coord) // nX = Sets x position // nY = Sets y position // nZ = Sets z position void position_matrix (GsCOORDINATE2 *Object_Coord, int nX, int nY, int nZ) { Object_Coord->coord.t[0]=nX; Object_Coord->coord.t[1]=nY; Object_Coord->coord.t[2]=nZ; Object_Coord->flg=0; } // Translates a matrix in certain direction // Object_Coord = Pointer to coordinates to rotate (e.g. &player.coord) // nX = Move matrix x position by nX amount // nY = Move matrix y position by nY amount // nZ = Move matrix z position by nZ amount void translate_matrix (GsCOORDINATE2 *Object_Coord, int nX, int nY, int nZ) { Object_Coord->coord.t[0]+=nX; Object_Coord->coord.t[1]+=nY; Object_Coord->coord.t[2]+=nZ; Object_Coord->flg=0; } // Finds the direction the matrix is facing and moves it a specific distance // Object_Coord = Pointer to coordinates to rotate (e.g. &player.coord) // distance = Distance to move matrix void move_matrix (GsCOORDINATE2 *Object_Coord,short distance) { VECTOR temp,direction; if (distance==0) return; temp.vx=temp.vy=0; temp.vz=4096; ApplyMatrixLV(&Object_Coord->coord,&temp,&direction); distance=4096/distance; Object_Coord->coord.t[0]+=direction.vx/distance; Object_Coord->coord.t[1]+=direction.vy/distance; Object_Coord->coord.t[2]+=direction.vz/distance; Object_Coord->flg=0; } // Rotate model in the y-axis // Object_Coord = Pointer to coordinates to rotate (e.g. &player.coord) // x = rotation (0-4096) void rotate_x (GsCOORDINATE2 *Object_Coord,long x) { RotMatrixX(x,&Object_Coord->coord); AdjustCoordinate2(Object_Coord); Object_Coord->flg=0; } // Rotate model in the y-axis // Object_Coord = Pointer to coordinates to rotate (e.g. &player.coord) // y = rotation (0-4096) void rotate_y (GsCOORDINATE2 *Object_Coord,long y) { RotMatrixY(y,&Object_Coord->coord); AdjustCoordinate2(Object_Coord); Object_Coord->flg=0; } // Rotate model in the y-axis // Object_Coord = Pointer to coordinates to rotate (e.g. &player.coord) // z = rotation (0-4096) void rotate_z (GsCOORDINATE2 *Object_Coord,long z) { RotMatrixZ(z,&Object_Coord->coord); AdjustCoordinate2(Object_Coord); Object_Coord->flg=0; } // ******************************************************************************************** Clipping & collision checking // Accurately test whether or not a sprite is on the screen // x,y = position of sprite (center of sprite) // w = half the width of the sprite // h = half the height of the sprite #clip_sprite (x,y,w,h) w+HALF_WIDTH>abs(HALF_WIDTH-x) && h+HALF_HEIGHT>abs(HALF_HEIGHT-y) // Test whether or not the centre of a sprite is on the screen // Good for very small sprites such as bullets // x,y = position of sprite (center of sprite) #define clip_sprite2(x,y) abs(HALF_WIDTH-x)abs(x1-x2) && (h1+h2)>abs(y1-y2) // Test collision between a point and a rectangular region (useful for bullets) // x1,y1 = position of first object (center of sprite) // x2,y2 = position of second object (center of sprite) // w2,h2 = half the width and half the height of the second object #define point_collision(x1,y1,x2,y2,w2,h2) abs(x1-x2)abs(x1-x2) && (h1+h2)>abs(y1-y2) && (d1+d2)>abs(z1-z2) // Detect whether two lines intersect using fixed point mathematics // x1,y1,x2,y2 = position of first line from point x1,y1 to x2,y2 // x3,y3,x4,y4 = position of first line from point x3,y3 to x4,y4 short intersection (long x1,long y1,long x2,long y2,long x3,long y3,long x4,long y4) { register long temp=((x2-x1)*(y4-y3)-(y2-y1)*(x4-x3))>>8,r,s; if (temp==0) temp=1; // Avoid divide by zero if (x1==x2 && x3==x4) x1++; // Avoid parallel horizontal lines if (y1==y2 && y3==y4) y1++; // Avoid parallel vertical lines r=((y1-y3)*(x4-x3)-(x1-x3)*(y4-y3))/temp; s=((y1-y3)*(x2-x1)-(x1-x3)*(y2-y1))/temp; if (r>=0 && r<=256 && s>=0 && s<=256) return 1; return 0; } // ********************************************************************************************************* Sprite functions // Various bit-macros from Peter Passmore's tutorial #define BitSet(_v,_b) (*(_v) = (*(_v)) | (_b)) #define BitClear(_v,_b) (*(_v) -= (*(_v)) & (_b)) #define BitCheck(_v,_b) (*(_v)& (_b)) // Set the transparency of a sprite // x = sprite name (& not required) #define transparency0(x) BitSet(&x.attribute,(1<<30)+(0<<28)) // 50% screen + 50% sprite #define transparency1(x) BitSet(&x.attribute,(1<<30)+(1<<28)) // 100% screen + 100% sprite #define transparency2(x) BitSet(&x.attribute,(1<<30)+(2<<28)) // 100% screen - 100% sprite #define transparency3(x) BitSet(&x.attribute,(1<<30)+(3<<28)) // 100% screen + 25% sprite // Turning off various attributes can speed up processing #define rotatescaleon(x) BitClear(&x.attribute,1<<27) // Turn on rotate/scale capabilities #define rotatescaleoff(x) BitSet(&x.attribute,1<<27) // Turn off rotate/scale capabilities #define brightnesson(x) BitClear(&x.attribute,1<<6) // Turn on rgb capabilities #define brightnessoff(x) BitSet(&x.attribute,1<<6) // Turn off rgb capabilities // Set brightness of sprite // E.g. if light is 128 then red/green/blue of a sprite is set to 128 // x = sprite name (& not required) // l = light (0-255) #define setspritelight(x,l) x.r=x.g=x.b=l; // Set rgb of sprite // s = sprite name (& not required) // x,y,z = r,g,b of sprite (0-255) #define setspritergb(s,x,y,z) {s.r=x;s.g=y;s.b=z;} // ********************************************************************************************************************* Math // Sine/Cosine lookup tables (c)1998 James Shaughnessy // Created with SCBUILD v1.1 See http://www.netyaroze-europe.com/~shaughnj long FSIN[361] = { 0, 71, 142, 213, 284, 356, 426, 497, 568, 638, 709, 779, 849, 918, 988, 1057, 1125, 1194, 1262, 1329, 1397, 1463, 1530, 1596, 1661, 1726, 1790, 1854, 1918, 1980, 2042, 2104, 2165, 2225, 2284, 2343, 2401, 2459, 2515, 2571, 2626, 2681, 2734, 2787, 2839, 2890, 2940, 2989, 3037, 3084, 3131, 3176, 3221, 3264, 3307, 3348, 3389, 3429, 3467, 3504, 3541, 3576, 3610, 3643, 3675, 3706, 3736, 3765, 3792, 3819, 3844, 3868, 3891, 3912, 3933, 3952, 3970, 3987, 4003, 4017, 4030, 4043, 4053, 4063, 4071, 4078, 4084, 4089, 4092, 4095, 4095, 4095, 4094, 4091, 4087, 4082, 4075, 4067, 4058, 4048, 4037, 4024, 4010, 3995, 3979, 3961, 3943, 3923, 3902, 3879, 3856, 3831, 3805, 3779, 3751, 3721, 3691, 3660, 3627, 3593, 3559, 3523, 3486, 3448, 3409, 3369, 3328, 3286, 3243, 3199, 3154, 3108, 3061, 3013, 2964, 2915, 2864, 2813, 2761, 2707, 2654, 2599, 2543, 2487, 2430, 2372, 2314, 2255, 2195, 2134, 2073, 2011, 1949, 1886, 1822, 1758, 1694, 1629, 1563, 1497, 1430, 1363, 1296, 1228, 1160, 1091, 1022, 953, 884, 814, 744, 674, 603, 533, 462, 391, 320, 249, 178, 106, 35, -35, -106, -178, -249, -320, -391, -462, -533, -603, -674, -744, -814, -884, -953, -1022, -1091, -1160, -1228, -1296, -1363, -1430, -1497, -1563, -1629, -1694, -1758, -1822, -1886, -1949, -2011, -2073, -2134, -2195, -2255, -2314, -2372, -2430, -2487, -2543, -2599, -2654, -2707, -2761, -2813, -2864, -2915, -2964, -3013, -3061, -3108, -3154, -3199, -3243, -3286, -3328, -3369, -3409, -3448, -3486, -3523, -3559, -3593, -3627, -3660, -3691, -3721, -3751, -3779, -3805, -3831, -3856, -3879, -3902, -3923, -3943, -3961, -3979, -3995, -4010, -4024, -4037, -4048, -4058, -4067, -4075, -4082, -4087, -4091, -4094, -4095, -4095, -4095, -4092, -4089, -4084, -4078, -4071, -4063, -4053, -4043, -4030, -4017, -4003, -3987, -3970, -3952, -3933, -3912, -3891, -3868, -3844, -3819, -3792, -3765, -3736, -3706, -3675, -3643, -3610, -3576, -3541, -3504, -3467, -3429, -3389, -3348, -3307, -3264, -3221, -3176, -3131, -3084, -3037, -2989, -2940, -2890, -2839, -2787, -2734, -2681, -2626, -2571, -2515, -2459, -2401, -2343, -2284, -2225, -2165, -2104, -2042, -1980, -1918, -1854, -1790, -1726, -1661, -1596, -1530, -1463, -1397, -1329, -1262, -1194, -1125, -1057, -988, -918, -849, -779, -709, -638, -568, -497, -426, -356, -284, -213, -142, -71 }; long FCOS[361] = { 4096, 4095, 4093, 4090, 4086, 4080, 4073, 4065, 4056, 4045, 4034, 4021, 4006, 3991, 3975, 3957, 3938, 3918, 3896, 3874, 3850, 3825, 3799, 3772, 3743, 3714, 3683, 3651, 3619, 3585, 3550, 3514, 3476, 3438, 3399, 3359, 3317, 3275, 3232, 3188, 3142, 3096, 3049, 3001, 2952, 2902, 2851, 2800, 2747, 2694, 2640, 2585, 2529, 2473, 2416, 2358, 2299, 2240, 2180, 2119, 2058, 1996, 1933, 1870, 1806, 1742, 1677, 1612, 1546, 1480, 1413, 1346, 1279, 1211, 1143, 1074, 1005, 936, 866, 796, 726, 656, 586, 515, 444, 373, 302, 231, 160, 89, 17, -53, -124, -195, -267, -338, -409, -480, -550, -621, -691, -761, -831, -901, -970, -1040, -1108, -1177, -1245, -1313, -1380, -1447, -1513, -1579, -1645, -1710, -1774, -1838, -1902, -1965, -2027, -2089, -2150, -2210, -2270, -2329, -2387, -2444, -2501, -2557, -2613, -2667, -2721, -2774, -2826, -2877, -2927, -2977, -3025, -3073, -3119, -3165, -3210, -3254, -3296, -3338, -3379, -3419, -3457, -3495, -3532, -3567, -3602, -3635, -3667, -3699, -3729, -3758, -3785, -3812, -3838, -3862, -3885, -3907, -3928, -3947, -3966, -3983, -3999, -4014, -4027, -4040, -4051, -4061, -4069, -4077, -4083, -4088, -4092, -4094, -4095, -4095, -4094, -4092, -4088, -4083, -4077, -4069, -4061, -4051, -4040, -4027, -4014, -3999, -3983, -3966, -3947, -3928, -3907, -3885, -3862, -3838, -3812, -3785, -3758, -3729, -3699, -3667, -3635, -3602, -3567, -3532, -3495, -3457, -3419, -3379, -3338, -3296, -3254, -3210, -3165, -3119, -3073, -3025, -2977, -2927, -2877, -2826, -2774, -2721, -2667, -2613, -2557, -2501, -2444, -2387, -2329, -2270, -2210, -2150, -2089, -2027, -1965, -1902, -1838, -1774, -1710, -1645, -1579, -1513, -1447, -1380, -1313, -1245, -1177, -1108, -1040, -970, -901, -831, -761, -691, -621, -550, -480, -409, -338, -267, -195, -124, -53, 17, 89, 160, 231, 302, 373, 444, 515, 586, 656, 726, 796, 866, 936, 1005, 1074, 1143, 1211, 1279, 1346, 1413, 1480, 1546, 1612, 1677, 1742, 1806, 1870, 1933, 1996, 2058, 2119, 2180, 2240, 2299, 2358, 2416, 2473, 2529, 2585, 2640, 2694, 2747, 2800, 2851, 2902, 2952, 3001, 3049, 3096, 3142, 3188, 3232, 3275, 3317, 3359, 3399, 3438, 3476, 3514, 3550, 3585, 3619, 3651, 3683, 3714, 3743, 3772, 3799, 3825, 3850, 3874, 3896, 3918, 3938, 3957, 3975, 3991, 4006, 4021, 4034, 4045, 4056, 4065, 4073, 4080, 4086, 4090, 4093, 4095 }; // Calculate the integer square root of X u_long isqrt (u_long X) { register int bitmax,Step=0; register u_long V1,V2=0; // get 1st estimate for(bitmax=0,V1=X;V1!=0;bitmax++) V1>>=1; V1=X>>(bitmax>>1); // iterative approximation (takes about 4 steps, Step is for unequal values of V1&V2) while((V1!=V2)&&(Step++<10)) { V2=X/V1; V1=(V1+V2)>>1; } return V1; } // Calculates the difference between two angles (result always between 0 and 180) // angle1 = first angle (0-360) // angle2 = second angle (0-360) #define angle_difference(angle1,angle2) (abs(angle1-angle2)>180 ? abs(abs(angle1-angle2)-360) : abs(angle1-angle2)) // Algorithm to determine which is the best way to turn in order to face a direction // Angle1 is the angle you wish to adjust to face angle2 and step is the degrees you wish to turn void adjust_angle (short *angle1,short angle2,short step) { if (angle_difference(*angle1,angle2)<=step) *angle1=angle2; // Stabilize angle else { if (*angle1>angle2) { if (*angle1-angle2<360-*angle1+angle2) *angle1-=step; else *angle1+=step; } else { if (angle2-*angle1<360-angle2+*angle1) *angle1+=step; else *angle1-=step; } } if (*angle1<0) *angle1+=360; else if (*angle1>360) *angle1-=360; } // Move a 2D vector in a given direction (uses fixed point tables) // x,y = vector to move // a = angle direction to move in // f = distance to move #define move_vector(x,y,a,f) {x+=(f*FCOS[a])>>12;y+=(f*FSIN[a])>>12;} // Calculate the distance between two points // x1,y1 = coordinates of first point // x2,y2 = coordinates of second point long distance (long x1,long y1,long x2,long y2) { register long dx=abs(x1-x2); register long dy=abs(y1-y2); return isqrt(dx*dx+((dy*dy)<<1)); } // Places a number within a bounds // x = the number itself // l = lower bound // h = upper bound #define limitrange(x,l,h) ((x)=((x)<(l)?(l):(x)>(h)?(h):(x))) // Detects whether x is position or negative #define sign(x) ((x)<0?-1:1) // ************************************************************************************************************** Control pad // Pad constants #define PADLup (1<<12) #define PADLdown (1<<14) #define PADLleft (1<<15) #define PADLright (1<<13) #define PADRup (1<< 4) #define PADRdown (1<< 6) #define PADRleft (1<< 7) #define PADRright (1<< 5) #define PADi (1<< 9) #define PADj (1<<10) #define PADk (1<< 8) #define PADl (1<< 3) #define PADm (1<< 1) #define PADn (1<< 2) #define PADo (1<< 0) #define PADh (1<<11) #define PADL1 PADn #define PADL2 PADo #define PADR1 PADl #define PADR2 PADm #define PADstart PADh #define PADselect PADk #define PADtriangle PADRup #define PADcross PADRdown #define PADsquare PADRleft #define PADcircle PADRright // Low level variables (do not need to touch) volatile u_char *bb0,*bb1; // Call this function at the beginning of main() to initialise pad #define initialise_pad() GetPadBuf(&bb0,&bb1) // Returns the state of the control pads // E.g. (pad_read & PADcross) #define pad_read() (~(*(bb0+3) | *(bb0+2) << 8 | *(bb1+3) << 16 | *(bb1+2) << 24)) // *************************************************************************************************************** Screenshot // Takes an immediate screenshot of your program and quits // Source code modified from Peter Passmore's tutorial void storescreen () { RECT rect; u_long *destination=(u_long*)0x80090000; *(destination+0)=0x00000010; *(destination+1)=0x00000002; *(destination+2)=(SCREEN_WIDTH*SCREEN_HEIGHT/2+3)*4; *(destination+3)=((0 & 0xffff)<<16)|(640 & 0xffff); *(destination+4)=((SCREEN_HEIGHT & 0xffff)<<16)|(SCREEN_WIDTH & 0xffff); rect.x=0; rect.y=0; rect.w=SCREEN_WIDTH; rect.h=SCREEN_HEIGHT; DrawSync(0); StoreImage(&rect,destination+5); printf("\n\nPress [F10][F4] for dsave, to get screen picture\n"); printf("Dsave[0]: filename %08x %x\n\n\n",destination,(rect.w*rect.h/2+5)*4); DrawSync(0); VSync(0); exit(0); }