1
0
Fork 0
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:
Björn Stenberg 2003-06-29 16:33:04 +00:00
parent 9bcbe3fd72
commit ba371fb595
29 changed files with 1869 additions and 1889 deletions

45
apps/plugins/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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(&current_info.level, &undo->level, sizeof(undo->level));
rb->memcpy(&current_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, &current_info.level, sizeof(undo->level));
/* Store our player info */
rb->memcpy(&undo->location[0], &current_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
View 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

File diff suppressed because it is too large Load diff