summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--LICENCE340
-rw-r--r--Makefile173
-rw-r--r--README22
-rw-r--r--data/alert.rawbin0 -> 38264 bytes
-rw-r--r--data/bigdrop.rawbin0 -> 67456 bytes
-rw-r--r--data/bigfont.ppmbin0 -> 115215 bytes
-rw-r--r--data/drop.rawbin0 -> 25718 bytes
-rw-r--r--data/gameover.rawbin0 -> 101392 bytes
-rw-r--r--data/illegal.rawbin0 -> 31148 bytes
-rw-r--r--data/row.rawbin0 -> 26992 bytes
-rw-r--r--data/swap.rawbin0 -> 12130 bytes
-rw-r--r--makefont/Makefile11
-rw-r--r--makefont/hockey.ttfbin0 -> 46560 bytes
-rw-r--r--makefont/makefont.c330
-rw-r--r--source/jewels.c2469
15 files changed, 3345 insertions, 0 deletions
diff --git a/LICENCE b/LICENCE
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..da03702
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,173 @@
+#---------------------------------------------------------------------------------
+# Clear the implicit built in rules
+#---------------------------------------------------------------------------------
+.SUFFIXES:
+#---------------------------------------------------------------------------------
+# prevent deletion of implicit targets
+#---------------------------------------------------------------------------------
+.SECONDARY:
+#---------------------------------------------------------------------------------
+
+ifeq ($(strip $(DEVKITPPC)),)
+$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
+endif
+
+include $(DEVKITPPC)/wii_rules
+
+#---------------------------------------------------------------------------------
+# TARGET is the name of the output
+# BUILD is the directory where object files & intermediate files will be placed
+# SOURCES is a list of directories containing source code
+# INCLUDES is a list of directories containing extra header files
+#---------------------------------------------------------------------------------
+TARGET := $(notdir $(CURDIR))
+BUILD := build
+SOURCES := source
+DATA := data
+TEXTURES := textures
+INCLUDES :=
+
+#---------------------------------------------------------------------------------
+# options for code generation
+#---------------------------------------------------------------------------------
+
+CFLAGS = -O3 -Wall $(MACHDEP) $(INCLUDE)
+CXXFLAGS = $(CFLAGS)
+
+LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
+
+#---------------------------------------------------------------------------------
+# any extra libraries we wish to link with the project
+#---------------------------------------------------------------------------------
+LIBS := -lwiiuse -lbte -lasnd -lfat -logc -lm
+
+#---------------------------------------------------------------------------------
+# list of directories containing libraries, this must be the top level containing
+# include and lib
+#---------------------------------------------------------------------------------
+LIBDIRS := $(PORTLIBS)
+
+#---------------------------------------------------------------------------------
+# no real need to edit anything past this point unless you need to add additional
+# rules for different file extensions
+#---------------------------------------------------------------------------------
+ifneq ($(BUILD),$(notdir $(CURDIR)))
+#---------------------------------------------------------------------------------
+
+export OUTPUT := $(CURDIR)/$(TARGET)
+
+export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
+ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
+ $(foreach dir,$(TEXTURES),$(CURDIR)/$(dir))
+
+
+export DEPSDIR := $(CURDIR)/$(BUILD)
+
+#---------------------------------------------------------------------------------
+# automatically build a list of object files for our project
+#---------------------------------------------------------------------------------
+CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
+CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
+sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
+SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
+BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
+SCFFILES := $(foreach dir,$(TEXTURES),$(notdir $(wildcard $(dir)/*.scf)))
+TPLFILES := $(SCFFILES:.scf=.tpl)
+
+#---------------------------------------------------------------------------------
+# use CXX for linking C++ projects, CC for standard C
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(CPPFILES)),)
+ export LD := $(CC)
+else
+ export LD := $(CXX)
+endif
+
+export OFILES := $(addsuffix .o,$(BINFILES)) \
+ $(addsuffix .o,$(TPLFILES)) \
+ $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
+ $(sFILES:.s=.o) $(SFILES:.S=.o)
+
+#---------------------------------------------------------------------------------
+# build a list of include paths
+#---------------------------------------------------------------------------------
+export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+ -I$(CURDIR)/$(BUILD) \
+ -I$(LIBOGC_INC)
+
+#---------------------------------------------------------------------------------
+# build a list of library paths
+#---------------------------------------------------------------------------------
+export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
+ -L$(LIBOGC_LIB)
+
+export OUTPUT := $(CURDIR)/$(TARGET)
+.PHONY: $(BUILD) clean
+
+#---------------------------------------------------------------------------------
+$(BUILD):
+ @[ -d $@ ] || mkdir -p $@
+ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
+
+#---------------------------------------------------------------------------------
+clean:
+ @echo clean ...
+ @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
+#---------------------------------------------------------------------------------
+run:
+ wiiload $(OUTPUT).dol
+
+#---------------------------------------------------------------------------------
+else
+
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+$(OUTPUT).dol: $(OUTPUT).elf
+$(OUTPUT).elf: $(OFILES)
+
+#---------------------------------------------------------------------------------
+# This rule links in binary data with the .bin extension
+#---------------------------------------------------------------------------------
+%.bin.o : %.bin
+#---------------------------------------------------------------------------------
+ @echo $(notdir $<)
+ $(bin2o)
+
+#---------------------------------------------------------------------------------
+%.tpl.o : %.tpl
+#---------------------------------------------------------------------------------
+ @echo $(notdir $<)
+ @$(bin2o)
+
+
+-include $(DEPSDIR)/*.d
+
+#---------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------------
+# This rule links in binary data with the .raw extension
+#---------------------------------------------------------------------------------
+%.raw.o : %.raw
+#---------------------------------------------------------------------------------
+ @echo $(notdir $<)
+ $(bin2o)
+
+#---------------------------------------------------------------------------------
+# This rule links in binary data with the .ppm extension
+#---------------------------------------------------------------------------------
+%.ppm.o : %.ppm
+#---------------------------------------------------------------------------------
+ @echo $(notdir $<)
+ $(bin2o)
+
+-include $(DEPENDS)
+
+
+
+test:
+ make
+ wiiload *.dol
diff --git a/README b/README
new file mode 100644
index 0000000..5024469
--- /dev/null
+++ b/README
@@ -0,0 +1,22 @@
+Jewels by David Ashley
+dashxdr@gmail.com
+http://www.xdr.com/dash
+
+http://www.linuxmotors.com
+
+Game based on gljewels:
+http://www.linuxmotors.com/gljewel/
+
+Just do "make" in this directory and it should build, if you've got a
+correct Wii devkitPro setup.
+
+
+CHANGELOG:
+
+---- v100, September 2010
+Initial release
+
+---- v101, October 15, 2010
+Updated icon from bg4545
+Improved count mechanism, more accurate number of moves shown
+Code for enabling cheat mode when 'b' is pressed, but disabled by default
diff --git a/data/alert.raw b/data/alert.raw
new file mode 100644
index 0000000..f0a5bf4
--- /dev/null
+++ b/data/alert.raw
Binary files differ
diff --git a/data/bigdrop.raw b/data/bigdrop.raw
new file mode 100644
index 0000000..384f512
--- /dev/null
+++ b/data/bigdrop.raw
Binary files differ
diff --git a/data/bigfont.ppm b/data/bigfont.ppm
new file mode 100644
index 0000000..2719080
--- /dev/null
+++ b/data/bigfont.ppm
Binary files differ
diff --git a/data/drop.raw b/data/drop.raw
new file mode 100644
index 0000000..4a5fced
--- /dev/null
+++ b/data/drop.raw
Binary files differ
diff --git a/data/gameover.raw b/data/gameover.raw
new file mode 100644
index 0000000..46b9d27
--- /dev/null
+++ b/data/gameover.raw
Binary files differ
diff --git a/data/illegal.raw b/data/illegal.raw
new file mode 100644
index 0000000..17cfd1e
--- /dev/null
+++ b/data/illegal.raw
Binary files differ
diff --git a/data/row.raw b/data/row.raw
new file mode 100644
index 0000000..03cc7b5
--- /dev/null
+++ b/data/row.raw
Binary files differ
diff --git a/data/swap.raw b/data/swap.raw
new file mode 100644
index 0000000..5613cd4
--- /dev/null
+++ b/data/swap.raw
Binary files differ
diff --git a/makefont/Makefile b/makefont/Makefile
new file mode 100644
index 0000000..28b5601
--- /dev/null
+++ b/makefont/Makefile
@@ -0,0 +1,11 @@
+CC = gcc
+#DFLG = -g
+CFLAGS = $(DFLG) -O2 -Wall $(shell sdl-config --cflags)
+LDFLAGS = $(DFLG) $(shell sdl-config --libs) -lSDL_ttf
+
+all: makefont
+makefont: makefont.c
+clean:
+ rm -f *.o makefont
+test: all
+ ./makefont
diff --git a/makefont/hockey.ttf b/makefont/hockey.ttf
new file mode 100644
index 0000000..ce7da93
--- /dev/null
+++ b/makefont/hockey.ttf
Binary files differ
diff --git a/makefont/makefont.c b/makefont/makefont.c
new file mode 100644
index 0000000..5480fb6
--- /dev/null
+++ b/makefont/makefont.c
@@ -0,0 +1,330 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <math.h>
+#include <fcntl.h>
+
+#include <SDL.h>
+#include <SDL/SDL_ttf.h>
+
+#define XSIZE 1200
+#define YSIZE 32
+
+Uint32 gridcolor,xcolor,ocolor,white;
+
+int mousex,mousey;
+
+int bgr=0, bgg=00, bgb=0;
+int fgr=255, fgg=255, fgb=255;
+
+
+SDL_Surface *readppm(char *name)
+{
+char line[1024*3], *p;
+int width=0, height=0;
+int len;
+SDL_Surface *s;
+int x;
+unsigned char *put;
+FILE *f;
+void *res;
+
+ f=fopen(name, "r");
+ if(!f)
+ {
+ fprintf(stderr, "Couldn't open %s\n", name);
+ exit(-1);
+ }
+ p=fgets(line, sizeof(line), f); // P6
+ if(!p || strncmp(p, "P6", 2))
+ {
+ fclose(f);
+ fprintf(stderr, "Not ppm file %s\n", line);
+ exit(-1);
+ }
+ res=fgets(line, sizeof(line), f); // 480 270
+ sscanf(line, "%d %d", &width, &height);
+ res=fgets(line, sizeof(line), f); // 255
+
+ s = SDL_AllocSurface(SDL_SWSURFACE, width, height, 24,
+ 0x0000ff, 0x00ff00, 0xff0000, 0x0);
+
+ x=0;
+ put = s->pixels;
+
+ while((len = fread(line, 1, sizeof(line), f)) > 0)
+ {
+ p=line;
+ while(len>0)
+ {
+ int r,g,b;
+ r=*p++;
+ g=*p++;
+ b=*p++;
+ put[x++] = r;
+ put[x++] = g;
+ put[x++] = b;
+ if(x==width*3)
+ {
+ x = 0;
+ put += s->pitch;
+ }
+ len-=3;
+ }
+ }
+ fclose(f);
+ return s;
+
+}
+
+
+
+SDL_Surface *thescreen;
+void clear(SDL_Surface *s)
+{
+int i,c;
+ c = SDL_MapRGB(s->format, bgr, bgg, bgb);
+ for(i=0;i<s->w;++i)
+ *(unsigned short *)(s->pixels+i*2) = c;
+ for(i=1;i<s->h;++i)
+ memcpy(s->pixels + i*s->pitch, s->pixels, s->w*2);
+
+}
+inline void colordot(SDL_Surface *s, unsigned x,unsigned y,int c)
+{
+ if(x<s->w && y<s->h)
+ *((uint32_t *)s->pixels+y*thescreen->pitch/4+x)=c;
+}
+
+
+void scrlock(SDL_Surface *s)
+{
+ if(SDL_MUSTLOCK(s))
+ {
+ if ( SDL_LockSurface(s) < 0 )
+ {
+ fprintf(stderr, "Couldn't lock display surface: %s\n",
+ SDL_GetError());
+ return;
+ }
+ }
+}
+void scrunlock(SDL_Surface *s)
+{
+ if(SDL_MUSTLOCK(s))
+ SDL_UnlockSurface(s);
+}
+void copyup(SDL_Surface *s)
+{
+ SDL_UpdateRect(s, 0, 0, 0, 0);
+}
+
+Uint32 maprgb(int r,int g,int b)
+{
+ return SDL_MapRGB(thescreen->format,r,g,b);
+}
+
+
+void circle(SDL_Surface *s, int cx,int cy,int radius,int c)
+{
+int x,y,e;
+
+ x=0;
+ y=radius;
+ e=3-(radius<<1);
+ while(x<=y)
+ {
+ colordot(s, cx+x,cy+y,c);
+ colordot(s, cx-x,cy+y,c);
+ colordot(s, cx+x,cy-y,c);
+ colordot(s, cx-x,cy-y,c);
+ colordot(s, cx+y,cy+x,c);
+ colordot(s, cx-y,cy+x,c);
+ colordot(s, cx+y,cy-x,c);
+ colordot(s, cx-y,cy-x,c);
+ if(e<0)
+ e+=(x<<2)+6;
+ else
+ {
+ e+=((x-y)<<2)+10;
+ --y;
+ }
+ ++x;
+ }
+}
+
+
+#define JUST_CENTER 0
+#define JUST_LEFT 1
+#define JUST_RIGHT 2
+
+void text_to(SDL_Surface *dest, TTF_Font *font, int x, int y, int just,
+ char *fmt, ...)
+{
+SDL_Surface *s;
+SDL_Rect r;
+char text[256];
+va_list ap;
+SDL_Color tc = {fgr, fgg, fgb, 0};
+
+
+ va_start(ap, fmt);
+ vsnprintf(text, sizeof(text), fmt, ap);
+ va_end(ap);
+
+ s = TTF_RenderUTF8_Blended(font, text, tc);
+ r.x = x;
+ if(just == JUST_CENTER)
+ r.x -= s->w/2;
+ else if(just == JUST_RIGHT)
+ r.x -= s->w;
+
+ r.y = y - s->h/2;
+ SDL_BlitSurface(s, 0, dest, &r);
+ SDL_FreeSurface(s);
+}
+
+struct state {
+ SDL_Surface *surface;
+ SDL_Surface *pictures;
+ TTF_Font *bigfont, *smallfont;
+ int mousex, mousey;
+};
+
+int writeppm(SDL_Surface *thescreen, char *name)
+{
+int ofile;
+unsigned char text[8192],*p;
+char temp[128];
+
+uint32_t *take;
+int i,j;
+int res;
+
+ ofile=open(name,O_WRONLY|O_CREAT|O_TRUNC,0644);
+ if(ofile<0) return -1;
+ sprintf(temp,"P6\n");
+ res=write(ofile,temp,strlen(temp));
+ sprintf(temp,"%d %d\n", thescreen->w, thescreen->h);
+ res=write(ofile,temp,strlen(temp));
+ sprintf(temp,"255\n");
+ res=write(ofile,temp,strlen(temp));
+ take=(void *) thescreen->pixels;
+ j=thescreen->h;
+ while(j--)
+ {
+ p = text;
+ for(i=0;i<thescreen->w;++i)
+ {
+ SDL_GetRGB(take[i],thescreen->format,p,p+1,p+2);
+ p+=3;
+ }
+ res=write(ofile,text,p-text);
+ take+=thescreen->pitch / sizeof(*take);
+ }
+//printf("%d\n", thescreen->format->BytesPerPixel);
+ return 0;
+}
+
+void paint_all(struct state *st)
+{
+SDL_Surface *s = st->surface;
+int x, y;
+char *p;
+SDL_Surface *ts;
+SDL_Color tc = {255, 255, 255, 0};
+SDL_Rect r;
+int gap = maprgb(255,0,255);
+
+ scrlock(s);
+ clear(s);
+ p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.!:>^@() + ";
+// p="uvwxyz0123456789.!:>^@() + ";
+
+// text_to(s, st->bigfont, 0, 15, JUST_LEFT, "foo!");
+
+ x = 0;
+ while(*p)
+ {
+ char text[2];
+ text[0] = *p++;
+ text[1] = 0;
+ ts = TTF_RenderUTF8_Blended(st->bigfont, text, tc);
+ r.x = x+1;
+ r.y = 15 - ts->h / 2;
+ SDL_BlitSurface(ts, 0, s, &r);
+ for(y=1;y<s->h-2;++y)
+ colordot(s, x, y, gap);
+ x += ts->w+1;
+ SDL_FreeSurface(ts);
+ }
+
+ scrunlock(st->surface);
+ copyup(st->surface);
+ writeppm(s, "/tmp/font.ppm");
+exit(0);
+
+}
+
+
+
+
+int main(int argc,char **argv)
+{
+int first;
+int code;
+SDL_Event event;
+Uint32 videoflags;
+struct state st;
+
+ if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
+ {
+ fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
+ exit(1);
+ }
+ videoflags = 0;
+ thescreen = SDL_SetVideoMode(XSIZE, YSIZE, 32, videoflags);
+ if ( thescreen == NULL )
+ {
+ fprintf(stderr, "Couldn't set display mode: %s\n",
+ SDL_GetError());
+ exit(5);
+ }
+
+ TTF_Init();
+
+ memset(&st, 0, sizeof(st));
+ st.surface = thescreen;
+// st.pictures = readppm("animals.ppm");
+ st.bigfont = TTF_OpenFont("hockey.ttf", 30);
+ st.smallfont = TTF_OpenFont("hockey.ttf", XSIZE/16);
+
+
+ first=0;
+
+ for(;;)
+ {
+ usleep(50000);
+ paint_all(&st);
+ while(SDL_PollEvent(&event))
+ {
+ switch(event.type)
+ {
+ case SDL_MOUSEMOTION:
+ mousex=event.motion.x;
+ mousey=event.motion.y;
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ break;
+ case SDL_KEYDOWN:
+ code=event.key.keysym.sym;
+ if(code==SDLK_ESCAPE) exit(0);
+ break;
+ }
+ }
+ }
+ return 0;
+}
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;
+}
+