summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/jewels.c2469
1 files changed, 2469 insertions, 0 deletions
diff --git a/source/jewels.c b/source/jewels.c
new file mode 100644
index 0000000..906ad10
--- /dev/null
+++ b/source/jewels.c
@@ -0,0 +1,2469 @@
+/*---------------------------------------------------------------------------------
+
+ Jewels by David Ashley
+
+---------------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <malloc.h>
+#include <math.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <gccore.h>
+#include <wiiuse/wpad.h>
+#include <asndlib.h>
+#include "alert_raw.h"
+#include "bigdrop_raw.h"
+#include "drop_raw.h"
+#include "gameover_raw.h"
+#include "illegal_raw.h"
+#include "row_raw.h"
+#include "swap_raw.h"
+#include "bigfont_ppm.h"
+
+#define DEFAULT_FIFO_SIZE (256*1024)
+
+static void *frameBuffer[2] = { NULL, NULL};
+GXRModeObj *rmode;
+
+void drawstring(Mtx44 view, f32 x, f32 y, f32 z,
+ f32 scale, int alignment, char *fmt, ...);
+void jmap(f32 *destx, f32 *desty, f32 *destz, f32 x, f32 y);
+
+static GXColor litcolors[] = {
+ { 0xD0, 0xD0, 0xD0, 0xFF }, // Light color 1
+ { 0x40, 0x40, 0x40, 0xFF }, // Ambient 1
+ { 0x80, 0x80, 0x80, 0xFF } // Material 1
+};
+
+void setlight(Mtx44 view,u32 theta,u32 phi,GXColor litcol, GXColor ambcol,
+ GXColor matcol)
+{
+ GXLightObj MyLight0;
+
+ guVector l0pos={-100.0f, 100.0f, 200.0f};
+ GX_InitLightPos(&MyLight0, l0pos.x, l0pos.y, l0pos.z);
+//GX_InitLightShininess(&MyLight0, 255); // between 4 and 255 !!!
+//GX_InitSpecularDir(&MyLight0, 0.0, 0.0, 0.0);
+#define LC 240
+ GX_InitLightColor(&MyLight0, (GXColor) { LC, LC, LC, 0xFF });
+ GX_InitLightSpot(&MyLight0, 0.0f, GX_SP_OFF);
+ GX_InitLightDistAttn(&MyLight0, 20.0f, 1.0f, GX_DA_MEDIUM); // DistAttn = 20.0 & Brightness=1.0f (full)
+ GX_LoadLightObj(&MyLight0, GX_LIGHT0);
+
+ /////////////////////// Turn light ON ////////////////////////////////////////////////
+ GX_SetNumChans(1);
+ GX_SetChanCtrl(GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_CLAMP,GX_AF_SPOT); //4th param is where come from the material color (REG(with setChanMatColor or VTX (vertex)) same for ambiant (3th param)
+
+ /////////////////////// Define MAterial and Ambiant color and draw object /////////////////////////////////////
+#define AMB 0x20
+ GX_SetChanAmbColor(GX_COLOR0A0, (GXColor) { AMB, AMB, AMB, 0xFF});
+#define MAT 255
+ GX_SetChanMatColor(GX_COLOR0A0, (GXColor) { MAT, MAT, MAT, 0xFF});
+}
+
+void light_brighter(void)
+{
+#define BRIGHTER 0x80
+ GX_SetChanAmbColor(GX_COLOR0A0, (GXColor) { BRIGHTER, BRIGHTER, BRIGHTER, 0xFF});
+}
+
+void light_regular(void)
+{
+ GX_SetChanAmbColor(GX_COLOR0A0, (GXColor) { AMB, AMB, AMB, 0xFF});
+}
+
+f32 coords[60][3]={
+{-0.449358F,0.730026F,0.514918F},
+{-0.277718F,0.201774F,0.939234F},
+{-0.277718F,-0.201774F,0.939234F},
+{-0.555436F,0.403548F,0.727076F},
+{-0.555436F,-0.403548F,0.727076F},
+{-0.833155F,0.201774F,0.514918F},
+{-0.833155F,-0.201774F,0.514918F},
+{0.106079F,-0.326477F,0.939234F},
+{0.212158F,-0.652955F,0.727076F},
+{-0.449358F,-0.730026F,0.514918F},
+{-0.065560F,-0.854729F,0.514918F},
+{0.343279F,0.000000F,0.939234F},
+{0.686557F,0.000000F,0.727076F},
+{0.555436F,-0.652955F,0.514918F},
+{0.792636F,-0.326477F,0.514918F},
+{0.661515F,0.730026F,-0.171639F},
+{0.898715F,0.403548F,-0.171639F},
+{0.489876F,0.854729F,0.171639F},
+{0.964275F,0.201774F,0.171639F},
+{0.555436F,0.652955F,0.514918F},
+{0.792636F,0.326477F,0.514918F},
+{-0.489876F,0.854729F,-0.171639F},
+{-0.106079F,0.979432F,-0.171639F},
+{-0.661515F,0.730026F,0.171639F},
+{0.106079F,0.979432F,0.171639F},
+{-0.065560F,0.854729F,0.514918F},
+{-0.964275F,-0.201774F,-0.171639F},
+{-0.964275F,0.201774F,-0.171639F},
+{-0.898715F,-0.403548F,0.171639F},
+{-0.898715F,0.403548F,0.171639F},
+{-0.106079F,-0.979432F,-0.171639F},
+{-0.489876F,-0.854729F,-0.171639F},
+{0.106079F,-0.979432F,0.171639F},
+{-0.661515F,-0.730026F,0.171639F},
+{0.898715F,-0.403548F,-0.171639F},
+{0.661515F,-0.730026F,-0.171639F},
+{0.964275F,-0.201774F,0.171639F},
+{0.489876F,-0.854729F,0.171639F},
+{0.065560F,0.854729F,-0.514918F},
+{0.449358F,0.730026F,-0.514918F},
+{-0.792636F,0.326477F,-0.514918F},
+{-0.555436F,0.652955F,-0.514918F},
+{-0.555436F,-0.652955F,-0.514918F},
+{-0.792636F,-0.326477F,-0.514918F},
+{0.449358F,-0.730026F,-0.514918F},
+{0.065560F,-0.854729F,-0.514918F},
+{0.833155F,0.201774F,-0.514918F},
+{0.833155F,-0.201774F,-0.514918F},
+{0.277718F,0.201774F,-0.939234F},
+{-0.106079F,0.326477F,-0.939234F},
+{0.555436F,0.403548F,-0.727076F},
+{-0.212158F,0.652955F,-0.727076F},
+{-0.343279F,0.000000F,-0.939234F},
+{-0.686557F,0.000000F,-0.727076F},
+{-0.106079F,-0.326477F,-0.939234F},
+{-0.212158F,-0.652955F,-0.727076F},
+{0.277718F,-0.201774F,-0.939234F},
+{0.555436F,-0.403548F,-0.727076F},
+{0.106079F,0.326477F,0.939234F},
+{0.212158F,0.652955F,0.727076F}
+};
+
+static f32 red[4] = {0.8, 0.1, 0.0, 1.0};
+static f32 green[4] = {0.0, 0.8, 0.2, 1.0};
+static f32 yellow[4] = {1.0, 1.0, 0.0, 1.0};
+static f32 blue[4] = {0.2, 0.2, 1.0, 1.0};
+static f32 white[4] = {1.0, 1.0, 1.0, 1.0};
+static f32 magenta[4] = {1.0, 0.0, 1.0, 1.0};
+static f32 orange[4] = {1.0, 0.5, 0.0, 1.0};
+
+static f32 grey[4] = {.25, .25, .25, 1.0};
+
+static f32 *colormaps[]={blue,orange,yellow,magenta,green,red,white};
+
+
+f32 buckyfix = 1.0;
+f32 pr, pg, pb;
+f32 nx, ny, nz;
+
+inline void set_normal(f32 x, f32 y, f32 z)
+{
+ nx=x;
+ ny=y;
+ nz=z;
+}
+inline void set_nnormal(f32 x, f32 y, f32 z)
+{
+f32 f = 1.0 / sqrt(x*x + y*y + z*z);
+ set_normal(x*f, y*f, z*f);
+}
+
+inline void point(f32 x, f32 y, f32 z)
+{
+ GX_Position3f32(x, y, z);
+ GX_Normal3f32(nx, ny, nz);
+ GX_Color3f32(pr, pg, pb);
+
+}
+inline void npoint(int n)
+{
+ point(coords[n][0]*buckyfix,coords[n][1]*buckyfix,coords[n][2]*buckyfix);
+}
+
+void norm(int p1,int p2,int p3)
+{
+//f32 nx,ny,nz;
+f32 x1,y1,z1;
+f32 x2,y2,z2;
+
+ x1=coords[p2][0]-coords[p1][0];
+ y1=coords[p2][1]-coords[p1][1];
+ z1=coords[p2][2]-coords[p1][2];
+
+ x2=coords[p3][0]-coords[p1][0];
+ y2=coords[p3][1]-coords[p1][1];
+ z2=coords[p3][2]-coords[p1][2];
+
+ nx=y1*z2-y2*z1;
+ ny=x2*z1-x1*z2;
+ nz=x1*y2-x2*y1;
+
+}
+void hex(int p1,int p2,int p3,int p4,int p5,int p6)
+{
+ GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, 6);
+ norm(p1,p3,p2);
+ npoint(p1);
+ npoint(p2);
+ npoint(p3);
+ npoint(p4);
+ npoint(p5);
+ npoint(p6);
+ GX_End();
+}
+void pent(int p1,int p2,int p3,int p4,int p5)
+{
+ GX_Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 5);
+ norm(p1,p3,p2);
+ npoint(p3);
+ npoint(p4);
+ npoint(p2);
+ npoint(p5);
+ npoint(p1);
+ GX_End();
+}
+void makebucky(f32 size)
+{
+
+ buckyfix=size;
+
+ pr = 1.0; pg = 0.0; pb = 0.0;
+ hex(2,7,8,10,9,4);
+ hex(1,2,4,6,5,3);
+ hex(7,11,12,14,13,8);
+ hex(9,10,32,30,31,33);
+ hex(5,6,28,26,27,29);
+ hex(0,25,59,58,1,3);
+ hex(11,58,59,19,20,12);
+ hex(21,22,24,25,00,23);
+ hex(30,32,37,35,44,45);
+ hex(26,28,33,31,42,43);
+ hex(15,17,24,22,38,39);
+ hex(15,16,18,20,19,17);
+ hex(38,51,49,48,50,39);
+ hex(13,14,36,34,35,37);
+ hex(16,46,47,34,36,18);
+ hex(21,23,29,27,40,41);
+ hex(40,53,52,49,51,41);
+ hex(44,57,56,54,55,45);
+ hex(46,50,48,56,57,47);
+ hex(42,55,54,52,53,43);
+
+
+ pr = 1.0; pg = 1.0; pb = 1.0;
+ pent(1,58,11,7,2);
+ pent(8,13,37,32,10);
+ pent(4,9,33,28,6);
+ pent(0,3,5,29,23);
+ pent(17,19,59,25,24);
+ pent(12,20,18,36,14);
+ pent(30,45,55,42,31);
+ pent(21,41,51,38,22);
+ pent(48,49,52,54,56);
+ pent(15,39,50,46,16);
+ pent(34,47,57,44,35);
+ pent(26,43,53,40,27);
+}
+
+
+void makebcube(f32 scale)
+{
+f32 sizex,sizey,sizez;
+f32 bsizex,bsizey,bsizez;
+f32 bevel;
+
+ sizex=sizey=sizez=0.6*scale;
+ bevel=0.15*scale;
+ bsizex=sizex+bevel;
+ bsizey=sizey+bevel;
+ bsizez=sizez+bevel;
+
+ GX_Begin(GX_QUADS, GX_VTXFMT0, 72);
+ set_normal( 0.0, sizey, 0.0);
+ point(-sizex, bsizey, sizez);
+ point(-sizex, bsizey,-sizez);
+ point( sizex, bsizey,-sizez);
+ point( sizex, bsizey, sizez);
+
+ set_normal( 0.0, 0.0, sizez);
+ point( sizex,-sizey, bsizez);
+ point(-sizex,-sizey, bsizez);
+ point(-sizex, sizey, bsizez);
+ point( sizex, sizey, bsizez);
+
+
+ set_normal( 0.0, 0.0,-sizez);
+ point( sizex,-sizey,-bsizez);
+ point( sizex, sizey,-bsizez);
+ point(-sizex, sizey,-bsizez);
+ point(-sizex,-sizey,-bsizez);
+
+ set_normal( sizex, 0.0, 0.0);
+ point( bsizex, sizey,-sizez);
+ point( bsizex,-sizey,-sizez);
+ point( bsizex,-sizey, sizez);
+ point( bsizex, sizey, sizez);
+
+ set_normal(-sizex, 0.0, 0.0);
+ point(-bsizex, sizey,-sizez);
+ point(-bsizex, sizey, sizez);
+ point(-bsizex,-sizey, sizez);
+ point(-bsizex,-sizey,-sizez);
+
+ set_normal( 0.0,-sizey, 0.0);
+ point(-sizex,-bsizey, sizez);
+ point( sizex,-bsizey, sizez);
+ point( sizex,-bsizey,-sizez);
+ point(-sizex,-bsizey,-sizez);
+
+ set_normal( 0.0, sizey, sizez);
+ point( sizex, bsizey, sizez);
+ point( sizex, sizey, bsizez);
+ point( -sizex, sizey, bsizez);
+ point( -sizex, bsizey, sizez);
+
+ set_normal( sizex, 0.0, sizez);
+ point( bsizex, -sizey, sizez);
+ point( sizex, -sizey, bsizez);
+ point( sizex, sizey, bsizez);
+ point( bsizex, sizey, sizez);
+
+ set_normal( sizex, sizey, 0.0);
+ point(bsizex, sizey, sizez);
+ point(sizex, bsizey, sizez);
+ point(sizex, bsizey, -sizez);
+ point(bsizex, sizey, -sizez);
+
+ set_normal( 0.0, -sizey, -sizez);
+ point( sizex, -bsizey, -sizez);
+ point( sizex, -sizey, -bsizez);
+ point( -sizex, -sizey, -bsizez);
+ point( -sizex, -bsizey, -sizez);
+
+ set_normal( -sizex, 0.0, -sizez);
+ point( -bsizex, -sizey, -sizez);
+ point( -sizex, -sizey, -bsizez);
+ point( -sizex, sizey, -bsizez);
+ point( -bsizex, sizey, -sizez);
+
+ set_normal( -sizex, -sizey, 0.0);
+ point(-bsizex, -sizey, sizez);
+ point(-sizex, -bsizey, sizez);
+ point(-sizex, -bsizey, -sizez);
+ point(-bsizex, -sizey, -sizez);
+
+ set_normal( 0.0, -sizey, sizez);
+ point( -sizex, -bsizey, sizez);
+ point( -sizex, -sizey, bsizez);
+ point( sizex, -sizey, bsizez);
+ point( sizex, -bsizey, sizez);
+
+ set_normal( 0.0, sizey, -sizez);
+ point( sizex, sizey, -bsizez);
+ point( sizex, bsizey, -sizez);
+ point( -sizex, bsizey, -sizez);
+ point( -sizex, sizey, -bsizez);
+
+ set_normal( -sizex, 0.0, sizez);
+ point( -bsizex,sizey, sizez);
+ point( -sizex, sizey, bsizez);
+ point( -sizex, -sizey, bsizez);
+ point( -bsizex, -sizey, sizez);
+
+ set_normal( sizex, 0.0, -sizez);
+ point( sizex,-sizey, -bsizez);
+ point( bsizex, -sizey, -sizez);
+ point( bsizex, sizey, -sizez);
+ point( sizex, sizey, -bsizez);
+
+ set_normal( -sizex, sizey, 0.0);
+ point( -bsizex, sizey, -sizez);
+ point( -sizex, bsizey, -sizez);
+ point( -sizex, bsizey, sizez);
+ point( -bsizex,sizey, sizez);
+
+ set_normal( sizex, -sizey, 0.0);
+ point( sizex, -bsizey, sizez);
+ point( bsizex, -sizey, sizez);
+ point( bsizex, -sizey, -sizez);
+ point( sizex, -bsizey, -sizez);
+
+ GX_End();
+
+ GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 24);
+
+ set_normal(sizex,sizey,sizez);
+ point(bsizex,sizey,sizez);
+ point(sizex,sizey,bsizez);
+ point(sizex,bsizey,sizez);
+
+ set_normal(-sizex,sizey,sizez);
+ point(-sizex,bsizey,sizez);
+ point(-sizex,sizey,bsizez);
+ point(-bsizex,sizey,sizez);
+
+ set_normal(-sizex,-sizey,sizez);
+ point(-bsizex,-sizey,sizez);
+ point(-sizex,-sizey,bsizez);
+ point(-sizex,-bsizey,sizez);
+
+ set_normal(sizex,-sizey,sizez);
+ point(sizex,-bsizey,sizez);
+ point(sizex,-sizey,bsizez);
+ point(bsizex,-sizey,sizez);
+
+
+ set_normal(-sizex,-sizey,-sizez);
+ point(-sizex,-sizey,-bsizez);
+ point(-bsizex,-sizey,-sizez);
+ point(-sizex,-bsizey,-sizez);
+
+ set_normal(sizex,-sizey,-sizez);
+ point(sizex,-sizey,-bsizez);
+ point(sizex,-bsizey,-sizez);
+ point(bsizex,-sizey,-sizez);
+
+ set_normal(sizex,sizey,-sizez);
+ point(sizex,sizey,-bsizez);
+ point(bsizex,sizey,-sizez);
+ point(sizex,bsizey,-sizez);
+
+ set_normal(-sizex,sizey,-sizez);
+ point(-sizex,sizey,-bsizez);
+ point(-sizex,bsizey,-sizez);
+ point(-bsizex,sizey,-sizez);
+
+ GX_End();
+}
+
+
+void makepyramid(f32 size)
+{
+ GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
+ set_nnormal( 0.0, -size, 0.0);
+ point( size,-size,-size);
+ point(-size,-size,-size);
+ point(-size,-size, size);
+ point( size,-size, size);
+ GX_End();
+
+ GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 12);
+ set_nnormal( 2.0, -1.0, 0.0);
+ point( 0.0, size, 0.0);
+ point( size,-size,-size);
+ point( size,-size, size);
+
+
+ set_nnormal( 0.0, -1.0,-2.0);
+ point( 0.0, size, 0.0);
+ point(-size,-size,-size);
+ point( size,-size,-size);
+
+ set_nnormal( -2.0, -1.0, 0.0);
+ point( 0.0, size, 0.0);
+ point(-size,-size, size);
+ point(-size,-size,-size);
+
+ set_nnormal( 0.0, -1.0, 2.0);
+ point( 0.0, size, 0.0);
+ point( size,-size, size);
+ point(-size,-size, size);
+ GX_End();
+}
+
+#define X .525731112119133606
+#define Z .850650808352039932
+
+static f32 vdata [12][3] = {
+{-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z},
+{X, 0.0, -Z}, {0.0, Z, X}, {0.0, Z, -X},
+{0.0, -Z, X}, {0.0, -Z, -X}, {Z, X, 0.0},
+{-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
+};
+
+static int tindices [20][3] = {
+ {1, 4, 0}, {4, 9, 0},
+ {4, 5, 9}, {8, 5, 4},
+ {1, 8, 4}, {1, 10, 8},
+ {10, 3, 8}, {8, 3, 5},
+ {3, 2, 5}, {3, 7, 2},
+ {3, 10, 7}, {10, 6, 7},
+ {6, 11, 7}, {6, 0, 11},
+ {6, 1, 0}, {10, 1, 6},
+ {11, 0, 9}, {2, 11, 9},
+ {5, 2, 9}, {11, 2, 7}
+};
+
+void dup3(float *a,float *b)
+{
+ *a++=*b++;
+ *a++=*b++;
+ *a=*b;
+}
+
+void mid(float *a,float *b,float *c)
+{
+float d;
+ a[0]=(*b++ + *c++)/2.0;
+ a[1]=(*b++ + *c++)/2.0;
+ a[2]=(*b + *c)/2.0;
+ d=1.0/sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
+ a[0]*=d;
+ a[1]*=d;
+ a[2]*=d;
+
+}
+void norm2(float *p1,float *p2,float *p3)
+{
+float nx,ny,nz;
+float x1,y1,z1;
+float x2,y2,z2;
+
+ x1=p2[0]-p1[0];
+ y1=p2[1]-p1[1];
+ z1=p2[2]-p1[2];
+
+ x2=p3[0]-p1[0];
+ y2=p3[1]-p1[1];
+ z2=p3[2]-p1[2];
+
+ nx=y1*z2-y2*z1;
+ ny=x2*z1-x1*z2;
+ nz=x1*y2-x2*y1;
+ set_nnormal(nx,ny,nz);
+}
+
+void makeicosahedron(int sub,float scale)
+{
+f32 tris[200][3];
+int i,j,p,q;
+int numt;
+ numt=0;
+ j=0;
+ for(i=0;i<20;++i)
+ {
+ p=tindices[i][0];
+ tris[j][0]=vdata[p][0];
+ tris[j][1]=vdata[p][1];
+ tris[j][2]=vdata[p][2];
+ ++j;
+ p=tindices[i][1];
+ tris[j][0]=vdata[p][0];
+ tris[j][1]=vdata[p][1];
+ tris[j][2]=vdata[p][2];
+ ++j;
+ p=tindices[i][2];
+ tris[j][0]=vdata[p][0];
+ tris[j][1]=vdata[p][1];
+ tris[j][2]=vdata[p][2];
+ ++j;
+ ++numt;
+ }
+ while(sub--)
+ {
+ j=numt;
+ numt<<=2;
+ while(--j>=0)
+ {
+ float ttt[3][3];
+ p=j*3;
+ q=p*4;
+ memcpy(ttt,tris[p],sizeof(ttt));
+
+ mid(tris[q++],ttt[0],ttt[1]);
+ dup3(tris[q++],ttt[1]);
+ mid(tris[q++],ttt[1],ttt[2]);
+
+ dup3(tris[q++],ttt[0]);
+ mid(tris[q++],ttt[0],ttt[1]);
+ mid(tris[q++],ttt[0],ttt[2]);
+
+ mid(tris[q++],ttt[1],ttt[2]);
+ dup3(tris[q++],ttt[2]);
+ mid(tris[q++],ttt[0],ttt[2]);
+
+ mid(tris[q++],ttt[0],ttt[1]);
+ mid(tris[q++],ttt[1],ttt[2]);
+ mid(tris[q++],ttt[0],ttt[2]);
+
+ }
+ }
+void icpoint(f32 *p, f32 scale) {point(p[0]*scale,p[1]*scale,p[2]*scale);}
+ p=0;
+ GX_Begin(GX_TRIANGLES, GX_VTXFMT0, numt*3);
+ for(i=0;i<numt;++i)
+ {
+ norm2(tris[p],tris[p+1],tris[p+2]);
+ icpoint(tris[p], scale);
+ icpoint(tris[p+2], scale);
+ icpoint(tris[p+1], scale);
+ p+=3;
+ }
+ GX_End();
+
+
+}
+#define CSQUEEZE 0.8
+void makecyllinder(f32 size)
+{
+#define CSIDES 12
+f32 x[CSIDES],z[CSIDES];
+int i,j,k;
+f32 a;
+ for(i=0;i<CSIDES;++i)
+ {
+ a=i*3.1415928*2.0/CSIDES;
+ x[i]=cos(a)*size*CSQUEEZE;
+ z[i]=sin(a)*size*CSQUEEZE;
+ }
+
+ for(j=0;j<2;++j)
+ {
+ f32 p=(j&1) ? -size : size;
+ set_nnormal(0.0, p, 0.0);
+ GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, CSIDES);
+ for(i=0;i<CSIDES;++i)
+ {
+ k=(j&1) ? (CSIDES-1-i) : i;
+ point(x[k],p,z[k]);
+ }
+ GX_End();
+ }
+ GX_Begin(GX_QUADS, GX_VTXFMT0, CSIDES*4);
+
+ for(i=0;i<CSIDES;++i)
+ {
+ j=i+1;
+ if(j>=CSIDES) j-=CSIDES;
+ set_nnormal((x[i]+x[j])/2.0, 0.0, (z[i]+z[j])/2.0);
+
+ point(x[i], size, z[i]);
+ point(x[i], -size, z[i]);
+
+ point(x[j], -size, z[j]);
+ point(x[j], size, z[j]);
+
+ }
+ GX_End();
+
+}
+
+void makediamond(f32 size)
+{
+#define DSIDES 9
+f32 x[DSIDES],z[DSIDES];
+int i,j,t,o=0;
+f32 a;
+f32 c,s,d,h;
+f32 p2;
+f32 lx, ly, lz;
+ for(i=0;i<DSIDES;++i)
+ {
+ a=i*3.1415928*2.0/DSIDES;
+ x[i]=cos(a)*size;
+ z[i]=sin(a)*size;
+ }
+
+
+ p2=size*0.5;
+ for(t=0;t<2;++t)
+ {
+ f32 p1=(t&1) ? -size : size;
+
+ GX_Begin(GX_TRIANGLES, GX_VTXFMT0, DSIDES*3);
+ d=(!t) ? size-p2 : size+p2;
+ h=sqrt(size*size+d*d);
+ c=(!t) ? size/h : -size/h;
+ s=d/h;
+ lx = ly = lz = 0.0;
+ for(i=0;i<DSIDES+1;++i)
+ {
+ j=(i<DSIDES) ? i : i-DSIDES;
+ if(!t) j=DSIDES-1-j;
+ if(i)
+ {
+ set_nnormal((x[j]+x[o])/2.0*s,size*c,(z[j]+z[o])/2.0*s);
+ point(lx, ly, lz);
+ point(0.0, p1, 0.0);
+ }
+ lx = x[j];
+ ly = p2;
+ lz = z[j];
+ if(i)
+ point(lx, ly, lz);
+
+ o=j;
+ }
+ GX_End();
+ }
+
+}
+
+
+void makeuvsphere(f32 size)
+{
+#define USIDES 15
+#define VSIDES 9
+f32 x[USIDES],z[USIDES];
+int i,j,t,o;
+f32 a;
+f32 c1,s1,c2,s2;
+f32 lx1, ly1, lz1;
+f32 lx2, ly2, lz2;
+
+ for(i=0;i<USIDES;++i)
+ {
+ a=i*3.1415927*2.0/USIDES;
+ x[i]=cos(a)*size;
+ z[i]=sin(a)*size;
+ }
+
+ for(i=0;i<VSIDES;++i)
+ {
+ a=i*3.1415927/VSIDES;
+ c1=cos(a);
+ s1=sin(a);
+ a=(i+1)*3.1415927/VSIDES;
+ c2=cos(a);
+ s2=sin(a);
+ GX_Begin(GX_QUADS, GX_VTXFMT0, USIDES*4);
+ lx1 = ly1 = lz1 = 0.0;
+ lx2 = ly2 = lz2 = 0.0;
+ for(j=0;j<USIDES+1;++j)
+ {
+ t=(j<USIDES) ? j : j-USIDES;
+ if(j)
+ {
+ f32 s,c;
+ a=(i+0.5)*3.1415927/VSIDES;
+ c=cos(a);
+ s=sin(a);
+ a=(j-0.5)*3.1415927*2.0/USIDES;
+ set_nnormal(cos(a)*s,c,sin(a)*s);
+ }
+ if(j)
+ {
+ point(lx2, ly2, lz2);
+ point(lx1, ly1, lz1);
+ }
+ lx1 = x[t]*s2;
+ ly1 = c2*size;
+ lz1 = z[t]*s2;
+
+ lx2 = x[t]*s1;
+ ly2 = c1*size;
+ lz2 = z[t]*s1;
+ if(j)
+ {
+ point(lx1, ly1, lz1);
+ point(lx2, ly2, lz2);
+ }
+
+ o=t;
+ }
+ GX_End();
+ }
+}
+
+
+void makespiky(f32 scale)
+{
+#define SPIKES 12
+#define SPIKEZ 0.5
+#define SPIKEIN 0.7
+f32 x1[SPIKES],y1[SPIKES];
+f32 x2[SPIKES],y2[SPIKES];
+f32 a,b,b2;
+int i,j;
+f32 p0[3],p1[3],p2[3];
+
+ b=3.1415927*2/SPIKES;
+ b2=b/2.0;
+ for(i=0;i<SPIKES;++i)
+ {
+ a=i*b;
+ x1[i]=cos(a)*scale*SPIKEIN;
+ y1[i]=sin(a)*scale*SPIKEIN;
+ x2[i]=cos(a+b2)*scale;
+ y2[i]=sin(a+b2)*scale;
+ }
+
+ GX_Begin(GX_TRIANGLES, GX_VTXFMT0, SPIKES*6);
+ p0[0]=0.0;
+ p0[1]=0.0;
+ p0[2]=SPIKEZ*scale;
+
+ p1[0]=x1[0];
+ p1[1]=y1[0];
+ p1[2]=0.0;
+
+ for(i=0;i<SPIKES;++i)
+ {
+ j=i+1;
+ if(j>=SPIKES) j-=SPIKES;
+
+ p2[0]=x2[i];
+ p2[1]=y2[i];
+ p2[2]=0.0;
+
+ norm2(p0,p1,p2);
+ point(p0[0], p0[1], p0[2]);
+ point(p2[0], p2[1], p2[2]);
+ point(p1[0], p1[1], p1[2]);
+
+ p1[0]=x1[j];
+ p1[1]=y1[j];
+ p1[2]=0.0;
+
+ norm2(p0,p2,p1);
+ point(p0[0], p0[1], p0[2]);
+ point(p1[0], p1[1], p1[2]);
+ point(p2[0], p2[1], p2[2]);
+
+ }
+ GX_End();
+}
+
+void makeselector(f32 scale)
+{
+#define MS_TICKS 12
+#define MS_WIDE .15
+#define MS_LONG .3
+#define MS_HIGH .1
+f32 a, b;
+f32 pc[3], p1[3], p2[3], p3[3], p4[3];
+int i;
+
+ b = M_PI*2.0 / MS_TICKS;
+
+ for(i=0;i<MS_TICKS;++i)
+ {
+ GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 12);
+ a = i*b;
+ pc[0] = cos(a)*scale;
+ pc[1] = sin(a)*scale;
+ pc[2] = MS_HIGH*scale;
+
+ p1[0] = cos(a)*scale*(1.0 - MS_LONG);
+ p1[1] = sin(a)*scale*(1.0 - MS_LONG);
+ p1[2] = 0.0;
+
+ p3[0] = cos(a)*scale*(1.0 + MS_LONG);
+ p3[1] = sin(a)*scale*(1.0 + MS_LONG);
+ p3[2] = 0.0;
+
+ a = b*(i+MS_WIDE);
+ p2[0] = cos(a)*scale;
+ p2[1] = sin(a)*scale;
+ p2[2] = 0.0;
+
+ a = b*(i-MS_WIDE);
+ p4[0] = cos(a)*scale;
+ p4[1] = sin(a)*scale;
+ p4[2] = 0.0;
+
+ norm2(pc, p2, p1);
+ point(pc[0], pc[1], pc[2]);
+ point(p1[0], p1[1], p1[2]);
+ point(p2[0], p2[1], p2[2]);
+
+ norm2(pc, p3, p2);
+ point(pc[0], pc[1], pc[2]);
+ point(p2[0], p2[1], p2[2]);
+ point(p3[0], p3[1], p3[2]);
+
+ norm2(pc, p4, p3);
+ point(pc[0], pc[1], pc[2]);
+ point(p3[0], p3[1], p3[2]);
+ point(p4[0], p4[1], p4[2]);
+
+ norm2(pc, p1, p4);
+ point(pc[0], pc[1], pc[2]);
+ point(p4[0], p4[1], p4[2]);
+ point(p1[0], p1[1], p1[2]);
+
+ GX_End();
+ }
+}
+
+
+
+int gamestate;
+float life,decay;
+int stage,score,level,highscore=0;
+int nummoves;
+int cumulative;
+int cumulativebuildup;
+float cumulativefade;
+int enteringline;
+int baseshow;
+int chainreaction;
+int alertcounter;
+int actionmode;
+float timeindicator;
+int dropsound;
+int waspicked;
+int xsize, ysize;
+int cposx, cposy;
+f32 downx,downy,downz;
+int isdown;
+
+enum actionstates {
+ACTION_LOOKING,
+ACTION_WAITING,
+ACTION_SWAPPING,
+ACTION_UNSWAPPING,
+ACTION_REMOVING,
+ACTION_DROPPING,
+};
+
+enum sounds {
+ROWSOUND,
+DROPSOUND,
+BIGDROPSOUND,
+SWAPSOUND,
+GAMEOVERSOUND,
+ALERTSOUND,
+ILLEGALSOUND,
+};
+
+
+enum gamestate {
+GAMEOVER,
+PLAYING,
+ENTERHIGH,
+};
+// position/scaling settings
+#define SCALE 0.9 // size of each jewel
+#define SPACING 1.8 // how much to move for each row/column
+#define SHIFTX 4.0 // shift the jewels sideways so they're not centered
+#define SHIFTY 0.0
+
+#define SWAPTIME 20
+
+#define SCORESPRITEFADE 0.01
+#define FALLRATE 0.02
+#define VANISHRATE 0.05
+
+#define STARTLIFE 1000.0
+#define ALARMLEVEL 10.0 // seconds before death
+#define CREDIT 50.0
+#define INITIALDECAY (0.4)
+#define DECAYADD 0.02
+#define NEXTLEVEL 10
+
+#define LIFEVISIBLE (STARTLIFE*2.0)
+
+#define EX 8
+#define EY 8
+
+struct element {
+int type;
+float ax,ay,az;
+float angle;
+float fall,speed;
+float vanish;
+float dx,dy;
+int swapping;
+} elements[EY][EX];
+
+#define MAXSCORESPRITES 12
+struct scoresprite {
+float x,y,z;
+float fade;
+int value;
+} scoresprites[MAXSCORESPRITES];
+
+#define MAXHIGHSCORES 100
+
+#define MAXNAMELENGTH 12
+struct highscore {
+char name[MAXNAMELENGTH];
+int score;
+int level;
+} highscores[MAXHIGHSCORES];
+char lastentered[MAXNAMELENGTH]={0};
+
+
+
+#define RLEN 55
+#define RTAP 31
+
+static int tap = 0;
+
+static unsigned int rtab[RLEN], rmaster[RLEN] = {
+0xce5b72a6,0xf142f1f0,0xe38c7808,0x9f6489d0,
+0xfaae5295,0xb0756d37,0x71781266,0x12286b7b,
+0xb3890fde,0xdb665594,0x3bf69e17,0xa7c13049,
+0xe5bd5e62,0x31f90815,0xbf6382bc,0x7e4a5707,
+0x0ee4c5e1,0xfc2c4931,0x7caca3ff,0x26ea64b5,
+0x7be5e6bd,0xba4f37ad,0x33d4856f,0xfe82d5b8,
+0x945bacae,0xf4ce5e24,0x15fd2334,0x05db20c3,
+0xa5164863,0xd6a06874,0xc7199828,0xf1238636,
+0xa4463b7e,0xccddfa34,0x03111ccf,0xe68ba5b0,
+0xa8bff874,0x6ed71aad,0xed30825f,0x9e43caf5,
+0x6db2f302,0x56437555,0x97f250fe,0x8375633b,
+0x9c3b7d60,0x2edd849d,0xab376fcf,0x757e836b,
+0x2e6c9cca,0x9db3695a,0xfbdc0f27,0xea41369b,
+0xdfde1cce,0xb6d74760,0x7f67fc17
+};
+
+
+void myseed(unsigned int s)
+{
+int i;
+int is, ic;
+
+ memcpy(rtab, rmaster, sizeof(rtab));
+ tap = 0;
+ ic = 0;
+ is = s;
+ for(i=0;i<RLEN;++i)
+ {
+ rtab[i] ^= s;
+ rtab[i] += ic;
+ ic += is;
+ s ^= (s<<3) ^ (s>>29);
+ }
+}
+
+unsigned int myrand(void)
+{
+int j, v;
+ j = tap - RTAP;
+ if(j<0) j+=RLEN;
+ v = (rtab[tap] ^= rtab[j]);
+ ++tap;
+ if(tap==RLEN) tap = 0;
+ return v & 0x7fffffff;
+}
+
+void playsound(int n)
+{
+ switch(n)
+ {
+ case ROWSOUND:
+ ASND_SetVoice(0, VOICE_MONO_16BIT, 22050, 0, (void *)row_raw, row_raw_size, 255, 255, 0);
+ break;
+ case DROPSOUND:
+ ASND_SetVoice(1, VOICE_MONO_16BIT, 22050, 0, (void *)drop_raw, drop_raw_size, 255, 255, 0);
+ break;
+ case BIGDROPSOUND:
+ ASND_SetVoice(2, VOICE_MONO_16BIT, 22050, 0, (void *)bigdrop_raw, bigdrop_raw_size, 255, 255, 0);
+ break;
+ case SWAPSOUND:
+ ASND_SetVoice(3, VOICE_MONO_16BIT, 22050, 0, (void *)swap_raw, swap_raw_size, 255, 255, 0);
+ break;
+ case GAMEOVERSOUND:
+ ASND_SetVoice(4, VOICE_MONO_16BIT, 22050, 0, (void *)gameover_raw, gameover_raw_size, 255, 255, 0);
+ break;
+ case ALERTSOUND:
+ ASND_SetVoice(5, VOICE_MONO_16BIT, 22050, 0, (void *)alert_raw, alert_raw_size, 255, 255, 0);
+ break;
+ case ILLEGALSOUND:
+ ASND_SetVoice(6, VOICE_MONO_16BIT, 22050, 0, (void *)illegal_raw, illegal_raw_size, 255, 255, 0);
+ break;
+ }
+}
+
+
+void illegal(struct element *e1,struct element *e2)
+{
+struct element t;
+ t=*e1;
+ *e1=*e2;
+ *e2=t;
+ e1->dx=-e1->dx;
+ e1->dy=-e1->dy;
+ e1->swapping=1;
+ e2->dx=-e2->dx;
+ e2->dy=-e2->dy;
+ e2->swapping=1;
+ waspicked=0;
+}
+
+
+#define SWAPMAX 4
+int swapfifo[SWAPMAX][4];
+int swapput=0,swaptake=0;
+void addswap(int px,int py,int dx,int dy)
+{
+int *p;
+ if(((swapput+1) & (SWAPMAX-1)) == swaptake) return;
+ p=swapfifo[swapput++];
+ swapput&=SWAPMAX-1;
+ *p++=px;
+ *p++=py;
+ *p++=dx;
+ *p=dy;
+}
+
+
+int tryswap(void)
+{
+struct element t;
+struct element *e1,*e2;
+int *p;
+int px,py,dx,dy;
+ if(swapput==swaptake) return 0;
+
+ playsound(SWAPSOUND);
+ p=swapfifo[swaptake++];
+ swaptake&=SWAPMAX-1;
+ px=*p++;
+ py=*p++;
+ dx=*p++;
+ dy=*p;
+ e1=elements[py]+px;
+ e2=elements[py+dy]+px+dx;
+ t=*e1;
+ *e1=*e2;
+ *e2=t;
+ e1->dx=dx;
+ e1->dy=-dy;
+ e1->swapping=1;
+ e2->dx=-dx;
+ e2->dy=dy;
+ e2->swapping=1;
+ return 1;
+}
+
+int wins[4][4]={
+{-2,-1,-1,-1},
+{-1,-1,1,-1},
+{1,-1,2,-1},
+{0,-2,0,-3},
+};
+unsigned char movebits[EY][EX];
+int anymoves(void)
+{
+unsigned char temp[EY][EX];
+struct element *e;
+int i,j,k,t, dir;
+int moves;
+int dx1, dy1, dx2, dy2;
+ memset(temp,0xff,sizeof(temp));
+ memset(movebits, 0, sizeof(movebits));
+ e=elements[0];
+ for(j=0;j<EY;++j)
+ for(i=0;i<EX;++i)
+ temp[j][i]=e++ -> type;
+
+ moves=0;
+ for(j=0;j<EY;++j)
+ for(i=0;i<EX;++i)
+ for(k=0;k<16;++k)
+ {
+ int *p = wins[k&3];
+ dir = k>>2; // 0=up, 1=left, 2=down, 3=right
+ dx1 = p[0];
+ dy1 = p[1];
+ dx2 = p[2];
+ dy2 = p[3];
+ if(dir&1) // transpose x + y
+ {
+ t=dx1;
+ dx1=dy1;
+ dy1=t;
+
+ t=dx2;
+ dx2=dy2;
+ dy2=t;
+ }
+ if(dir&2) // negate x + y
+ {
+ dx1=-dx1;
+ dy1=-dy1;
+ dx2=-dx2;
+ dy2=-dy2;
+ }
+ if(i+dx1<0 || i+dx1>=EX) continue;
+ if(j+dy1<0 || j+dy1>=EY) continue;
+ if(i+dx2<0 || i+dx2>=EX) continue;
+ if(j+dy2<0 || j+dy2>=EY) continue;
+ t=temp[j][i];
+
+ if(t!=temp[j+dy1][i+dx1]) continue;
+ if(t!=temp[j+dy2][i+dx2]) continue;
+// we know we've got a win, just want to make sure we don't count the move
+// multiple times...
+ if(dir<2) dx1=0,dy1=0; // up or left
+ else if(dir==2) dx1=0,dy1=1; // down
+ else dx1=1,dy1=0; // right
+ t = (dir&1) ? 1 : 2; // bit0 = X, bit1 = Y
+ if(movebits[j+dy1][i+dx1]&t) continue;
+ ++moves;
+ movebits[j+dy1][i+dx1]|=t;
+ }
+ return nummoves=moves;
+}
+void tossall(void)
+{
+int j;
+struct element *e;
+ e=elements[0];
+ j=EX*EY;
+ while(j--) e++ -> vanish=0.999;
+ playsound(BIGDROPSOUND);
+}
+
+void randomvector(float *x,float *y,float *z)
+{
+int ix,iy,iz;
+float d;
+
+ do
+ {
+ ix=(myrand()&1023)-512;
+ iy=(myrand()&1023)-512;
+ iz=(myrand()&1023)-512;
+ } while(ix==0 && iy==0 && iz==0);
+ d=1.0/sqrt((float)(ix*ix+iy*iy+iz*iz));
+ *x=ix*d;
+ *y=iy*d;
+ *z=iz*d;
+*x=*z=0;*y=1.0;
+}
+
+
+void addlife(int chain,int len,float x,float y)
+{
+int value;
+int i;
+struct scoresprite *ss;
+ value=chain+len;
+ cumulative=cumulativebuildup+=value;
+ cumulativefade=1.0;
+ for(ss=scoresprites,i=0;i<MAXSCORESPRITES;++i,++ss)
+ {
+ if(ss->fade!=0.0) continue;
+ jmap(&ss->x, &ss->y, &ss->z, x, y);
+ ss->z += SCALE*2.0;
+ ss->fade=1.0;
+ ss->value=value;
+ break;
+ }
+
+ score+=value;
+ if(score>highscore) highscore = score;
+ life+=(value)*CREDIT;
+ stage+=len;
+ if(stage>=NEXTLEVEL)
+ {
+ stage-=NEXTLEVEL;
+ decay+=DECAYADD;
+ ++level;
+ }
+}
+void endgame(void)
+{
+struct highscore *h;
+
+ gamestate=GAMEOVER;
+return;
+ h=highscores+MAXHIGHSCORES;
+ while(h>highscores && h[-1].score<score) --h;
+ enteringline=h-highscores;
+ baseshow=enteringline-5;
+ if(baseshow<0) baseshow=0;
+ if(baseshow>MAXHIGHSCORES-10) baseshow=MAXHIGHSCORES-10;
+ if(enteringline==MAXHIGHSCORES) return;
+ memmove(h+1,h,(MAXHIGHSCORES-enteringline)*sizeof(struct highscore));
+ strcpy(h->name,lastentered);
+ h->score=score;
+ h->level=level;
+ gamestate=ENTERHIGH;
+}
+void declife()
+{
+ timeindicator-=decay*5.0;
+ life-=decay;
+ if(life<0.0)
+ {
+ life=0.0;
+ if(gamestate!=GAMEOVER)
+ {
+ endgame();
+ playsound(GAMEOVERSOUND);
+ }
+ }
+}
+
+
+int findwins(int justchecking)
+{
+int i,j,k;
+struct element *e;
+int hadsome=0;
+float x,y;
+
+ for(j=0;j<EY;++j)
+ {
+ k=0;
+ for(i=1;i<EX+1;++i)
+ {
+ e=elements[j]+i;
+ if(i<EX && e->type==e[-1].type) ++k;
+ else if(k>=2)
+ {
+ hadsome=1;
+ if(!justchecking)
+ {
+ x=i-1-k/2.0;
+ y=j+0.5;
+ addlife(chainreaction,k-1,x,y);
+ }
+ ++k;
+ while(k) e[-k--].vanish=0.999;
+ k=0;
+ } else k=0;
+ }
+ }
+
+ for(j=0;j<EX;++j)
+ {
+ k=0;
+ for(i=1;i<EY+1;++i)
+ {
+ e=elements[i]+j;
+ if(i<EY && e->type==e[-EX].type) ++k;
+ else if(k>=2)
+ {
+ hadsome=1;
+ if(!justchecking)
+ {
+ x=j;
+ y=i-0.5-k/2.0;
+ addlife(chainreaction,k-1,x,y);
+ }
+ ++k;
+ while(k) e[-EX*k--].vanish=0.999;
+ k=0;
+ } else k=0;
+ }
+ }
+ if(!justchecking)
+ {
+ if(hadsome)
+ {
+ playsound(ROWSOUND);
+ ++chainreaction;
+ } else chainreaction=0,cumulativebuildup=0;
+ }
+ return hadsome;
+}
+
+void initelement(struct element *e)
+{
+
+ memset(e,0,sizeof(*e));
+ e->type=(myrand()&0xffff)%7;
+ e->angle=(myrand()&1023)*360.0/1024.0;
+ e->vanish=1.0;
+ e->fall=0.0;
+ randomvector(&e->ax,&e->ay,&e->az);
+}
+
+void initelements(void)
+{
+int i,j;
+struct element *e;
+ e=elements[0];
+ j=EX*EY;
+ for(i=0;i<j;++i)
+ initelement(e++);
+}
+
+void replace(void)
+{
+int i,j,k;
+struct element *e,*e2;
+int falls[EX];
+
+ for(i=0;i<EX;++i)
+ falls[i]=1;
+ for(j=EY-1;j>=0;--j)
+ {
+ for(i=0;i<EX;++i)
+ {
+ e=elements[j]+i;
+ if(e->vanish!=0.0) continue;
+ k=j;
+ while(--k>=0)
+ {
+ e2=elements[k]+i;
+ if(e2->vanish!=0.0) break;
+ }
+ if(k>=0)
+ {
+ *e=*e2;
+ e2->vanish=0.0;
+ e->fall=j-k;
+ } else
+ {
+ initelement(e);
+ e->fall=j+falls[i]++;
+ }
+ }
+ }
+}
+
+
+void initgame(void)
+{
+int i;
+ life=STARTLIFE;
+ decay=INITIALDECAY;
+ do initelements(); while(findwins(1));
+ chainreaction=swapput=swaptake=0;
+ stage=0;
+ score=0;
+ level=1;
+ gamestate=PLAYING;
+ cumulative=0;
+ cumulativebuildup=0;
+ cumulativefade=0.0;
+ alertcounter=0;
+ baseshow=0;
+ enteringline=-1;
+ for(i=0;i<MAXSCORESPRITES;++i) scoresprites[i].fade=0.0;
+ actionmode=ACTION_LOOKING;
+ cposx = cposy = -1;
+}
+
+void action(void)
+{
+struct element *e,*le;
+struct element *e1=0,*e2=0;
+int i;
+int hadsome;
+struct scoresprite *ss;
+
+ if(gamestate==PLAYING && life<ALARMLEVEL*50*decay)
+ {
+ --alertcounter;
+ if(alertcounter<=0)
+ {
+ playsound(ALERTSOUND);
+ alertcounter=50;
+ }
+ }
+
+ for(i=0,ss=scoresprites;i<MAXSCORESPRITES;++i,++ss)
+ {
+ ss->fade-=SCORESPRITEFADE;
+ if(ss->fade<0.0) ss->fade=0.0;
+ }
+
+ cumulativefade-=SCORESPRITEFADE;
+ if(cumulativefade<0.0) cumulativefade=0.0;
+
+ e=elements[0];
+ le=e+EX*EY;
+ while(e<le) e++ ->angle+=3.0;
+
+ switch(actionmode)
+ {
+ case ACTION_LOOKING:
+ if(findwins(0))
+ actionmode=ACTION_REMOVING;
+ else
+ if(anymoves())
+ actionmode=ACTION_WAITING;
+ else
+ {tossall();actionmode=ACTION_REMOVING;}
+ break;
+ case ACTION_WAITING:
+ if(gamestate!=PLAYING) break;
+ declife();
+ if(tryswap()) actionmode=ACTION_SWAPPING;
+ break;
+ case ACTION_UNSWAPPING:
+ declife();
+ case ACTION_SWAPPING:
+ e=elements[0];
+ hadsome=0;
+ while(e<le)
+ {
+ if(e->swapping)
+ {
+ hadsome=1;
+ ++e->swapping;
+ if(e->swapping==SWAPTIME)
+ {
+ e->swapping=0;
+ e1=e2;
+ e2=e;
+ hadsome=2;
+ }
+ }
+ ++e;
+ }
+ if(hadsome==2)
+ {
+ if(findwins(0))
+ actionmode=ACTION_REMOVING;
+ else if(actionmode==ACTION_SWAPPING)
+ {
+ playsound(ILLEGALSOUND);
+ illegal(e1,e2);
+ actionmode=ACTION_UNSWAPPING;
+ } else
+ actionmode=ACTION_WAITING;
+ }
+ break;
+ case ACTION_REMOVING:
+ hadsome=0;
+ e=elements[0];
+ while(e<le)
+ {
+ if(e->vanish<1.0)
+ {
+ e->vanish-=VANISHRATE;
+ if(e->vanish<=0.0)
+ {
+ e->vanish=0.0;
+ ++hadsome;
+ }
+ }
+ ++e;
+ }
+ if(hadsome)
+ {
+ replace();
+ dropsound=1;
+ actionmode=ACTION_DROPPING;
+ }
+ break;
+ case ACTION_DROPPING:
+ e=elements[0];
+ hadsome=0;
+ while(e<le)
+ {
+ if(e->fall>0.0)
+ {
+ ++hadsome;
+ e->fall-=e->speed;
+ e->speed+=FALLRATE;
+ if(e->fall<=0.0)
+ {
+ e->fall=e->speed=0.0;
+ if(dropsound)
+ {
+ playsound(DROPSOUND);
+ dropsound=0;
+ }
+ }
+ }
+ ++e;
+ }
+ if(!hadsome) actionmode=ACTION_LOOKING;
+ break;
+ }
+}
+
+void f0(void) {makebucky(0.9*SCALE);}
+void f1(void) {makebcube(SCALE);}
+void f2(void) {makepyramid(0.7*SCALE);}
+void f3(void) {makeicosahedron(0, SCALE);}
+void f4(void) {makecyllinder(0.8 * SCALE);}
+void f5(void) {makediamond(0.9 * SCALE);}
+void f6(void) {makeuvsphere(0.9 * SCALE);}
+
+void (*functab[])(void) = {f0, f1, f2, f3, f4, f5, f6};
+
+void setmaterial(f32 *color)
+{
+int r, g,b;
+
+ r = color[0]*255;
+ g = color[1]*255;
+ b = color[2]*255;
+
+ GX_SetChanMatColor(GX_COLOR0A0, (GXColor) {r, g, b, 255});
+}
+
+void showlife(Mtx44 view)
+{
+float a,b;
+int i;
+guVector tvector;
+f32 cutoff;
+Mtx44 model, modelview;
+
+#define SECTIONS 24
+#define LIFEX -8.5
+#define LIFEY -3.0
+#define LIFEZ1 -18.0
+#define LIFEZ2 1.0
+#define LIFESIZE 3.5
+#define LIFENORMAL 0.7
+
+#define SECTIONYELLOW 4
+#define SECTIONRED 1
+
+
+ guMtxIdentity(model);
+ tvector.x = 0.0;
+ tvector.y = 1.0;
+ tvector.z = 0.0;
+ guMtxTransApply(model, model, LIFEX, LIFEY, LIFEZ1);
+ guMtxConcat(view,model,modelview);
+ GX_LoadPosMtxImm(modelview, GX_PNMTX0);
+ GX_LoadNrmMtxImm(modelview, GX_PNMTX0);
+
+ b=3.1415927*2.0/SECTIONS;
+
+ a=0;
+ set_normal(0.0, 0.0, 1.0);
+
+ setmaterial(grey);
+ GX_Begin(GX_LINESTRIP, GX_VTXFMT0, SECTIONS+1);
+ for(i=0;i<=SECTIONS;++i)
+ {
+ point(sin(a)*LIFESIZE,cos(a)*LIFESIZE, 0.01);
+ a+=b;
+ }
+ GX_End();
+
+ cutoff = life * SECTIONS / LIFEVISIBLE;
+
+ for(i=0;i<SECTIONS && i < cutoff;++i)
+ {
+ if(i<=SECTIONRED)
+ setmaterial(red);
+ else if(i<=SECTIONYELLOW)
+ setmaterial(yellow);
+ else
+ setmaterial(green);
+ a = (i+0.5) * b;
+ set_nnormal(sin(a), cos(a), LIFENORMAL);
+ GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
+ point(0.0, 0.0, LIFEZ2);
+ a = i * b;
+ point(sin(a) * LIFESIZE, cos(a) * LIFESIZE, 0.0);
+ a = i+1;
+ if(a > cutoff) a = cutoff;
+ a *= b;
+ point(sin(a) * LIFESIZE, cos(a) * LIFESIZE, 0.0);
+ GX_End();
+ }
+
+ setmaterial(blue);
+ guMtxIdentity(model);
+ tvector.x = 0.0;
+ tvector.y = 0.0;
+ tvector.z = 1.0;
+ guMtxRotAxisDeg(model, &tvector, timeindicator);
+ guMtxTransApply(model, model, LIFEX, LIFEY - 4.6, LIFEZ1);
+ guMtxConcat(view,model,modelview);
+ GX_LoadPosMtxImm(modelview, GX_PNMTX0);
+ GX_LoadNrmMtxImm(modelview, GX_PNMTX0);
+
+ makespiky(LIFESIZE * .3);
+}
+
+void figure2(Mtx44 view, f32 xp, f32 yp, f32 zp, f32 angle,
+ f32 *color, int orient)
+{
+float nx;
+float ny;
+float nz;
+int i,j,k;
+float t1,t2;
+guVector tvector;
+Mtx44 model, trot, temp;
+
+ tvector.x = 0.1;
+ tvector.y = 1.0;
+ tvector.z = 0.0;
+ guMtxIdentity(trot);
+ guMtxRotAxisDeg(trot, &tvector, angle);
+
+ nx=ny=nz=0.0;
+
+ setmaterial(color);
+
+
+ for(k=0;k<15;++k)
+ {
+ i=k%3;
+ j=k/3;
+ if(i==1 && j>=1 && j<4) continue;
+
+#define TSCALE .7
+
+
+ t1=(i-1)*TSCALE;
+ t2=(j-2)*TSCALE;
+ switch(orient)
+ {
+ case 0:
+ nx = t1;
+ ny = t2;
+ nz = 0.0;
+ break;
+ case 1:
+ nx = t2;
+ nz = t1;
+ ny = 0.0;
+ break;
+ case 2:
+ ny = t1;
+ nz = t2;
+ nx = 0.0;
+ break;
+ }
+
+//void c_guMtxTransApply(Mtx src,Mtx dst,f32 xT,f32 yT,f32 zT);
+//void c_guMtxConcat(Mtx a,Mtx b,Mtx ab);
+
+
+ guMtxTrans(model, xp, yp , zp);
+ guMtxConcat(model, trot, model); // model = model * trot
+ guMtxTrans(temp, nx, ny, nz);
+ guMtxConcat(model, temp, model); // model = model * temp
+
+ guMtxConcat(view,model,model); // model = view * model
+
+ GX_LoadPosMtxImm(model, GX_PNMTX0);
+ GX_LoadNrmMtxImm(model, GX_PNMTX0);
+
+ makebcube(TSCALE*.65);
+ }
+
+}
+
+void figure(Mtx44 view, f32 xp, f32 yp, f32 zp)
+{
+static float angle=0.0;
+
+ figure2(view, xp, yp, zp, angle, blue, 0);
+ figure2(view, xp, yp, zp, angle, red, 1);
+ figure2(view, xp, yp, zp, angle, green, 2);
+ angle+=1.0;
+}
+
+
+void jmap(f32 *destx, f32 *desty, f32 *destz, f32 x, f32 y)
+{
+ *destx = SHIFTX + SPACING*( x - EX/2.0+0.5);
+ *desty = SHIFTY + SPACING*(-y + EY/2.0-0.5);
+ *destz = 0.0;
+}
+
+static void draw(Mtx44 view, int cheat)
+{
+int i,j,k;
+struct element *e;
+int c=0;
+f32 a;
+f32 nx,ny,nz;
+Mtx44 model, modelview;
+
+ if(gamestate==PLAYING) showlife(view);
+
+
+#define SCOREX -10.5
+#define SCORETAB 7.1
+#define SCOREXC (SCOREX + SCORETAB*0.5)
+#define SCOREY 5.5
+#define SCOREZ 6.0
+#define LINESPACE 1.0
+#define SCOREY1 (SCOREY - LINESPACE*0)
+#define SCOREY2 (SCOREY - LINESPACE*1)
+#define SCOREY3 (SCOREY - LINESPACE*2)
+#define SCOREY4 (SCOREY - LINESPACE*3)
+#define SCOREY5 (SCOREY - LINESPACE*4)
+#define SCOREY6 (SCOREY - LINESPACE*5)
+#define SCOREY7 (SCOREY - LINESPACE*6)
+#define SCOREY8 (SCOREY - LINESPACE*7)
+#define SCOREY9 (SCOREY - LINESPACE*8)
+#define SCOREY10 (SCOREY - LINESPACE*9)
+#define SCOREY11 (SCOREY - LINESPACE*10)
+#define SCOREY12 (SCOREY - LINESPACE*11)
+
+ setmaterial(white);
+ drawstring(view, SCOREX, SCOREY1, SCOREZ, SCALE, 0, "Score");
+ drawstring(view, SCOREX+SCORETAB, SCOREY1, SCOREZ, SCALE, 2, "%d",score);
+ drawstring(view, SCOREX, SCOREY2, SCOREZ, SCALE, 0, "High");
+ drawstring(view, SCOREX+SCORETAB, SCOREY2, SCOREZ, SCALE, 2, "%d", highscore);
+
+ drawstring(view, SCOREX, SCOREY3, SCOREZ, SCALE, 0, "Level",level);
+ drawstring(view, SCOREX+SCORETAB, SCOREY3, SCOREZ, SCALE, 2, "%d",level);
+ drawstring(view, SCOREX, SCOREY4, SCOREZ, SCALE, 0, "Moves",level);
+ drawstring(view, SCOREX+SCORETAB, SCOREY4, SCOREZ, SCALE, 2, "%d",nummoves);
+ if(gamestate != PLAYING)
+ {
+ drawstring(view, SCOREXC, SCOREY6, SCOREZ, SCALE, 1, "Game Over");
+ figure(view, SCOREXC, SCOREY11, SCOREZ);
+ setmaterial(green);
+ drawstring(view, SCOREXC, SCOREY8, SCOREZ, SCALE, 1, "Jewels");
+ drawstring(view, SCOREXC, SCOREY9, SCOREZ, SCALE, 1, "by David Ashley");
+ }
+ else if(cumulativefade>0.0)
+ {
+// setgrey(cumulativefade);
+ GX_SetChanMatColor(GX_COLOR0A0, (GXColor) {255, 255, 255, 255 * cumulativefade});
+ drawstring(view, SCOREXC, SCOREY6, SCOREZ, SCALE, 1, "+%d",cumulative);
+ GX_SetChanMatColor(GX_COLOR0A0, (GXColor) {255, 255, 255, 255});
+ }
+
+
+
+
+// t=SPACING;
+// y=t*(EY/2.0-0.5);
+ e=elements[0];
+ k=EX*EY;
+// glDisable(GL_DEPTH_TEST);
+// glEnable(GL_BLEND);
+ for(j=0;j<EY;++j)
+ {
+// x=-t*(EX/2.0-0.5);
+ for(i=0;i<EX;++i)
+ {
+ guVector tvector;
+
+ jmap(&nx, &ny, &nz, i, j);
+// nx=x+SHIFTX;
+// ny=y;
+// nz=(1.0-e->vanish)*50.0;
+ nz += (1.0-e->vanish)*100.0;
+ if(e->swapping)
+ {
+ f32 s;
+ a=e->swapping*3.1415927/2.0/SWAPTIME;
+ s=SPACING*cos(a);
+ nx+=s*e->dx;
+ ny+=s*e->dy;
+ s=SPACING*sin(a*2.0);
+ if(c++ & 1) s=-s;
+ nz+=s;
+ }
+ ny+=e->fall*SPACING;
+
+
+ guMtxIdentity(model);
+ tvector.x = e->ax;
+ tvector.y = e->ay;
+ tvector.z = e->az;
+ guMtxRotAxisDeg(model, &tvector, e->angle);
+ guMtxTransApply(model, model, nx, ny, nz);
+ guMtxConcat(view,model,modelview);
+ // load the modelview matrix into matrix memory
+ GX_LoadPosMtxImm(modelview, GX_PNMTX0);
+ GX_LoadNrmMtxImm(modelview, GX_PNMTX0);
+
+
+ if(gamestate==PLAYING && cposx==i && cposy==j)
+ {
+ light_brighter();
+ }
+ if(e->swapping)
+ {
+// glDisable(GL_BLEND);
+// glEnable(GL_DEPTH_TEST);
+ }
+
+ if(e->type >=0 && e->type <= 6)
+ {
+ setmaterial(colormaps[e->type]);
+ functab[e->type]();
+ }
+ if(e->swapping)
+ {
+// glEnable(GL_BLEND);
+// glDisable(GL_DEPTH_TEST);
+ }
+ if(gamestate==PLAYING && cposx==i && cposy==j)
+ {
+ light_regular();
+ }
+ ++e;
+ }
+ }
+cheat = 0;
+ if(cheat && actionmode == ACTION_WAITING)
+ {
+ setmaterial(green);
+ GX_SetZMode(GX_TRUE, GX_ALWAYS, GX_FALSE);
+ for(j=0;j<EY;++j)
+ {
+ for(i=0;i<EX;++i)
+ {
+ for(k=0;k<2;++k)
+ {
+ f32 dx, dy;
+ if(~movebits[j][i]&(1<<k)) continue;
+ if(k==0) dx=-0.5, dy=0.0;
+ else dx=0.0, dy=-0.5;
+ jmap(&nx, &ny, &nz, i+dx, j+dy);
+ guMtxTrans(model, nx, ny, nz);
+ guMtxConcat(view,model,modelview);
+ GX_LoadPosMtxImm(modelview, GX_PNMTX0);
+ GX_LoadNrmMtxImm(modelview, GX_PNMTX0);
+ GX_SetZMode(GX_TRUE, GX_ALWAYS, GX_FALSE);
+ makebucky(SCALE*.2);
+ GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
+ }
+ }
+ }
+ setmaterial(white);
+ GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
+ }
+
+ if(cposx>=0 && cposx<EX && cposy>=0 && cposy<EY)
+ {
+ jmap(&nx, &ny, &nz, cposx, cposy);
+
+ setmaterial(white);
+ guMtxIdentity(model);
+ guMtxTransApply(model, model, nx, ny, nz);
+ guMtxConcat(view,model,modelview);
+ GX_LoadPosMtxImm(modelview, GX_PNMTX0);
+ GX_LoadNrmMtxImm(modelview, GX_PNMTX0);
+ GX_SetZMode(GX_TRUE, GX_ALWAYS, GX_FALSE);
+// makeselector(SCALE*1.4);
+ GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
+ }
+
+ GX_SetZMode(GX_TRUE, GX_ALWAYS, GX_FALSE);
+ for(i=0;i<MAXSCORESPRITES;++i)
+ {
+ struct scoresprite *ss=scoresprites+i;
+ if(ss->fade==0.0) continue;
+ GX_SetChanMatColor(GX_COLOR0A0, (GXColor) {255, 255, 255, 255*ss->fade});
+ drawstring(view, ss->x, ss->y-(1.0-ss->fade), ss->z, SCALE, 1,"+%d",ss->value);
+ }
+ GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
+ GX_SetChanMatColor(GX_COLOR0A0, (GXColor) {255, 255, 255, 255});
+
+}
+
+void getpos(int *dx, int *dy, f32 x, f32 y, f32 z)
+{
+int u, v, bu=-1, bv=-1;
+f32 bestdist = 100000000000.0, d;
+f32 tx, ty, tz;
+
+ for(v=0;v<EY;++v)
+ for(u=0;u<EX;++u)
+ {
+ jmap(&tx, &ty, &tz, u, v);
+ tx -= x;
+ ty -= y;
+ tz -= z;
+ d = tx*tx + ty*ty + tz*tz;
+ if(d < bestdist)
+ {
+ bestdist = d;
+ bu = u;
+ bv = v;
+ }
+ }
+ if(1 || bestdist < SPACING*SPACING)
+ *dx = bu, *dy = bv;
+ else
+ *dx = -1, *dy = -1;
+}
+
+void down(f32 x,f32 y, f32 z)
+{
+ downx=x;
+ downy=y;
+ downz=z;
+ isdown=1;
+}
+
+#define DIST 20
+#define ABS(x) (((x)<0) ? (-(x)) : (x))
+void moved(f32 x,f32 y, f32 z)
+{
+f32 dx,dy,dz;
+int px=-1, py=-1;
+
+ getpos(&cposx,&cposy,x,y,z);
+ if(!isdown) return;
+ dx=x-downx;
+ dy=y-downy;
+ dz=z-downz;
+ if(dx*dx+dy*dy+dz*dz<SPACING*SPACING/4.0) return;
+ isdown=0;
+ if(ABS(dx)>ABS(dy))
+ {
+ if(dx<0) dx=-1;
+ else dx=1;
+ dy=0;
+ } else
+ {
+ if(dy<0) dy=1;
+ else dy=-1;
+ dx=0;
+ }
+ getpos(&px,&py,downx,downy,downz);
+
+ if(px<0 || px>=EX || py<0 || py>=EY) return;
+ if(px+dx<0 || px+dx>=EX || py+dy<0 || py+dy>=EY) return;
+ addswap(px,py,dx,dy);
+
+}
+
+void buttonup(f32 x, f32 y, f32 z)
+{
+ isdown=0;
+}
+
+unsigned char *ppmtake;
+int ppmin;
+unsigned char ppmbuff[2048],*ppmp;
+inline int ppmci()
+{
+ return *ppmtake++;
+}
+
+void ppmline(unsigned char *put)
+{
+int c;
+ while((c=ppmci())>=0)
+ if(c==0x0a) break;
+ else *put++=c;
+ *put=0;
+}
+struct pic {
+unsigned char *image;
+int w,h;
+};
+
+int readppm(unsigned char *data,struct pic *pic)
+{
+unsigned char line[8192];
+int w,h;
+unsigned int i,j;
+unsigned char *put;
+
+ ppmtake = data;
+ ppmin=0;
+ ppmline(line);
+ if(strcmp((char *)line,"P6")) return 1;
+ ppmline(line);
+ if(sscanf((char *)line,"%d %d",&w,&h)!=2) return 2;
+ pic->w=w;
+ pic->h=h;
+ pic->image=put=memalign(4, w*h*3);
+ if(!put) return -3;
+ ppmline(line);
+ for(j=0;j<h;++j)
+ {
+ for(i=0;i<w;++i)
+ {
+ *put++=ppmci();
+ *put++=ppmci();
+ *put++=ppmci();
+ }
+ }
+ return 0;
+}
+
+
+#define TW 256
+#define TH TW
+#define MAXCHARS 72
+unsigned char *fontcharacters=(void *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.!:>^@() +";
+GXTexObj fonttexture;
+struct fontchar {
+ f32 ulx, uly;
+ f32 lrx, lry;
+ int width;
+} fontchars[MAXCHARS];
+unsigned char fontmap[128];
+
+
+void initfont(void)
+{
+
+// Texture setup
+// RGBA format divides real texture into 4x4 pixel squares
+// they are outputted left to right, top to bottom
+// Each square is 4 rows of 4 pixels of AR (1 byte each)
+// followed by 4 rows of 4 pixels of GB (1 byte each)
+int x,y, base;
+unsigned char *b2;
+struct pic pic;
+int nextx, nexty;
+unsigned char keyr,keyg,keyb,*p;
+unsigned char gapr,gapg,gapb,r,g,b,a;
+unsigned char *txdata;
+int wc;
+int cc;
+int u,v;
+
+ memset(fontmap, 255, sizeof(fontmap));
+ readppm((void *)bigfont_ppm, &pic);
+ txdata = memalign(32, TW*TH*4);
+ memset(txdata, 0, TW*TH*4);
+
+ nextx = nexty = 0;
+ p=pic.image+3*(pic.w*pic.h-1);
+ keyr=*p++;
+ keyg=*p++;
+ keyb=*p++;
+
+ p=pic.image+3*pic.w;
+ gapr=*p++;
+ gapg=*p++;
+ gapb=*p++;
+
+ wc = pic.w - 1;
+
+ for(cc=0;cc<MAXCHARS;++cc)
+ {
+ int cw;
+ struct fontchar *fc;
+
+ fontmap[fontcharacters[cc]] = cc;
+ fc = fontchars+cc;
+
+ cw = 0;
+ while(wc--)
+ {
+ r = *p++;
+ g = *p++;
+ b = *p++;
+ if(r==gapr && g==gapg && b==gapb) break;
+ ++cw;
+ }
+ if(!cw) break;
+ fc->width = cw;
+
+ if(nextx + cw > TW)
+ {
+ nexty += pic.h;
+ nextx = 0;
+ }
+ fc->ulx = (f32)nextx / TW;
+ fc->uly = (f32)nexty / TH;
+ fc->lrx = (f32)(nextx + cw) / TW;
+ fc->lry = (f32)(nexty + pic.h-2) / TH;
+ for(v=0;v<pic.h-2;++v)
+ {
+ y=nexty+v;
+ for(u=0;u<cw;++u)
+ {
+ x=nextx+u;
+ base = (y&3)*8 + (x>>2)*64 + (x&3)*2 + (y>>2)*TW*16;
+ b2 = p + (u - cw - 1 + v*pic.w)*3;
+ r = b2[0];
+ g = b2[1];
+ b = b2[2];
+ a = 255;
+ if(r==keyr && g==keyg && b==keyb)
+ r = g = b = a = 0;
+ txdata[base+ 0] = a; // alpha
+ txdata[base+ 1] = r; // red
+ txdata[base+32] = g; // green
+ txdata[base+33] = b; // blue
+ }
+ }
+ nextx += cw;
+
+ }
+
+
+ DCFlushRange(txdata, TW*TH*4);
+ GX_InvVtxCache();
+ GX_InvalidateTexAll();
+ GX_InitTexObj(&fonttexture, txdata, TW, TH, GX_TF_RGBA8, GX_REPEAT, GX_REPEAT, GX_FALSE);
+ GX_LoadTexObj(&fonttexture, GX_TEXMAP0);
+}
+
+void drawstring(Mtx44 view, f32 x, f32 y, f32 z,
+ f32 scale, int alignment, char *fmt, ...)
+{
+char temp[128], *p;
+va_list ap;
+struct fontchar *fc;
+Mtx44 model, modelview;
+
+ va_start(ap, fmt);
+ vsprintf(temp,fmt,ap);
+ va_end(ap);
+
+ GX_InvalidateTexAll();
+ GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
+ GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
+
+ GX_SetNumTexGens(1);
+ GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
+ GX_SetTevOp(GX_TEVSTAGE0,GX_MODULATE); //GX_REPLACE);
+ GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
+
+ GX_LoadTexObj(&fonttexture, GX_TEXMAP0);
+
+ GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
+
+
+scale *= 10;
+
+ if(alignment)
+ {
+ f32 advance = 0.0;
+
+ p = temp;
+ while(*p)
+ {
+ fc = fontchars + (fontmap[(unsigned char)(*p++)] & 127);
+ advance += fc->lrx - fc->ulx;
+ }
+ advance *= scale;
+ if(alignment==1) advance *= .5;
+ x -= advance;
+ }
+ guMtxIdentity(model);
+ guMtxTransApply(model, model, x, y, z);
+ guMtxConcat(view,model,modelview);
+ GX_LoadPosMtxImm(modelview, GX_PNMTX0);
+ GX_LoadNrmMtxImm(modelview, GX_PNMTX0);
+
+ x = y = z = 0.0;
+ p = temp;
+ while(*p)
+ {
+ f32 x2, y2;
+
+ fc = fontchars + (fontmap[(unsigned char)(*p++)] & 127);
+
+ x2 = x + scale*(fc->lrx - fc->ulx);
+ y2 = y + scale*(fc->lry - fc->uly);
+
+ GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
+ GX_Position3f32(x, y2, z);// -----POS
+ GX_Normal3f32(0.0f, 0.0f, 1.0f);
+ GX_Color3f32(1.0f, 1.0f, 1.0f);
+ GX_TexCoord2f32(fc->ulx, fc->uly);
+
+ GX_Position3f32(x2, y2, z);// -----POS
+ GX_Normal3f32(0.0f, 0.0f, 1.0f);
+ GX_Color3f32(1.0f, 1.0f, 1.0f);
+ GX_TexCoord2f32(fc->lrx, fc->uly);
+
+ GX_Position3f32(x2, y, z);// -----POS
+ GX_Normal3f32(0.0f, 0.0f, 1.0f);
+ GX_Color3f32(1.0f, 1.0f, 1.0f);
+ GX_TexCoord2f32(fc->lrx, fc->lry);
+
+ GX_Position3f32(x, y, z);// -----POS
+ GX_Normal3f32(0.0f, 0.0f, 1.0f);
+ GX_Color3f32(1.0f, 1.0f, 1.0f);
+ GX_TexCoord2f32(fc->ulx, fc->lry);
+ GX_End();
+
+ x = x2;
+ }
+
+ GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
+ GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
+ GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
+ GX_SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
+}
+
+
+int main(int argc, char **argv)
+{
+f32 yscale;
+u32 xfbHeight;
+Mtx44 view;
+Mtx44 perspective;
+Mtx44 model, modelview;
+f32 rtri = 0.0f , rquad = 0.0f;
+u32 fb = 0; // initial framebuffer index
+GXColor background = {0, 0, 0, 0xff};
+f32 cx=0.0, cy=0.0, cz = 0.0;
+
+ myseed(1);
+
+ // init the vi.
+ VIDEO_Init();
+ WPAD_Init();
+ rmode = VIDEO_GetPreferredMode(NULL);
+
+ // Initialise the audio subsystem
+ //ASND_Init(NULL);
+ ASND_Init();
+ ASND_Pause(0);
+
+ WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
+ WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight);
+
+ // allocate 2 framebuffers for double buffering
+ frameBuffer[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
+ frameBuffer[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
+
+ VIDEO_Configure(rmode);
+ VIDEO_SetNextFramebuffer(frameBuffer[fb]);
+ VIDEO_SetBlack(FALSE);
+ VIDEO_Flush();
+ VIDEO_WaitVSync();
+ if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
+
+ // setup the fifo and then init the flipper
+ void *gp_fifo = NULL;
+ gp_fifo = memalign(32,DEFAULT_FIFO_SIZE);
+ memset(gp_fifo,0,DEFAULT_FIFO_SIZE);
+
+ GX_Init(gp_fifo,DEFAULT_FIFO_SIZE);
+
+ // clears the bg to color and clears the z buffer
+ GX_SetCopyClear(background, 0x00ffffff);
+
+ // other gx setup
+ GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
+ yscale = GX_GetYScaleFactor(rmode->efbHeight,rmode->xfbHeight);
+ xfbHeight = GX_SetDispCopyYScale(yscale);
+ GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
+ GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
+ GX_SetDispCopyDst(rmode->fbWidth,xfbHeight);
+ GX_SetCopyFilter(rmode->aa,rmode->sample_pattern,GX_TRUE,rmode->vfilter);
+ GX_SetFieldMode(rmode->field_rendering,((rmode->viHeight==2*rmode->xfbHeight)?GX_ENABLE:GX_DISABLE));
+
+ GX_SetCullMode(GX_CULL_BACK);
+ GX_CopyDisp(frameBuffer[fb],GX_TRUE);
+ GX_SetDispCopyGamma(GX_GM_1_0);
+
+
+ // setup the vertex descriptor
+ // tells the flipper to expect direct data
+ GX_ClearVtxDesc();
+ GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
+ GX_SetVtxDesc(GX_VA_NRM, GX_DIRECT);
+// GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
+ GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
+ GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
+
+ // setup the vertex attribute table
+ // describes the data
+ // args: vat location 0-7, type of data, data format, size, scale
+ // so for ex. in the first call we are sending position data with
+ // 3 values X,Y,Z of size F32. scale sets the number of fractional
+ // bits for non float data.
+ GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
+ GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
+ GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
+ GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGB8, 0);
+
+// GX_SetNumChans(1);
+// GX_SetNumTexGens(1);
+ GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
+// GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
+
+// GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE);
+ GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
+ GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
+
+
+ initfont();
+
+#if 0
+{
+fatInitDefault();
+int fd = open("/davettt.foo", O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if(fd>=0) close(fd);
+exit(0);
+}
+#endif
+
+
+ // setup our camera at the origin
+ // looking down the -z axis with y up
+ guVector cam = {0.0F, 0.0F, 100.0F},
+ up = {0.0F, .1F, 0.0F},
+ look = {0.0F, 0.0F, 90.0F};
+ guLookAt(view, &cam, &up, &look);
+
+ // setup our projection matrix
+ // this creates a perspective matrix with a view angle of 90,
+ // and aspect ratio based on the display resolution
+ f32 w = rmode->viWidth;
+ f32 h = rmode->viHeight;
+ guPerspective(perspective, 10, (f32)w/h, 0.1F, 300.0F);
+ GX_LoadProjectionMtx(perspective, GX_PERSPECTIVE);
+
+ xsize = rmode->fbWidth;
+ ysize = rmode->xfbHeight;
+
+ initgame();
+ endgame();
+
+ while(1) {
+ int res;
+ u32 type;
+ WPADData *wd;
+ WPAD_ScanPads();
+ myrand();
+
+ if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) exit(0);
+ if(gamestate==GAMEOVER &&
+ (WPAD_ButtonsDown(0) & (WPAD_BUTTON_1 | WPAD_BUTTON_2)))
+ initgame();
+
+ res = WPAD_Probe(0, &type);
+ if(res == WPAD_ERR_NONE)
+ wd = WPAD_Data(0);
+ else
+ wd = 0;
+
+
+ // do this before drawing
+ GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
+
+
+ setlight(view,8, 20, litcolors[0], litcolors[1], litcolors[2]);
+
+ action();
+ draw(view, WPAD_ButtonsHeld(0) & WPAD_BUTTON_B);
+
+ if(wd)
+ {
+#define IF 0.04
+ f32 x = IF * (-rmode->fbWidth/2.0 + wd->ir.x);
+ f32 y = IF * (rmode->xfbHeight/2.0 - wd->ir.y);
+ f32 z = 0.0;
+
+ moved(cx = x, cy = y, cz = z);
+ guMtxIdentity(model);
+ guMtxTransApply(model, model, x, y, 0.0);
+ guMtxConcat(view,model,modelview);
+ GX_LoadPosMtxImm(modelview, GX_PNMTX0);
+ GX_LoadNrmMtxImm(modelview, GX_PNMTX0);
+ setmaterial(white);
+ GX_SetZMode(GX_TRUE, GX_ALWAYS, GX_FALSE);
+ makebucky(0.2 * SCALE);
+ GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
+ }
+
+ if(WPAD_ButtonsDown(0) & WPAD_BUTTON_A)
+ down(cx, cy, cz);
+ if(WPAD_ButtonsUp(0) & WPAD_BUTTON_A)
+ buttonup(cx, cy, cz);
+
+ // do this stuff after drawing
+ GX_DrawDone();
+
+ fb ^= 1; // flip framebuffer
+ GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
+ GX_SetColorUpdate(GX_TRUE);
+ GX_CopyDisp(frameBuffer[fb],GX_TRUE);
+
+ VIDEO_SetNextFramebuffer(frameBuffer[fb]);
+
+ VIDEO_Flush();
+
+ VIDEO_WaitVSync();
+
+ rtri+=0.2f; // Increase The Rotation Variable For The Triangle ( NEW )
+ rquad-=0.15*10.0f; // Decrease The Rotation Variable For The Quad ( NEW )
+
+ }
+ return 0;
+}
+