forked from len0rd/rockbox
Added plugin loader. Moved games, demos and the text viewer to loadable plugins. Copy your *.rock files to /.rockbox/rocks/
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3769 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
9bcbe3fd72
commit
ba371fb595
29 changed files with 1869 additions and 1889 deletions
45
apps/plugins/Makefile
Normal file
45
apps/plugins/Makefile
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
# $Id$
|
||||
#
|
||||
|
||||
CC = sh-elf-gcc
|
||||
OC = sh-elf-objcopy
|
||||
|
||||
FIRMWARE = ../../firmware
|
||||
|
||||
INCLUDES = -I$(FIRMWARE)/include -I$(FIRMWARE)/export -I$(FIRMWARE)/common -I$(FIRMWARE)/drivers -I..
|
||||
CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes $(INCLUDES) $(TARGET) $(EXTRA_DEFINES)
|
||||
|
||||
LINKFILE = plugin.lds
|
||||
|
||||
SRC := $(wildcard *.c)
|
||||
ROCKS := $(SRC:%.c=$(OBJDIR)/%.rock)
|
||||
|
||||
ifndef OBJDIR
|
||||
no_configure:
|
||||
@echo "Don't run make here. Run the tools/configure script from your own build"
|
||||
@echo "directory, then run make there."
|
||||
@echo
|
||||
@echo "More help on how to build rockbox can be found here:"
|
||||
@echo "http://rockbox.haxx.se/docs/how_to_compile.html"
|
||||
endif
|
||||
|
||||
$(OBJDIR)/%.elf: $(OBJDIR)/%.o $(LINKFILE)
|
||||
$(CC) -O -nostdlib -o $@ $< -lgcc -T$(LINKFILE) -Wl,-Map,$*.map
|
||||
|
||||
$(OBJDIR)/%.rock : $(OBJDIR)/%.elf
|
||||
$(OC) -O binary $< $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c ../plugin.h Makefile
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
all: $(ROCKS)
|
||||
@echo done
|
||||
|
||||
clean:
|
||||
-rm -f $(ROCKS)
|
||||
409
apps/plugins/bounce.c
Normal file
409
apps/plugins/bounce.c
Normal file
|
|
@ -0,0 +1,409 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Daniel Stenberg
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
#include "plugin.h"
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
|
||||
#define SS_TITLE "Bouncer"
|
||||
#define SS_TITLE_FONT 2
|
||||
|
||||
#define LETTERS_ON_SCREEN 12
|
||||
|
||||
#define YSPEED 2
|
||||
#define XSPEED 3
|
||||
#define YADD -4
|
||||
|
||||
static struct plugin_api* rb;
|
||||
|
||||
static unsigned char table[]={
|
||||
26,28,30,33,35,37,39,40,42,43,45,46,46,47,47,47,47,47,46,46,45,43,42,40,39,37,35,33,30,28,26,24,21,19,17,14,12,10,8,7,5,4,2,1,1,0,0,0,0,0,1,1,2,4,5,7,8,10,12,14,17,19,21,23,
|
||||
};
|
||||
|
||||
static unsigned char xtable[]={
|
||||
54,58,63,67,71,75,79,82,85,88,91,93,95,97,98,99,99,99,99,99,97,96,94,92,90,87,84,80,77,73,69,65,60,56,52,47,43,39,34,30,26,22,19,15,12,9,7,5,3,2,0,0,0,0,0,1,2,4,6,8,11,14,17,20,24,28,32,36,41,45,49
|
||||
};
|
||||
|
||||
static signed char speed[]={
|
||||
1,2,3,3,3,2,1,0,-1,-2,-2,-2,-1,0,0,1,
|
||||
};
|
||||
|
||||
const unsigned char char_gen_12x16[][22] =
|
||||
{
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0xff,0x33,0xff,0x33,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x3c,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x02,0x10,0x1e,0x90,0x1f,0xf0,0x03,0x7e,0x02,0x1e,0x1e,0x90,0x1f,0xf0,0x03,0x7e,0x02,0x1e,0x00,0x10,0x00 },
|
||||
{ 0x00,0x00,0x78,0x04,0xfc,0x0c,0xcc,0x0c,0xff,0x3f,0xff,0x3f,0xcc,0x0c,0xcc,0x0f,0x88,0x07,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x30,0x38,0x38,0x38,0x1c,0x38,0x0e,0x00,0x07,0x80,0x03,0xc0,0x01,0xe0,0x38,0x70,0x38,0x38,0x38,0x1c,0x00 },
|
||||
{ 0x00,0x00,0x00,0x1f,0xb8,0x3f,0xfc,0x31,0xc6,0x21,0xe2,0x37,0x3e,0x1e,0x1c,0x1c,0x00,0x36,0x00,0x22,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x00,0x3f,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0xf0,0x03,0xfc,0x0f,0xfe,0x1f,0x07,0x38,0x01,0x20,0x01,0x20,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x01,0x20,0x01,0x20,0x07,0x38,0xfe,0x1f,0xfc,0x0f,0xf0,0x03,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x98,0x0c,0xb8,0x0e,0xe0,0x03,0xf8,0x0f,0xf8,0x0f,0xe0,0x03,0xb8,0x0e,0x98,0x0c,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0xf0,0x0f,0xf0,0x0f,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x00,0xf8,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x18,0x00,0x1c,0x00,0x0e,0x00,0x07,0x80,0x03,0xc0,0x01,0xe0,0x00,0x70,0x00,0x38,0x00,0x1c,0x00,0x0e,0x00 },
|
||||
{ 0xf8,0x07,0xfe,0x1f,0x06,0x1e,0x03,0x33,0x83,0x31,0xc3,0x30,0x63,0x30,0x33,0x30,0x1e,0x18,0xfe,0x1f,0xf8,0x07 },
|
||||
{ 0x00,0x00,0x00,0x00,0x0c,0x30,0x0c,0x30,0x0e,0x30,0xff,0x3f,0xff,0x3f,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x00 },
|
||||
{ 0x1c,0x30,0x1e,0x38,0x07,0x3c,0x03,0x3e,0x03,0x37,0x83,0x33,0xc3,0x31,0xe3,0x30,0x77,0x30,0x3e,0x30,0x1c,0x30 },
|
||||
{ 0x0c,0x0c,0x0e,0x1c,0x07,0x38,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xe7,0x39,0x7e,0x1f,0x3c,0x0e },
|
||||
{ 0xc0,0x03,0xe0,0x03,0x70,0x03,0x38,0x03,0x1c,0x03,0x0e,0x03,0x07,0x03,0xff,0x3f,0xff,0x3f,0x00,0x03,0x00,0x03 },
|
||||
{ 0x3f,0x0c,0x7f,0x1c,0x63,0x38,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0xe3,0x38,0xc3,0x1f,0x83,0x0f },
|
||||
{ 0xc0,0x0f,0xf0,0x1f,0xf8,0x39,0xdc,0x30,0xce,0x30,0xc7,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x39,0x80,0x1f,0x00,0x0f },
|
||||
{ 0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x30,0x03,0x3c,0x03,0x0f,0xc3,0x03,0xf3,0x00,0x3f,0x00,0x0f,0x00,0x03,0x00 },
|
||||
{ 0x00,0x0f,0xbc,0x1f,0xfe,0x39,0xe7,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xe7,0x30,0xfe,0x39,0xbc,0x1f,0x00,0x0f },
|
||||
{ 0x3c,0x00,0x7e,0x00,0xe7,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x38,0xc3,0x1c,0xc3,0x0e,0xe7,0x07,0xfe,0x03,0xfc,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x1c,0x70,0x1c,0x70,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x9c,0x70,0xfc,0x70,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0xc0,0x00,0xe0,0x01,0xf0,0x03,0x38,0x07,0x1c,0x0e,0x0e,0x1c,0x07,0x38,0x03,0x30,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x00,0x00 },
|
||||
{ 0x00,0x00,0x03,0x30,0x07,0x38,0x0e,0x1c,0x1c,0x0e,0x38,0x07,0xf0,0x03,0xe0,0x01,0xc0,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x1c,0x00,0x1e,0x00,0x07,0x00,0x03,0x00,0x83,0x37,0xc3,0x37,0xe3,0x00,0x77,0x00,0x3e,0x00,0x1c,0x00,0x00,0x00 },
|
||||
{ 0xf8,0x0f,0xfe,0x1f,0x07,0x18,0xf3,0x33,0xfb,0x37,0x1b,0x36,0xfb,0x37,0xfb,0x37,0x07,0x36,0xfe,0x03,0xf8,0x01 },
|
||||
{ 0x00,0x38,0x00,0x3f,0xe0,0x07,0xfc,0x06,0x1f,0x06,0x1f,0x06,0xfc,0x06,0xe0,0x07,0x00,0x3f,0x00,0x38,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xe7,0x30,0xfe,0x39,0xbc,0x1f,0x00,0x0f,0x00,0x00 },
|
||||
{ 0xf0,0x03,0xfc,0x0f,0x0e,0x1c,0x07,0x38,0x03,0x30,0x03,0x30,0x03,0x30,0x07,0x38,0x0e,0x1c,0x0c,0x0c,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0x03,0x30,0x03,0x30,0x03,0x30,0x03,0x30,0x07,0x38,0x0e,0x1c,0xfc,0x0f,0xf0,0x03,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x30,0x03,0x30,0x03,0x30,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0xc3,0x00,0xc3,0x00,0xc3,0x00,0xc3,0x00,0xc3,0x00,0xc3,0x00,0x03,0x00,0x03,0x00,0x00,0x00 },
|
||||
{ 0xf0,0x03,0xfc,0x0f,0x0e,0x1c,0x07,0x38,0x03,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xc7,0x3f,0xc6,0x3f,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xff,0x3f,0xff,0x3f,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x03,0x30,0x03,0x30,0xff,0x3f,0xff,0x3f,0x03,0x30,0x03,0x30,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x0e,0x00,0x1e,0x00,0x38,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x38,0xff,0x1f,0xff,0x07,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0xc0,0x00,0xe0,0x01,0xf0,0x03,0x38,0x07,0x1c,0x0e,0x0e,0x1c,0x07,0x38,0x03,0x30,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0x1e,0x00,0x78,0x00,0xe0,0x01,0xe0,0x01,0x78,0x00,0x1e,0x00,0xff,0x3f,0xff,0x3f,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0x0e,0x00,0x38,0x00,0xf0,0x00,0xc0,0x03,0x00,0x07,0x00,0x1c,0xff,0x3f,0xff,0x3f,0x00,0x00 },
|
||||
{ 0xf0,0x03,0xfc,0x0f,0x0e,0x1c,0x07,0x38,0x03,0x30,0x03,0x30,0x07,0x38,0x0e,0x1c,0xfc,0x0f,0xf0,0x03,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0x83,0x01,0x83,0x01,0x83,0x01,0x83,0x01,0x83,0x01,0xc7,0x01,0xfe,0x00,0x7c,0x00,0x00,0x00 },
|
||||
{ 0xf0,0x03,0xfc,0x0f,0x0e,0x1c,0x07,0x38,0x03,0x30,0x03,0x36,0x07,0x3e,0x0e,0x1c,0xfc,0x3f,0xf0,0x33,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0x83,0x01,0x83,0x01,0x83,0x03,0x83,0x07,0x83,0x0f,0xc7,0x1d,0xfe,0x38,0x7c,0x30,0x00,0x00 },
|
||||
{ 0x3c,0x0c,0x7e,0x1c,0xe7,0x38,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xc3,0x30,0xc7,0x39,0x8e,0x1f,0x0c,0x0f,0x00,0x00 },
|
||||
{ 0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0xff,0x3f,0xff,0x3f,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0xff,0x07,0xff,0x1f,0x00,0x38,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x38,0xff,0x1f,0xff,0x07,0x00,0x00 },
|
||||
{ 0x07,0x00,0x3f,0x00,0xf8,0x01,0xc0,0x0f,0x00,0x3e,0x00,0x3e,0xc0,0x0f,0xf8,0x01,0x3f,0x00,0x07,0x00,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0x00,0x1c,0x00,0x06,0x80,0x03,0x80,0x03,0x00,0x06,0x00,0x1c,0xff,0x3f,0xff,0x3f,0x00,0x00 },
|
||||
{ 0x03,0x30,0x0f,0x3c,0x1c,0x0e,0x30,0x03,0xe0,0x01,0xe0,0x01,0x30,0x03,0x1c,0x0e,0x0f,0x3c,0x03,0x30,0x00,0x00 },
|
||||
{ 0x03,0x00,0x0f,0x00,0x3c,0x00,0xf0,0x00,0xc0,0x3f,0xc0,0x3f,0xf0,0x00,0x3c,0x00,0x0f,0x00,0x03,0x00,0x00,0x00 },
|
||||
{ 0x03,0x30,0x03,0x3c,0x03,0x3e,0x03,0x33,0xc3,0x31,0xe3,0x30,0x33,0x30,0x1f,0x30,0x0f,0x30,0x03,0x30,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0xff,0x3f,0xff,0x3f,0x03,0x30,0x03,0x30,0x03,0x30,0x03,0x30,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x0e,0x00,0x1c,0x00,0x38,0x00,0x70,0x00,0xe0,0x00,0xc0,0x01,0x80,0x03,0x00,0x07,0x00,0x0e,0x00,0x1c,0x00,0x18 },
|
||||
{ 0x00,0x00,0x00,0x00,0x03,0x30,0x03,0x30,0x03,0x30,0x03,0x30,0xff,0x3f,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x60,0x00,0x70,0x00,0x38,0x00,0x1c,0x00,0x0e,0x00,0x07,0x00,0x0e,0x00,0x1c,0x00,0x38,0x00,0x70,0x00,0x60,0x00 },
|
||||
{ 0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0,0x00,0xc0 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x7e,0x00,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x1c,0x40,0x3e,0x60,0x33,0x60,0x33,0x60,0x33,0x60,0x33,0x60,0x33,0x60,0x33,0xe0,0x3f,0xc0,0x3f,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0xc0,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xe0,0x38,0xc0,0x1f,0x80,0x0f,0x00,0x00 },
|
||||
{ 0x80,0x0f,0xc0,0x1f,0xe0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xc0,0x18,0x80,0x08,0x00,0x00 },
|
||||
{ 0x80,0x0f,0xc0,0x1f,0xe0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0xe0,0x30,0xc0,0x30,0xff,0x3f,0xff,0x3f,0x00,0x00 },
|
||||
{ 0x80,0x0f,0xc0,0x1f,0xe0,0x3b,0x60,0x33,0x60,0x33,0x60,0x33,0x60,0x33,0x60,0x33,0xc0,0x13,0x80,0x01,0x00,0x00 },
|
||||
{ 0xc0,0x00,0xc0,0x00,0xfc,0x3f,0xfe,0x3f,0xc7,0x00,0xc3,0x00,0xc3,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x80,0x03,0xc0,0xc7,0xe0,0xce,0x60,0xcc,0x60,0xcc,0x60,0xcc,0x60,0xcc,0x60,0xe6,0xe0,0x7f,0xe0,0x3f,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0xc0,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xe0,0x00,0xc0,0x3f,0x80,0x3f,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0x30,0xec,0x3f,0xec,0x3f,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x60,0x00,0xe0,0x00,0xc0,0x60,0xc0,0xec,0xff,0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0xff,0x3f,0xff,0x3f,0x00,0x03,0x80,0x07,0xc0,0x0f,0xe0,0x1c,0x60,0x38,0x00,0x30,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x30,0x03,0x30,0xff,0x3f,0xff,0x3f,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0xe0,0x3f,0xc0,0x3f,0xe0,0x00,0xe0,0x00,0xc0,0x3f,0xc0,0x3f,0xe0,0x00,0xe0,0x00,0xc0,0x3f,0x80,0x3f,0x00,0x00 },
|
||||
{ 0x00,0x00,0xe0,0x3f,0xe0,0x3f,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xe0,0x00,0xc0,0x3f,0x80,0x3f,0x00,0x00 },
|
||||
{ 0x80,0x0f,0xc0,0x1f,0xe0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xe0,0x38,0xc0,0x1f,0x80,0x0f,0x00,0x00 },
|
||||
{ 0xe0,0xff,0xe0,0xff,0x60,0x0c,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0xe0,0x1c,0xc0,0x0f,0x80,0x07,0x00,0x00 },
|
||||
{ 0x80,0x07,0xc0,0x0f,0xe0,0x1c,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x0c,0xe0,0xff,0xe0,0xff,0x00,0x00 },
|
||||
{ 0x00,0x00,0xe0,0x3f,0xe0,0x3f,0xc0,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xe0,0x00,0xc0,0x00,0x00,0x00 },
|
||||
{ 0xc0,0x11,0xe0,0x33,0x60,0x33,0x60,0x33,0x60,0x33,0x60,0x33,0x60,0x3f,0x40,0x1e,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x60,0x00,0x60,0x00,0xfe,0x1f,0xfe,0x3f,0x60,0x30,0x60,0x30,0x60,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0xe0,0x0f,0xe0,0x1f,0x00,0x38,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x18,0xe0,0x3f,0xe0,0x3f,0x00,0x00 },
|
||||
{ 0x60,0x00,0xe0,0x01,0x80,0x07,0x00,0x1e,0x00,0x38,0x00,0x38,0x00,0x1e,0x80,0x07,0xe0,0x01,0x60,0x00,0x00,0x00 },
|
||||
{ 0xe0,0x07,0xe0,0x1f,0x00,0x38,0x00,0x1c,0xe0,0x0f,0xe0,0x0f,0x00,0x1c,0x00,0x38,0xe0,0x1f,0xe0,0x07,0x00,0x00 },
|
||||
{ 0x60,0x30,0xe0,0x38,0xc0,0x1d,0x80,0x0f,0x00,0x07,0x80,0x0f,0xc0,0x1d,0xe0,0x38,0x60,0x30,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x60,0x00,0xe0,0x81,0x80,0xe7,0x00,0x7e,0x00,0x1e,0x80,0x07,0xe0,0x01,0x60,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x60,0x30,0x60,0x38,0x60,0x3c,0x60,0x36,0x60,0x33,0xe0,0x31,0xe0,0x30,0x60,0x30,0x20,0x30,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x80,0x00,0xc0,0x01,0xfc,0x1f,0x7e,0x3f,0x07,0x70,0x03,0x60,0x03,0x60,0x03,0x60,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x3f,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x00,0x00,0x03,0x60,0x03,0x60,0x03,0x60,0x07,0x70,0x7e,0x3f,0xfc,0x1f,0xc0,0x01,0x80,0x00,0x00,0x00,0x00,0x00 },
|
||||
{ 0x10,0x00,0x18,0x00,0x0c,0x00,0x04,0x00,0x0c,0x00,0x18,0x00,0x10,0x00,0x18,0x00,0x0c,0x00,0x04,0x00,0x00,0x00 },
|
||||
{ 0xff,0x3f,0xff,0x3f,0xff,0x3f,0xff,0x3f,0xff,0x3f,0xff,0x3f,0xff,0x3f,0xff,0x3f,0xff,0x3f,0xff,0x3f,0x00,0x00 }
|
||||
};
|
||||
|
||||
#define XDIFF -4
|
||||
#define YDIFF -6
|
||||
|
||||
enum {
|
||||
NUM_XSANKE,
|
||||
NUM_YSANKE,
|
||||
NUM_XADD,
|
||||
NUM_YADD,
|
||||
NUM_XDIST,
|
||||
NUM_YDIST,
|
||||
|
||||
NUM_LAST
|
||||
};
|
||||
|
||||
struct counter {
|
||||
char *what;
|
||||
int num;
|
||||
};
|
||||
|
||||
struct counter values[]={
|
||||
{"xsanke", 1},
|
||||
{"ysanke", 1},
|
||||
{"xadd", 1},
|
||||
{"yadd", 1},
|
||||
{"xdist", -4},
|
||||
{"ydistt", -6},
|
||||
};
|
||||
|
||||
#ifdef USE_CLOCK
|
||||
static unsigned char yminute[]={
|
||||
53,53,52,52,51,50,49,47,46,44,42,40,38,36,34,32,29,27,25,23,21,19,17,16,14,13,12,11,11,10,10,10,11,11,12,13,14,16,17,19,21,23,25,27,29,31,34,36,38,40,42,44,46,47,49,50,51,52,52,53,
|
||||
};
|
||||
static unsigned char yhour[]={
|
||||
42,42,42,42,41,41,40,39,39,38,37,36,35,34,33,32,30,29,28,27,26,25,24,24,23,22,22,21,21,21,21,21,21,21,22,22,23,24,24,25,26,27,28,29,30,31,33,34,35,36,37,38,39,39,40,41,41,42,42,42,
|
||||
};
|
||||
|
||||
static unsigned char xminute[]={
|
||||
56,59,63,67,71,74,77,80,83,86,88,90,91,92,93,93,93,92,91,90,88,86,83,80,77,74,71,67,63,59,56,52,48,44,40,37,34,31,28,25,23,21,20,19,18,18,18,19,20,21,23,25,28,31,34,37,40,44,48,52,
|
||||
};
|
||||
static unsigned char xhour[]={
|
||||
56,57,59,61,63,65,66,68,69,71,72,73,73,74,74,74,74,74,73,73,72,71,69,68,66,65,63,61,59,57,56,54,52,50,48,46,45,43,42,40,39,38,38,37,37,37,37,37,38,38,39,40,42,43,45,46,48,50,52,54,
|
||||
};
|
||||
|
||||
static void addclock(void)
|
||||
{
|
||||
int i;
|
||||
int hour;
|
||||
int minute;
|
||||
int pos;
|
||||
|
||||
hour = rtc_read(3);
|
||||
hour = (((hour & 0x30) >> 4) * 10 + (hour & 0x0f))%12;
|
||||
minute = rtc_read(2);
|
||||
minute = ((minute & 0x70) >> 4) * 10 + (minute & 0x0f);
|
||||
|
||||
pos = 90-minute;
|
||||
if(pos >= 60)
|
||||
pos -= 60;
|
||||
|
||||
rb->lcd_drawline(LCD_WIDTH/2, LCD_HEIGHT/2, xminute[pos], yminute[pos]);
|
||||
|
||||
hour = hour*5 + minute/12;
|
||||
pos = 90-hour;
|
||||
if(pos >= 60)
|
||||
pos -= 60;
|
||||
|
||||
rb->lcd_drawline(LCD_WIDTH/2, LCD_HEIGHT/2, xhour[pos], yhour[pos]);
|
||||
|
||||
/* draw a circle */
|
||||
for(i=0; i < 60; i+=3) {
|
||||
rb->lcd_drawline( xminute[i],
|
||||
yminute[i],
|
||||
xminute[(i+1)%60],
|
||||
yminute[(i+1)%60]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int scrollit(void)
|
||||
{
|
||||
int b;
|
||||
unsigned int y=100;
|
||||
int x=LCD_WIDTH;
|
||||
unsigned int yy,xx;
|
||||
unsigned int i;
|
||||
int textpos=0;
|
||||
|
||||
char* rock="Rockbox! Pure pleasure. Pure fun. Oooh. What fun! ;-) ";
|
||||
int letter;
|
||||
|
||||
rb->lcd_clear_display();
|
||||
while(1)
|
||||
{
|
||||
b = rb->button_get_w_tmo(HZ/10);
|
||||
if ( b == (BUTTON_OFF|BUTTON_REL) )
|
||||
return 0;
|
||||
else if ( b == (BUTTON_ON|BUTTON_REL) )
|
||||
return 1;
|
||||
|
||||
rb->lcd_clear_display();
|
||||
|
||||
for(i=0, yy=y, xx=x; i< LETTERS_ON_SCREEN; i++) {
|
||||
letter = rock[(i+textpos) % (sizeof(rock)-1) ];
|
||||
|
||||
rb->lcd_bitmap((char *)char_gen_12x16[letter-0x20],
|
||||
xx, table[yy&63],
|
||||
11, 16, false);
|
||||
yy += YADD;
|
||||
xx+= LCD_WIDTH/LETTERS_ON_SCREEN;
|
||||
}
|
||||
#ifdef USE_CLOCK
|
||||
addclock();
|
||||
#endif
|
||||
rb->lcd_update();
|
||||
|
||||
x-= XSPEED;
|
||||
|
||||
if(x < 0) {
|
||||
x += LCD_WIDTH/LETTERS_ON_SCREEN;
|
||||
y += YADD;
|
||||
textpos++;
|
||||
}
|
||||
|
||||
y+=YSPEED;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int loopit(void)
|
||||
{
|
||||
int b;
|
||||
unsigned int y=100;
|
||||
unsigned int x=100;
|
||||
unsigned int yy,xx;
|
||||
unsigned int i;
|
||||
unsigned int ysanke=0;
|
||||
unsigned int xsanke=0;
|
||||
|
||||
char* rock="ROCKbox";
|
||||
|
||||
int show=0;
|
||||
int timeout=0;
|
||||
char buffer[30];
|
||||
|
||||
rb->lcd_clear_display();
|
||||
while(1)
|
||||
{
|
||||
b = rb->button_get_w_tmo(HZ/10);
|
||||
if ( b == (BUTTON_OFF|BUTTON_REL) )
|
||||
return 0;
|
||||
|
||||
if ( b == SYS_USB_CONNECTED) {
|
||||
rb->usb_screen();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( b == (BUTTON_ON|BUTTON_REL) )
|
||||
return 1;
|
||||
else if(b != BUTTON_NONE)
|
||||
timeout=20;
|
||||
|
||||
y+= speed[ysanke&15] + values[NUM_YADD].num;
|
||||
x+= speed[xsanke&15] + values[NUM_XADD].num;
|
||||
|
||||
rb->lcd_clear_display();
|
||||
#ifdef USE_CLOCK
|
||||
addclock();
|
||||
#endif
|
||||
if(timeout) {
|
||||
switch(b) {
|
||||
case BUTTON_LEFT:
|
||||
values[show].num--;
|
||||
break;
|
||||
case BUTTON_RIGHT:
|
||||
values[show].num++;
|
||||
break;
|
||||
case BUTTON_UP:
|
||||
if(++show == NUM_LAST)
|
||||
show=0;
|
||||
break;
|
||||
case BUTTON_DOWN:
|
||||
if(--show < 0)
|
||||
show=NUM_LAST-1;
|
||||
break;
|
||||
}
|
||||
rb->snprintf(buffer, 30, "%s: %d",
|
||||
values[show].what, values[show].num);
|
||||
rb->lcd_putsxy(0, 56, buffer);
|
||||
timeout--;
|
||||
}
|
||||
for(i=0, yy=y, xx=x;
|
||||
i<sizeof(rock)-1;
|
||||
i++, yy+=values[NUM_YDIST].num, xx+=values[NUM_XDIST].num)
|
||||
rb->lcd_bitmap((char *)char_gen_12x16[rock[i]-0x20],
|
||||
xtable[xx%71], table[yy&63],
|
||||
11, 16, false);
|
||||
rb->lcd_update();
|
||||
|
||||
ysanke+= values[NUM_YSANKE].num;
|
||||
xsanke+= values[NUM_XSANKE].num;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||
{
|
||||
int w, h;
|
||||
char *off = "[Off] to stop";
|
||||
int len;
|
||||
|
||||
TEST_PLUGIN_API(api);
|
||||
(void)(parameter);
|
||||
rb = api;
|
||||
|
||||
len = rb->strlen(SS_TITLE);
|
||||
rb->lcd_setfont(FONT_SYSFIXED);
|
||||
rb->lcd_getstringsize(SS_TITLE,&w, &h);
|
||||
|
||||
/* Get horizontel centering for text */
|
||||
len *= w;
|
||||
if (len%2 != 0)
|
||||
len = ((len+1)/2)+(w/2);
|
||||
else
|
||||
len /= 2;
|
||||
|
||||
if (h%2 != 0)
|
||||
h = (h/2)+1;
|
||||
else
|
||||
h /= 2;
|
||||
|
||||
rb->lcd_clear_display();
|
||||
rb->lcd_putsxy(LCD_WIDTH/2-len, (LCD_HEIGHT/2)-h, SS_TITLE);
|
||||
|
||||
len = 1;
|
||||
rb->lcd_getstringsize(off, &w, &h);
|
||||
|
||||
/* Get horizontel centering for text */
|
||||
len *= w;
|
||||
if (len%2 != 0)
|
||||
len = ((len+1)/2)+(w/2);
|
||||
else
|
||||
len /= 2;
|
||||
|
||||
if (h%2 != 0)
|
||||
h = (h/2)+1;
|
||||
else
|
||||
h /= 2;
|
||||
|
||||
rb->lcd_putsxy(LCD_WIDTH/2-len, LCD_HEIGHT-(2*h), off);
|
||||
rb->lcd_update();
|
||||
rb->sleep(HZ);
|
||||
|
||||
do {
|
||||
h= loopit();
|
||||
if(h)
|
||||
h = scrollit();
|
||||
} while(h);
|
||||
|
||||
rb->lcd_setfont(FONT_UI);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
338
apps/plugins/cube.c
Normal file
338
apps/plugins/cube.c
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Damien Teney
|
||||
* modified to use int instead of float math by Andreas Zwirtes
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "plugin.h"
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
|
||||
/* Loops that the values are displayed */
|
||||
#define DISP_TIME 30
|
||||
|
||||
struct point_3D {
|
||||
long x, y, z;
|
||||
};
|
||||
|
||||
struct point_2D {
|
||||
long x, y;
|
||||
};
|
||||
|
||||
static struct point_3D sommet[8];
|
||||
static struct point_3D point3D[8];
|
||||
static struct point_2D point2D[8];
|
||||
|
||||
static long matrice[3][3];
|
||||
|
||||
static int nb_points = 8;
|
||||
|
||||
static int x_off = 56;
|
||||
static int y_off = 95;
|
||||
static int z_off = 600;
|
||||
|
||||
/* Precalculated sine and cosine * 10000 (four digit fixed point math) */
|
||||
static int sin_table[91] =
|
||||
{
|
||||
0, 174, 348, 523, 697,
|
||||
871,1045,1218,1391,1564,
|
||||
1736,1908,2079,2249,2419,
|
||||
2588,2756,2923,3090,3255,
|
||||
3420,3583,3746,3907,4067,
|
||||
4226,4383,4539,4694,4848,
|
||||
5000,5150,5299,5446,5591,
|
||||
5735,5877,6018,6156,6293,
|
||||
6427,6560,6691,6819,6946,
|
||||
7071,7193,7313,7431,7547,
|
||||
7660,7771,7880,7986,8090,
|
||||
8191,8290,8386,8480,8571,
|
||||
8660,8746,8829,8910,8987,
|
||||
9063,9135,9205,9271,9335,
|
||||
9396,9455,9510,9563,9612,
|
||||
9659,9702,9743,9781,9816,
|
||||
9848,9876,9902,9925,9945,
|
||||
9961,9975,9986,9993,9998,
|
||||
10000
|
||||
};
|
||||
|
||||
static struct plugin_api* rb;
|
||||
|
||||
static long sin(int val)
|
||||
{
|
||||
/* Speed improvement through sukzessive lookup */
|
||||
if (val<181)
|
||||
{
|
||||
if (val<91)
|
||||
{
|
||||
/* phase 0-90 degree */
|
||||
return (long)sin_table[val];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* phase 91-180 degree */
|
||||
return (long)sin_table[180-val];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val<271)
|
||||
{
|
||||
/* phase 181-270 degree */
|
||||
return (-1L)*(long)sin_table[val-180];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* phase 270-359 degree */
|
||||
return (-1L)*(long)sin_table[360-val];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cos(int val)
|
||||
{
|
||||
/* Speed improvement through sukzessive lookup */
|
||||
if (val<181)
|
||||
{
|
||||
if (val<91)
|
||||
{
|
||||
/* phase 0-90 degree */
|
||||
return (long)sin_table[90-val];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* phase 91-180 degree */
|
||||
return (-1L)*(long)sin_table[val-90];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val<271)
|
||||
{
|
||||
/* phase 181-270 degree */
|
||||
return (-1L)*(long)sin_table[270-val];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* phase 270-359 degree */
|
||||
return (long)sin_table[val-270];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void cube_rotate(int xa, int ya, int za)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Just to prevent unnecessary lookups */
|
||||
long sxa,cxa,sya,cya,sza,cza;
|
||||
sxa=sin(xa);
|
||||
cxa=cos(xa);
|
||||
sya=sin(ya);
|
||||
cya=cos(ya);
|
||||
sza=sin(za);
|
||||
cza=cos(za);
|
||||
|
||||
/* calculate overall translation matrix */
|
||||
matrice[0][0] = cza*cya/10000L;
|
||||
matrice[1][0] = sza*cya/10000L;
|
||||
matrice[2][0] = -sya;
|
||||
|
||||
matrice[0][1] = cza*sya/10000L*sxa/10000L - sza*cxa/10000L;
|
||||
matrice[1][1] = sza*sya/10000L*sxa/10000L + cxa*cza/10000L;
|
||||
matrice[2][1] = sxa*cya/10000L;
|
||||
|
||||
matrice[0][2] = cza*sya/10000L*cxa/10000L + sza*sxa/10000L;
|
||||
matrice[1][2] = sza*sya/10000L*cxa/10000L - cza*sxa/10000L;
|
||||
matrice[2][2] = cxa*cya/10000L;
|
||||
|
||||
/* apply translation matrix to all points */
|
||||
for(i=0;i<nb_points;i++)
|
||||
{
|
||||
point3D[i].x = matrice[0][0]*sommet[i].x + matrice[1][0]*sommet[i].y
|
||||
+ matrice[2][0]*sommet[i].z;
|
||||
|
||||
point3D[i].y = matrice[0][1]*sommet[i].x + matrice[1][1]*sommet[i].y
|
||||
+ matrice[2][1]*sommet[i].z;
|
||||
|
||||
point3D[i].z = matrice[0][2]*sommet[i].x + matrice[1][2]*sommet[i].y
|
||||
+ matrice[2][2]*sommet[i].z;
|
||||
}
|
||||
}
|
||||
|
||||
static void cube_viewport(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Do viewport transformation for all points */
|
||||
for(i=0;i<nb_points;i++)
|
||||
{
|
||||
point2D[i].x=(((point3D[i].x)<<8)/10000L)/
|
||||
(point3D[i].z/10000L+z_off)+x_off;
|
||||
point2D[i].y=(((point3D[i].y)<<8)/10000L)/
|
||||
(point3D[i].z/10000L+z_off)+y_off;
|
||||
}
|
||||
}
|
||||
|
||||
static void cube_init(void)
|
||||
{
|
||||
/* Original 3D-position of cube's corners */
|
||||
sommet[0].x = -40; sommet[0].y = -40; sommet[0].z = -40;
|
||||
sommet[1].x = 40; sommet[1].y = -40; sommet[1].z = -40;
|
||||
sommet[2].x = 40; sommet[2].y = 40; sommet[2].z = -40;
|
||||
sommet[3].x = -40; sommet[3].y = 40; sommet[3].z = -40;
|
||||
sommet[4].x = 40; sommet[4].y = -40; sommet[4].z = 40;
|
||||
sommet[5].x = -40; sommet[5].y = -40; sommet[5].z = 40;
|
||||
sommet[6].x = -40; sommet[6].y = 40; sommet[6].z = 40;
|
||||
sommet[7].x = 40; sommet[7].y = 40; sommet[7].z = 40;
|
||||
}
|
||||
|
||||
static void line(int a, int b)
|
||||
{
|
||||
rb->lcd_drawline(point2D[a].x, point2D[a].y, point2D[b].x, point2D[b].y);
|
||||
}
|
||||
|
||||
static void cube_draw(void)
|
||||
{
|
||||
/* Draws front face */
|
||||
line(0,1); line(1,2);
|
||||
line(2,3); line(3,0);
|
||||
|
||||
/* Draws rear face */
|
||||
line(4,5); line(5,6);
|
||||
line(6,7); line(7,4);
|
||||
|
||||
/* Draws the other edges */
|
||||
line(0,5);
|
||||
line(1,4);
|
||||
line(2,7);
|
||||
line(3,6);
|
||||
}
|
||||
|
||||
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||
{
|
||||
int t_disp=0;
|
||||
char buffer[30];
|
||||
|
||||
int xa=0;
|
||||
int ya=0;
|
||||
int za=0;
|
||||
int xs=1;
|
||||
int ys=3;
|
||||
int zs=1;
|
||||
bool highspeed=0;
|
||||
bool exit=0;
|
||||
|
||||
TEST_PLUGIN_API(api);
|
||||
(void)(parameter);
|
||||
rb = api;
|
||||
|
||||
rb->lcd_setfont(FONT_SYSFIXED);
|
||||
|
||||
cube_init();
|
||||
|
||||
while(!exit)
|
||||
{
|
||||
if (!highspeed)
|
||||
rb->sleep(4);
|
||||
|
||||
rb->lcd_clear_display();
|
||||
cube_rotate(xa,ya,za);
|
||||
cube_viewport();
|
||||
cube_draw();
|
||||
if (t_disp>0)
|
||||
{
|
||||
t_disp--;
|
||||
rb->snprintf(buffer, 30, "x:%d y:%d z:%d h:%d",xs,ys,zs,highspeed);
|
||||
rb->lcd_putsxy(0, 56, buffer);
|
||||
}
|
||||
rb->lcd_update();
|
||||
|
||||
xa+=xs;
|
||||
if (xa>359)
|
||||
xa-=360;
|
||||
if (xa<0)
|
||||
xa+=360;
|
||||
ya+=ys;
|
||||
if (ya>359)
|
||||
ya-=360;
|
||||
if (ya<0)
|
||||
ya+=360;
|
||||
za+=zs;
|
||||
if (za>359)
|
||||
za-=360;
|
||||
if (za<0)
|
||||
za+=360;
|
||||
|
||||
switch(rb->button_get(false))
|
||||
{
|
||||
case BUTTON_RIGHT:
|
||||
xs+=1;
|
||||
if (xs>10)
|
||||
xs=10;
|
||||
t_disp=DISP_TIME;
|
||||
break;
|
||||
case BUTTON_LEFT:
|
||||
xs-=1;
|
||||
if (xs<-10)
|
||||
xs=-10;
|
||||
t_disp=DISP_TIME;
|
||||
break;
|
||||
case BUTTON_UP:
|
||||
ys+=1;
|
||||
if (ys>10)
|
||||
ys=10;
|
||||
t_disp=DISP_TIME;
|
||||
break;
|
||||
case BUTTON_DOWN:
|
||||
ys-=1;
|
||||
if (ys<-10)
|
||||
ys=-10;
|
||||
t_disp=DISP_TIME;
|
||||
break;
|
||||
case BUTTON_F2:
|
||||
zs+=1;
|
||||
if (zs>10)
|
||||
zs=10;
|
||||
t_disp=DISP_TIME;
|
||||
break;
|
||||
case BUTTON_F1:
|
||||
zs-=1;
|
||||
if (zs<-10)
|
||||
zs=-10;
|
||||
t_disp=DISP_TIME;
|
||||
break;
|
||||
case BUTTON_PLAY:
|
||||
highspeed=!highspeed;
|
||||
t_disp=DISP_TIME;
|
||||
break;
|
||||
case BUTTON_OFF|BUTTON_REL:
|
||||
exit=1;
|
||||
break;
|
||||
|
||||
case SYS_USB_CONNECTED:
|
||||
rb->usb_screen();
|
||||
return PLUGIN_USB_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
48
apps/plugins/helloworld.c
Normal file
48
apps/plugins/helloworld.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Björn Stenberg
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "plugin.h"
|
||||
|
||||
/* welcome to the example rockbox plugin */
|
||||
|
||||
/* here is a global api struct pointer. while not strictly necessary,
|
||||
it's nice not to have to pass the api pointer in all function calls
|
||||
in the plugin */
|
||||
static struct plugin_api* rb;
|
||||
|
||||
/* this is the plugin entry point */
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||
{
|
||||
/* this macro should be called as the first thing you do in the plugin.
|
||||
it test that the api version and model the plugin was compiled for
|
||||
matches the machine it is running on */
|
||||
TEST_PLUGIN_API(api);
|
||||
|
||||
/* if you don't use the parameter, you can do like
|
||||
this to avoid the compiler warning about it */
|
||||
(void)parameter;
|
||||
|
||||
/* if you are using a global api pointer, don't forget to copy it!
|
||||
otherwise you will get lovely "I04: IllInstr" errors... :-) */
|
||||
rb = api;
|
||||
|
||||
/* now go ahead and have fun! */
|
||||
rb->splash(HZ*2, 0, true, "Hello world!");
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
207
apps/plugins/oscillograph.c
Normal file
207
apps/plugins/oscillograph.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Philipp Pertermann
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "plugin.h"
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
#ifndef SIMULATOR /* don't want this code in the simulator */
|
||||
|
||||
/* The different drawing modes */
|
||||
#define DRAW_MODE_FILLED 0
|
||||
#define DRAW_MODE_OUTLINE 1
|
||||
#define DRAW_MODE_PIXEL 2
|
||||
#define DRAW_MODE_COUNT 3
|
||||
|
||||
#define MAX_PEAK 0x8000
|
||||
|
||||
/* number of ticks between two volume samples */
|
||||
static int speed = 1;
|
||||
/* roll == true -> lcd rolls */
|
||||
static bool roll = true;
|
||||
/* see DRAW_MODE_XXX constants for valid values */
|
||||
static int drawMode = DRAW_MODE_FILLED;
|
||||
|
||||
/**
|
||||
* Displays a vertically scrolling oscillosgraph using
|
||||
* hardware scrolling of the display. The user can change
|
||||
* speed
|
||||
*/
|
||||
enum plugin_status plugin_start(struct plugin_api* rb, void* parameter)
|
||||
{
|
||||
/* stores current volume value left */
|
||||
int left;
|
||||
/* stores current volume value right */
|
||||
int right;
|
||||
/* specifies the current position on the lcd */
|
||||
int y = LCD_WIDTH - 1;
|
||||
|
||||
/* only needed when drawing lines */
|
||||
int lastLeft = 0;
|
||||
int lastRight = 0;
|
||||
int lasty = 0;
|
||||
|
||||
bool exit = false;
|
||||
|
||||
TEST_PLUGIN_API(rb);
|
||||
(void)parameter;
|
||||
|
||||
/* the main loop */
|
||||
while (!exit) {
|
||||
|
||||
/* read the volume info from MAS */
|
||||
left = rb->mas_codec_readreg(0xC) / (MAX_PEAK / (LCD_WIDTH / 2 - 2));
|
||||
right = rb->mas_codec_readreg(0xD) / (MAX_PEAK / (LCD_WIDTH / 2 - 2));
|
||||
|
||||
/* delete current line */
|
||||
rb->lcd_clearline(0, y, LCD_WIDTH-1, y);
|
||||
|
||||
switch (drawMode) {
|
||||
case DRAW_MODE_FILLED:
|
||||
rb->lcd_drawline(LCD_WIDTH / 2 + 1 , y,
|
||||
LCD_WIDTH / 2 + 1 + right, y);
|
||||
rb->lcd_drawline(LCD_WIDTH / 2 - 1 , y,
|
||||
LCD_WIDTH / 2 - 1 -left , y);
|
||||
break;
|
||||
|
||||
case DRAW_MODE_OUTLINE:
|
||||
/* last position needed for lines */
|
||||
lasty = MAX(y-1, 0);
|
||||
|
||||
/* Here real lines were neccessary because
|
||||
anything else was ugly. */
|
||||
rb->lcd_drawline(LCD_WIDTH / 2 + right , y,
|
||||
LCD_WIDTH / 2 + lastRight , lasty);
|
||||
rb->lcd_drawline(LCD_WIDTH / 2 - left , y,
|
||||
LCD_WIDTH / 2 - lastLeft, lasty);
|
||||
|
||||
/* have to store the old values for drawing lines
|
||||
the next time */
|
||||
lastRight = right;
|
||||
lastLeft = left;
|
||||
break;
|
||||
|
||||
case DRAW_MODE_PIXEL:
|
||||
/* straight and simple */
|
||||
rb->lcd_drawpixel(LCD_WIDTH / 2 + right, y);
|
||||
rb->lcd_drawpixel(LCD_WIDTH / 2 - left, y);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* increment and adjust the drawing position */
|
||||
y++;
|
||||
if (y >= LCD_HEIGHT)
|
||||
y = 0;
|
||||
|
||||
/* I roll before update because otherwise the new
|
||||
line would appear at the wrong end of the display */
|
||||
if (roll)
|
||||
rb->lcd_roll(y);
|
||||
|
||||
/* now finally make the new sample visible */
|
||||
rb->lcd_update_rect(0, MAX(y-1, 0), LCD_WIDTH, 2);
|
||||
|
||||
/* There are two mechanisms to alter speed:
|
||||
1.) slowing down is achieved by increasing
|
||||
the time waiting for user input. This
|
||||
mechanism uses positive values.
|
||||
2.) speeding up is achieved by leaving out
|
||||
the user input check for (-speed) volume
|
||||
samples. For this mechanism negative values
|
||||
are used.
|
||||
*/
|
||||
|
||||
if (speed >= 0 || ((speed < 0) && (y % (-speed) == 0))) {
|
||||
bool draw = false;
|
||||
|
||||
/* speed values > 0 slow the oszi down. By user input
|
||||
speed might become < 1. If a value < 1 was
|
||||
passed user input would be disabled. Thus
|
||||
it must be ensured that at least 1 is passed. */
|
||||
|
||||
/* react to user input */
|
||||
switch (rb->button_get_w_tmo(MAX(speed, 1))) {
|
||||
case BUTTON_UP:
|
||||
speed++;
|
||||
draw = true;
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
speed--;
|
||||
draw = true;
|
||||
break;
|
||||
|
||||
case BUTTON_PLAY:
|
||||
/* pause the demo */
|
||||
rb->button_get(true);
|
||||
break;
|
||||
|
||||
case BUTTON_F1:
|
||||
/* toggle rolling */
|
||||
roll = !roll;
|
||||
break;
|
||||
|
||||
case BUTTON_F2:
|
||||
/* step through the display modes */
|
||||
drawMode ++;
|
||||
drawMode = drawMode % DRAW_MODE_COUNT;
|
||||
|
||||
/* lcd buffer might be rolled so that
|
||||
the transition from LCD_HEIGHT to 0
|
||||
takes place in the middle of the screen.
|
||||
That produces ugly results in DRAW_MODE_OUTLINE
|
||||
mode. If rolling is enabled this change will
|
||||
be reverted before the next update anyway.*/
|
||||
rb->lcd_roll(0);
|
||||
break;
|
||||
|
||||
case BUTTON_F3:
|
||||
speed = 1;
|
||||
draw = true;
|
||||
break;
|
||||
|
||||
case BUTTON_OFF:
|
||||
exit = true;
|
||||
break;
|
||||
|
||||
case SYS_USB_CONNECTED:
|
||||
rb->usb_screen();
|
||||
return PLUGIN_USB_CONNECTED;
|
||||
}
|
||||
|
||||
if (draw) {
|
||||
char buf[16];
|
||||
rb->snprintf(buf, sizeof buf, "Speed: %d", -speed);
|
||||
rb->lcd_putsxy(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT, buf);
|
||||
rb->lcd_update_rect(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT,
|
||||
LCD_WIDTH, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* restore to default roll position.
|
||||
Looks funny if you forget to do this... */
|
||||
rb->lcd_roll(0);
|
||||
rb->lcd_update();
|
||||
|
||||
/* standard return */
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
#endif /* #ifndef SIMULATOR */
|
||||
#endif
|
||||
26
apps/plugins/plugin.lds
Normal file
26
apps/plugins/plugin.lds
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
OUTPUT_FORMAT(elf32-sh)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
PLUGIN_RAM : ORIGIN = 0x091f8000, LENGTH = 0x8000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
*(.entry)
|
||||
*(.text)
|
||||
} > PLUGIN_RAM
|
||||
|
||||
.data : {
|
||||
*(.data)
|
||||
} > PLUGIN_RAM
|
||||
|
||||
.bss : {
|
||||
*(.bss)
|
||||
} > PLUGIN_RAM
|
||||
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
} > PLUGIN_RAM
|
||||
}
|
||||
111
apps/plugins/snow.c
Normal file
111
apps/plugins/snow.c
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Itai Shaked
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
**************************************************************************/
|
||||
#include "plugin.h"
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
|
||||
#define NUM_PARTICLES 100
|
||||
|
||||
static short particles[NUM_PARTICLES][2];
|
||||
static struct plugin_api* rb;
|
||||
|
||||
static bool particle_exists(int particle)
|
||||
{
|
||||
if (particles[particle][0]>=0 && particles[particle][1]>=0 &&
|
||||
particles[particle][0]<112 && particles[particle][1]<64)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static int create_particle(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NUM_PARTICLES; i++) {
|
||||
if (!particle_exists(i)) {
|
||||
particles[i][0]=(rb->rand()%112);
|
||||
particles[i][1]=0;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void snow_move(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!(rb->rand()%2))
|
||||
create_particle();
|
||||
|
||||
for (i=0; i<NUM_PARTICLES; i++) {
|
||||
if (particle_exists(i)) {
|
||||
rb->lcd_clearpixel(particles[i][0],particles[i][1]);
|
||||
switch ((rb->rand()%7)) {
|
||||
case 0:
|
||||
particles[i][0]++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
particles[i][0]--;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
break;
|
||||
|
||||
default:
|
||||
particles[i][1]++;
|
||||
break;
|
||||
}
|
||||
if (particle_exists(i))
|
||||
rb->lcd_drawpixel(particles[i][0],particles[i][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void snow_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NUM_PARTICLES; i++) {
|
||||
particles[i][0]=-1;
|
||||
particles[i][1]=-1;
|
||||
}
|
||||
rb->lcd_clear_display();
|
||||
}
|
||||
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||
{
|
||||
TEST_PLUGIN_API(api);
|
||||
(void)(parameter);
|
||||
rb = api;
|
||||
|
||||
snow_init();
|
||||
while (1) {
|
||||
snow_move();
|
||||
rb->lcd_update();
|
||||
rb->sleep(HZ/20);
|
||||
|
||||
if (rb->button_get(false) == BUTTON_OFF)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
868
apps/plugins/sokoban.c
Normal file
868
apps/plugins/sokoban.c
Normal file
|
|
@ -0,0 +1,868 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Eric Linenberg
|
||||
* February 2003: Robert Hak performs a cleanup/rewrite/feature addition.
|
||||
* Eric smiles. Bjorn cries. Linus say 'huh?'.
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "plugin.h"
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
|
||||
#define SOKOBAN_TITLE "Sokoban"
|
||||
#define SOKOBAN_TITLE_FONT 2
|
||||
|
||||
#define LEVELS_FILE "/.rockbox/sokoban/levels.txt"
|
||||
|
||||
#define ROWS 16
|
||||
#define COLS 20
|
||||
#define MAX_UNDOS 5
|
||||
|
||||
#define SOKOBAN_LEVEL_SIZE (ROWS*COLS)
|
||||
|
||||
static void init_undo(void);
|
||||
static void undo(void);
|
||||
static void add_undo(int button);
|
||||
|
||||
static int get_level(char *level, int level_size);
|
||||
static int get_level_count(void);
|
||||
static int load_level(void);
|
||||
static void draw_level(void);
|
||||
|
||||
static void init_boards(void);
|
||||
static void update_screen(void);
|
||||
static bool sokoban_loop(void);
|
||||
|
||||
/* The Location, Undo and LevelInfo structs are OO-flavored.
|
||||
* (oooh!-flavored as Schnueff puts it.) It makes more you have to know,
|
||||
* but the overall data layout becomes more manageable. */
|
||||
|
||||
/* We use the same three values in 2 structs. Makeing them a struct
|
||||
* hopefully ensures that if you change things in one, the other changes
|
||||
* as well. */
|
||||
struct LevelInfo {
|
||||
short level;
|
||||
short moves;
|
||||
short boxes_to_go;
|
||||
};
|
||||
|
||||
/* What a given location on the board looks like at a given time */
|
||||
struct Location {
|
||||
char spot;
|
||||
short row;
|
||||
short col;
|
||||
};
|
||||
|
||||
/* A single level of undo. Each undo move can affect upto,
|
||||
* but not more then, 3 spots on the board */
|
||||
struct Undo {
|
||||
struct LevelInfo level;
|
||||
struct Location location[3];
|
||||
};
|
||||
|
||||
/* Our full undo history */
|
||||
static struct UndoInfo {
|
||||
short count; /* How many undos are there in history */
|
||||
short current; /* Which history is the current undo */
|
||||
struct Undo history[MAX_UNDOS];
|
||||
} undo_info;
|
||||
|
||||
/* Our playing board */
|
||||
static struct BoardInfo {
|
||||
char board[ROWS][COLS];
|
||||
struct LevelInfo level;
|
||||
struct Location player;
|
||||
int max_level; /* How many levels do we have? */
|
||||
int level_offset; /* Where in the level file is this level */
|
||||
int loaded_level; /* Which level is in memory */
|
||||
} current_info;
|
||||
|
||||
static struct plugin_api* rb;
|
||||
|
||||
static void init_undo(void)
|
||||
{
|
||||
undo_info.count = 0;
|
||||
undo_info.current = 0;
|
||||
}
|
||||
|
||||
static void undo(void)
|
||||
{
|
||||
struct Undo *undo;
|
||||
int i = 0;
|
||||
short row, col;
|
||||
|
||||
if (undo_info.count == 0)
|
||||
return;
|
||||
|
||||
/* Update board info */
|
||||
undo = &undo_info.history[undo_info.current];
|
||||
|
||||
rb->memcpy(¤t_info.level, &undo->level, sizeof(undo->level));
|
||||
rb->memcpy(¤t_info.player, &undo->location[0], sizeof(undo->location[0]));
|
||||
|
||||
row = undo->location[0].row;
|
||||
col = undo->location[0].col;
|
||||
current_info.board[row][col] = '@';
|
||||
|
||||
/* Update the two other possible spots */
|
||||
for (i = 1; i < 3; i++) {
|
||||
if (undo->location[i].spot != '\0') {
|
||||
row = undo->location[i].row;
|
||||
col = undo->location[i].col;
|
||||
current_info.board[row][col] = undo->location[i].spot;
|
||||
undo->location[i].spot = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove this undo from the list */
|
||||
if (undo_info.current == 0) {
|
||||
if (undo_info.count > 1)
|
||||
undo_info.current = MAX_UNDOS - 1;
|
||||
} else {
|
||||
undo_info.current--;
|
||||
}
|
||||
|
||||
undo_info.count--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void add_undo(int button)
|
||||
{
|
||||
struct Undo *undo;
|
||||
int row, col, i;
|
||||
bool storable;
|
||||
|
||||
if ((button != BUTTON_LEFT) && (button != BUTTON_RIGHT) &&
|
||||
(button != BUTTON_UP) && (button != BUTTON_DOWN))
|
||||
return;
|
||||
|
||||
if (undo_info.count != 0) {
|
||||
if (undo_info.current < (MAX_UNDOS - 1))
|
||||
undo_info.current++;
|
||||
else
|
||||
undo_info.current = 0;
|
||||
}
|
||||
|
||||
/* Make what follows more readable */
|
||||
undo = &undo_info.history[undo_info.current];
|
||||
|
||||
/* Store our level info */
|
||||
rb->memcpy(&undo->level, ¤t_info.level, sizeof(undo->level));
|
||||
|
||||
/* Store our player info */
|
||||
rb->memcpy(&undo->location[0], ¤t_info.player, sizeof(undo->location[0]));
|
||||
|
||||
/* Now we need to store upto 2 blocks that may be affected.
|
||||
* If player.spot is NULL, then there is no info stored
|
||||
* for that block */
|
||||
|
||||
row = current_info.player.row;
|
||||
col = current_info.player.col;
|
||||
|
||||
/* This must stay as _1_ because the first block (0) is the player */
|
||||
for (i = 1; i < 3; i++) {
|
||||
storable = true;
|
||||
|
||||
switch (button) {
|
||||
case BUTTON_LEFT:
|
||||
col--;
|
||||
if (col < 0)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
case BUTTON_RIGHT:
|
||||
col++;
|
||||
if (col >= COLS)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
case BUTTON_UP:
|
||||
row--;
|
||||
if (row < 0)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
row++;
|
||||
if (row >= ROWS)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (storable) {
|
||||
undo->location[i].col = col;
|
||||
undo->location[i].row = row;
|
||||
undo->location[i].spot = current_info.board[row][col];
|
||||
} else {
|
||||
undo->location[i].spot = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (undo_info.count < MAX_UNDOS)
|
||||
undo_info.count++;
|
||||
}
|
||||
|
||||
static void init_boards(void)
|
||||
{
|
||||
current_info.level.level = 0;
|
||||
current_info.level.moves = 0;
|
||||
current_info.level.boxes_to_go = 0;
|
||||
current_info.player.row = 0;
|
||||
current_info.player.col = 0;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.max_level = 0;
|
||||
current_info.level_offset = 0;
|
||||
current_info.loaded_level = 0;
|
||||
|
||||
init_undo();
|
||||
}
|
||||
|
||||
static int get_level_count(void)
|
||||
{
|
||||
int fd = 0;
|
||||
int lastlen = 0;
|
||||
char buffer[COLS + 3]; /* COLS plus CR/LF and \0 */
|
||||
|
||||
if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0) {
|
||||
rb->splash(0, 0, true, "Unable to open %s", LEVELS_FILE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
int len = rb->read_line(fd, buffer, sizeof(buffer));
|
||||
if(len <= 0)
|
||||
break;
|
||||
|
||||
/* Two short lines in a row means new level */
|
||||
if(len < 3 && lastlen < 3)
|
||||
current_info.max_level++;
|
||||
|
||||
lastlen = len;
|
||||
}
|
||||
|
||||
rb->close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_level(char *level, int level_size)
|
||||
{
|
||||
int fd = 0, i = 0;
|
||||
int nread = 0;
|
||||
int count = 0;
|
||||
int lastlen = 0;
|
||||
int level_ct = 1;
|
||||
unsigned char buffer[SOKOBAN_LEVEL_SIZE * 2];
|
||||
bool level_found = false;
|
||||
|
||||
/* open file */
|
||||
if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0)
|
||||
return -1;
|
||||
|
||||
/* Lets not reparse the full file if we can avoid it */
|
||||
if (current_info.loaded_level < current_info.level.level) {
|
||||
rb->lseek(fd, current_info.level_offset, SEEK_SET);
|
||||
level_ct = current_info.loaded_level;
|
||||
}
|
||||
|
||||
if(current_info.level.level > 1) {
|
||||
while(!level_found) {
|
||||
int len = rb->read_line(fd, buffer, SOKOBAN_LEVEL_SIZE);
|
||||
if(len <= 0) {
|
||||
rb->close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Two short lines in a row means new level */
|
||||
if(len < 3 && lastlen < 3) {
|
||||
level_ct++;
|
||||
if(level_ct == current_info.level.level)
|
||||
level_found = true;
|
||||
}
|
||||
lastlen = len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the current offset */
|
||||
current_info.level_offset = rb->lseek(fd, 0, SEEK_CUR);
|
||||
|
||||
/* read a full buffer chunk from here */
|
||||
nread = rb->read(fd, buffer, sizeof(buffer)-1);
|
||||
if (nread < 0)
|
||||
return -1;
|
||||
buffer[nread] = 0;
|
||||
|
||||
rb->close(fd);
|
||||
|
||||
/* If we read less then a level, error */
|
||||
if (nread < level_size)
|
||||
return -1;
|
||||
|
||||
/* Load our new level */
|
||||
for(i=0, count=0; (count < nread) && (i<level_size);) {
|
||||
if (buffer[count] != '\n' && buffer[count] != '\r')
|
||||
level[i++] = buffer[count];
|
||||
count++;
|
||||
}
|
||||
level[i] = 0;
|
||||
|
||||
current_info.loaded_level = current_info.level.level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return non-zero on error */
|
||||
static int load_level(void)
|
||||
{
|
||||
short c = 0;
|
||||
short r = 0;
|
||||
short i = 0;
|
||||
char level[ROWS*COLS+1];
|
||||
int x = 0;
|
||||
|
||||
current_info.player.spot=' ';
|
||||
current_info.level.boxes_to_go = 0;
|
||||
current_info.level.moves = 0;
|
||||
|
||||
if (get_level(level, sizeof(level)) != 0)
|
||||
return -1;
|
||||
|
||||
i = 0;
|
||||
for (r = 0; r < ROWS; r++) {
|
||||
x++;
|
||||
for (c = 0; c < COLS; c++, i++) {
|
||||
current_info.board[r][c] = level[i];
|
||||
|
||||
if (current_info.board[r][c] == '.')
|
||||
current_info.level.boxes_to_go++;
|
||||
|
||||
else if (current_info.board[r][c] == '@') {
|
||||
current_info.player.row = r;
|
||||
current_info.player.col = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_screen(void)
|
||||
{
|
||||
short b = 0, c = 0;
|
||||
short rows = 0, cols = 0;
|
||||
char s[25];
|
||||
|
||||
short magnify = 4;
|
||||
|
||||
/* load the board to the screen */
|
||||
for (rows=0 ; rows < ROWS ; rows++) {
|
||||
for (cols = 0 ; cols < COLS ; cols++) {
|
||||
c = cols * magnify;
|
||||
b = rows * magnify;
|
||||
|
||||
switch(current_info.board[rows][cols]) {
|
||||
case 'X': /* black space */
|
||||
rb->lcd_drawrect(c, b, magnify, magnify);
|
||||
rb->lcd_drawrect(c+1, b+1, 2, 2);
|
||||
break;
|
||||
|
||||
case '#': /* this is a wall */
|
||||
rb->lcd_drawpixel(c, b);
|
||||
rb->lcd_drawpixel(c+2, b);
|
||||
rb->lcd_drawpixel(c+1, b+1);
|
||||
rb->lcd_drawpixel(c+3, b+1);
|
||||
rb->lcd_drawpixel(c, b+2);
|
||||
rb->lcd_drawpixel(c+2, b+2);
|
||||
rb->lcd_drawpixel(c+1, b+3);
|
||||
rb->lcd_drawpixel(c+3, b+3);
|
||||
break;
|
||||
|
||||
case '.': /* this is a home location */
|
||||
rb->lcd_drawrect(c+1, b+1, 2, 2);
|
||||
break;
|
||||
|
||||
case '$': /* this is a box */
|
||||
rb->lcd_drawrect(c, b, magnify, magnify);
|
||||
break;
|
||||
|
||||
case '@': /* this is you */
|
||||
rb->lcd_drawline(c+1, b, c+2, b);
|
||||
rb->lcd_drawline(c, b+1, c+3, b+1);
|
||||
rb->lcd_drawline(c+1, b+2, c+2, b+2);
|
||||
|
||||
rb->lcd_drawpixel(c, b+3);
|
||||
rb->lcd_drawpixel(c+3, b+3);
|
||||
break;
|
||||
|
||||
case '%': /* this is a box on a home spot */
|
||||
rb->lcd_drawrect(c, b, magnify, magnify);
|
||||
rb->lcd_drawrect(c+1, b+1, 2, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rb->snprintf(s, sizeof(s), "%d", current_info.level.level);
|
||||
rb->lcd_putsxy(86, 22, s);
|
||||
rb->snprintf(s, sizeof(s), "%d", current_info.level.moves);
|
||||
rb->lcd_putsxy(86, 54, s);
|
||||
|
||||
rb->lcd_drawrect(80,0,32,32);
|
||||
rb->lcd_drawrect(80,32,32,64);
|
||||
rb->lcd_putsxy(81, 10, "Level");
|
||||
rb->lcd_putsxy(81, 42, "Moves");
|
||||
|
||||
/* print out the screen */
|
||||
rb->lcd_update();
|
||||
}
|
||||
|
||||
static void draw_level(void)
|
||||
{
|
||||
load_level();
|
||||
rb->lcd_clear_display();
|
||||
update_screen();
|
||||
}
|
||||
|
||||
static bool sokoban_loop(void)
|
||||
{
|
||||
char new_spot;
|
||||
bool moved = true;
|
||||
int i = 0, button = 0;
|
||||
short r = 0, c = 0;
|
||||
|
||||
current_info.level.level = 1;
|
||||
|
||||
load_level();
|
||||
update_screen();
|
||||
|
||||
while (1) {
|
||||
moved = true;
|
||||
|
||||
r = current_info.player.row;
|
||||
c = current_info.player.col;
|
||||
|
||||
button = rb->button_get(true);
|
||||
|
||||
add_undo(button);
|
||||
|
||||
switch(button)
|
||||
{
|
||||
case BUTTON_OFF:
|
||||
/* get out of here */
|
||||
return PLUGIN_OK;
|
||||
|
||||
case BUTTON_ON:
|
||||
case BUTTON_ON | BUTTON_REPEAT:
|
||||
/* this is UNDO */
|
||||
undo();
|
||||
rb->lcd_clear_display();
|
||||
update_screen();
|
||||
moved = false;
|
||||
break;
|
||||
|
||||
case BUTTON_F3:
|
||||
case BUTTON_F3 | BUTTON_REPEAT:
|
||||
/* increase level */
|
||||
init_undo();
|
||||
current_info.level.boxes_to_go=0;
|
||||
moved = true;
|
||||
break;
|
||||
|
||||
case BUTTON_F1:
|
||||
case BUTTON_F1 | BUTTON_REPEAT:
|
||||
/* previous level */
|
||||
init_undo();
|
||||
if (current_info.level.level > 1)
|
||||
current_info.level.level--;
|
||||
|
||||
draw_level();
|
||||
moved = false;
|
||||
break;
|
||||
|
||||
case BUTTON_F2:
|
||||
case BUTTON_F2 | BUTTON_REPEAT:
|
||||
/* same level */
|
||||
init_undo();
|
||||
draw_level();
|
||||
moved = false;
|
||||
break;
|
||||
|
||||
case BUTTON_LEFT:
|
||||
switch(current_info.board[r][c-1])
|
||||
{
|
||||
case ' ': /* if it is a blank spot */
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r][c-1];
|
||||
current_info.board[r][c-1] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r][c-2])
|
||||
{
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r][c-2] = current_info.board[r][c-1];
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r][c-2] = '%';
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r][c-2]) {
|
||||
case ' ': /* we are going from a home to a blank */
|
||||
current_info.board[r][c-2] = '$';
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.': /* if we are going from a home to home */
|
||||
current_info.board[r][c-2] = '%';
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.col--;
|
||||
break;
|
||||
|
||||
case BUTTON_RIGHT: /* if it is a blank spot */
|
||||
switch(current_info.board[r][c+1]) {
|
||||
case ' ':
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r][c+1];
|
||||
current_info.board[r][c+1] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r][c+2]) {
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r][c+2] = current_info.board[r][c+1];
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r][c+2] = '%';
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r][c+2]) {
|
||||
case ' ': /* going from a home to a blank */
|
||||
current_info.board[r][c+2] = '$';
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
current_info.board[r][c+2] = '%';
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.col++;
|
||||
break;
|
||||
|
||||
case BUTTON_UP:
|
||||
switch(current_info.board[r-1][c]) {
|
||||
case ' ': /* if it is a blank spot */
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r-1][c];
|
||||
current_info.board[r-1][c] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r-2][c]) {
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r-2][c] = current_info.board[r-1][c];
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r-2][c] = '%';
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r-2][c]) {
|
||||
case ' ': /* we are going from a home to a blank */
|
||||
current_info.board[r-2][c] = '$';
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.': /* if we are going from a home to home */
|
||||
current_info.board[r-2][c] = '%';
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.row--;
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
switch(current_info.board[r+1][c]) {
|
||||
case ' ': /* if it is a blank spot */
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r+1][c];
|
||||
current_info.board[r+1][c] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r+2][c]) {
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r+2][c] = current_info.board[r+1][c];
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r+2][c] = '%';
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r+2][c]) {
|
||||
case ' ': /* going from a home to a blank */
|
||||
current_info.board[r+2][c] = '$';
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.': /* going from a home to home */
|
||||
current_info.board[r+2][c] = '%';
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.row++;
|
||||
break;
|
||||
|
||||
case SYS_USB_CONNECTED:
|
||||
rb->usb_screen();
|
||||
return PLUGIN_USB_CONNECTED;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved) {
|
||||
current_info.level.moves++;
|
||||
rb->lcd_clear_display();
|
||||
update_screen();
|
||||
}
|
||||
|
||||
/* We have completed this level */
|
||||
if (current_info.level.boxes_to_go == 0) {
|
||||
current_info.level.level++;
|
||||
|
||||
/* clear undo stats */
|
||||
init_undo();
|
||||
|
||||
rb->lcd_clear_display();
|
||||
|
||||
if (current_info.level.level > current_info.max_level) {
|
||||
rb->lcd_putsxy(10, 20, "You WIN!!");
|
||||
|
||||
for (i = 0; i < 30000 ; i++) {
|
||||
rb->lcd_invertrect(0, 0, 111, 63);
|
||||
rb->lcd_update();
|
||||
|
||||
button = rb->button_get(false);
|
||||
if (button && ((button & BUTTON_REL) != BUTTON_REL))
|
||||
break;
|
||||
}
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
load_level();
|
||||
update_screen();
|
||||
}
|
||||
|
||||
} /* end while */
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||
{
|
||||
int w, h;
|
||||
int len;
|
||||
|
||||
TEST_PLUGIN_API(api);
|
||||
(void)(parameter);
|
||||
rb = api;
|
||||
|
||||
rb->lcd_setfont(FONT_SYSFIXED);
|
||||
rb->lcd_getstringsize(SOKOBAN_TITLE, &w, &h);
|
||||
|
||||
/* Get horizontel centering for text */
|
||||
len = w;
|
||||
if (len%2 != 0)
|
||||
len =((len+1)/2)+(w/2);
|
||||
else
|
||||
len /= 2;
|
||||
|
||||
if (h%2 != 0)
|
||||
h = (h/2)+1;
|
||||
else
|
||||
h /= 2;
|
||||
|
||||
rb->lcd_clear_display();
|
||||
rb->lcd_putsxy(LCD_WIDTH/2-len,(LCD_HEIGHT/2)-h, SOKOBAN_TITLE);
|
||||
rb->lcd_update();
|
||||
rb->sleep(HZ*2);
|
||||
|
||||
rb->lcd_clear_display();
|
||||
|
||||
rb->lcd_putsxy(3, 6, "[OFF] To Stop");
|
||||
rb->lcd_putsxy(3, 16, "[ON] To Undo");
|
||||
rb->lcd_putsxy(3, 26, "[F1] - Level");
|
||||
rb->lcd_putsxy(3, 36, "[F2] Same Level");
|
||||
rb->lcd_putsxy(3, 46, "[F3] + Level");
|
||||
|
||||
rb->lcd_update();
|
||||
rb->sleep(HZ*2);
|
||||
rb->lcd_clear_display();
|
||||
|
||||
init_boards();
|
||||
|
||||
if (get_level_count() != 0) {
|
||||
rb->splash(HZ*2,0,true,"Failed loading levels!");
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
return sokoban_loop();
|
||||
}
|
||||
|
||||
#endif
|
||||
415
apps/plugins/viewer.c
Normal file
415
apps/plugins/viewer.c
Normal file
|
|
@ -0,0 +1,415 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Gilles Roux
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "plugin.h"
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
#define OUTSIDE_BUFFER -10
|
||||
#define OUTSIDE_FILE -11
|
||||
|
||||
static int fd;
|
||||
static int file_size;
|
||||
|
||||
static char buffer[BUFFER_SIZE+1];
|
||||
static int buffer_pos; /* Position of the buffer in the file */
|
||||
|
||||
static char display_lines; /* number of lines on the display */
|
||||
static char display_columns; /* number of columns on the display */
|
||||
static int begin_line; /* Index of the first line displayed on the lcd */
|
||||
static int end_line; /* Index of the last line displayed on the lcd */
|
||||
static int begin_line_pos; /* Position of the first_line in the bufffer */
|
||||
static int end_line_pos; /* Position of the last_line in the buffer */
|
||||
static struct plugin_api* rb;
|
||||
|
||||
/*
|
||||
* Known issue: The caching algorithm will fail (display incoherent data) if
|
||||
* the total space of the lines that are displayed on the screen exceeds the
|
||||
* buffer size (only happens with very long lines).
|
||||
*/
|
||||
|
||||
static void display_line_count(void)
|
||||
{
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
int w,h;
|
||||
rb->lcd_getstringsize("M", &w, &h);
|
||||
display_lines = LCD_HEIGHT / h;
|
||||
display_columns = LCD_WIDTH / w;
|
||||
#else
|
||||
display_lines = 2;
|
||||
display_columns = 11;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int find_next_line(int pos)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE)
|
||||
return pos;
|
||||
|
||||
i = pos;
|
||||
if (buffer_pos+i>=file_size) {
|
||||
return OUTSIDE_FILE;
|
||||
}
|
||||
while (1) {
|
||||
i++;
|
||||
if (buffer_pos+i==file_size) {
|
||||
return i;
|
||||
}
|
||||
if (i>=BUFFER_SIZE) {
|
||||
return OUTSIDE_BUFFER;
|
||||
}
|
||||
if (buffer[i]==0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int find_prev_line(int pos)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE)
|
||||
return pos;
|
||||
|
||||
i = pos;
|
||||
if (buffer_pos+i<0) {
|
||||
return OUTSIDE_FILE;
|
||||
}
|
||||
while (1) {
|
||||
i--;
|
||||
if (buffer_pos+i<0) {
|
||||
return i;
|
||||
}
|
||||
if (i<0) {
|
||||
return OUTSIDE_BUFFER;
|
||||
}
|
||||
if (buffer[i]==0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void viewer_draw(int col)
|
||||
{
|
||||
int i, j;
|
||||
char* str;
|
||||
int line_pos;
|
||||
|
||||
rb->lcd_clear_display();
|
||||
|
||||
line_pos = begin_line_pos;
|
||||
|
||||
for (i=0; i <= end_line - begin_line; i++) {
|
||||
if (line_pos == OUTSIDE_BUFFER ||
|
||||
line_pos == OUTSIDE_FILE)
|
||||
break;
|
||||
str = buffer + line_pos + 1;
|
||||
for (j=0; j<col && *str!=0; ++j)
|
||||
str++;
|
||||
rb->lcd_puts(0, i, str);
|
||||
line_pos = find_next_line(line_pos);
|
||||
}
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
rb->lcd_update();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void fill_buffer(int pos)
|
||||
{
|
||||
int i;
|
||||
int numread;
|
||||
|
||||
if (pos>=file_size-BUFFER_SIZE)
|
||||
pos = file_size-BUFFER_SIZE;
|
||||
if (pos<0)
|
||||
pos = 0;
|
||||
|
||||
rb->lseek(fd, pos, SEEK_SET);
|
||||
numread = rb->read(fd, buffer, BUFFER_SIZE);
|
||||
|
||||
begin_line_pos -= pos - buffer_pos;
|
||||
end_line_pos -= pos - buffer_pos;
|
||||
buffer_pos = pos;
|
||||
|
||||
buffer[numread] = 0;
|
||||
for(i=0;i<numread;i++) {
|
||||
switch(buffer[i]) {
|
||||
case '\r':
|
||||
buffer[i] = ' ';
|
||||
break;
|
||||
case '\n':
|
||||
buffer[i] = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool viewer_init(char* file)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
fd = rb->open(file, O_RDONLY);
|
||||
if (fd==-1)
|
||||
return false;
|
||||
|
||||
file_size = rb->lseek(fd, 0, SEEK_END);
|
||||
|
||||
buffer_pos = 0;
|
||||
begin_line = 0;
|
||||
begin_line_pos = -1;
|
||||
end_line = -1;
|
||||
end_line_pos = -1;
|
||||
fill_buffer(0);
|
||||
display_line_count();
|
||||
for (i=0; i<display_lines; ++i) {
|
||||
ret = find_next_line(end_line_pos);
|
||||
if (ret!=OUTSIDE_FILE && ret!=OUTSIDE_BUFFER) {
|
||||
end_line_pos = ret;
|
||||
end_line++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void viewer_exit(void)
|
||||
{
|
||||
rb->close(fd);
|
||||
}
|
||||
|
||||
static void viewer_scroll_down(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = find_next_line(end_line_pos);
|
||||
switch ( ret ) {
|
||||
case OUTSIDE_BUFFER:
|
||||
begin_line_pos = find_next_line(begin_line_pos);
|
||||
fill_buffer(begin_line_pos+buffer_pos);
|
||||
end_line_pos = find_next_line(end_line_pos);
|
||||
break;
|
||||
|
||||
case OUTSIDE_FILE:
|
||||
return;
|
||||
|
||||
default:
|
||||
begin_line_pos = find_next_line(begin_line_pos);
|
||||
end_line_pos = ret;
|
||||
break;
|
||||
}
|
||||
begin_line++;
|
||||
end_line++;
|
||||
}
|
||||
|
||||
static void viewer_scroll_up(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = find_prev_line(begin_line_pos);
|
||||
switch ( ret ) {
|
||||
case OUTSIDE_BUFFER:
|
||||
end_line_pos = find_prev_line(end_line_pos);
|
||||
fill_buffer(buffer_pos+end_line_pos-BUFFER_SIZE);
|
||||
begin_line_pos = find_prev_line(begin_line_pos);
|
||||
break;
|
||||
|
||||
case OUTSIDE_FILE:
|
||||
return;
|
||||
|
||||
default:
|
||||
end_line_pos = find_prev_line(end_line_pos);
|
||||
begin_line_pos = ret;
|
||||
break;
|
||||
}
|
||||
begin_line--;
|
||||
end_line--;
|
||||
}
|
||||
|
||||
static int pagescroll(int col)
|
||||
{
|
||||
bool exit = false;
|
||||
int i;
|
||||
|
||||
while (!exit) {
|
||||
switch (rb->button_get(true)) {
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_ON | BUTTON_UP:
|
||||
case BUTTON_ON | BUTTON_UP | BUTTON_REPEAT:
|
||||
#else
|
||||
case BUTTON_ON | BUTTON_LEFT:
|
||||
case BUTTON_ON | BUTTON_LEFT | BUTTON_REPEAT:
|
||||
#endif
|
||||
for (i=0; i<display_lines; i++)
|
||||
viewer_scroll_up();
|
||||
break;
|
||||
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_ON | BUTTON_DOWN:
|
||||
case BUTTON_ON | BUTTON_DOWN | BUTTON_REPEAT:
|
||||
#else
|
||||
case BUTTON_ON | BUTTON_RIGHT:
|
||||
case BUTTON_ON | BUTTON_RIGHT | BUTTON_REPEAT:
|
||||
#endif
|
||||
for (i=0; i<display_lines; i++)
|
||||
viewer_scroll_down();
|
||||
break;
|
||||
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_ON | BUTTON_LEFT:
|
||||
case BUTTON_ON | BUTTON_LEFT | BUTTON_REPEAT:
|
||||
#else
|
||||
case BUTTON_ON | BUTTON_MENU | BUTTON_LEFT:
|
||||
case BUTTON_ON | BUTTON_MENU | BUTTON_LEFT | BUTTON_REPEAT:
|
||||
#endif
|
||||
col -= display_columns;
|
||||
if (col < 0)
|
||||
col = 0;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_ON | BUTTON_RIGHT:
|
||||
case BUTTON_ON | BUTTON_RIGHT | BUTTON_REPEAT:
|
||||
#else
|
||||
case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT:
|
||||
case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT | BUTTON_REPEAT:
|
||||
#endif
|
||||
col += display_columns;
|
||||
break;
|
||||
|
||||
case BUTTON_ON | BUTTON_REL:
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_ON | BUTTON_DOWN | BUTTON_REL:
|
||||
case BUTTON_ON | BUTTON_UP | BUTTON_REL:
|
||||
#else
|
||||
case BUTTON_ON | BUTTON_RIGHT | BUTTON_REL:
|
||||
case BUTTON_ON | BUTTON_LEFT | BUTTON_REL:
|
||||
case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT | BUTTON_REL:
|
||||
case BUTTON_ON | BUTTON_MENU | BUTTON_LEFT | BUTTON_REL:
|
||||
#endif
|
||||
exit = true;
|
||||
break;
|
||||
}
|
||||
if ( !exit )
|
||||
viewer_draw(col);
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* file)
|
||||
{
|
||||
bool exit=false;
|
||||
int button;
|
||||
int col = 0;
|
||||
int ok;
|
||||
|
||||
TEST_PLUGIN_API(api);
|
||||
rb = api;
|
||||
|
||||
if (!file)
|
||||
return PLUGIN_ERROR;
|
||||
|
||||
ok = viewer_init(file);
|
||||
if (!ok) {
|
||||
rb->splash(HZ, 0, false, "Error");
|
||||
viewer_exit();
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
viewer_draw(col);
|
||||
while (!exit) {
|
||||
button = rb->button_get(true);
|
||||
|
||||
switch ( button ) {
|
||||
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_F1:
|
||||
case BUTTON_OFF:
|
||||
#else
|
||||
case BUTTON_STOP:
|
||||
#endif
|
||||
viewer_exit();
|
||||
exit = true;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_UP:
|
||||
case BUTTON_UP | BUTTON_REPEAT:
|
||||
#else
|
||||
case BUTTON_LEFT:
|
||||
case BUTTON_LEFT | BUTTON_REPEAT:
|
||||
#endif
|
||||
viewer_scroll_up();
|
||||
viewer_draw(col);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_DOWN:
|
||||
case BUTTON_DOWN | BUTTON_REPEAT:
|
||||
#else
|
||||
case BUTTON_RIGHT:
|
||||
case BUTTON_RIGHT | BUTTON_REPEAT:
|
||||
#endif
|
||||
viewer_scroll_down();
|
||||
viewer_draw(col);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_LEFT:
|
||||
case BUTTON_LEFT | BUTTON_REPEAT:
|
||||
#else
|
||||
case BUTTON_MENU | BUTTON_LEFT:
|
||||
case BUTTON_MENU | BUTTON_LEFT | BUTTON_REPEAT:
|
||||
#endif
|
||||
col--;
|
||||
if (col < 0)
|
||||
col = 0;
|
||||
viewer_draw(col);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
case BUTTON_RIGHT:
|
||||
case BUTTON_RIGHT | BUTTON_REPEAT:
|
||||
#else
|
||||
case BUTTON_MENU | BUTTON_RIGHT:
|
||||
case BUTTON_MENU | BUTTON_RIGHT | BUTTON_REPEAT:
|
||||
#endif
|
||||
col++;
|
||||
viewer_draw(col);
|
||||
break;
|
||||
|
||||
case BUTTON_ON:
|
||||
#ifdef HAVE_PLAYER_KEYPAD
|
||||
case BUTTON_ON | BUTTON_MENU:
|
||||
#endif
|
||||
col = pagescroll(col);
|
||||
break;
|
||||
|
||||
case SYS_USB_CONNECTED:
|
||||
rb->usb_screen();
|
||||
viewer_exit();
|
||||
return PLUGIN_USB_CONNECTED;
|
||||
}
|
||||
}
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
2009
apps/plugins/wormlet.c
Normal file
2009
apps/plugins/wormlet.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue