changeset 2686:e9f27fe4f2a1 gsoc2008_nds

Existing testsprite programs made into NDS projects
author Darren Alton <dalton@stevens.edu>
date Wed, 13 Aug 2008 00:49:03 +0000
parents 2190b873ff00
children 5166b19b6808
files test/nds-test-progs/general/Makefile test/nds-test-progs/general/source/main.c test/nds-test-progs/sprite/Makefile test/nds-test-progs/sprite/source/common.c test/nds-test-progs/sprite/source/common.h test/nds-test-progs/sprite/source/testsprite.c test/nds-test-progs/sprite2/Makefile test/nds-test-progs/sprite2/source/common.c test/nds-test-progs/sprite2/source/common.h test/nds-test-progs/sprite2/source/testsprite2.c
diffstat 10 files changed, 3120 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/general/Makefile	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,132 @@
+#---------------------------------------------------------------------------------
+.SUFFIXES:
+#---------------------------------------------------------------------------------
+
+ifeq ($(strip $(DEVKITARM)),)
+$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
+endif
+
+include $(DEVKITARM)/ds_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		:=	$(shell basename $(CURDIR))
+BUILD		:=	build
+SOURCES		:=	source
+DATA		:=	data  
+INCLUDES	:=	include
+
+#---------------------------------------------------------------------------------
+# options for code generation
+#---------------------------------------------------------------------------------
+ARCH	:=	-mthumb -mthumb-interwork
+
+# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD
+# *insists* it has a FPU or VFP, and it won't take no for an answer!
+CFLAGS	:=	-save-temps -g -Wall -O0\
+ 			-mcpu=arm9tdmi -mtune=arm9tdmi \
+			$(ARCH)
+
+CFLAGS	+=	$(INCLUDE) -DARM9 -D__NDS__
+CXXFLAGS	:= $(CFLAGS) -fno-rtti -fno-exceptions -fno-exceptions -fno-rtti
+
+ASFLAGS	:=	-g $(ARCH)
+LDFLAGS	=	-specs=ds_arm9.specs -g $(ARCH) -mno-fpu -Wl,-Map,$(notdir $*.map)
+
+#---------------------------------------------------------------------------------
+# any extra libraries we wish to link with the project
+#---------------------------------------------------------------------------------
+LIBS	:= -lSDL -lfat -lnds9
+ 
+ 
+#---------------------------------------------------------------------------------
+# list of directories containing libraries, this must be the top level containing
+# include and lib
+#---------------------------------------------------------------------------------
+LIBDIRS	:=	$(LIBNDS)
+ 
+#---------------------------------------------------------------------------------
+# 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))
+
+export DEPSDIR	:=	$(CURDIR)/$(BUILD)
+
+CFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
+CPPFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
+SFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
+BINFILES	:=	$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
+ 
+#---------------------------------------------------------------------------------
+# 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)) \
+					$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
+ 
+export INCLUDE	:=	$(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+					$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+					$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+					-I$(CURDIR)/$(BUILD)
+ 
+export LIBPATHS	:=	$(foreach dir,$(LIBDIRS),-L$(dir)/lib)
+ 
+.PHONY: $(BUILD) clean
+ 
+#---------------------------------------------------------------------------------
+$(BUILD):
+	@[ -d $@ ] || mkdir -p $@
+	@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
+ 
+#---------------------------------------------------------------------------------
+clean:
+	@echo clean ...
+	@rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).arm9 $(TARGET).ds.gba 
+ 
+ 
+#---------------------------------------------------------------------------------
+else
+ 
+DEPENDS	:=	$(OFILES:.o=.d)
+ 
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+$(OUTPUT).ds.gba	: 	$(OUTPUT).nds
+$(OUTPUT).nds	: 	$(OUTPUT).arm9
+$(OUTPUT).arm9	:	$(OUTPUT).elf
+$(OUTPUT).elf	:	$(OFILES)
+ 
+#---------------------------------------------------------------------------------
+%.pcx.o	:	%.pcx
+#---------------------------------------------------------------------------------
+	@echo $(notdir $<)
+	@$(bin2o)
+ 
+ 
+-include $(DEPENDS)
+ 
+#---------------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/general/source/main.c	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,77 @@
+
+#include <SDL/SDL.h>
+#if defined(NDS) || defined(__NDS__) || defined (__NDS)
+#include <nds.h>
+#else
+#define swiWaitForVBlank() 
+#define consoleDemoInit() 
+#define RGB15(r,g,b) SDL_MapRGB(screen->format,((r)<<3),((g)<<3),((b)<<3))
+#endif
+
+void delay(int s) {
+	while(s-- > 0) {
+		int i = 60;
+		while(--i) swiWaitForVBlank();
+	}
+}
+
+int main(void) {
+	SDL_Surface *screen;
+	SDL_Joystick *stick;
+	SDL_Event event;
+	SDL_Rect rect = {8,8,240,176};
+
+	consoleDemoInit();
+	if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0) {
+		puts("# error initializing SDL");
+		puts(SDL_GetError());
+		return 1;
+	}
+	puts("* initialized SDL\n"); delay(1);
+
+	screen = SDL_SetVideoMode(256, 192, 16, SDL_SWSURFACE);
+	if(!screen) {
+		puts("# error setting video mode");
+		puts(SDL_GetError());
+		return 2;
+	}
+	puts("* set video mode\n"); delay(1);
+
+	stick = SDL_JoystickOpen(0);
+	if(stick == NULL) {
+		puts("# error opening joystick");
+		puts(SDL_GetError());
+//		return 3;
+	}
+	puts("* opened joystick"); delay(1);
+	SDL_FillRect(screen, &rect, RGB15(0,0,31)|0x8000);
+	SDL_Flip(screen);
+
+	while(1)
+	while(SDL_PollEvent(&event))
+	switch(event.type) {
+		case SDL_JOYBUTTONDOWN:
+		switch(event.jbutton.which) {
+			case 0:
+			SDL_FillRect(screen, &rect, RGB15(31,0,0)|0x8000);
+			break;
+			case 1:
+			SDL_FillRect(screen, &rect, RGB15(0,31,0)|0x8000);
+			break;
+			case 2:
+			SDL_FillRect(screen, &rect, RGB15(0,0,31)|0x8000);
+			break;
+			case 3:
+			SDL_FillRect(screen, &rect, RGB15(0,0,0)|0x8000);
+			break;
+			default: break;
+		}
+		printf("joy_%d\n", event.jbutton.which);
+		SDL_Flip(screen);
+		break;
+		case SDL_QUIT: SDL_Quit(); return 0;
+		default: break;
+	}
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/sprite/Makefile	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,132 @@
+#---------------------------------------------------------------------------------
+.SUFFIXES:
+#---------------------------------------------------------------------------------
+
+ifeq ($(strip $(DEVKITARM)),)
+$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
+endif
+
+include $(DEVKITARM)/ds_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		:=	$(shell basename $(CURDIR))
+BUILD		:=	build
+SOURCES		:=	source
+DATA		:=	data  
+INCLUDES	:=	include
+
+#---------------------------------------------------------------------------------
+# options for code generation
+#---------------------------------------------------------------------------------
+ARCH	:=	-mthumb -mthumb-interwork
+
+# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD
+# *insists* it has a FPU or VFP, and it won't take no for an answer!
+CFLAGS	:=	-save-temps -g -Wall -O0\
+ 			-mcpu=arm9tdmi -mtune=arm9tdmi \
+			$(ARCH)
+
+CFLAGS	+=	$(INCLUDE) -DARM9 -D__NDS__
+CXXFLAGS	:= $(CFLAGS) -fno-rtti -fno-exceptions -fno-exceptions -fno-rtti
+
+ASFLAGS	:=	-g $(ARCH)
+LDFLAGS	=	-specs=ds_arm9.specs -g $(ARCH) -mno-fpu -Wl,-Map,$(notdir $*.map)
+
+#---------------------------------------------------------------------------------
+# any extra libraries we wish to link with the project
+#---------------------------------------------------------------------------------
+LIBS	:= -lSDL -lfat -lnds9
+ 
+ 
+#---------------------------------------------------------------------------------
+# list of directories containing libraries, this must be the top level containing
+# include and lib
+#---------------------------------------------------------------------------------
+LIBDIRS	:=	$(LIBNDS)
+ 
+#---------------------------------------------------------------------------------
+# 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))
+
+export DEPSDIR	:=	$(CURDIR)/$(BUILD)
+
+CFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
+CPPFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
+SFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
+BINFILES	:=	$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
+ 
+#---------------------------------------------------------------------------------
+# 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)) \
+					$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
+ 
+export INCLUDE	:=	$(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+					$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+					$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+					-I$(CURDIR)/$(BUILD)
+ 
+export LIBPATHS	:=	$(foreach dir,$(LIBDIRS),-L$(dir)/lib)
+ 
+.PHONY: $(BUILD) clean
+ 
+#---------------------------------------------------------------------------------
+$(BUILD):
+	@[ -d $@ ] || mkdir -p $@
+	@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
+ 
+#---------------------------------------------------------------------------------
+clean:
+	@echo clean ...
+	@rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).arm9 $(TARGET).ds.gba 
+ 
+ 
+#---------------------------------------------------------------------------------
+else
+ 
+DEPENDS	:=	$(OFILES:.o=.d)
+ 
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+$(OUTPUT).ds.gba	: 	$(OUTPUT).nds
+$(OUTPUT).nds	: 	$(OUTPUT).arm9
+$(OUTPUT).arm9	:	$(OUTPUT).elf
+$(OUTPUT).elf	:	$(OFILES)
+ 
+#---------------------------------------------------------------------------------
+%.pcx.o	:	%.pcx
+#---------------------------------------------------------------------------------
+	@echo $(notdir $<)
+	@$(bin2o)
+ 
+ 
+-include $(DEPENDS)
+ 
+#---------------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/sprite/source/common.c	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,965 @@
+
+/* A simple test program framework */
+
+#include <stdio.h>
+
+#include "common.h"
+
+#define VIDEO_USAGE \
+"[--video driver] [--renderer driver] [--info all|video|modes|render|event] [--display %d] [--fullscreen | --windows N] [--title title] [--center | --position X,Y] [--geometry WxH] [--depth N] [--refresh R] [--vsync] [--noframe] [--resize] [--minimize] [--maximize] [--grab]"
+
+#define AUDIO_USAGE \
+"[--rate N] [--format U8|S8|U16|U16LE|U16BE|S16|S16LE|S16BE] [--channels N] [--samples N]"
+
+CommonState *
+CommonCreateState(char **argv, Uint32 flags)
+{
+    CommonState *state = SDL_calloc(1, sizeof(*state));
+    if (!state) {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+
+    /* Initialize some defaults */
+    state->argv = argv;
+    state->flags = flags;
+    state->window_title = argv[0];
+    state->window_flags = SDL_WINDOW_SHOWN;
+    state->window_x = SDL_WINDOWPOS_UNDEFINED;
+    state->window_y = SDL_WINDOWPOS_UNDEFINED;
+    state->window_w = 256;
+    state->window_h = 192;
+    state->num_windows = 1;
+    state->audiospec.freq = 22050;
+    state->audiospec.format = AUDIO_S16;
+    state->audiospec.channels = 2;
+    state->audiospec.samples = 2048;
+    return state;
+}
+
+int
+CommonArg(CommonState * state, int index)
+{
+    char **argv = state->argv;
+
+    if (SDL_strcasecmp(argv[index], "--video") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->videodriver = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->renderdriver = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--info") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        if (SDL_strcasecmp(argv[index], "all") == 0) {
+            state->verbose |=
+                (VERBOSE_VIDEO | VERBOSE_MODES | VERBOSE_RENDER |
+                 VERBOSE_EVENT);
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "video") == 0) {
+            state->verbose |= VERBOSE_VIDEO;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "modes") == 0) {
+            state->verbose |= VERBOSE_MODES;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "render") == 0) {
+            state->verbose |= VERBOSE_RENDER;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "event") == 0) {
+            state->verbose |= VERBOSE_EVENT;
+            return 2;
+        }
+        return -1;
+    }
+    if (SDL_strcasecmp(argv[index], "--display") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->display = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--fullscreen") == 0) {
+        state->window_flags |= SDL_WINDOW_FULLSCREEN;
+        state->num_windows = 1;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--windows") == 0) {
+        ++index;
+        if (!argv[index] || !SDL_isdigit(*argv[index])) {
+            return -1;
+        }
+        if (!(state->window_flags & SDL_WINDOW_FULLSCREEN)) {
+            state->num_windows = SDL_atoi(argv[index]);
+        }
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--title") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->window_title = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--center") == 0) {
+        state->window_x = SDL_WINDOWPOS_CENTERED;
+        state->window_y = SDL_WINDOWPOS_CENTERED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--position") == 0) {
+        char *x, *y;
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        x = argv[index];
+        y = argv[index];
+        while (*y && *y != ',') {
+            ++y;
+        }
+        if (!*y) {
+            return -1;
+        }
+        *y++ = '\0';
+        state->window_x = SDL_atoi(x);
+        state->window_y = SDL_atoi(y);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--geometry") == 0) {
+        char *w, *h;
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        w = argv[index];
+        h = argv[index];
+        while (*h && *h != 'x') {
+            ++h;
+        }
+        if (!*h) {
+            return -1;
+        }
+        *h++ = '\0';
+        state->window_w = SDL_atoi(w);
+        state->window_h = SDL_atoi(h);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--depth") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->depth = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--refresh") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->refresh_rate = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--vsync") == 0) {
+        state->render_flags |= SDL_RENDERER_PRESENTVSYNC;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--noframe") == 0) {
+        state->window_flags |= SDL_WINDOW_BORDERLESS;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--resize") == 0) {
+        state->window_flags |= SDL_WINDOW_RESIZABLE;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
+        state->window_flags |= SDL_WINDOW_MINIMIZED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--maximize") == 0) {
+        state->window_flags |= SDL_WINDOW_MAXIMIZED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--grab") == 0) {
+        state->window_flags |= SDL_WINDOW_INPUT_GRABBED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--rate") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->audiospec.freq = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--format") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        if (SDL_strcasecmp(argv[index], "U8") == 0) {
+            state->audiospec.format = AUDIO_U8;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S8") == 0) {
+            state->audiospec.format = AUDIO_S8;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "U16") == 0) {
+            state->audiospec.format = AUDIO_U16;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "U16LE") == 0) {
+            state->audiospec.format = AUDIO_U16LSB;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "U16BE") == 0) {
+            state->audiospec.format = AUDIO_U16MSB;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S16") == 0) {
+            state->audiospec.format = AUDIO_S16;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S16LE") == 0) {
+            state->audiospec.format = AUDIO_S16LSB;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S16BE") == 0) {
+            state->audiospec.format = AUDIO_S16MSB;
+            return 2;
+        }
+        return -1;
+    }
+    if (SDL_strcasecmp(argv[index], "--channels") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->audiospec.channels = (Uint8) SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--samples") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->audiospec.samples = (Uint16) SDL_atoi(argv[index]);
+        return 2;
+    }
+    if ((SDL_strcasecmp(argv[index], "-h") == 0)
+        || (SDL_strcasecmp(argv[index], "--help") == 0)) {
+        /* Print the usage message */
+        return -1;
+    }
+    return 0;
+}
+
+const char *
+CommonUsage(CommonState * state)
+{
+    switch (state->flags & (SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
+    case SDL_INIT_VIDEO:
+        return VIDEO_USAGE;
+    case SDL_INIT_AUDIO:
+        return AUDIO_USAGE;
+    case (SDL_INIT_VIDEO | SDL_INIT_AUDIO):
+        return VIDEO_USAGE " " AUDIO_USAGE;
+    default:
+        return "";
+    }
+}
+
+static void
+PrintRendererFlag(Uint32 flag)
+{
+    switch (flag) {
+    case SDL_RENDERER_SINGLEBUFFER:
+        fprintf(stderr, "SingleBuffer");
+        break;
+    case SDL_RENDERER_PRESENTCOPY:
+        fprintf(stderr, "PresentCopy");
+        break;
+    case SDL_RENDERER_PRESENTFLIP2:
+        fprintf(stderr, "PresentFlip2");
+        break;
+    case SDL_RENDERER_PRESENTFLIP3:
+        fprintf(stderr, "PresentFlip3");
+        break;
+    case SDL_RENDERER_PRESENTDISCARD:
+        fprintf(stderr, "PresentDiscard");
+        break;
+    case SDL_RENDERER_PRESENTVSYNC:
+        fprintf(stderr, "PresentVSync");
+        break;
+    case SDL_RENDERER_ACCELERATED:
+        fprintf(stderr, "Accelerated");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", flag);
+        break;
+    }
+}
+
+static void
+PrintBlendMode(Uint32 flag)
+{
+    switch (flag) {
+    case SDL_TEXTUREBLENDMODE_NONE:
+        fprintf(stderr, "None");
+        break;
+    case SDL_TEXTUREBLENDMODE_MASK:
+        fprintf(stderr, "Mask");
+        break;
+    case SDL_TEXTUREBLENDMODE_BLEND:
+        fprintf(stderr, "Blend");
+        break;
+    case SDL_TEXTUREBLENDMODE_ADD:
+        fprintf(stderr, "Add");
+        break;
+    case SDL_TEXTUREBLENDMODE_MOD:
+        fprintf(stderr, "Mod");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", flag);
+        break;
+    }
+}
+
+static void
+PrintScaleMode(Uint32 flag)
+{
+    switch (flag) {
+    case SDL_TEXTURESCALEMODE_NONE:
+        fprintf(stderr, "None");
+        break;
+    case SDL_TEXTURESCALEMODE_FAST:
+        fprintf(stderr, "Fast");
+        break;
+    case SDL_TEXTURESCALEMODE_SLOW:
+        fprintf(stderr, "Slow");
+        break;
+    case SDL_TEXTURESCALEMODE_BEST:
+        fprintf(stderr, "Best");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", flag);
+        break;
+    }
+}
+
+static void
+PrintPixelFormat(Uint32 format)
+{
+    switch (format) {
+    case SDL_PIXELFORMAT_UNKNOWN:
+        fprintf(stderr, "Unknwon");
+        break;
+    case SDL_PIXELFORMAT_INDEX1LSB:
+        fprintf(stderr, "Index1LSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX1MSB:
+        fprintf(stderr, "Index1MSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX4LSB:
+        fprintf(stderr, "Index4LSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX4MSB:
+        fprintf(stderr, "Index4MSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX8:
+        fprintf(stderr, "Index8");
+        break;
+    case SDL_PIXELFORMAT_RGB332:
+        fprintf(stderr, "RGB332");
+        break;
+    case SDL_PIXELFORMAT_RGB444:
+        fprintf(stderr, "RGB444");
+        break;
+    case SDL_PIXELFORMAT_RGB555:
+        fprintf(stderr, "RGB555");
+        break;
+    case SDL_PIXELFORMAT_ARGB4444:
+        fprintf(stderr, "ARGB4444");
+        break;
+    case SDL_PIXELFORMAT_ARGB1555:
+        fprintf(stderr, "ARGB1555");
+        break;
+    case SDL_PIXELFORMAT_RGB565:
+        fprintf(stderr, "RGB565");
+        break;
+    case SDL_PIXELFORMAT_RGB24:
+        fprintf(stderr, "RGB24");
+        break;
+    case SDL_PIXELFORMAT_BGR24:
+        fprintf(stderr, "BGR24");
+        break;
+    case SDL_PIXELFORMAT_RGB888:
+        fprintf(stderr, "RGB888");
+        break;
+    case SDL_PIXELFORMAT_BGR888:
+        fprintf(stderr, "BGR888");
+        break;
+    case SDL_PIXELFORMAT_ARGB8888:
+        fprintf(stderr, "ARGB8888");
+        break;
+    case SDL_PIXELFORMAT_RGBA8888:
+        fprintf(stderr, "RGBA8888");
+        break;
+    case SDL_PIXELFORMAT_ABGR8888:
+        fprintf(stderr, "ABGR8888");
+        break;
+    case SDL_PIXELFORMAT_BGRA8888:
+        fprintf(stderr, "BGRA8888");
+        break;
+    case SDL_PIXELFORMAT_ARGB2101010:
+        fprintf(stderr, "ARGB2101010");
+        break;
+    case SDL_PIXELFORMAT_YV12:
+        fprintf(stderr, "YV12");
+        break;
+    case SDL_PIXELFORMAT_IYUV:
+        fprintf(stderr, "IYUV");
+        break;
+    case SDL_PIXELFORMAT_YUY2:
+        fprintf(stderr, "YUY2");
+        break;
+    case SDL_PIXELFORMAT_UYVY:
+        fprintf(stderr, "UYVY");
+        break;
+    case SDL_PIXELFORMAT_YVYU:
+        fprintf(stderr, "YVYU");
+        break;
+    case SDL_PIXELFORMAT_ABGR1555:
+        fprintf(stderr, "ABGR1555");
+        break;
+    case SDL_PIXELFORMAT_BGR555:
+        fprintf(stderr, "BGR555");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", format);
+        break;
+    }
+}
+
+static void
+PrintRenderer(SDL_RendererInfo * info)
+{
+    int i, count;
+
+    fprintf(stderr, "  Renderer %s:\n", info->name);
+
+    fprintf(stderr, "    Flags: 0x%8.8X", info->flags);
+    fprintf(stderr, " (");
+    count = 0;
+    for (i = 0; i < sizeof(info->flags) * 8; ++i) {
+        Uint32 flag = (1 << i);
+        if (info->flags & flag) {
+            if (count > 0) {
+                fprintf(stderr, " | ");
+            }
+            PrintRendererFlag(flag);
+            ++count;
+        }
+    }
+    fprintf(stderr, ")\n");
+
+    fprintf(stderr, "    Blend: 0x%8.8X", info->blend_modes);
+    fprintf(stderr, " (");
+    count = 0;
+    for (i = 0; i < sizeof(info->blend_modes) * 8; ++i) {
+        Uint32 flag = (1 << i);
+        if (info->blend_modes & flag) {
+            if (count > 0) {
+                fprintf(stderr, " | ");
+            }
+            PrintBlendMode(flag);
+            ++count;
+        }
+    }
+    fprintf(stderr, ")\n");
+
+    fprintf(stderr, "    Scale: 0x%8.8X", info->scale_modes);
+    fprintf(stderr, " (");
+    count = 0;
+    for (i = 0; i < sizeof(info->scale_modes) * 8; ++i) {
+        Uint32 flag = (1 << i);
+        if (info->scale_modes & flag) {
+            if (count > 0) {
+                fprintf(stderr, " | ");
+            }
+            PrintScaleMode(flag);
+            ++count;
+        }
+    }
+    fprintf(stderr, ")\n");
+
+    fprintf(stderr, "    Texture formats (%d): ", info->num_texture_formats);
+    for (i = 0; i < (int) info->num_texture_formats; ++i) {
+        if (i > 0) {
+            fprintf(stderr, ", ");
+        }
+        PrintPixelFormat(info->texture_formats[i]);
+    }
+    fprintf(stderr, "\n");
+
+    if (info->max_texture_width || info->max_texture_height) {
+        fprintf(stderr, "    Max Texture Size: %dx%d\n",
+                info->max_texture_width, info->max_texture_height);
+    }
+}
+
+SDL_bool
+CommonInit(CommonState * state)
+{
+    int i, j, m, n;
+    SDL_DisplayMode fullscreen_mode;
+
+    if (state->flags & SDL_INIT_VIDEO) {
+        if (state->verbose & VERBOSE_VIDEO) {
+            n = SDL_GetNumVideoDrivers();
+            if (n == 0) {
+                fprintf(stderr, "No built-in video drivers\n");
+            } else {
+                fprintf(stderr, "Built-in video drivers:");
+                for (i = 0; i < n; ++i) {
+                    if (i > 0) {
+                        fprintf(stderr, ",");
+                    }
+                    fprintf(stderr, " %s", SDL_GetVideoDriver(i));
+                }
+                fprintf(stderr, "\n");
+            }
+        }
+        if (SDL_VideoInit(state->videodriver, 0) < 0) {
+            fprintf(stderr, "Couldn't initialize video driver: %s\n",
+                    SDL_GetError());
+            return SDL_FALSE;
+        }
+        if (state->verbose & VERBOSE_VIDEO) {
+            fprintf(stderr, "Video driver: %s\n",
+                    SDL_GetCurrentVideoDriver());
+        }
+
+        if (state->verbose & VERBOSE_MODES) {
+            SDL_DisplayMode mode;
+            int bpp;
+            Uint32 Rmask, Gmask, Bmask, Amask;
+
+            n = SDL_GetNumVideoDisplays();
+            fprintf(stderr, "Number of displays: %d\n", n);
+            for (i = 0; i < n; ++i) {
+                fprintf(stderr, "Display %d:\n", i);
+                SDL_SelectVideoDisplay(i);
+
+                SDL_GetDesktopDisplayMode(&mode);
+                SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask, &Gmask,
+                                           &Bmask, &Amask);
+                fprintf(stderr,
+                        "  Current mode: %dx%d@%dHz, %d bits-per-pixel\n",
+                        mode.w, mode.h, mode.refresh_rate, bpp);
+                if (Rmask || Gmask || Bmask) {
+                    fprintf(stderr, "      Red Mask = 0x%.8x\n", Rmask);
+                    fprintf(stderr, "      Green Mask = 0x%.8x\n", Gmask);
+                    fprintf(stderr, "      Blue Mask = 0x%.8x\n", Bmask);
+                    if (Amask)
+                        fprintf(stderr, "      Alpha Mask = 0x%.8x\n", Amask);
+                }
+
+                /* Print available fullscreen video modes */
+                m = SDL_GetNumDisplayModes();
+                if (m == 0) {
+                    fprintf(stderr, "No available fullscreen video modes\n");
+                } else {
+                    fprintf(stderr, "  Fullscreen video modes:\n");
+                    for (j = 0; j < m; ++j) {
+                        SDL_GetDisplayMode(j, &mode);
+                        SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask,
+                                                   &Gmask, &Bmask, &Amask);
+                        fprintf(stderr,
+                                "    Mode %d: %dx%d@%dHz, %d bits-per-pixel\n",
+                                j, mode.w, mode.h, mode.refresh_rate, bpp);
+                        if (Rmask || Gmask || Bmask) {
+                            fprintf(stderr, "        Red Mask = 0x%.8x\n",
+                                    Rmask);
+                            fprintf(stderr, "        Green Mask = 0x%.8x\n",
+                                    Gmask);
+                            fprintf(stderr, "        Blue Mask = 0x%.8x\n",
+                                    Bmask);
+                            if (Amask)
+                                fprintf(stderr,
+                                        "        Alpha Mask = 0x%.8x\n",
+                                        Amask);
+                        }
+                    }
+                }
+            }
+        }
+
+        SDL_SelectVideoDisplay(state->display);
+        if (state->verbose & VERBOSE_RENDER) {
+            SDL_RendererInfo info;
+
+            n = SDL_GetNumRenderDrivers();
+            if (n == 0) {
+                fprintf(stderr, "No built-in render drivers\n");
+            } else {
+                fprintf(stderr, "Built-in render drivers:\n");
+                for (i = 0; i < n; ++i) {
+                    SDL_GetRenderDriverInfo(i, &info);
+                    PrintRenderer(&info);
+                }
+            }
+        }
+
+        switch (state->depth) {
+        case 8:
+            fullscreen_mode.format = SDL_PIXELFORMAT_INDEX8;
+            break;
+        case 15:
+            fullscreen_mode.format = SDL_PIXELFORMAT_BGR555;
+            break;
+        case 16:
+        default:
+            fullscreen_mode.format = SDL_PIXELFORMAT_ABGR1555;
+            break;
+/* NDS       default:
+            fullscreen_mode.format = SDL_PIXELFORMAT_RGB888;
+            break;*/
+        }
+        fullscreen_mode.w = state->window_w;
+        fullscreen_mode.h = state->window_h;
+        fullscreen_mode.refresh_rate = state->refresh_rate;
+        SDL_SetFullscreenDisplayMode(&fullscreen_mode);
+
+        state->windows =
+            (SDL_WindowID *) SDL_malloc(state->num_windows *
+                                        sizeof(*state->windows));
+        if (!state->windows) {
+            fprintf(stderr, "Out of memory!\n");
+            return SDL_FALSE;
+        }
+        for (i = 0; i < state->num_windows; ++i) {
+            char title[1024];
+
+            if (state->num_windows > 1) {
+                SDL_snprintf(title, SDL_arraysize(title), "%s %d",
+                             state->window_title, i + 1);
+            } else {
+                SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
+            }
+            state->windows[i] =
+                SDL_CreateWindow(title, state->window_x, state->window_y,
+                                 state->window_w, state->window_h,
+                                 state->window_flags);
+            if (!state->windows[i]) {
+                fprintf(stderr, "Couldn't create window: %s\n",
+                        SDL_GetError());
+                return SDL_FALSE;
+            }
+
+            if (!state->skip_renderer
+                && (state->renderdriver
+                    || !(state->window_flags & SDL_WINDOW_OPENGL))) {
+                m = -1;
+                if (state->renderdriver) {
+                    SDL_RendererInfo info;
+                    n = SDL_GetNumRenderDrivers();
+                    for (j = 0; j < n; ++j) {
+                        SDL_GetRenderDriverInfo(j, &info);
+                        if (SDL_strcasecmp(info.name, state->renderdriver) ==
+                            0) {
+                            m = j;
+                            break;
+                        }
+                    }
+                    if (m == n) {
+                        fprintf(stderr,
+                                "Couldn't find render driver named %s",
+                                state->renderdriver);
+                        return SDL_FALSE;
+                    }
+                }
+                if (SDL_CreateRenderer
+                    (state->windows[i], m, state->render_flags) < 0) {
+                    fprintf(stderr, "Couldn't create renderer: %s\n",
+                            SDL_GetError());
+                    return SDL_FALSE;
+                }
+                if (state->verbose & VERBOSE_RENDER) {
+                    SDL_RendererInfo info;
+
+                    fprintf(stderr, "Current renderer:\n");
+                    SDL_GetRendererInfo(&info);
+                    PrintRenderer(&info);
+                }
+            }
+        }
+        SDL_SelectRenderer(state->windows[0]);
+    }
+
+    if (state->flags & SDL_INIT_AUDIO) {
+        if (state->verbose & VERBOSE_AUDIO) {
+            n = SDL_GetNumAudioDrivers();
+            if (n == 0) {
+                fprintf(stderr, "No built-in audio drivers\n");
+            } else {
+                fprintf(stderr, "Built-in audio drivers:");
+                for (i = 0; i < n; ++i) {
+                    if (i > 0) {
+                        fprintf(stderr, ",");
+                    }
+                    fprintf(stderr, " %s", SDL_GetAudioDriver(i));
+                }
+                fprintf(stderr, "\n");
+            }
+        }
+        if (SDL_AudioInit(state->audiodriver) < 0) {
+            fprintf(stderr, "Couldn't initialize audio driver: %s\n",
+                    SDL_GetError());
+            return SDL_FALSE;
+        }
+        if (state->verbose & VERBOSE_VIDEO) {
+            fprintf(stderr, "Audio driver: %s\n",
+                    SDL_GetCurrentAudioDriver());
+        }
+
+        if (SDL_OpenAudio(&state->audiospec, NULL) < 0) {
+            fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
+            return SDL_FALSE;
+        }
+    }
+
+    return SDL_TRUE;
+}
+
+static void
+PrintEvent(SDL_Event * event)
+{
+    fprintf(stderr, "SDL EVENT: ");
+    switch (event->type) {
+    case SDL_WINDOWEVENT:
+        switch (event->window.event) {
+        case SDL_WINDOWEVENT_SHOWN:
+            fprintf(stderr, "Window %d shown", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_HIDDEN:
+            fprintf(stderr, "Window %d hidden", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_EXPOSED:
+            fprintf(stderr, "Window %d exposed", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_MOVED:
+            fprintf(stderr, "Window %d moved to %d,%d",
+                    event->window.windowID, event->window.data1,
+                    event->window.data2);
+            break;
+        case SDL_WINDOWEVENT_RESIZED:
+            fprintf(stderr, "Window %d resized to %dx%d",
+                    event->window.windowID, event->window.data1,
+                    event->window.data2);
+            break;
+        case SDL_WINDOWEVENT_MINIMIZED:
+            fprintf(stderr, "Window %d minimized", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_MAXIMIZED:
+            fprintf(stderr, "Window %d maximized", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_RESTORED:
+            fprintf(stderr, "Window %d restored", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_ENTER:
+            fprintf(stderr, "Mouse entered window %d",
+                    event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_LEAVE:
+            fprintf(stderr, "Mouse left window %d", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_FOCUS_GAINED:
+            fprintf(stderr, "Window %d gained keyboard focus",
+                    event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_FOCUS_LOST:
+            fprintf(stderr, "Window %d lost keyboard focus",
+                    event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_CLOSE:
+            fprintf(stderr, "Window %d closed", event->window.windowID);
+            break;
+        default:
+            fprintf(stderr, "Window %d got unknown event %d",
+                    event->window.windowID, event->window.event);
+            break;
+        }
+        break;
+    case SDL_KEYDOWN:
+        fprintf(stderr,
+                "Keyboard %d: key pressed  in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
+                event->key.which, event->key.windowID,
+                event->key.keysym.scancode,
+                SDL_GetScancodeName(event->key.keysym.scancode),
+                event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
+        break;
+    case SDL_KEYUP:
+        fprintf(stderr,
+                "Keyboard %d: key released in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
+                event->key.which, event->key.windowID,
+                event->key.keysym.scancode,
+                SDL_GetScancodeName(event->key.keysym.scancode),
+                event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
+        break;
+    case SDL_TEXTINPUT:
+        fprintf(stderr, "Keyboard %d: text input \"%s\" in window %d",
+                event->text.which, event->text.text, event->text.windowID);
+        break;
+    case SDL_MOUSEMOTION:
+        fprintf(stderr, "Mouse %d: moved to %d,%d (%d,%d) in window %d",
+                event->motion.which, event->motion.x, event->motion.y,
+                event->motion.xrel, event->motion.yrel,
+                event->motion.windowID);
+        break;
+    case SDL_MOUSEBUTTONDOWN:
+        fprintf(stderr, "Mouse %d: button %d pressed at %d,%d in window %d",
+                event->button.which, event->button.button, event->button.x,
+                event->button.y, event->button.windowID);
+        break;
+    case SDL_MOUSEBUTTONUP:
+        fprintf(stderr, "Mouse %d: button %d released at %d,%d in window %d",
+                event->button.which, event->button.button, event->button.x,
+                event->button.y, event->button.windowID);
+        break;
+    case SDL_MOUSEWHEEL:
+        fprintf(stderr,
+                "Mouse %d: wheel scrolled %d in x and %d in y in window %d",
+                event->wheel.which, event->wheel.x, event->wheel.y,
+                event->wheel.windowID);
+        break;
+    case SDL_JOYBALLMOTION:
+        fprintf(stderr, "Joystick %d: ball %d moved by %d,%d",
+                event->jball.which, event->jball.ball, event->jball.xrel,
+                event->jball.yrel);
+        break;
+    case SDL_JOYHATMOTION:
+        fprintf(stderr, "Joystick %d: hat %d moved to ", event->jhat.which,
+                event->jhat.hat);
+        switch (event->jhat.value) {
+        case SDL_HAT_CENTERED:
+            fprintf(stderr, "CENTER");
+            break;
+        case SDL_HAT_UP:
+            fprintf(stderr, "UP");
+            break;
+        case SDL_HAT_RIGHTUP:
+            fprintf(stderr, "RIGHTUP");
+            break;
+        case SDL_HAT_RIGHT:
+            fprintf(stderr, "RIGHT");
+            break;
+        case SDL_HAT_RIGHTDOWN:
+            fprintf(stderr, "RIGHTDOWN");
+            break;
+        case SDL_HAT_DOWN:
+            fprintf(stderr, "DOWN");
+            break;
+        case SDL_HAT_LEFTDOWN:
+            fprintf(stderr, "LEFTDOWN");
+            break;
+        case SDL_HAT_LEFT:
+            fprintf(stderr, "LEFT");
+            break;
+        case SDL_HAT_LEFTUP:
+            fprintf(stderr, "LEFTUP");
+            break;
+        default:
+            fprintf(stderr, "UNKNOWN");
+            break;
+        }
+        break;
+    case SDL_JOYBUTTONDOWN:
+        fprintf(stderr, "Joystick %d: button %d pressed",
+                event->jbutton.which, event->jbutton.button);
+        break;
+    case SDL_JOYBUTTONUP:
+        fprintf(stderr, "Joystick %d: button %d released",
+                event->jbutton.which, event->jbutton.button);
+        break;
+    case SDL_QUIT:
+        fprintf(stderr, "Quit requested");
+        break;
+    case SDL_USEREVENT:
+        fprintf(stderr, "User event %d", event->user.code);
+        break;
+    default:
+        fprintf(stderr, "Unknown event %d", event->type);
+        break;
+    }
+    fprintf(stderr, "\n");
+}
+
+void
+CommonEvent(CommonState * state, SDL_Event * event, int *done)
+{
+    if (state->verbose & VERBOSE_EVENT) {
+        PrintEvent(event);
+    }
+
+    switch (event->type) {
+    case SDL_WINDOWEVENT:
+        switch (event->window.event) {
+        case SDL_WINDOWEVENT_CLOSE:
+            *done = 1;
+            break;
+        }
+        break;
+    case SDL_KEYDOWN:
+        switch (event->key.keysym.sym) {
+            /* Add hotkeys here */
+        case SDLK_g:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-G toggle grab */
+            }
+            break;
+        case SDLK_ESCAPE:
+            *done = 1;
+            break;
+        default:
+            break;
+        }
+        break;
+    case SDL_QUIT:
+        *done = 1;
+        break;
+    }
+}
+
+void
+CommonQuit(CommonState * state)
+{
+    if (state->flags & SDL_INIT_VIDEO) {
+        SDL_VideoQuit();
+    }
+    if (state->flags & SDL_INIT_AUDIO) {
+        SDL_AudioQuit();
+    }
+    if (state->windows) {
+        SDL_free(state->windows);
+    }
+    SDL_free(state);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/sprite/source/common.h	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,48 @@
+
+/* A simple test program framework */
+
+#include <SDL/SDL.h>
+
+#define VERBOSE_VIDEO   0x00000001
+#define VERBOSE_MODES   0x00000002
+#define VERBOSE_RENDER  0x00000004
+#define VERBOSE_EVENT   0x00000008
+#define VERBOSE_AUDIO   0x00000010
+
+typedef struct
+{
+    /* SDL init flags */
+    char **argv;
+    Uint32 flags;
+    Uint32 verbose;
+
+    /* Video info */
+    const char *videodriver;
+    int display;
+    const char *window_title;
+    Uint32 window_flags;
+    int window_x;
+    int window_y;
+    int window_w;
+    int window_h;
+    int depth;
+    int refresh_rate;
+    int num_windows;
+    SDL_WindowID *windows;
+
+    /* Renderer info */
+    const char *renderdriver;
+    Uint32 render_flags;
+    SDL_bool skip_renderer;
+
+    /* Audio info */
+    const char *audiodriver;
+    SDL_AudioSpec audiospec;
+} CommonState;
+
+extern CommonState *CommonCreateState(char **argv, Uint32 flags);
+extern int CommonArg(CommonState * state, int index);
+extern const char *CommonUsage(CommonState * state);
+extern SDL_bool CommonInit(CommonState * state);
+extern void CommonEvent(CommonState * state, SDL_Event * event, int *done);
+extern void CommonQuit(CommonState * state);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/sprite/source/testsprite.c	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,319 @@
+/* Simple program:  Move N sprites around on the screen as fast as possible */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <math.h>
+
+#include "SDL.h"
+
+#define NUM_SPRITES	100
+#define MAX_SPEED 	1
+
+SDL_Surface *sprite;
+int numsprites;
+SDL_Rect *sprite_rects;
+SDL_Rect *positions;
+SDL_Rect *velocities;
+int sprites_visible;
+int debug_flip;
+Uint16 sprite_w, sprite_h;
+
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void
+quit(int rc)
+{
+    SDL_Quit();
+    exit(rc);
+}
+
+int
+LoadSprite(char *file)
+{
+    SDL_Surface *temp;
+
+    /* Load the sprite image */
+    sprite = SDL_LoadBMP(file);
+    if (sprite == NULL) {
+        fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
+        return (-1);
+    }
+
+    /* Set transparent pixel as the pixel at (0,0) */
+    if (sprite->format->palette) {
+        SDL_SetColorKey(sprite, (SDL_SRCCOLORKEY | SDL_RLEACCEL),
+                        *(Uint8 *) sprite->pixels);
+    }
+
+    /* Convert sprite to video format */
+    temp = SDL_DisplayFormat(sprite);
+    SDL_FreeSurface(sprite);
+    if (temp == NULL) {
+        fprintf(stderr, "Couldn't convert background: %s\n", SDL_GetError());
+        return (-1);
+    }
+    sprite = temp;
+
+    /* We're ready to roll. :) */
+    return (0);
+}
+
+void
+MoveSprites(SDL_Surface * screen, Uint32 background)
+{
+    int i, nupdates;
+    SDL_Rect area, *position, *velocity;
+
+    nupdates = 0;
+    /* Erase all the sprites if necessary */
+    if (sprites_visible) {
+        SDL_FillRect(screen, NULL, background);
+    }
+
+    /* Move the sprite, bounce at the wall, and draw */
+    for (i = 0; i < numsprites; ++i) {
+        position = &positions[i];
+        velocity = &velocities[i];
+        position->x += velocity->x;
+        if ((position->x < 0) || (position->x >= (screen->w - sprite_w))) {
+            velocity->x = -velocity->x;
+            position->x += velocity->x;
+        }
+        position->y += velocity->y;
+        if ((position->y < 0) || (position->y >= (screen->h - sprite_w))) {
+            velocity->y = -velocity->y;
+            position->y += velocity->y;
+        }
+
+        /* Blit the sprite onto the screen */
+        area = *position;
+        SDL_BlitSurface(sprite, NULL, screen, &area);
+        sprite_rects[nupdates++] = area;
+    }
+
+    if (debug_flip) {
+        if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
+            static int t = 0;
+
+            Uint32 color = SDL_MapRGB(screen->format, 255, 0, 0);
+            SDL_Rect r;
+            r.x =
+                (sin((float) t * 2 * 3.1459) + 1.0) / 2.0 * (screen->w - 20);
+            r.y = 0;
+            r.w = 20;
+            r.h = screen->h;
+
+            SDL_FillRect(screen, &r, color);
+            t += 2;
+        }
+    }
+
+    /* Update the screen! */
+    if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
+        SDL_Flip(screen);
+    } else {
+        SDL_UpdateRects(screen, nupdates, sprite_rects);
+    }
+    sprites_visible = 1;
+}
+
+/* This is a way of telling whether or not to use hardware surfaces */
+Uint32
+FastestFlags(Uint32 flags, int width, int height, int bpp)
+{
+    const SDL_VideoInfo *info;
+
+    /* Hardware acceleration is only used in fullscreen mode */
+    flags |= SDL_FULLSCREEN;
+
+    /* Check for various video capabilities */
+    info = SDL_GetVideoInfo();
+    if (info->blit_hw_CC && info->blit_fill) {
+        /* We use accelerated colorkeying and color filling */
+        flags |= SDL_HWSURFACE;
+    }
+    /* If we have enough video memory, and will use accelerated
+       blits directly to it, then use page flipping.
+     */
+    if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
+        /* Direct hardware blitting without double-buffering
+           causes really bad flickering.
+         */
+        if (info->video_mem * 1024 > (height * width * bpp / 8)) {
+            flags |= SDL_DOUBLEBUF;
+        } else {
+            flags &= ~SDL_HWSURFACE;
+        }
+    }
+
+    /* Return the flags */
+    return (flags);
+}
+
+int
+main(int argc, char *argv[])
+{
+    SDL_Surface *screen;
+    Uint8 *mem;
+    int width, height;
+    Uint8 video_bpp;
+    Uint32 videoflags;
+    Uint32 background;
+    int i, done;
+    SDL_Event event;
+    Uint32 then, now, frames;
+
+    /* Initialize SDL */
+    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
+        return (1);
+    }
+
+    numsprites = NUM_SPRITES;
+    videoflags = SDL_SWSURFACE | SDL_ANYFORMAT;
+    width = 640;
+    height = 480;
+    video_bpp = 8;
+    debug_flip = 0;
+    while (argc > 1) {
+        --argc;
+        if (strcmp(argv[argc - 1], "-width") == 0) {
+            width = atoi(argv[argc]);
+            --argc;
+        } else if (strcmp(argv[argc - 1], "-height") == 0) {
+            height = atoi(argv[argc]);
+            --argc;
+        } else if (strcmp(argv[argc - 1], "-bpp") == 0) {
+            video_bpp = atoi(argv[argc]);
+            videoflags &= ~SDL_ANYFORMAT;
+            --argc;
+        } else if (strcmp(argv[argc], "-fast") == 0) {
+            videoflags = FastestFlags(videoflags, width, height, video_bpp);
+        } else if (strcmp(argv[argc], "-hw") == 0) {
+            videoflags ^= SDL_HWSURFACE;
+        } else if (strcmp(argv[argc], "-flip") == 0) {
+            videoflags ^= SDL_DOUBLEBUF;
+        } else if (strcmp(argv[argc], "-debugflip") == 0) {
+            debug_flip ^= 1;
+        } else if (strcmp(argv[argc], "-fullscreen") == 0) {
+            videoflags ^= SDL_FULLSCREEN;
+        } else if (isdigit(argv[argc][0])) {
+            numsprites = atoi(argv[argc]);
+        } else {
+            fprintf(stderr,
+                    "Usage: %s [-bpp N] [-hw] [-flip] [-fast] [-fullscreen] [numsprites]\n",
+                    argv[0]);
+            quit(1);
+        }
+    }
+
+    /* Set video mode */
+    screen = SDL_SetVideoMode(width, height, video_bpp, videoflags);
+    if (!screen) {
+        fprintf(stderr, "Couldn't set %dx%d video mode: %s\n",
+                width, height, SDL_GetError());
+        quit(2);
+    }
+
+    /* Load the sprite */
+    if (LoadSprite("icon.bmp") < 0) {
+        quit(1);
+    }
+
+    /* Allocate memory for the sprite info */
+    mem = (Uint8 *) malloc(4 * sizeof(SDL_Rect) * numsprites);
+    if (mem == NULL) {
+        SDL_FreeSurface(sprite);
+        fprintf(stderr, "Out of memory!\n");
+        quit(2);
+    }
+    sprite_rects = (SDL_Rect *) mem;
+    positions = sprite_rects;
+    sprite_rects += numsprites;
+    velocities = sprite_rects;
+    sprite_rects += numsprites;
+    sprite_w = sprite->w;
+    sprite_h = sprite->h;
+    srand(time(NULL));
+    for (i = 0; i < numsprites; ++i) {
+        positions[i].x = rand() % (screen->w - sprite_w);
+        positions[i].y = rand() % (screen->h - sprite_h);
+        positions[i].w = sprite->w;
+        positions[i].h = sprite->h;
+        velocities[i].x = 0;
+        velocities[i].y = 0;
+        while (!velocities[i].x && !velocities[i].y) {
+            velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
+            velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
+        }
+    }
+    background = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
+
+    /* Print out information about our surfaces */
+    printf("Screen is at %d bits per pixel\n", screen->format->BitsPerPixel);
+    if ((screen->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
+        printf("Screen is in video memory\n");
+    } else {
+        printf("Screen is in system memory\n");
+    }
+    if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
+        printf("Screen has double-buffering enabled\n");
+    }
+    if ((sprite->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
+        printf("Sprite is in video memory\n");
+    } else {
+        printf("Sprite is in system memory\n");
+    }
+    /* Run a sample blit to trigger blit acceleration */
+    {
+        SDL_Rect dst;
+        dst.x = 0;
+        dst.y = 0;
+        dst.w = sprite->w;
+        dst.h = sprite->h;
+        SDL_BlitSurface(sprite, NULL, screen, &dst);
+        SDL_FillRect(screen, &dst, background);
+    }
+    if ((sprite->flags & SDL_HWACCEL) == SDL_HWACCEL) {
+        printf("Sprite blit uses hardware acceleration\n");
+    }
+    if ((sprite->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
+        printf("Sprite blit uses RLE acceleration\n");
+    }
+
+    /* Loop, blitting sprites and waiting for a keystroke */
+    frames = 0;
+    then = SDL_GetTicks();
+    done = 0;
+    sprites_visible = 0;
+    while (!done) {
+        /* Check for events */
+        ++frames;
+        while (SDL_PollEvent(&event)) {
+            switch (event.type) {
+            case SDL_MOUSEBUTTONDOWN:
+                SDL_WarpMouse(screen->w / 2, screen->h / 2);
+                break;
+            case SDL_KEYDOWN:
+                /* Any keypress quits the app... */
+            case SDL_QUIT:
+                done = 1;
+                break;
+            default:
+                break;
+            }
+        }
+        MoveSprites(screen, background);
+    }
+    SDL_FreeSurface(sprite);
+    free(mem);
+
+    /* Print out some timing information */
+    now = SDL_GetTicks();
+    if (now > then) {
+        printf("%2.2f frames per second\n",
+               ((double) frames * 1000) / (now - then));
+    }
+    SDL_Quit();
+    return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/sprite2/Makefile	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,132 @@
+#---------------------------------------------------------------------------------
+.SUFFIXES:
+#---------------------------------------------------------------------------------
+
+ifeq ($(strip $(DEVKITARM)),)
+$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
+endif
+
+include $(DEVKITARM)/ds_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		:=	$(shell basename $(CURDIR))
+BUILD		:=	build
+SOURCES		:=	source
+DATA		:=	data  
+INCLUDES	:=	include
+
+#---------------------------------------------------------------------------------
+# options for code generation
+#---------------------------------------------------------------------------------
+ARCH	:=	-mthumb -mthumb-interwork
+
+# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD
+# *insists* it has a FPU or VFP, and it won't take no for an answer!
+CFLAGS	:=	-save-temps -g -Wall -O0\
+ 			-mcpu=arm9tdmi -mtune=arm9tdmi \
+			$(ARCH)
+
+CFLAGS	+=	$(INCLUDE) -DARM9 -D__NDS__
+CXXFLAGS	:= $(CFLAGS) -fno-rtti -fno-exceptions -fno-exceptions -fno-rtti
+
+ASFLAGS	:=	-g $(ARCH)
+LDFLAGS	=	-specs=ds_arm9.specs -g $(ARCH) -mno-fpu -Wl,-Map,$(notdir $*.map)
+
+#---------------------------------------------------------------------------------
+# any extra libraries we wish to link with the project
+#---------------------------------------------------------------------------------
+LIBS	:= -lSDL -lfat -lnds9
+ 
+ 
+#---------------------------------------------------------------------------------
+# list of directories containing libraries, this must be the top level containing
+# include and lib
+#---------------------------------------------------------------------------------
+LIBDIRS	:=	$(LIBNDS)
+ 
+#---------------------------------------------------------------------------------
+# 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))
+
+export DEPSDIR	:=	$(CURDIR)/$(BUILD)
+
+CFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
+CPPFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
+SFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
+BINFILES	:=	$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
+ 
+#---------------------------------------------------------------------------------
+# 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)) \
+					$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
+ 
+export INCLUDE	:=	$(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+					$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+					$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+					-I$(CURDIR)/$(BUILD)
+ 
+export LIBPATHS	:=	$(foreach dir,$(LIBDIRS),-L$(dir)/lib)
+ 
+.PHONY: $(BUILD) clean
+ 
+#---------------------------------------------------------------------------------
+$(BUILD):
+	@[ -d $@ ] || mkdir -p $@
+	@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
+ 
+#---------------------------------------------------------------------------------
+clean:
+	@echo clean ...
+	@rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).arm9 $(TARGET).ds.gba 
+ 
+ 
+#---------------------------------------------------------------------------------
+else
+ 
+DEPENDS	:=	$(OFILES:.o=.d)
+ 
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+$(OUTPUT).ds.gba	: 	$(OUTPUT).nds
+$(OUTPUT).nds	: 	$(OUTPUT).arm9
+$(OUTPUT).arm9	:	$(OUTPUT).elf
+$(OUTPUT).elf	:	$(OFILES)
+ 
+#---------------------------------------------------------------------------------
+%.pcx.o	:	%.pcx
+#---------------------------------------------------------------------------------
+	@echo $(notdir $<)
+	@$(bin2o)
+ 
+ 
+-include $(DEPENDS)
+ 
+#---------------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/sprite2/source/common.c	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,965 @@
+
+/* A simple test program framework */
+
+#include <stdio.h>
+
+#include "common.h"
+
+#define VIDEO_USAGE \
+"[--video driver] [--renderer driver] [--info all|video|modes|render|event] [--display %d] [--fullscreen | --windows N] [--title title] [--center | --position X,Y] [--geometry WxH] [--depth N] [--refresh R] [--vsync] [--noframe] [--resize] [--minimize] [--maximize] [--grab]"
+
+#define AUDIO_USAGE \
+"[--rate N] [--format U8|S8|U16|U16LE|U16BE|S16|S16LE|S16BE] [--channels N] [--samples N]"
+
+CommonState *
+CommonCreateState(char **argv, Uint32 flags)
+{
+    CommonState *state = SDL_calloc(1, sizeof(*state));
+    if (!state) {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+
+    /* Initialize some defaults */
+    state->argv = argv;
+    state->flags = flags;
+    state->window_title = argv[0];
+    state->window_flags = SDL_WINDOW_SHOWN;
+    state->window_x = SDL_WINDOWPOS_UNDEFINED;
+    state->window_y = SDL_WINDOWPOS_UNDEFINED;
+    state->window_w = 256;
+    state->window_h = 192;
+    state->num_windows = 1;
+    state->audiospec.freq = 22050;
+    state->audiospec.format = AUDIO_S16;
+    state->audiospec.channels = 2;
+    state->audiospec.samples = 2048;
+    return state;
+}
+
+int
+CommonArg(CommonState * state, int index)
+{
+    char **argv = state->argv;
+
+    if (SDL_strcasecmp(argv[index], "--video") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->videodriver = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->renderdriver = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--info") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        if (SDL_strcasecmp(argv[index], "all") == 0) {
+            state->verbose |=
+                (VERBOSE_VIDEO | VERBOSE_MODES | VERBOSE_RENDER |
+                 VERBOSE_EVENT);
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "video") == 0) {
+            state->verbose |= VERBOSE_VIDEO;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "modes") == 0) {
+            state->verbose |= VERBOSE_MODES;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "render") == 0) {
+            state->verbose |= VERBOSE_RENDER;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "event") == 0) {
+            state->verbose |= VERBOSE_EVENT;
+            return 2;
+        }
+        return -1;
+    }
+    if (SDL_strcasecmp(argv[index], "--display") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->display = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--fullscreen") == 0) {
+        state->window_flags |= SDL_WINDOW_FULLSCREEN;
+        state->num_windows = 1;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--windows") == 0) {
+        ++index;
+        if (!argv[index] || !SDL_isdigit(*argv[index])) {
+            return -1;
+        }
+        if (!(state->window_flags & SDL_WINDOW_FULLSCREEN)) {
+            state->num_windows = SDL_atoi(argv[index]);
+        }
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--title") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->window_title = argv[index];
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--center") == 0) {
+        state->window_x = SDL_WINDOWPOS_CENTERED;
+        state->window_y = SDL_WINDOWPOS_CENTERED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--position") == 0) {
+        char *x, *y;
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        x = argv[index];
+        y = argv[index];
+        while (*y && *y != ',') {
+            ++y;
+        }
+        if (!*y) {
+            return -1;
+        }
+        *y++ = '\0';
+        state->window_x = SDL_atoi(x);
+        state->window_y = SDL_atoi(y);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--geometry") == 0) {
+        char *w, *h;
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        w = argv[index];
+        h = argv[index];
+        while (*h && *h != 'x') {
+            ++h;
+        }
+        if (!*h) {
+            return -1;
+        }
+        *h++ = '\0';
+        state->window_w = SDL_atoi(w);
+        state->window_h = SDL_atoi(h);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--depth") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->depth = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--refresh") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->refresh_rate = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--vsync") == 0) {
+        state->render_flags |= SDL_RENDERER_PRESENTVSYNC;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--noframe") == 0) {
+        state->window_flags |= SDL_WINDOW_BORDERLESS;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--resize") == 0) {
+        state->window_flags |= SDL_WINDOW_RESIZABLE;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
+        state->window_flags |= SDL_WINDOW_MINIMIZED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--maximize") == 0) {
+        state->window_flags |= SDL_WINDOW_MAXIMIZED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--grab") == 0) {
+        state->window_flags |= SDL_WINDOW_INPUT_GRABBED;
+        return 1;
+    }
+    if (SDL_strcasecmp(argv[index], "--rate") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->audiospec.freq = SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--format") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        if (SDL_strcasecmp(argv[index], "U8") == 0) {
+            state->audiospec.format = AUDIO_U8;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S8") == 0) {
+            state->audiospec.format = AUDIO_S8;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "U16") == 0) {
+            state->audiospec.format = AUDIO_U16;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "U16LE") == 0) {
+            state->audiospec.format = AUDIO_U16LSB;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "U16BE") == 0) {
+            state->audiospec.format = AUDIO_U16MSB;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S16") == 0) {
+            state->audiospec.format = AUDIO_S16;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S16LE") == 0) {
+            state->audiospec.format = AUDIO_S16LSB;
+            return 2;
+        }
+        if (SDL_strcasecmp(argv[index], "S16BE") == 0) {
+            state->audiospec.format = AUDIO_S16MSB;
+            return 2;
+        }
+        return -1;
+    }
+    if (SDL_strcasecmp(argv[index], "--channels") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->audiospec.channels = (Uint8) SDL_atoi(argv[index]);
+        return 2;
+    }
+    if (SDL_strcasecmp(argv[index], "--samples") == 0) {
+        ++index;
+        if (!argv[index]) {
+            return -1;
+        }
+        state->audiospec.samples = (Uint16) SDL_atoi(argv[index]);
+        return 2;
+    }
+    if ((SDL_strcasecmp(argv[index], "-h") == 0)
+        || (SDL_strcasecmp(argv[index], "--help") == 0)) {
+        /* Print the usage message */
+        return -1;
+    }
+    return 0;
+}
+
+const char *
+CommonUsage(CommonState * state)
+{
+    switch (state->flags & (SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
+    case SDL_INIT_VIDEO:
+        return VIDEO_USAGE;
+    case SDL_INIT_AUDIO:
+        return AUDIO_USAGE;
+    case (SDL_INIT_VIDEO | SDL_INIT_AUDIO):
+        return VIDEO_USAGE " " AUDIO_USAGE;
+    default:
+        return "";
+    }
+}
+
+static void
+PrintRendererFlag(Uint32 flag)
+{
+    switch (flag) {
+    case SDL_RENDERER_SINGLEBUFFER:
+        fprintf(stderr, "SingleBuffer");
+        break;
+    case SDL_RENDERER_PRESENTCOPY:
+        fprintf(stderr, "PresentCopy");
+        break;
+    case SDL_RENDERER_PRESENTFLIP2:
+        fprintf(stderr, "PresentFlip2");
+        break;
+    case SDL_RENDERER_PRESENTFLIP3:
+        fprintf(stderr, "PresentFlip3");
+        break;
+    case SDL_RENDERER_PRESENTDISCARD:
+        fprintf(stderr, "PresentDiscard");
+        break;
+    case SDL_RENDERER_PRESENTVSYNC:
+        fprintf(stderr, "PresentVSync");
+        break;
+    case SDL_RENDERER_ACCELERATED:
+        fprintf(stderr, "Accelerated");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", flag);
+        break;
+    }
+}
+
+static void
+PrintBlendMode(Uint32 flag)
+{
+    switch (flag) {
+    case SDL_TEXTUREBLENDMODE_NONE:
+        fprintf(stderr, "None");
+        break;
+    case SDL_TEXTUREBLENDMODE_MASK:
+        fprintf(stderr, "Mask");
+        break;
+    case SDL_TEXTUREBLENDMODE_BLEND:
+        fprintf(stderr, "Blend");
+        break;
+    case SDL_TEXTUREBLENDMODE_ADD:
+        fprintf(stderr, "Add");
+        break;
+    case SDL_TEXTUREBLENDMODE_MOD:
+        fprintf(stderr, "Mod");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", flag);
+        break;
+    }
+}
+
+static void
+PrintScaleMode(Uint32 flag)
+{
+    switch (flag) {
+    case SDL_TEXTURESCALEMODE_NONE:
+        fprintf(stderr, "None");
+        break;
+    case SDL_TEXTURESCALEMODE_FAST:
+        fprintf(stderr, "Fast");
+        break;
+    case SDL_TEXTURESCALEMODE_SLOW:
+        fprintf(stderr, "Slow");
+        break;
+    case SDL_TEXTURESCALEMODE_BEST:
+        fprintf(stderr, "Best");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", flag);
+        break;
+    }
+}
+
+static void
+PrintPixelFormat(Uint32 format)
+{
+    switch (format) {
+    case SDL_PIXELFORMAT_UNKNOWN:
+        fprintf(stderr, "Unknwon");
+        break;
+    case SDL_PIXELFORMAT_INDEX1LSB:
+        fprintf(stderr, "Index1LSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX1MSB:
+        fprintf(stderr, "Index1MSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX4LSB:
+        fprintf(stderr, "Index4LSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX4MSB:
+        fprintf(stderr, "Index4MSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX8:
+        fprintf(stderr, "Index8");
+        break;
+    case SDL_PIXELFORMAT_RGB332:
+        fprintf(stderr, "RGB332");
+        break;
+    case SDL_PIXELFORMAT_RGB444:
+        fprintf(stderr, "RGB444");
+        break;
+    case SDL_PIXELFORMAT_RGB555:
+        fprintf(stderr, "RGB555");
+        break;
+    case SDL_PIXELFORMAT_ARGB4444:
+        fprintf(stderr, "ARGB4444");
+        break;
+    case SDL_PIXELFORMAT_ARGB1555:
+        fprintf(stderr, "ARGB1555");
+        break;
+    case SDL_PIXELFORMAT_RGB565:
+        fprintf(stderr, "RGB565");
+        break;
+    case SDL_PIXELFORMAT_RGB24:
+        fprintf(stderr, "RGB24");
+        break;
+    case SDL_PIXELFORMAT_BGR24:
+        fprintf(stderr, "BGR24");
+        break;
+    case SDL_PIXELFORMAT_RGB888:
+        fprintf(stderr, "RGB888");
+        break;
+    case SDL_PIXELFORMAT_BGR888:
+        fprintf(stderr, "BGR888");
+        break;
+    case SDL_PIXELFORMAT_ARGB8888:
+        fprintf(stderr, "ARGB8888");
+        break;
+    case SDL_PIXELFORMAT_RGBA8888:
+        fprintf(stderr, "RGBA8888");
+        break;
+    case SDL_PIXELFORMAT_ABGR8888:
+        fprintf(stderr, "ABGR8888");
+        break;
+    case SDL_PIXELFORMAT_BGRA8888:
+        fprintf(stderr, "BGRA8888");
+        break;
+    case SDL_PIXELFORMAT_ARGB2101010:
+        fprintf(stderr, "ARGB2101010");
+        break;
+    case SDL_PIXELFORMAT_YV12:
+        fprintf(stderr, "YV12");
+        break;
+    case SDL_PIXELFORMAT_IYUV:
+        fprintf(stderr, "IYUV");
+        break;
+    case SDL_PIXELFORMAT_YUY2:
+        fprintf(stderr, "YUY2");
+        break;
+    case SDL_PIXELFORMAT_UYVY:
+        fprintf(stderr, "UYVY");
+        break;
+    case SDL_PIXELFORMAT_YVYU:
+        fprintf(stderr, "YVYU");
+        break;
+    case SDL_PIXELFORMAT_ABGR1555:
+        fprintf(stderr, "ABGR1555");
+        break;
+    case SDL_PIXELFORMAT_BGR555:
+        fprintf(stderr, "BGR555");
+        break;
+    default:
+        fprintf(stderr, "0x%8.8x", format);
+        break;
+    }
+}
+
+static void
+PrintRenderer(SDL_RendererInfo * info)
+{
+    int i, count;
+
+    fprintf(stderr, "  Renderer %s:\n", info->name);
+
+    fprintf(stderr, "    Flags: 0x%8.8X", info->flags);
+    fprintf(stderr, " (");
+    count = 0;
+    for (i = 0; i < sizeof(info->flags) * 8; ++i) {
+        Uint32 flag = (1 << i);
+        if (info->flags & flag) {
+            if (count > 0) {
+                fprintf(stderr, " | ");
+            }
+            PrintRendererFlag(flag);
+            ++count;
+        }
+    }
+    fprintf(stderr, ")\n");
+
+    fprintf(stderr, "    Blend: 0x%8.8X", info->blend_modes);
+    fprintf(stderr, " (");
+    count = 0;
+    for (i = 0; i < sizeof(info->blend_modes) * 8; ++i) {
+        Uint32 flag = (1 << i);
+        if (info->blend_modes & flag) {
+            if (count > 0) {
+                fprintf(stderr, " | ");
+            }
+            PrintBlendMode(flag);
+            ++count;
+        }
+    }
+    fprintf(stderr, ")\n");
+
+    fprintf(stderr, "    Scale: 0x%8.8X", info->scale_modes);
+    fprintf(stderr, " (");
+    count = 0;
+    for (i = 0; i < sizeof(info->scale_modes) * 8; ++i) {
+        Uint32 flag = (1 << i);
+        if (info->scale_modes & flag) {
+            if (count > 0) {
+                fprintf(stderr, " | ");
+            }
+            PrintScaleMode(flag);
+            ++count;
+        }
+    }
+    fprintf(stderr, ")\n");
+
+    fprintf(stderr, "    Texture formats (%d): ", info->num_texture_formats);
+    for (i = 0; i < (int) info->num_texture_formats; ++i) {
+        if (i > 0) {
+            fprintf(stderr, ", ");
+        }
+        PrintPixelFormat(info->texture_formats[i]);
+    }
+    fprintf(stderr, "\n");
+
+    if (info->max_texture_width || info->max_texture_height) {
+        fprintf(stderr, "    Max Texture Size: %dx%d\n",
+                info->max_texture_width, info->max_texture_height);
+    }
+}
+
+SDL_bool
+CommonInit(CommonState * state)
+{
+    int i, j, m, n;
+    SDL_DisplayMode fullscreen_mode;
+
+    if (state->flags & SDL_INIT_VIDEO) {
+        if (state->verbose & VERBOSE_VIDEO) {
+            n = SDL_GetNumVideoDrivers();
+            if (n == 0) {
+                fprintf(stderr, "No built-in video drivers\n");
+            } else {
+                fprintf(stderr, "Built-in video drivers:");
+                for (i = 0; i < n; ++i) {
+                    if (i > 0) {
+                        fprintf(stderr, ",");
+                    }
+                    fprintf(stderr, " %s", SDL_GetVideoDriver(i));
+                }
+                fprintf(stderr, "\n");
+            }
+        }
+        if (SDL_VideoInit(state->videodriver, 0) < 0) {
+            fprintf(stderr, "Couldn't initialize video driver: %s\n",
+                    SDL_GetError());
+            return SDL_FALSE;
+        }
+        if (state->verbose & VERBOSE_VIDEO) {
+            fprintf(stderr, "Video driver: %s\n",
+                    SDL_GetCurrentVideoDriver());
+        }
+
+        if (state->verbose & VERBOSE_MODES) {
+            SDL_DisplayMode mode;
+            int bpp;
+            Uint32 Rmask, Gmask, Bmask, Amask;
+
+            n = SDL_GetNumVideoDisplays();
+            fprintf(stderr, "Number of displays: %d\n", n);
+            for (i = 0; i < n; ++i) {
+                fprintf(stderr, "Display %d:\n", i);
+                SDL_SelectVideoDisplay(i);
+
+                SDL_GetDesktopDisplayMode(&mode);
+                SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask, &Gmask,
+                                           &Bmask, &Amask);
+                fprintf(stderr,
+                        "  Current mode: %dx%d@%dHz, %d bits-per-pixel\n",
+                        mode.w, mode.h, mode.refresh_rate, bpp);
+                if (Rmask || Gmask || Bmask) {
+                    fprintf(stderr, "      Red Mask = 0x%.8x\n", Rmask);
+                    fprintf(stderr, "      Green Mask = 0x%.8x\n", Gmask);
+                    fprintf(stderr, "      Blue Mask = 0x%.8x\n", Bmask);
+                    if (Amask)
+                        fprintf(stderr, "      Alpha Mask = 0x%.8x\n", Amask);
+                }
+
+                /* Print available fullscreen video modes */
+                m = SDL_GetNumDisplayModes();
+                if (m == 0) {
+                    fprintf(stderr, "No available fullscreen video modes\n");
+                } else {
+                    fprintf(stderr, "  Fullscreen video modes:\n");
+                    for (j = 0; j < m; ++j) {
+                        SDL_GetDisplayMode(j, &mode);
+                        SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask,
+                                                   &Gmask, &Bmask, &Amask);
+                        fprintf(stderr,
+                                "    Mode %d: %dx%d@%dHz, %d bits-per-pixel\n",
+                                j, mode.w, mode.h, mode.refresh_rate, bpp);
+                        if (Rmask || Gmask || Bmask) {
+                            fprintf(stderr, "        Red Mask = 0x%.8x\n",
+                                    Rmask);
+                            fprintf(stderr, "        Green Mask = 0x%.8x\n",
+                                    Gmask);
+                            fprintf(stderr, "        Blue Mask = 0x%.8x\n",
+                                    Bmask);
+                            if (Amask)
+                                fprintf(stderr,
+                                        "        Alpha Mask = 0x%.8x\n",
+                                        Amask);
+                        }
+                    }
+                }
+            }
+        }
+
+        SDL_SelectVideoDisplay(state->display);
+        if (state->verbose & VERBOSE_RENDER) {
+            SDL_RendererInfo info;
+
+            n = SDL_GetNumRenderDrivers();
+            if (n == 0) {
+                fprintf(stderr, "No built-in render drivers\n");
+            } else {
+                fprintf(stderr, "Built-in render drivers:\n");
+                for (i = 0; i < n; ++i) {
+                    SDL_GetRenderDriverInfo(i, &info);
+                    PrintRenderer(&info);
+                }
+            }
+        }
+
+        switch (state->depth) {
+        case 8:
+            fullscreen_mode.format = SDL_PIXELFORMAT_INDEX8;
+            break;
+        case 15:
+            fullscreen_mode.format = SDL_PIXELFORMAT_BGR555;
+            break;
+        case 16:
+        default:
+            fullscreen_mode.format = SDL_PIXELFORMAT_ABGR1555;
+            break;
+/* NDS       default:
+            fullscreen_mode.format = SDL_PIXELFORMAT_RGB888;
+            break;*/
+        }
+        fullscreen_mode.w = state->window_w;
+        fullscreen_mode.h = state->window_h;
+        fullscreen_mode.refresh_rate = state->refresh_rate;
+        SDL_SetFullscreenDisplayMode(&fullscreen_mode);
+
+        state->windows =
+            (SDL_WindowID *) SDL_malloc(state->num_windows *
+                                        sizeof(*state->windows));
+        if (!state->windows) {
+            fprintf(stderr, "Out of memory!\n");
+            return SDL_FALSE;
+        }
+        for (i = 0; i < state->num_windows; ++i) {
+            char title[1024];
+
+            if (state->num_windows > 1) {
+                SDL_snprintf(title, SDL_arraysize(title), "%s %d",
+                             state->window_title, i + 1);
+            } else {
+                SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
+            }
+            state->windows[i] =
+                SDL_CreateWindow(title, state->window_x, state->window_y,
+                                 state->window_w, state->window_h,
+                                 state->window_flags);
+            if (!state->windows[i]) {
+                fprintf(stderr, "Couldn't create window: %s\n",
+                        SDL_GetError());
+                return SDL_FALSE;
+            }
+
+            if (!state->skip_renderer
+                && (state->renderdriver
+                    || !(state->window_flags & SDL_WINDOW_OPENGL))) {
+                m = -1;
+                if (state->renderdriver) {
+                    SDL_RendererInfo info;
+                    n = SDL_GetNumRenderDrivers();
+                    for (j = 0; j < n; ++j) {
+                        SDL_GetRenderDriverInfo(j, &info);
+                        if (SDL_strcasecmp(info.name, state->renderdriver) ==
+                            0) {
+                            m = j;
+                            break;
+                        }
+                    }
+                    if (m == n) {
+                        fprintf(stderr,
+                                "Couldn't find render driver named %s",
+                                state->renderdriver);
+                        return SDL_FALSE;
+                    }
+                }
+                if (SDL_CreateRenderer
+                    (state->windows[i], m, state->render_flags) < 0) {
+                    fprintf(stderr, "Couldn't create renderer: %s\n",
+                            SDL_GetError());
+                    return SDL_FALSE;
+                }
+                if (state->verbose & VERBOSE_RENDER) {
+                    SDL_RendererInfo info;
+
+                    fprintf(stderr, "Current renderer:\n");
+                    SDL_GetRendererInfo(&info);
+                    PrintRenderer(&info);
+                }
+            }
+        }
+        SDL_SelectRenderer(state->windows[0]);
+    }
+
+    if (state->flags & SDL_INIT_AUDIO) {
+        if (state->verbose & VERBOSE_AUDIO) {
+            n = SDL_GetNumAudioDrivers();
+            if (n == 0) {
+                fprintf(stderr, "No built-in audio drivers\n");
+            } else {
+                fprintf(stderr, "Built-in audio drivers:");
+                for (i = 0; i < n; ++i) {
+                    if (i > 0) {
+                        fprintf(stderr, ",");
+                    }
+                    fprintf(stderr, " %s", SDL_GetAudioDriver(i));
+                }
+                fprintf(stderr, "\n");
+            }
+        }
+        if (SDL_AudioInit(state->audiodriver) < 0) {
+            fprintf(stderr, "Couldn't initialize audio driver: %s\n",
+                    SDL_GetError());
+            return SDL_FALSE;
+        }
+        if (state->verbose & VERBOSE_VIDEO) {
+            fprintf(stderr, "Audio driver: %s\n",
+                    SDL_GetCurrentAudioDriver());
+        }
+
+        if (SDL_OpenAudio(&state->audiospec, NULL) < 0) {
+            fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
+            return SDL_FALSE;
+        }
+    }
+
+    return SDL_TRUE;
+}
+
+static void
+PrintEvent(SDL_Event * event)
+{
+    fprintf(stderr, "SDL EVENT: ");
+    switch (event->type) {
+    case SDL_WINDOWEVENT:
+        switch (event->window.event) {
+        case SDL_WINDOWEVENT_SHOWN:
+            fprintf(stderr, "Window %d shown", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_HIDDEN:
+            fprintf(stderr, "Window %d hidden", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_EXPOSED:
+            fprintf(stderr, "Window %d exposed", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_MOVED:
+            fprintf(stderr, "Window %d moved to %d,%d",
+                    event->window.windowID, event->window.data1,
+                    event->window.data2);
+            break;
+        case SDL_WINDOWEVENT_RESIZED:
+            fprintf(stderr, "Window %d resized to %dx%d",
+                    event->window.windowID, event->window.data1,
+                    event->window.data2);
+            break;
+        case SDL_WINDOWEVENT_MINIMIZED:
+            fprintf(stderr, "Window %d minimized", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_MAXIMIZED:
+            fprintf(stderr, "Window %d maximized", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_RESTORED:
+            fprintf(stderr, "Window %d restored", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_ENTER:
+            fprintf(stderr, "Mouse entered window %d",
+                    event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_LEAVE:
+            fprintf(stderr, "Mouse left window %d", event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_FOCUS_GAINED:
+            fprintf(stderr, "Window %d gained keyboard focus",
+                    event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_FOCUS_LOST:
+            fprintf(stderr, "Window %d lost keyboard focus",
+                    event->window.windowID);
+            break;
+        case SDL_WINDOWEVENT_CLOSE:
+            fprintf(stderr, "Window %d closed", event->window.windowID);
+            break;
+        default:
+            fprintf(stderr, "Window %d got unknown event %d",
+                    event->window.windowID, event->window.event);
+            break;
+        }
+        break;
+    case SDL_KEYDOWN:
+        fprintf(stderr,
+                "Keyboard %d: key pressed  in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
+                event->key.which, event->key.windowID,
+                event->key.keysym.scancode,
+                SDL_GetScancodeName(event->key.keysym.scancode),
+                event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
+        break;
+    case SDL_KEYUP:
+        fprintf(stderr,
+                "Keyboard %d: key released in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
+                event->key.which, event->key.windowID,
+                event->key.keysym.scancode,
+                SDL_GetScancodeName(event->key.keysym.scancode),
+                event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
+        break;
+    case SDL_TEXTINPUT:
+        fprintf(stderr, "Keyboard %d: text input \"%s\" in window %d",
+                event->text.which, event->text.text, event->text.windowID);
+        break;
+    case SDL_MOUSEMOTION:
+        fprintf(stderr, "Mouse %d: moved to %d,%d (%d,%d) in window %d",
+                event->motion.which, event->motion.x, event->motion.y,
+                event->motion.xrel, event->motion.yrel,
+                event->motion.windowID);
+        break;
+    case SDL_MOUSEBUTTONDOWN:
+        fprintf(stderr, "Mouse %d: button %d pressed at %d,%d in window %d",
+                event->button.which, event->button.button, event->button.x,
+                event->button.y, event->button.windowID);
+        break;
+    case SDL_MOUSEBUTTONUP:
+        fprintf(stderr, "Mouse %d: button %d released at %d,%d in window %d",
+                event->button.which, event->button.button, event->button.x,
+                event->button.y, event->button.windowID);
+        break;
+    case SDL_MOUSEWHEEL:
+        fprintf(stderr,
+                "Mouse %d: wheel scrolled %d in x and %d in y in window %d",
+                event->wheel.which, event->wheel.x, event->wheel.y,
+                event->wheel.windowID);
+        break;
+    case SDL_JOYBALLMOTION:
+        fprintf(stderr, "Joystick %d: ball %d moved by %d,%d",
+                event->jball.which, event->jball.ball, event->jball.xrel,
+                event->jball.yrel);
+        break;
+    case SDL_JOYHATMOTION:
+        fprintf(stderr, "Joystick %d: hat %d moved to ", event->jhat.which,
+                event->jhat.hat);
+        switch (event->jhat.value) {
+        case SDL_HAT_CENTERED:
+            fprintf(stderr, "CENTER");
+            break;
+        case SDL_HAT_UP:
+            fprintf(stderr, "UP");
+            break;
+        case SDL_HAT_RIGHTUP:
+            fprintf(stderr, "RIGHTUP");
+            break;
+        case SDL_HAT_RIGHT:
+            fprintf(stderr, "RIGHT");
+            break;
+        case SDL_HAT_RIGHTDOWN:
+            fprintf(stderr, "RIGHTDOWN");
+            break;
+        case SDL_HAT_DOWN:
+            fprintf(stderr, "DOWN");
+            break;
+        case SDL_HAT_LEFTDOWN:
+            fprintf(stderr, "LEFTDOWN");
+            break;
+        case SDL_HAT_LEFT:
+            fprintf(stderr, "LEFT");
+            break;
+        case SDL_HAT_LEFTUP:
+            fprintf(stderr, "LEFTUP");
+            break;
+        default:
+            fprintf(stderr, "UNKNOWN");
+            break;
+        }
+        break;
+    case SDL_JOYBUTTONDOWN:
+        fprintf(stderr, "Joystick %d: button %d pressed",
+                event->jbutton.which, event->jbutton.button);
+        break;
+    case SDL_JOYBUTTONUP:
+        fprintf(stderr, "Joystick %d: button %d released",
+                event->jbutton.which, event->jbutton.button);
+        break;
+    case SDL_QUIT:
+        fprintf(stderr, "Quit requested");
+        break;
+    case SDL_USEREVENT:
+        fprintf(stderr, "User event %d", event->user.code);
+        break;
+    default:
+        fprintf(stderr, "Unknown event %d", event->type);
+        break;
+    }
+    fprintf(stderr, "\n");
+}
+
+void
+CommonEvent(CommonState * state, SDL_Event * event, int *done)
+{
+    if (state->verbose & VERBOSE_EVENT) {
+        PrintEvent(event);
+    }
+
+    switch (event->type) {
+    case SDL_WINDOWEVENT:
+        switch (event->window.event) {
+        case SDL_WINDOWEVENT_CLOSE:
+            *done = 1;
+            break;
+        }
+        break;
+    case SDL_KEYDOWN:
+        switch (event->key.keysym.sym) {
+            /* Add hotkeys here */
+        case SDLK_g:
+            if (event->key.keysym.mod & KMOD_CTRL) {
+                /* Ctrl-G toggle grab */
+            }
+            break;
+        case SDLK_ESCAPE:
+            *done = 1;
+            break;
+        default:
+            break;
+        }
+        break;
+    case SDL_QUIT:
+        *done = 1;
+        break;
+    }
+}
+
+void
+CommonQuit(CommonState * state)
+{
+    if (state->flags & SDL_INIT_VIDEO) {
+        SDL_VideoQuit();
+    }
+    if (state->flags & SDL_INIT_AUDIO) {
+        SDL_AudioQuit();
+    }
+    if (state->windows) {
+        SDL_free(state->windows);
+    }
+    SDL_free(state);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/sprite2/source/common.h	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,48 @@
+
+/* A simple test program framework */
+
+#include <SDL/SDL.h>
+
+#define VERBOSE_VIDEO   0x00000001
+#define VERBOSE_MODES   0x00000002
+#define VERBOSE_RENDER  0x00000004
+#define VERBOSE_EVENT   0x00000008
+#define VERBOSE_AUDIO   0x00000010
+
+typedef struct
+{
+    /* SDL init flags */
+    char **argv;
+    Uint32 flags;
+    Uint32 verbose;
+
+    /* Video info */
+    const char *videodriver;
+    int display;
+    const char *window_title;
+    Uint32 window_flags;
+    int window_x;
+    int window_y;
+    int window_w;
+    int window_h;
+    int depth;
+    int refresh_rate;
+    int num_windows;
+    SDL_WindowID *windows;
+
+    /* Renderer info */
+    const char *renderdriver;
+    Uint32 render_flags;
+    SDL_bool skip_renderer;
+
+    /* Audio info */
+    const char *audiodriver;
+    SDL_AudioSpec audiospec;
+} CommonState;
+
+extern CommonState *CommonCreateState(char **argv, Uint32 flags);
+extern int CommonArg(CommonState * state, int index);
+extern const char *CommonUsage(CommonState * state);
+extern SDL_bool CommonInit(CommonState * state);
+extern void CommonEvent(CommonState * state, SDL_Event * event, int *done);
+extern void CommonQuit(CommonState * state);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nds-test-progs/sprite2/source/testsprite2.c	Wed Aug 13 00:49:03 2008 +0000
@@ -0,0 +1,302 @@
+/* Simple program:  Move N sprites around on the screen as fast as possible */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <nds.h>
+#include "common.h"
+
+#define NUM_SPRITES	100
+#define MAX_SPEED 	1
+
+static CommonState *state;
+static int num_sprites;
+static SDL_TextureID *sprites;
+static SDL_bool cycle_color;
+static SDL_bool cycle_alpha;
+static int cycle_direction = 1;
+static int current_alpha = 0;
+static int current_color = 0;
+static SDL_Rect *positions;
+static SDL_Rect *velocities;
+static int sprite_w, sprite_h;
+static SDL_TextureBlendMode blendMode = SDL_TEXTUREBLENDMODE_MASK;
+static SDL_TextureScaleMode scaleMode = SDL_TEXTURESCALEMODE_NONE;
+
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void
+quit(int rc)
+{
+    if (sprites) {
+        SDL_free(sprites);
+    }
+    if (positions) {
+        SDL_free(positions);
+    }
+    if (velocities) {
+        SDL_free(velocities);
+    }
+    CommonQuit(state);
+    exit(rc);
+}
+
+int
+LoadSprite(char *file)
+{
+    int i;
+    SDL_Surface *temp;
+
+    /* Load the sprite image */
+    temp = SDL_LoadBMP(file);
+    if (temp == NULL) {
+        fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
+        return (-1);
+    }
+    sprite_w = temp->w;
+    sprite_h = temp->h;
+
+    /* Set transparent pixel as the pixel at (0,0) */
+    if (temp->format->palette) {
+        SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint8 *) temp->pixels);
+    }
+
+    /* Create textures from the image */
+    for (i = 0; i < state->num_windows; ++i) {
+        SDL_SelectRenderer(state->windows[i]);
+        sprites[i] = SDL_CreateTextureFromSurface(0, temp);
+        if (!sprites[i]) {
+            fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
+            SDL_FreeSurface(temp);
+            return (-1);
+        }
+        SDL_SetTextureBlendMode(sprites[i], blendMode);
+        SDL_SetTextureScaleMode(sprites[i], scaleMode);
+    }
+    SDL_FreeSurface(temp);
+
+    /* We're ready to roll. :) */
+    return (0);
+}
+
+void
+MoveSprites(SDL_WindowID window, SDL_TextureID sprite)
+{
+    int i, n;
+    int window_w, window_h;
+    SDL_Rect area, *position, *velocity;
+
+    SDL_SelectRenderer(window);
+
+    /* Query the sizes */
+    SDL_GetWindowSize(window, &window_w, &window_h);
+
+    /* Cycle the color and alpha, if desired */
+    if (cycle_color) {
+        current_color += cycle_direction;
+        if (current_color < 0) {
+            current_color = 0;
+            cycle_direction = -cycle_direction;
+        }
+        if (current_color > 255) {
+            current_color = 255;
+            cycle_direction = -cycle_direction;
+        }
+        SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color,
+                               (Uint8) current_color);
+    }
+    if (cycle_alpha) {
+        current_alpha += cycle_direction;
+        if (current_alpha < 0) {
+            current_alpha = 0;
+            cycle_direction = -cycle_direction;
+        }
+        if (current_alpha > 255) {
+            current_alpha = 255;
+            cycle_direction = -cycle_direction;
+        }
+        SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha);
+    }
+
+    /* Move the sprite, bounce at the wall, and draw */
+    n = 0;
+    SDL_RenderFill(0xA0, 0xA0, 0xA0, 0xFF, NULL);
+    for (i = 0; i < num_sprites; ++i) {
+        position = &positions[i];
+        velocity = &velocities[i];
+        position->x += velocity->x;
+        if ((position->x < 0) || (position->x >= (window_w - sprite_w))) {
+            velocity->x = -velocity->x;
+            position->x += velocity->x;
+        }
+        position->y += velocity->y;
+        if ((position->y < 0) || (position->y >= (window_h - sprite_w))) {
+            velocity->y = -velocity->y;
+            position->y += velocity->y;
+        }
+
+        /* Blit the sprite onto the screen */
+        SDL_RenderCopy(sprite, NULL, position);
+    }
+
+    /* Update the screen! */
+    SDL_RenderPresent();
+}
+
+int
+main(int argc, char *argv[])
+{
+    int i, done;
+    SDL_Event event;
+    Uint32 then, now, frames;
+
+    /* Initialize parameters */
+    num_sprites = NUM_SPRITES;
+
+    /* Initialize test framework */
+    state = CommonCreateState(argv, SDL_INIT_VIDEO);
+    if (!state) {
+        return 1;
+    }
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = CommonArg(state, i);
+        if (consumed == 0) {
+            consumed = -1;
+            if (SDL_strcasecmp(argv[i], "--blend") == 0) {
+                if (argv[i + 1]) {
+                    if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
+                        blendMode = SDL_TEXTUREBLENDMODE_NONE;
+                        consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "mask") == 0) {
+                        blendMode = SDL_TEXTUREBLENDMODE_MASK;
+                        consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
+                        blendMode = SDL_TEXTUREBLENDMODE_BLEND;
+                        consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
+                        blendMode = SDL_TEXTUREBLENDMODE_ADD;
+                        consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
+                        blendMode = SDL_TEXTUREBLENDMODE_MOD;
+                        consumed = 2;
+                    }
+                }
+            } else if (SDL_strcasecmp(argv[i], "--scale") == 0) {
+                if (argv[i + 1]) {
+                    if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
+                        scaleMode = SDL_TEXTURESCALEMODE_NONE;
+                        consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "fast") == 0) {
+                        scaleMode = SDL_TEXTURESCALEMODE_FAST;
+                        consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "slow") == 0) {
+                        scaleMode = SDL_TEXTURESCALEMODE_SLOW;
+                        consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "best") == 0) {
+                        scaleMode = SDL_TEXTURESCALEMODE_BEST;
+                        consumed = 2;
+                    }
+                }
+            } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) {
+                cycle_color = SDL_TRUE;
+                consumed = 1;
+            } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
+                cycle_alpha = SDL_TRUE;
+                consumed = 1;
+            } else if (SDL_isdigit(*argv[i])) {
+                num_sprites = SDL_atoi(argv[i]);
+                consumed = 1;
+            }
+        }
+        if (consumed < 0) {
+            fprintf(stderr,
+                    "Usage: %s %s [--blend none|mask|blend|add|mod] [--scale none|fast|slow|best] [--cyclecolor] [--cyclealpha]\n",
+                    argv[0], CommonUsage(state));
+            quit(1);
+        }
+        i += consumed;
+    }
+    if (!CommonInit(state)) {
+        quit(2);
+    }
+
+    /* Create the windows, initialize the renderers, and load the textures */
+    sprites =
+        (SDL_TextureID *) SDL_malloc(state->num_windows * sizeof(*sprites));
+    if (!sprites) {
+        fprintf(stderr, "Out of memory!\n");
+        quit(2);
+    }
+    for (i = 0; i < state->num_windows; ++i) {
+        SDL_SelectRenderer(state->windows[i]);
+        SDL_RenderFill(0xA0, 0xA0, 0xA0, 0xFF, NULL);
+    }
+    if (LoadSprite("icon.bmp") < 0) {
+        quit(2);
+    }
+
+    /* Allocate memory for the sprite info */
+    positions = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
+    velocities = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
+    if (!positions || !velocities) {
+        fprintf(stderr, "Out of memory!\n");
+        quit(2);
+    }
+    srand(time(NULL));
+    if (scaleMode != SDL_TEXTURESCALEMODE_NONE) {
+        sprite_w += sprite_w / 2;
+        sprite_h += sprite_h / 2;
+    }
+    for (i = 0; i < num_sprites; ++i) {
+        positions[i].x = rand() % (state->window_w - sprite_w);
+        positions[i].y = rand() % (state->window_h - sprite_h);
+        positions[i].w = sprite_w;
+        positions[i].h = sprite_h;
+        velocities[i].x = 0;
+        velocities[i].y = 0;
+        while (!velocities[i].x && !velocities[i].y) {
+            velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
+            velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
+        }
+    }
+
+    /* Main render loop */
+    frames = 0;
+    then = SDL_GetTicks();
+    done = 0;
+    while (!done) {
+        /* Check for events */
+        ++frames;
+        while (SDL_PollEvent(&event)) {
+            CommonEvent(state, &event, &done);
+            switch (event.type) {
+            case SDL_WINDOWEVENT:
+                switch (event.window.event) {
+                case SDL_WINDOWEVENT_EXPOSED:
+                    SDL_SelectRenderer(event.window.windowID);
+                    SDL_RenderFill(0xA0, 0xA0, 0xA0, 0xFF, NULL);
+                    break;
+                }
+                break;
+            default:
+                break;
+            }
+        }
+        for (i = 0; i < state->num_windows; ++i) {
+            MoveSprites(state->windows[i], sprites[i]);
+        }
+    }
+
+    /* Print out some timing information */
+    now = SDL_GetTicks();
+    if (now > then) {
+        printf("%2.2f frames per second\n",
+               ((double) frames * 1000) / (now - then));
+    }
+
+    quit(0);
+    return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */