summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2003-06-29 16:33:04 +0000
committerBjörn Stenberg <bjorn@haxx.se>2003-06-29 16:33:04 +0000
commitba371fb595affd68c823926b85718d1d613dc7d3 (patch)
treecfda303d0603d623cdb12f3928905d3ae02f1d87
parent9bcbe3fd723d23a709873a0855f27b86bc5c96f1 (diff)
downloadrockbox-ba371fb595affd68c823926b85718d1d613dc7d3.tar.gz
rockbox-ba371fb595affd68c823926b85718d1d613dc7d3.zip
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
-rw-r--r--apps/Makefile8
-rw-r--r--apps/demo_menu.c37
-rw-r--r--apps/games_menu.c29
-rw-r--r--apps/lang/english.lang76
-rw-r--r--apps/player/icons.h3
-rw-r--r--apps/plugin.c221
-rw-r--r--apps/plugin.h161
-rw-r--r--apps/plugins/Makefile45
-rw-r--r--apps/plugins/bounce.c (renamed from apps/recorder/bounce.c)96
-rw-r--r--apps/plugins/cube.c (renamed from apps/recorder/cube.c)63
-rw-r--r--apps/plugins/helloworld.c48
-rw-r--r--apps/plugins/oscillograph.c (renamed from apps/recorder/oscillograph.c)82
-rw-r--r--apps/plugins/plugin.lds26
-rw-r--r--apps/plugins/snow.c (renamed from apps/recorder/snow.c)46
-rw-r--r--apps/plugins/sokoban.c868
-rw-r--r--apps/plugins/viewer.c (renamed from apps/viewer.c)71
-rw-r--r--apps/plugins/wormlet.c (renamed from apps/recorder/wormlet.c)427
-rw-r--r--apps/recorder/icons.c1
-rw-r--r--apps/recorder/icons.h1
-rw-r--r--apps/recorder/sokoban.c891
-rw-r--r--apps/recorder/sokoban.h28
-rw-r--r--apps/recorder/tetris.c438
-rw-r--r--apps/recorder/wormlet.h28
-rw-r--r--apps/screens.c1
-rw-r--r--apps/tree.c19
-rw-r--r--apps/tree.h1
-rw-r--r--apps/viewer.h24
-rw-r--r--firmware/app.lds15
-rw-r--r--firmware/drivers/lcd-player-charset.c4
29 files changed, 1869 insertions, 1889 deletions
diff --git a/apps/Makefile b/apps/Makefile
index 3e5fbdc2dd..9614050cda 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -20,7 +20,7 @@ DOCSDIR := ../docs
INCLUDES= -I$(FIRMWARE)/include -I$(FIRMWARE)/export -I. -I$(OBJDIR)
-CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(TARGET) $(DEFINES) -DAPPSVERSION=\"$(VERSION)\" $(EXTRA_DEFINES) -DMEM=${MEM}
+CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(TARGET) $(DEFINES) -DAPPSVERSION=\"$(VERSION)\" $(EXTRA_DEFINES) -DMEM=${MEM} -DPLUGIN=1
AFLAGS += -small -relax
# Check if this is a kind of Recorder
@@ -71,7 +71,10 @@ ifndef TOOLSDIR
TOOLSDIR=../tools
endif
-all : $(OBJDIR)/$(OUTNAME)
+all : $(OBJDIR)/$(OUTNAME) rocks
+
+rocks:
+ $(MAKE) -C plugins TARGET=$(TARGET) DEBUG=$(DEBUG) OBJDIR=$(OBJDIR) VERSION=$(VERSION) EXTRA_DEFINES="$(EXTRA_DEFINES)"
$(OBJDIR)/librockbox.a:
make -C $(FIRMWARE) TARGET=$(TARGET) DEBUG=$(DEBUG) OBJDIR=$(OBJDIR)
@@ -117,6 +120,7 @@ clean:
$(OBJDIR)/lang.o $(OBJDIR)/build.lang $(OBJDIR)/lang.[ch] \
$(OBJDIR)/credits.raw $(LINKFILE)
-$(RM) -r $(OBJDIR)/$(DEPS)
+ $(MAKE) -C plugins clean
DEPS:=.deps
DEPDIRS:=$(DEPS)
diff --git a/apps/demo_menu.c b/apps/demo_menu.c
index f6934e49be..be8e44522c 100644
--- a/apps/demo_menu.c
+++ b/apps/demo_menu.c
@@ -24,19 +24,38 @@
#include <stdio.h>
#include <stdbool.h>
-#include "lcd.h"
#include "menu.h"
#include "demo_menu.h"
-#include "button.h"
-#include "kernel.h"
-#include "sprintf.h"
-
#include "lang.h"
+#include "plugin.h"
+
+static bool bounce(void)
+{
+ if (plugin_load("/.rockbox/rocks/bounce.rock",NULL)==PLUGIN_USB_CONNECTED)
+ return true;
+ return false;
+}
+
+static bool snow(void)
+{
+ if (plugin_load("/.rockbox/rocks/snow.rock",NULL) == PLUGIN_USB_CONNECTED)
+ return true;
+ return false;
+}
+
+static bool cube(void)
+{
+ if (plugin_load("/.rockbox/rocks/cube.rock",NULL) == PLUGIN_USB_CONNECTED)
+ return true;
+ return false;
+}
-extern bool bounce(void);
-extern bool snow(void);
-extern bool cube(void);
-extern bool oscillograph(void);
+static bool oscillograph(void)
+{
+ if (plugin_load("/.rockbox/rocks/oscillograph.rock",NULL)==PLUGIN_USB_CONNECTED)
+ return true;
+ return false;
+}
bool demo_menu(void)
{
diff --git a/apps/games_menu.c b/apps/games_menu.c
index 0c37203f4e..780c4b7415 100644
--- a/apps/games_menu.c
+++ b/apps/games_menu.c
@@ -25,18 +25,31 @@
#include <stdio.h>
#include <stdbool.h>
-#include "lcd.h"
#include "menu.h"
#include "games_menu.h"
-#include "button.h"
-#include "kernel.h"
-#include "sprintf.h"
-
-#include "sokoban.h"
-#include "wormlet.h"
#include "lang.h"
+#include "plugin.h"
-extern bool tetris(void);
+static bool tetris(void)
+{
+ if (plugin_load("/.rockbox/rocks/tetris.rock",NULL)==PLUGIN_USB_CONNECTED)
+ return true;
+ return false;
+}
+
+static bool sokoban(void)
+{
+ if (plugin_load("/.rockbox/rocks/sokoban.rock",NULL)==PLUGIN_USB_CONNECTED)
+ return true;
+ return false;
+}
+
+static bool wormlet(void)
+{
+ if (plugin_load("/.rockbox/rocks/wormlet.rock",NULL)==PLUGIN_USB_CONNECTED)
+ return true;
+ return false;
+}
bool games_menu(void)
{
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 12249ee048..1d7b3088a6 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -677,37 +677,37 @@ new:
id: LANG_SOKOBAN_LEVEL
desc: must be smaller than 6 characters
-eng: "Level"
+eng: ""
new:
id: LANG_SOKOBAN_MOVE
desc: must be smaller than 6 characters
-eng: "Moves"
+eng: ""
new:
id: LANG_SOKOBAN_WIN
desc: displayed when you win
-eng: "YOU WIN!!"
+eng: ""
new:
id: LANG_SOKOBAN_QUIT
desc: how to quit game
-eng: "[OFF] To Stop"
+eng: ""
new:
id: LANG_SOKOBAN_F1
desc: what does F1 do
-eng: "[F1] - Level"
+eng: ""
new:
id: LANG_SOKOBAN_F2
desc: what does F2 do
-eng: "[F2] Same Level"
+eng: ""
new:
id: LANG_SOKOBAN_F3
desc: what does F3 do
-eng: "[F3] + Level"
+eng: ""
new:
# Next ids are for Worlmet Game.
@@ -717,37 +717,37 @@ new:
id: LANG_WORMLET_LENGTH
desc: wormlet game
-eng: "Len:%d"
+eng: ""
new:
id: LANG_WORMLET_GROWING
desc: wormlet game
-eng: "Growing"
+eng: ""
new:
id: LANG_WORMLET_HUNGRY
desc: wormlet game
-eng: "Hungry"
+eng: ""
new:
id: LANG_WORMLET_WORMED
desc: wormlet game
-eng: "Wormed"
+eng: ""
new:
id: LANG_WORMLET_ARGH
desc: wormlet game
-eng: "Argh"
+eng: ""
new:
id: LANG_WORMLET_CRASHED
desc: wormlet game
-eng: "Crashed"
+eng: ""
new:
id: LANG_WORMLET_HIGHSCORE
desc: wormlet game
-eng: "Hs: %d"
+eng: ""
new:
# Length restrictions for wormlet config screen strings (LANG_CS_XXX)
@@ -756,49 +756,49 @@ new:
id: LANG_WORMLET_PLAYERS
desc: wormlet game
-eng: "%d Players UP/DN"
+eng: ""
new:
id: LANG_WORMLET_WORMS
desc: wormlet game
-eng: "%d Worms L/R"
+eng: ""
new:
id: LANG_WORMLET_REMOTE_CTRL
desc: wormlet game
-eng: "Remote Control F1"
+eng: ""
new:
id: LANG_WORMLET_NO_REM_CTRL
desc: wormlet game
-eng: "No Rem. Control F1"
+eng: ""
new:
id: LANG_WORMLET_2_KEY_CTRL
desc: wormlet game
-eng: "2 Key Control F1"
+eng: ""
new:
id: LANG_WORMLET_4_KEY_CTRL
desc: wormlet game
-eng: "4 Key Control F1"
+eng: ""
new:
id: LANG_WORMLET_NO_CONTROL
desc: wormlet game
-eng: "Out Of Control"
+eng: ""
new:
# Wormlet game ids ended
id: LANG_TETRIS_LOSE
desc: tetris game
-eng: "You Lose!"
+eng: ""
new:
id: LANG_TETRIS_LEVEL
desc: tetris game
-eng: "Rows - Level"
+eng: ""
new:
id: LANG_POWEROFF_IDLE
@@ -1569,3 +1569,33 @@ id: LANG_CANCEL_WITH_ANY_RECORDER
desc: Generic recorder string to use to cancel
eng: "Any Other = No"
new:
+
+##
+## Strings used in the plugin loader:
+##
+
+id: LANG_PLUGIN_CANT_OPEN
+desc: Plugin open error message
+eng: "Can't open %s"
+new:
+
+id: LANG_READ_FAILED
+desc: There was an error reading a file
+eng: "Failed reading %s"
+new:
+
+id: LANG_PLUGIN_WRONG_MODEL
+desc: The plugin is not compatible with the archos model trying to run it
+eng: "Incompatible model"
+new:
+
+id: LANG_PLUGIN_WRONG_VERSION
+desc: The plugin is not compatible with the rockbox version trying to run it
+eng: "Incompatible version"
+new:
+
+id: LANG_PLUGIN_ERROR
+desc: The plugin return an error code
+eng: "Plugin returned error"
+new:
+
diff --git a/apps/player/icons.h b/apps/player/icons.h
index 1c9c68d66c..c96f821cfa 100644
--- a/apps/player/icons.h
+++ b/apps/player/icons.h
@@ -26,7 +26,8 @@
enum {
Unknown=0x90,
- Folder=0x18, Mod_Ajz, Language, File, Wps, Playlist, Text, Config
+ Plugin = 0x17,
+ Folder, Mod_Ajz, Language, File, Wps, Playlist, Text, Config,
};
#endif
diff --git a/apps/plugin.c b/apps/plugin.c
new file mode 100644
index 0000000000..6366580a56
--- /dev/null
+++ b/apps/plugin.c
@@ -0,0 +1,221 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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 <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include "button.h"
+#include "lcd.h"
+#include "dir.h"
+#include "file.h"
+#include "kernel.h"
+#include "sprintf.h"
+#include "screens.h"
+#include "misc.h"
+#include "mas.h"
+#include "plugin.h"
+#include "lang.h"
+
+#ifdef SIMULATOR
+#include <dlfcn.h>
+#define PREFIX(_x_) x11_ ## _x_
+#else
+#define PREFIX(_x_) _x_
+#endif
+
+static int plugin_test(int api_version, int model);
+
+static struct plugin_api rockbox_api = {
+ PLUGIN_API_VERSION,
+
+ plugin_test,
+
+ /* lcd */
+ lcd_clear_display,
+ lcd_puts,
+ lcd_puts_scroll,
+ lcd_stop_scroll,
+#ifdef HAVE_LCD_CHARCELLS
+ lcd_define_pattern,
+#else
+ lcd_putsxy,
+ lcd_bitmap,
+ lcd_drawline,
+ lcd_clearline,
+ lcd_drawpixel,
+ lcd_clearpixel,
+ lcd_setfont,
+ lcd_clearrect,
+ lcd_fillrect,
+ lcd_drawrect,
+ lcd_invertrect,
+ lcd_getstringsize,
+ lcd_update,
+ lcd_update_rect,
+#ifndef SIMULATOR
+ lcd_roll,
+#endif
+#endif
+
+ /* button */
+ button_get,
+ button_get_w_tmo,
+
+ /* file */
+ PREFIX(open),
+ PREFIX(close),
+ read,
+ lseek,
+ PREFIX(creat),
+ write,
+ remove,
+ rename,
+ ftruncate,
+ PREFIX(filesize),
+ fprintf,
+ read_line,
+
+ /* dir */
+ PREFIX(opendir),
+ PREFIX(closedir),
+ PREFIX(readdir),
+
+ /* kernel */
+ PREFIX(sleep),
+ usb_screen,
+ &current_tick,
+
+ /* strings and memory */
+ snprintf,
+ strcpy,
+ strlen,
+ memset,
+ memcpy,
+
+ /* sound */
+#ifndef SIMULATOR
+#ifdef HAVE_MAS3587F
+ mas_codec_readreg,
+#endif
+#endif
+
+ /* misc */
+ srand,
+ rand,
+ splash,
+};
+
+int plugin_load(char* plugin, void* parameter)
+{
+ enum plugin_status (*plugin_start)(struct plugin_api* api, void* param);
+ int rc;
+ char buf[64];
+#ifdef SIMULATOR
+ void* pd;
+ char path[256];
+#else
+ extern unsigned char pluginbuf[];
+ int fd;
+#endif
+
+ lcd_clear_display();
+#ifdef HAVE_LCD_BITMAP
+ lcd_setmargins(0,0);
+ lcd_update();
+#endif
+#ifdef SIMULATOR
+ snprintf(path, sizeof path, "archos%s", plugin);
+ pd = dlopen(path, RTLD_NOW);
+ if (!pd) {
+ snprintf(buf, sizeof buf, "Can't open %s", plugin);
+ splash(HZ*2, 0, true, buf);
+ dlclose(pd);
+ return -1;
+ }
+
+ plugin_start = dlsym(pd, "plugin_start");
+ if (!plugin_start) {
+ plugin_start = dlsym(pd, "_plugin_start");
+ if (!plugin_start) {
+ splash(HZ*2, 0, true, "Can't find entry point");
+ dlclose(pd);
+ return -1;
+ }
+ }
+#else
+ fd = open(plugin, O_RDONLY);
+ if (fd < 0) {
+ snprintf(buf, sizeof buf, str(LANG_PLUGIN_CANT_OPEN), plugin);
+ splash(HZ*2, 0, true, buf);
+ return fd;
+ }
+
+ plugin_start = (void*)&pluginbuf;
+ rc = read(fd, plugin_start, 0x8000);
+ close(fd);
+ if (rc < 0) {
+ /* read error */
+ snprintf(buf, sizeof buf, str(LANG_READ_FAILED), plugin);
+ splash(HZ*2, 0, true, buf);
+ return -1;
+ }
+ if (rc == 0) {
+ /* loaded a 0-byte plugin, implying it's not for this model */
+ splash(HZ*2, 0, true, str(LANG_PLUGIN_WRONG_MODEL));
+ return -1;
+ }
+#endif
+
+ rc = plugin_start(&rockbox_api, parameter);
+ switch (rc) {
+ case PLUGIN_OK:
+ break;
+
+ case PLUGIN_USB_CONNECTED:
+ return PLUGIN_USB_CONNECTED;
+
+ case PLUGIN_WRONG_API_VERSION:
+ splash(HZ*2, 0, true, str(LANG_PLUGIN_WRONG_VERSION));
+ break;
+
+ case PLUGIN_WRONG_MODEL:
+ splash(HZ*2, 0, true, str(LANG_PLUGIN_WRONG_MODEL));
+ break;
+
+ default:
+ splash(HZ*2, 0, true, str(LANG_PLUGIN_ERROR));
+ break;
+ }
+
+#ifdef SIMULATOR
+ dlclose(pd);
+#endif
+
+ return PLUGIN_OK;
+}
+
+int plugin_test(int api_version, int model)
+{
+ if (api_version != PLUGIN_API_VERSION)
+ return PLUGIN_WRONG_API_VERSION;
+
+ if (model != MODEL)
+ return PLUGIN_WRONG_MODEL;
+
+ return PLUGIN_OK;
+}
diff --git a/apps/plugin.h b/apps/plugin.h
new file mode 100644
index 0000000000..3b79edefc6
--- /dev/null
+++ b/apps/plugin.h
@@ -0,0 +1,161 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+/* instruct simulator code to not redefine any symbols when compiling plugins.
+ (the PLUGIN macro is defined in apps/plugins/Makefile) */
+#ifdef PLUGIN
+#define NO_REDEFINES_PLEASE
+#endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "config.h"
+#include "dir.h"
+#include "kernel.h"
+#include "button.h"
+#include "font.h"
+#include "system.h"
+#include "lcd.h"
+
+/* increase this every time the api struct changes */
+#define PLUGIN_API_VERSION 1
+
+/* plugin return codes */
+enum plugin_status {
+ PLUGIN_OK = 0,
+ PLUGIN_USB_CONNECTED,
+
+ PLUGIN_WRONG_API_VERSION = -1,
+ PLUGIN_WRONG_MODEL = -2,
+ PLUGIN_ERROR = -3,
+};
+
+/* different (incompatible) plugin models */
+enum model {
+ PLAYER,
+ RECORDER
+};
+
+#ifdef HAVE_LCD_CHARCELLS
+#define MODEL PLAYER
+#else
+#define MODEL RECORDER
+#endif
+
+/* compatibility test macro */
+#define TEST_PLUGIN_API(_api_) \
+do { \
+ int _rc_ = _api_->plugin_test(PLUGIN_API_VERSION, MODEL); \
+ if (_rc_<0) \
+ return _rc_; \
+} while(0)
+
+struct plugin_api {
+ /* these two fields must always be first, to ensure
+ TEST_PLUGIN_API will always work */
+ int version;
+ int (*plugin_test)(int api_version, int model);
+
+ /* lcd */
+ void (*lcd_clear_display)(void);
+ void (*lcd_puts)(int x, int y, unsigned char *string);
+ void (*lcd_puts_scroll)(int x, int y, unsigned char* string);
+ void (*lcd_stop_scroll)(void);
+#ifdef HAVE_LCD_CHARCELLS
+ void (*lcd_define_pattern)(int which,char *pattern);
+#else
+ void (*lcd_putsxy)(int x, int y, unsigned char *string);
+ void (*lcd_bitmap)(unsigned char *src, int x, int y,
+ int nx, int ny, bool clear);
+ void (*lcd_drawline)(int x1, int y1, int x2, int y2);
+ void (*lcd_clearline)(int x1, int y1, int x2, int y2);
+ void (*lcd_drawpixel)(int x, int y);
+ void (*lcd_clearpixel)(int x, int y);
+ void (*lcd_setfont)(int font);
+ void (*lcd_clearrect)(int x, int y, int nx, int ny);
+ void (*lcd_fillrect)(int x, int y, int nx, int ny);
+ void (*lcd_drawrect)(int x, int y, int nx, int ny);
+ void (*lcd_invertrect)(int x, int y, int nx, int ny);
+ int (*lcd_getstringsize)(unsigned char *str, int *w, int *h);
+ void (*lcd_update)(void);
+ void (*lcd_update_rect)(int x, int y, int width, int height);
+#ifndef SIMULATOR
+ void (*lcd_roll)(int pixels);
+#endif
+#endif
+
+ /* button */
+ int (*button_get)(bool block);
+ int (*button_get_w_tmo)(int ticks);
+
+ /* file */
+ int (*open)(const char* pathname, int flags);
+ int (*close)(int fd);
+ int (*read)(int fd, void* buf, int count);
+ int (*lseek)(int fd, int offset, int whence);
+ int (*creat)(const char *pathname, int mode);
+ int (*write)(int fd, void* buf, int count);
+ int (*remove)(const char* pathname);
+ int (*rename)(const char* path, const char* newname);
+ int (*ftruncate)(int fd, unsigned int size);
+ int (*filesize)(int fd);
+ int (*fprintf)(int fd, const char *fmt, ...);
+ int (*read_line)(int fd, char* buffer, int buffer_size);
+
+ /* dir */
+ DIR* (*opendir)(char* name);
+ int (*closedir)(DIR* dir);
+ struct dirent* (*readdir)(DIR* dir);
+
+ /* kernel */
+ void (*sleep)(int ticks);
+ void (*usb_screen)(void);
+ long* current_tick;
+
+ /* strings and memory */
+ int (*snprintf)(char *buf, size_t size, const char *fmt, ...);
+ char* (*strcpy)(char *dst, const char *src);
+ size_t (*strlen)(const char *str);
+ void* (*memset)(void *dst, int c, size_t length);
+ void* (*memcpy)(void *out, const void *in, size_t n);
+
+ /* sound */
+#ifndef SIMULATOR
+#ifdef HAVE_MAS3587F
+ int (*mas_codec_readreg)(int reg);
+#endif
+#endif
+
+ /* misc */
+ void (*srand)(unsigned int seed);
+ int (*rand)(void);
+ void (*splash)(int ticks, int keymask, bool center, char *fmt, ...);
+};
+
+/* defined by the plugin loader (plugin.c) */
+int plugin_load(char* plugin, void* parameter);
+
+/* defined by the plugin */
+enum plugin_status plugin_start(struct plugin_api* rockbox, void* parameter)
+ __attribute__ ((section (".entry")));
+
+#endif
diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile
new file mode 100644
index 0000000000..4c02207016
--- /dev/null
+++ b/apps/plugins/Makefile
@@ -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)
diff --git a/apps/recorder/bounce.c b/apps/plugins/bounce.c
index ed4885bc39..0c53d49887 100644
--- a/apps/recorder/bounce.c
+++ b/apps/plugins/bounce.c
@@ -15,26 +15,10 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
- ****************************************************************************/
+ **************************************************************************/
+#include "plugin.h"
-#include "config.h"
-#include "options.h"
-
-#ifdef USE_DEMOS
-
-#include "lcd.h"
-#include "button.h"
-#include "kernel.h"
-#include "menu.h"
-#include "sprintf.h"
-#include "rtc.h"
-#include "font.h"
-#include "screens.h"
-
-#ifdef SIMULATOR
-#include <stdio.h>
-#endif
-#include <string.h>
+#ifdef HAVE_LCD_BITMAP
#define SS_TITLE "Bouncer"
#define SS_TITLE_FONT 2
@@ -45,6 +29,7 @@
#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,
@@ -186,6 +171,7 @@ struct counter values[]={
{"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,
};
@@ -216,23 +202,24 @@ static void addclock(void)
if(pos >= 60)
pos -= 60;
- lcd_drawline(LCD_WIDTH/2, LCD_HEIGHT/2, xminute[pos], yminute[pos]);
+ 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;
- lcd_drawline(LCD_WIDTH/2, LCD_HEIGHT/2, xhour[pos], yhour[pos]);
+ rb->lcd_drawline(LCD_WIDTH/2, LCD_HEIGHT/2, xhour[pos], yhour[pos]);
/* draw a circle */
for(i=0; i < 60; i+=3) {
- lcd_drawline( xminute[i],
+ rb->lcd_drawline( xminute[i],
yminute[i],
xminute[(i+1)%60],
yminute[(i+1)%60]);
}
}
+#endif
static int scrollit(void)
{
@@ -243,31 +230,33 @@ static int scrollit(void)
unsigned int i;
int textpos=0;
- char rock[]="Rockbox! Pure pleasure. Pure fun. Oooh. What fun! ;-) ";
+ char* rock="Rockbox! Pure pleasure. Pure fun. Oooh. What fun! ;-) ";
int letter;
- lcd_clear_display();
+ rb->lcd_clear_display();
while(1)
{
- b = button_get_w_tmo(HZ/10);
+ 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;
- lcd_clear_display();
+ rb->lcd_clear_display();
for(i=0, yy=y, xx=x; i< LETTERS_ON_SCREEN; i++) {
letter = rock[(i+textpos) % (sizeof(rock)-1) ];
- lcd_bitmap((char *)char_gen_12x16[letter-0x20],
+ 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();
- lcd_update();
+#endif
+ rb->lcd_update();
x-= XSPEED;
@@ -292,21 +281,21 @@ static int loopit(void)
unsigned int ysanke=0;
unsigned int xsanke=0;
- char rock[]="ROCKbox";
+ char* rock="ROCKbox";
int show=0;
int timeout=0;
char buffer[30];
- lcd_clear_display();
+ rb->lcd_clear_display();
while(1)
{
- b = button_get_w_tmo(HZ/10);
+ b = rb->button_get_w_tmo(HZ/10);
if ( b == (BUTTON_OFF|BUTTON_REL) )
return 0;
if ( b == SYS_USB_CONNECTED) {
- usb_screen();
+ rb->usb_screen();
return 0;
}
@@ -318,10 +307,10 @@ static int loopit(void)
y+= speed[ysanke&15] + values[NUM_YADD].num;
x+= speed[xsanke&15] + values[NUM_XADD].num;
- lcd_clear_display();
-
+ rb->lcd_clear_display();
+#ifdef USE_CLOCK
addclock();
-
+#endif
if(timeout) {
switch(b) {
case BUTTON_LEFT:
@@ -339,18 +328,18 @@ static int loopit(void)
show=NUM_LAST-1;
break;
}
- snprintf(buffer, 30, "%s: %d",
- values[show].what, values[show].num);
- lcd_putsxy(0, 56, buffer);
+ 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)
- lcd_bitmap((char *)char_gen_12x16[rock[i]-0x20],
+ rb->lcd_bitmap((char *)char_gen_12x16[rock[i]-0x20],
xtable[xx%71], table[yy&63],
11, 16, false);
- lcd_update();
+ rb->lcd_update();
ysanke+= values[NUM_YSANKE].num;
xsanke+= values[NUM_XSANKE].num;
@@ -358,15 +347,19 @@ static int loopit(void)
}
-bool bounce(void)
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{
int w, h;
char *off = "[Off] to stop";
- int len = strlen(SS_TITLE);
+ int len;
- lcd_setfont(FONT_SYSFIXED);
+ TEST_PLUGIN_API(api);
+ (void)(parameter);
+ rb = api;
- lcd_getstringsize(SS_TITLE,&w, &h);
+ len = rb->strlen(SS_TITLE);
+ rb->lcd_setfont(FONT_SYSFIXED);
+ rb->lcd_getstringsize(SS_TITLE,&w, &h);
/* Get horizontel centering for text */
len *= w;
@@ -380,11 +373,11 @@ bool bounce(void)
else
h /= 2;
- lcd_clear_display();
- lcd_putsxy(LCD_WIDTH/2-len, (LCD_HEIGHT/2)-h, SS_TITLE);
+ rb->lcd_clear_display();
+ rb->lcd_putsxy(LCD_WIDTH/2-len, (LCD_HEIGHT/2)-h, SS_TITLE);
len = 1;
- lcd_getstringsize(off, &w, &h);
+ rb->lcd_getstringsize(off, &w, &h);
/* Get horizontel centering for text */
len *= w;
@@ -398,10 +391,9 @@ bool bounce(void)
else
h /= 2;
- lcd_putsxy(LCD_WIDTH/2-len, LCD_HEIGHT-(2*h), off);
-
- lcd_update();
- sleep(HZ);
+ rb->lcd_putsxy(LCD_WIDTH/2-len, LCD_HEIGHT-(2*h), off);
+ rb->lcd_update();
+ rb->sleep(HZ);
do {
h= loopit();
@@ -409,7 +401,7 @@ bool bounce(void)
h = scrollit();
} while(h);
- lcd_setfont(FONT_UI);
+ rb->lcd_setfont(FONT_UI);
return false;
}
diff --git a/apps/recorder/cube.c b/apps/plugins/cube.c
index ad3af91c87..996a1a81dd 100644
--- a/apps/recorder/cube.c
+++ b/apps/plugins/cube.c
@@ -16,22 +16,10 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
-****************************************************************************/
+***************************************************************************/
+#include "plugin.h"
-#include "config.h"
-#include "options.h"
-
-#ifdef USE_DEMOS
-
-#include <stdlib.h>
-#include "lcd.h"
-#include "config.h"
-#include "kernel.h"
-#include "menu.h"
-#include "button.h"
-#include "sprintf.h"
-#include "screens.h"
-#include "font.h"
+#ifdef HAVE_LCD_BITMAP
/* Loops that the values are displayed */
#define DISP_TIME 30
@@ -80,6 +68,8 @@ static int sin_table[91] =
10000
};
+static struct plugin_api* rb;
+
static long sin(int val)
{
/* Speed improvement through sukzessive lookup */
@@ -214,7 +204,7 @@ static void cube_init(void)
static void line(int a, int b)
{
- lcd_drawline(point2D[a].x, point2D[a].y, point2D[b].x, point2D[b].y);
+ rb->lcd_drawline(point2D[a].x, point2D[a].y, point2D[b].x, point2D[b].y);
}
static void cube_draw(void)
@@ -234,7 +224,8 @@ static void cube_draw(void)
line(3,6);
}
-bool cube(void)
+
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{
int t_disp=0;
char buffer[30];
@@ -247,27 +238,31 @@ bool cube(void)
int zs=1;
bool highspeed=0;
bool exit=0;
-
- lcd_setfont(FONT_SYSFIXED);
+
+ TEST_PLUGIN_API(api);
+ (void)(parameter);
+ rb = api;
+
+ rb->lcd_setfont(FONT_SYSFIXED);
cube_init();
while(!exit)
{
if (!highspeed)
- sleep(4);
+ rb->sleep(4);
- lcd_clear_display();
+ rb->lcd_clear_display();
cube_rotate(xa,ya,za);
cube_viewport();
cube_draw();
if (t_disp>0)
{
t_disp--;
- snprintf(buffer, 30, "x:%d y:%d z:%d h:%d",xs,ys,zs,highspeed);
- lcd_putsxy(0, 56, buffer);
+ rb->snprintf(buffer, 30, "x:%d y:%d z:%d h:%d",xs,ys,zs,highspeed);
+ rb->lcd_putsxy(0, 56, buffer);
}
- lcd_update();
+ rb->lcd_update();
xa+=xs;
if (xa>359)
@@ -285,7 +280,7 @@ bool cube(void)
if (za<0)
za+=360;
- switch(button_get(false))
+ switch(rb->button_get(false))
{
case BUTTON_RIGHT:
xs+=1;
@@ -332,22 +327,12 @@ bool cube(void)
break;
case SYS_USB_CONNECTED:
- usb_screen();
- lcd_setfont(FONT_UI);
- return true;
+ rb->usb_screen();
+ return PLUGIN_USB_CONNECTED;
}
}
- lcd_setfont(FONT_UI);
-
- return false;
+ return PLUGIN_OK;
}
-#endif /* USE_DEMOS */
-
-/* -----------------------------------------------------------------
- * vim: et sw=4 ts=8 sts=4 tw=78
- */
-
-
-
+#endif
diff --git a/apps/plugins/helloworld.c b/apps/plugins/helloworld.c
new file mode 100644
index 0000000000..ea347fbf79
--- /dev/null
+++ b/apps/plugins/helloworld.c
@@ -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;
+}
diff --git a/apps/recorder/oscillograph.c b/apps/plugins/oscillograph.c
index bf94db168f..a34aa8bfa9 100644
--- a/apps/recorder/oscillograph.c
+++ b/apps/plugins/oscillograph.c
@@ -16,17 +16,11 @@
* KIND, either express or implied.
*
****************************************************************************/
+#include "plugin.h"
+#ifdef HAVE_LCD_BITMAP
#ifndef SIMULATOR /* don't want this code in the simulator */
-#include <stdlib.h>
-#include <sprintf.h>
-#include "menu.h"
-#include "lcd.h"
-#include "button.h"
-#include "mas.h"
-#include "system.h"
-
/* The different drawing modes */
#define DRAW_MODE_FILLED 0
#define DRAW_MODE_OUTLINE 1
@@ -47,7 +41,7 @@ static int drawMode = DRAW_MODE_FILLED;
* hardware scrolling of the display. The user can change
* speed
*/
-bool oscillograph(void)
+enum plugin_status plugin_start(struct plugin_api* rb, void* parameter)
{
/* stores current volume value left */
int left;
@@ -63,22 +57,25 @@ bool oscillograph(void)
bool exit = false;
+ TEST_PLUGIN_API(rb);
+ (void)parameter;
+
/* the main loop */
while (!exit) {
/* read the volume info from MAS */
- left = mas_codec_readreg(0xC) / (MAX_PEAK / (LCD_WIDTH / 2 - 2));
- right = mas_codec_readreg(0xD) / (MAX_PEAK / (LCD_WIDTH / 2 - 2));
+ 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 */
- lcd_clearline(0, y, LCD_WIDTH-1, y);
+ rb->lcd_clearline(0, y, LCD_WIDTH-1, y);
switch (drawMode) {
case DRAW_MODE_FILLED:
- lcd_drawline(LCD_WIDTH / 2 + 1 , y,
- LCD_WIDTH / 2 + 1 + right, y);
- lcd_drawline(LCD_WIDTH / 2 - 1 , y,
- LCD_WIDTH / 2 - 1 -left , y);
+ 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:
@@ -87,10 +84,10 @@ bool oscillograph(void)
/* Here real lines were neccessary because
anything else was ugly. */
- lcd_drawline(LCD_WIDTH / 2 + right , y,
- LCD_WIDTH / 2 + lastRight , lasty);
- lcd_drawline(LCD_WIDTH / 2 - left , y,
- LCD_WIDTH / 2 - lastLeft, lasty);
+ 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 */
@@ -100,8 +97,8 @@ bool oscillograph(void)
case DRAW_MODE_PIXEL:
/* straight and simple */
- lcd_drawpixel(LCD_WIDTH / 2 + right, y);
- lcd_drawpixel(LCD_WIDTH / 2 - left, y);
+ rb->lcd_drawpixel(LCD_WIDTH / 2 + right, y);
+ rb->lcd_drawpixel(LCD_WIDTH / 2 - left, y);
break;
}
@@ -114,19 +111,19 @@ bool oscillograph(void)
/* I roll before update because otherwise the new
line would appear at the wrong end of the display */
if (roll)
- lcd_roll(y);
+ rb->lcd_roll(y);
/* now finally make the new sample visible */
- lcd_update_rect(0, MAX(y-1, 0), LCD_WIDTH, 2);
+ 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.
+ 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.
+ the user input check for (-speed) volume
+ samples. For this mechanism negative values
+ are used.
*/
if (speed >= 0 || ((speed < 0) && (y % (-speed) == 0))) {
@@ -138,7 +135,7 @@ bool oscillograph(void)
it must be ensured that at least 1 is passed. */
/* react to user input */
- switch (button_get_w_tmo(MAX(speed, 1))) {
+ switch (rb->button_get_w_tmo(MAX(speed, 1))) {
case BUTTON_UP:
speed++;
draw = true;
@@ -151,7 +148,7 @@ bool oscillograph(void)
case BUTTON_PLAY:
/* pause the demo */
- button_get(true);
+ rb->button_get(true);
break;
case BUTTON_F1:
@@ -170,7 +167,7 @@ bool oscillograph(void)
That produces ugly results in DRAW_MODE_OUTLINE
mode. If rolling is enabled this change will
be reverted before the next update anyway.*/
- lcd_roll(0);
+ rb->lcd_roll(0);
break;
case BUTTON_F3:
@@ -181,27 +178,30 @@ bool oscillograph(void)
case BUTTON_OFF:
exit = true;
break;
+
+ case SYS_USB_CONNECTED:
+ rb->usb_screen();
+ return PLUGIN_USB_CONNECTED;
}
if (draw) {
char buf[16];
- snprintf(buf, sizeof buf, "Speed: %d", -speed);
- lcd_putsxy(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT, buf);
- lcd_update_rect(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT,
- LCD_WIDTH, 8);
+ 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... */
- lcd_roll(0);
- lcd_update();
+ rb->lcd_roll(0);
+ rb->lcd_update();
/* standard return */
- return false;
+ return PLUGIN_OK;
}
#endif /* #ifndef SIMULATOR */
-
-
+#endif
diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds
new file mode 100644
index 0000000000..be6b6fd0a6
--- /dev/null
+++ b/apps/plugins/plugin.lds
@@ -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
+}
diff --git a/apps/recorder/snow.c b/apps/plugins/snow.c
index c4e952f21d..df9966eb38 100644
--- a/apps/recorder/snow.c
+++ b/apps/plugins/snow.c
@@ -15,17 +15,15 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
- ****************************************************************************/
-#include <stdlib.h>
-#include "lcd.h"
-#include "config.h"
-#include "kernel.h"
-#include "menu.h"
-#include "button.h"
+ **************************************************************************/
+#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)
{
@@ -42,7 +40,7 @@ static int create_particle(void)
for (i=0; i<NUM_PARTICLES; i++) {
if (!particle_exists(i)) {
- particles[i][0]=(rand()%112);
+ particles[i][0]=(rb->rand()%112);
particles[i][1]=0;
return i;
}
@@ -54,13 +52,13 @@ static void snow_move(void)
{
int i;
- if (!(rand()%2))
+ if (!(rb->rand()%2))
create_particle();
for (i=0; i<NUM_PARTICLES; i++) {
if (particle_exists(i)) {
- lcd_clearpixel(particles[i][0],particles[i][1]);
- switch ((rand()%7)) {
+ rb->lcd_clearpixel(particles[i][0],particles[i][1]);
+ switch ((rb->rand()%7)) {
case 0:
particles[i][0]++;
break;
@@ -77,7 +75,7 @@ static void snow_move(void)
break;
}
if (particle_exists(i))
- lcd_drawpixel(particles[i][0],particles[i][1]);
+ rb->lcd_drawpixel(particles[i][0],particles[i][1]);
}
}
}
@@ -90,28 +88,24 @@ static void snow_init(void)
particles[i][0]=-1;
particles[i][1]=-1;
}
- lcd_clear_display();
+ rb->lcd_clear_display();
}
-bool snow(void)
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{
- snow_init();
+ TEST_PLUGIN_API(api);
+ (void)(parameter);
+ rb = api;
+ snow_init();
while (1) {
snow_move();
- lcd_update();
- sleep(HZ/20);
+ rb->lcd_update();
+ rb->sleep(HZ/20);
- if (button_get(false) == BUTTON_OFF)
+ if (rb->button_get(false) == BUTTON_OFF)
return false;
}
}
-
-
-
-
-
-
-
-
+#endif
diff --git a/apps/plugins/sokoban.c b/apps/plugins/sokoban.c
new file mode 100644
index 0000000000..2387fa9517
--- /dev/null
+++ b/apps/plugins/sokoban.c
@@ -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
diff --git a/apps/viewer.c b/apps/plugins/viewer.c
index f653866626..f8dc309a6e 100644
--- a/apps/viewer.c
+++ b/apps/plugins/viewer.c
@@ -17,24 +17,9 @@
* KIND, either express or implied.
*
****************************************************************************/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include "file.h"
-#include "lcd.h"
-#include "button.h"
-#include "kernel.h"
-#include "font.h"
-#include "settings.h"
-#include "icons.h"
-#include "screens.h"
-#include "status.h"
-
+#include "plugin.h"
#define BUFFER_SIZE 1024
-
#define OUTSIDE_BUFFER -10
#define OUTSIDE_FILE -11
@@ -50,6 +35,7 @@ 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
@@ -61,7 +47,7 @@ static void display_line_count(void)
{
#ifdef HAVE_LCD_BITMAP
int w,h;
- lcd_getstringsize("M", &w, &h);
+ rb->lcd_getstringsize("M", &w, &h);
display_lines = LCD_HEIGHT / h;
display_columns = LCD_WIDTH / w;
#else
@@ -126,7 +112,7 @@ static void viewer_draw(int col)
char* str;
int line_pos;
- lcd_clear_display();
+ rb->lcd_clear_display();
line_pos = begin_line_pos;
@@ -137,11 +123,12 @@ static void viewer_draw(int col)
str = buffer + line_pos + 1;
for (j=0; j<col && *str!=0; ++j)
str++;
- lcd_puts(0, i, str);
+ rb->lcd_puts(0, i, str);
line_pos = find_next_line(line_pos);
}
-
- lcd_update();
+#ifdef HAVE_LCD_BITMAP
+ rb->lcd_update();
+#endif
}
static void fill_buffer(int pos)
@@ -154,8 +141,8 @@ static void fill_buffer(int pos)
if (pos<0)
pos = 0;
- lseek(fd, pos, SEEK_SET);
- numread = read(fd, buffer, BUFFER_SIZE);
+ 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;
@@ -181,11 +168,11 @@ static bool viewer_init(char* file)
int i;
int ret;
- fd = open(file, O_RDONLY);
+ fd = rb->open(file, O_RDONLY);
if (fd==-1)
return false;
- file_size = lseek(fd, 0, SEEK_END);
+ file_size = rb->lseek(fd, 0, SEEK_END);
buffer_pos = 0;
begin_line = 0;
@@ -207,7 +194,7 @@ static bool viewer_init(char* file)
static void viewer_exit(void)
{
- close(fd);
+ rb->close(fd);
}
static void viewer_scroll_down(void)
@@ -264,7 +251,7 @@ static int pagescroll(int col)
int i;
while (!exit) {
- switch (button_get(true)) {
+ switch (rb->button_get(true)) {
#ifdef HAVE_RECORDER_KEYPAD
case BUTTON_ON | BUTTON_UP:
case BUTTON_ON | BUTTON_UP | BUTTON_REPEAT:
@@ -328,31 +315,30 @@ static int pagescroll(int col)
return col;
}
-bool viewer_run(char* file)
+
+enum plugin_status plugin_start(struct plugin_api* api, void* file)
{
bool exit=false;
int button;
int col = 0;
int ok;
-#ifdef HAVE_LCD_BITMAP
- /* no margins */
- lcd_setmargins(0, 0);
-#endif
+ TEST_PLUGIN_API(api);
+ rb = api;
+
+ if (!file)
+ return PLUGIN_ERROR;
ok = viewer_init(file);
if (!ok) {
- lcd_clear_display();
- lcd_puts(0, 0, "Error");
- lcd_update();
- sleep(HZ);
+ rb->splash(HZ, 0, false, "Error");
viewer_exit();
- return false;
+ return PLUGIN_OK;
}
viewer_draw(col);
while (!exit) {
- button = button_get(true);
+ button = rb->button_get(true);
switch ( button ) {
@@ -420,13 +406,10 @@ bool viewer_run(char* file)
break;
case SYS_USB_CONNECTED:
- usb_screen();
-#ifdef HAVE_LCD_CHARCELLS
- status_set_param(false);
-#endif
+ rb->usb_screen();
viewer_exit();
- return true;
+ return PLUGIN_USB_CONNECTED;
}
}
- return false;
+ return PLUGIN_OK;
}
diff --git a/apps/recorder/wormlet.c b/apps/plugins/wormlet.c
index 2937a1bb83..be089cdb7c 100644
--- a/apps/recorder/wormlet.c
+++ b/apps/plugins/wormlet.c
@@ -16,26 +16,9 @@
* KIND, either express or implied.
*
****************************************************************************/
+#include "plugin.h"
-#include "config.h"
-#include "options.h"
-
-#ifdef USE_GAMES
-
-/* #define DEBUG_WORMLET */
-
-#include <sprintf.h>
-#include <stdlib.h>
-#include <string.h>
-#include "system.h"
-#include "lcd.h"
-#include "button.h"
-#include "kernel.h"
-#include "menu.h"
-#include "rtc.h"
-#include "lang.h"
-#include "screens.h"
-#include "font.h"
+#ifdef HAVE_LCD_BITMAP
/* size of the field the worm lives in */
#define FIELD_RECT_X 1
@@ -149,6 +132,9 @@ static int player3_dir = EAST;
control a worm */
static int players = 1;
+/* the rockbox plugin api */
+static struct plugin_api* rb;
+
#ifdef DEBUG_WORMLET
static void set_debug_out(char *str){
strcpy(debugout, str);
@@ -507,8 +493,8 @@ static int make_food(int index) {
do {
/* make coordinates for a new food so that
the entire food lies within the FIELD */
- x = rand() % (FIELD_RECT_WIDTH - FOOD_SIZE);
- y = rand() % (FIELD_RECT_HEIGHT - FOOD_SIZE);
+ x = rb->rand() % (FIELD_RECT_WIDTH - FOOD_SIZE);
+ y = rb->rand() % (FIELD_RECT_HEIGHT - FOOD_SIZE);
tries ++;
/* Ensure that the new food doesn't collide with any
@@ -549,7 +535,7 @@ static int make_food(int index) {
static void clear_food(int index)
{
/* remove the old food from the screen */
- lcd_clearrect(foodx[index] + FIELD_RECT_X,
+ rb->lcd_clearrect(foodx[index] + FIELD_RECT_X,
foody[index] + FIELD_RECT_Y,
FOOD_SIZE, FOOD_SIZE);
}
@@ -563,10 +549,10 @@ static void clear_food(int index)
static void draw_food(int index)
{
/* draw the food object */
- lcd_fillrect(foodx[index] + FIELD_RECT_X,
+ rb->lcd_fillrect(foodx[index] + FIELD_RECT_X,
foody[index] + FIELD_RECT_Y,
FOOD_SIZE, FOOD_SIZE);
- lcd_clearrect(foodx[index] + FIELD_RECT_X + 1,
+ rb->lcd_clearrect(foodx[index] + FIELD_RECT_X + 1,
foody[index] + FIELD_RECT_Y + 1,
FOOD_SIZE - 2, FOOD_SIZE - 2);
}
@@ -588,8 +574,8 @@ static int make_argh(int index)
do {
/* make coordinates for a new argh so that
the entire food lies within the FIELD */
- x = rand() % (FIELD_RECT_WIDTH - ARGH_SIZE);
- y = rand() % (FIELD_RECT_HEIGHT - ARGH_SIZE);
+ x = rb->rand() % (FIELD_RECT_WIDTH - ARGH_SIZE);
+ y = rb->rand() % (FIELD_RECT_HEIGHT - ARGH_SIZE);
tries ++;
/* Ensure that the new argh doesn't intersect with any
@@ -631,7 +617,7 @@ static int make_argh(int index)
static void draw_argh(int index)
{
/* draw the new argh */
- lcd_fillrect(arghx[index] + FIELD_RECT_X,
+ rb->lcd_fillrect(arghx[index] + FIELD_RECT_X,
arghy[index] + FIELD_RECT_Y,
ARGH_SIZE, ARGH_SIZE);
}
@@ -744,7 +730,7 @@ static void init_wormlet(void)
}
/* Needed when the game is restarted using BUTTON_ON */
- lcd_clear_display();
+ rb->lcd_clear_display();
/* make and display some food and argh */
argh_count = MAX_FOOD;
@@ -756,11 +742,11 @@ static void init_wormlet(void)
}
/* draw the game field */
- lcd_invertrect(0, 0, FIELD_RECT_WIDTH + 2, FIELD_RECT_HEIGHT + 2);
- lcd_invertrect(1, 1, FIELD_RECT_WIDTH, FIELD_RECT_HEIGHT);
+ rb->lcd_invertrect(0, 0, FIELD_RECT_WIDTH + 2, FIELD_RECT_HEIGHT + 2);
+ rb->lcd_invertrect(1, 1, FIELD_RECT_WIDTH, FIELD_RECT_HEIGHT);
/* make everything visible */
- lcd_update();
+ rb->lcd_update();
}
@@ -852,14 +838,14 @@ static void draw_worm(struct worm *w)
int x = w->x[w->head];
int y = w->y[w->head];
if (x >= 0 && x < FIELD_RECT_WIDTH && y >= 0 && y < FIELD_RECT_HEIGHT) {
- lcd_drawpixel(x + FIELD_RECT_X, y + FIELD_RECT_Y);
+ rb->lcd_drawpixel(x + FIELD_RECT_X, y + FIELD_RECT_Y);
}
/* clear the space behind the worm */
x = w->x[w->tail] ;
y = w->y[w->tail] ;
if (x >= 0 && x < FIELD_RECT_WIDTH && y >= 0 && y < FIELD_RECT_HEIGHT) {
- lcd_clearpixel(x + FIELD_RECT_X, y + FIELD_RECT_Y);
+ rb->lcd_clearpixel(x + FIELD_RECT_X, y + FIELD_RECT_Y);
}
}
@@ -1166,10 +1152,10 @@ static void virtual_player(struct worm *w) {
static void score_board(void)
{
char buf[15];
- char buf2[15];
+ char* buf2 = NULL;
int i;
int y = 0;
- lcd_clearrect(FIELD_RECT_WIDTH + 2, 0, LCD_WIDTH - FIELD_RECT_WIDTH - 2, LCD_HEIGHT);
+ rb->lcd_clearrect(FIELD_RECT_WIDTH + 2, 0, LCD_WIDTH - FIELD_RECT_WIDTH - 2, LCD_HEIGHT);
for (i = 0; i < worm_count; i++) {
int score = get_score(&worms[i]);
@@ -1180,54 +1166,52 @@ static void score_board(void)
}
}
- /* length */
- snprintf(buf, sizeof (buf),str(LANG_WORMLET_LENGTH), score);
+ /* length */
+ rb->snprintf(buf, sizeof (buf),"Len:%d", score);
/* worm state */
switch (check_collision(&worms[i])) {
- case COLLISION_NONE:
- if (worms[i].growing > 0){
- snprintf(buf2, sizeof(buf2), str(LANG_WORMLET_GROWING));
- }
+ case COLLISION_NONE:
+ if (worms[i].growing > 0)
+ buf2 = "Growing";
else {
- if (worms[i].alive) {
- snprintf(buf2, sizeof(buf2), str(LANG_WORMLET_HUNGRY));
- } else {
- snprintf(buf2, sizeof(buf2), str(LANG_WORMLET_WORMED));
- }
+ if (worms[i].alive)
+ buf2 = "Hungry";
+ else
+ buf2 = "Wormed";
}
- break;
+ break;
- case COLLISION_WORM:
- snprintf(buf2, sizeof(buf2), str(LANG_WORMLET_WORMED));
- break;
+ case COLLISION_WORM:
+ buf2 = "Wormed";
+ break;
- case COLLISION_FOOD:
- snprintf(buf2, sizeof(buf2), str(LANG_WORMLET_GROWING));
- break;
+ case COLLISION_FOOD:
+ buf2 = "Growing";
+ break;
- case COLLISION_ARGH:
- snprintf(buf2, sizeof(buf2), str(LANG_WORMLET_ARGH));
- break;
+ case COLLISION_ARGH:
+ buf2 = "Argh";
+ break;
- case COLLISION_FIELD:
- snprintf(buf2, sizeof(buf2), str(LANG_WORMLET_CRASHED));
- break;
- }
- lcd_putsxy(FIELD_RECT_WIDTH + 3, y , buf);
- lcd_putsxy(FIELD_RECT_WIDTH + 3, y+8, buf2);
+ case COLLISION_FIELD:
+ buf2 = "Crashed";
+ break;
+ }
+ rb->lcd_putsxy(FIELD_RECT_WIDTH + 3, y , buf);
+ rb->lcd_putsxy(FIELD_RECT_WIDTH + 3, y+8, buf2);
if (!worms[i].alive){
- lcd_invertrect(FIELD_RECT_WIDTH + 2, y,
- LCD_WIDTH - FIELD_RECT_WIDTH - 2, 17);
+ rb->lcd_invertrect(FIELD_RECT_WIDTH + 2, y,
+ LCD_WIDTH - FIELD_RECT_WIDTH - 2, 17);
}
y += 19;
}
- snprintf(buf , sizeof(buf), str(LANG_WORMLET_HIGHSCORE), highscore);
+ rb->snprintf(buf , sizeof(buf), "Hs: %d", highscore);
#ifndef DEBUG_WORMLET
- lcd_putsxy(FIELD_RECT_WIDTH + 3, LCD_HEIGHT - 8, buf);
+ rb->lcd_putsxy(FIELD_RECT_WIDTH + 3, LCD_HEIGHT - 8, buf);
#else
- lcd_putsxy(FIELD_RECT_WIDTH + 3, LCD_HEIGHT - 8, debugout);
+ rb->lcd_putsxy(FIELD_RECT_WIDTH + 3, LCD_HEIGHT - 8, debugout);
#endif
}
@@ -1305,7 +1289,7 @@ static bool run(void)
/* initialize the board and so on */
init_wormlet();
- cycle_start = current_tick;
+ cycle_start = *rb->current_tick;
/* change the direction of the worm */
while (button != BUTTON_OFF && ! wormDead)
{
@@ -1358,7 +1342,7 @@ static bool run(void)
case BUTTON_PLAY:
do {
- button = button_get(true);
+ button = rb->button_get(true);
} while (button != BUTTON_PLAY &&
button != BUTTON_OFF &&
button != BUTTON_ON);
@@ -1377,7 +1361,7 @@ static bool run(void)
draw_worm(w);
}
score_board();
- lcd_update();
+ rb->lcd_update();
if (button == BUTTON_ON) {
wormDead = true;
}
@@ -1385,7 +1369,7 @@ static bool run(void)
/* here the wormlet game cycle ends
thus the current tick is stored
as end time */
- cycle_end = current_tick;
+ cycle_end = *rb->current_tick;
/* The duration of the game cycle */
cycle_duration = cycle_end - cycle_start;
@@ -1403,15 +1387,14 @@ static bool run(void)
max_cycle = cycle_duration;
ticks_to_max_cycle_reset = 20;
}
- snprintf(buf, sizeof buf, "ticks %d", max_cycle);
+ rb->snprintf(buf, sizeof buf, "ticks %d", max_cycle);
set_debug_out(buf);
#endif
/* adjust the number of ticks to wait for a button.
This ensures that a complete game cycle including
user input runs in constant time */
- button = button_get_w_tmo(SPEED - cycle_duration);
- cycle_start = current_tick;
-
+ button = rb->button_get_w_tmo(SPEED - cycle_duration);
+ cycle_start = *rb->current_tick;
}
return wormDead;
}
@@ -1425,7 +1408,7 @@ static bool run(void)
static void test_worm_food_collision(void) {
int collision_count = 0;
int i;
- lcd_clear_display();
+ rb->lcd_clear_display();
init_worm(&worms[0], 10, 10);
add_growing(&worms[0], 10);
set_worm_dir(&worms[0], EAST);
@@ -1451,12 +1434,12 @@ static void test_worm_food_collision(void) {
if (collision) {
collision_count++;
}
- snprintf(buf, sizeof buf, "collisions: %d", collision_count);
- lcd_putsxy(0, LCD_HEIGHT -8, buf);
- lcd_update();
+ rb->snprintf(buf, sizeof buf, "collisions: %d", collision_count);
+ rb->lcd_putsxy(0, LCD_HEIGHT -8, buf);
+ rb->lcd_update();
}
if (collision_count != FOOD_SIZE) {
- button_get(true);
+ rb->button_get(true);
}
@@ -1470,12 +1453,12 @@ static void test_worm_food_collision(void) {
if (collision) {
collision_count ++;
}
- snprintf(buf, sizeof buf, "collisions: %d", collision_count);
- lcd_putsxy(0, LCD_HEIGHT -8, buf);
- lcd_update();
+ rb->snprintf(buf, sizeof buf, "collisions: %d", collision_count);
+ rb->lcd_putsxy(0, LCD_HEIGHT -8, buf);
+ rb->lcd_update();
}
if (collision_count != FOOD_SIZE * 2) {
- button_get(true);
+ rb->button_get(true);
}
}
@@ -1498,7 +1481,7 @@ static void test_worm_argh_collision(void) {
int i;
int dir;
int collision_count = 0;
- lcd_clear_display();
+ rb->lcd_clear_display();
init_worm(&worms[0], 10, 10);
add_growing(&worms[0], 40);
for (dir = 0; dir < 4; dir++) {
@@ -1518,12 +1501,12 @@ static void test_worm_argh_collision(void) {
if (collision) {
collision_count ++;
}
- snprintf(buf, sizeof buf, "collisions: %d", collision_count);
- lcd_putsxy(0, LCD_HEIGHT -8, buf);
- lcd_update();
+ rb->snprintf(buf, sizeof buf, "collisions: %d", collision_count);
+ rb->lcd_putsxy(0, LCD_HEIGHT -8, buf);
+ rb->lcd_update();
}
if (collision_count != ARGH_SIZE * 2) {
- button_get(true);
+ rb->button_get(true);
}
arghy[0] = 12;
@@ -1535,12 +1518,12 @@ static void test_worm_argh_collision(void) {
if (collision) {
collision_count ++;
}
- snprintf(buf, sizeof buf, "collisions: %d", collision_count);
- lcd_putsxy(0, LCD_HEIGHT -8, buf);
- lcd_update();
+ rb->snprintf(buf, sizeof buf, "collisions: %d", collision_count);
+ rb->lcd_putsxy(0, LCD_HEIGHT -8, buf);
+ rb->lcd_update();
}
if (collision_count != ARGH_SIZE * 4) {
- button_get(true);
+ rb->button_get(true);
}
}
@@ -1560,11 +1543,11 @@ static int testline_in_rect(void) {
if (!line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
!line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_update();
- lcd_putsxy(0, 0, "failed 1");
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_update();
+ rb->lcd_putsxy(0, 0, "failed 1");
+ rb->button_get(true);
testfailed = 1;
}
@@ -1572,11 +1555,11 @@ static int testline_in_rect(void) {
y2 = 20;
if (!line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
!line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 2");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 2");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 2;
}
@@ -1584,11 +1567,11 @@ static int testline_in_rect(void) {
y1 = 30;
if (!line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
!line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 3");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 3");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 3;
}
@@ -1596,11 +1579,11 @@ static int testline_in_rect(void) {
y2 = 45;
if (!line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
!line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 4");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 4");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 4;
}
@@ -1608,11 +1591,11 @@ static int testline_in_rect(void) {
y1 = 50;
if (line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) ||
line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 5");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 5");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 5;
}
@@ -1621,11 +1604,11 @@ static int testline_in_rect(void) {
y2 = 7;
if (line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) ||
line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 6");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 6");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 6;
}
@@ -1636,11 +1619,11 @@ static int testline_in_rect(void) {
y2 = 20;
if (!line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
!line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 7");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 7");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 7;
}
@@ -1648,11 +1631,11 @@ static int testline_in_rect(void) {
x2 = 12;
if (!line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
!line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 8");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 8");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 8;
}
@@ -1660,11 +1643,11 @@ static int testline_in_rect(void) {
x1 = 25;
if (!line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
!line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 9");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 9");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 9;
}
@@ -1672,11 +1655,11 @@ static int testline_in_rect(void) {
x2 = 37;
if (!line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
!line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 10");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 10");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 10;
}
@@ -1684,11 +1667,11 @@ static int testline_in_rect(void) {
x1 = 42;
if (line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) ||
line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 11");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 11");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 11;
}
@@ -1697,11 +1680,11 @@ static int testline_in_rect(void) {
x2 = 7;
if (line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) ||
line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh)) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 12");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 12");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 12;
}
@@ -1717,11 +1700,11 @@ static int testline_in_rect(void) {
y2 = 20;
if (!(line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh))) {
- lcd_drawrect(rx, ry, rw, rh);
- lcd_drawline(x1, y1, x2, y2);
- lcd_putsxy(0, 0, "failed 13");
- lcd_update();
- button_get(true);
+ rb->lcd_drawrect(rx, ry, rw, rh);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_putsxy(0, 0, "failed 13");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 13;
}
@@ -1737,15 +1720,15 @@ static int testline_in_rect(void) {
y2 = 19;
if (!(line_in_rect(x1, y1, x2, y2, rx, ry, rw, rh) &&
line_in_rect(x2, y2, x1, y1, rx, ry, rw, rh))) {
- lcd_drawline(x1, y1, x2, y2);
- lcd_invertrect(rx, ry, rw, rh);
- lcd_putsxy(0, 0, "failed 14");
- lcd_update();
- button_get(true);
+ rb->lcd_drawline(x1, y1, x2, y2);
+ rb->lcd_invertrect(rx, ry, rw, rh);
+ rb->lcd_putsxy(0, 0, "failed 14");
+ rb->lcd_update();
+ rb->button_get(true);
testfailed = 14;
}
- lcd_clear_display();
+ rb->lcd_clear_display();
return testfailed;
}
@@ -1759,7 +1742,7 @@ static int test_specific_worm_collision(void) {
int x = 0;
int y = 0;
char buf[20];
- lcd_clear_display();
+ rb->lcd_clear_display();
init_worm(&worms[0], 10, 20);
add_growing(&worms[0], 20 - INITIAL_WORM_LENGTH);
@@ -1779,14 +1762,14 @@ static int test_specific_worm_collision(void) {
if (specific_worm_collision(&worms[0], x, y) != -1) {
collisions ++;
}
- lcd_invertpixel(x + FIELD_RECT_X, y + FIELD_RECT_Y);
- snprintf(buf, sizeof buf, "collisions %d", collisions);
- lcd_putsxy(0, LCD_HEIGHT - 8, buf);
- lcd_update();
+ rb->lcd_invertpixel(x + FIELD_RECT_X, y + FIELD_RECT_Y);
+ rb->snprintf(buf, sizeof buf, "collisions %d", collisions);
+ rb->lcd_putsxy(0, LCD_HEIGHT - 8, buf);
+ rb->lcd_update();
}
}
if (collisions != 21) {
- button_get(true);
+ rb->button_get(true);
}
return collisions;
}
@@ -1798,7 +1781,7 @@ static void test_make_argh(void){
int failures = 0;
int last_failures = 0;
int i, worm_idx;
- lcd_clear_display();
+ rb->lcd_clear_display();
worm_count = 3;
for (worm_idx = 0; worm_idx < worm_count; worm_idx++) {
@@ -1818,37 +1801,37 @@ static void test_make_argh(void){
}
}
- lcd_update();
+ rb->lcd_update();
for (seed = 0; hit < 20; seed += 2) {
char buf[20];
int x, y;
- srand(seed);
- x = rand() % (FIELD_RECT_WIDTH - ARGH_SIZE);
- y = rand() % (FIELD_RECT_HEIGHT - ARGH_SIZE);
+ rb->srand(seed);
+ x = rb->rand() % (FIELD_RECT_WIDTH - ARGH_SIZE);
+ y = rb->rand() % (FIELD_RECT_HEIGHT - ARGH_SIZE);
for (worm_idx = 0; worm_idx < worm_count; worm_idx++){
if (expensive_worm_in_rect(&worms[worm_idx], x, y, ARGH_SIZE, ARGH_SIZE)) {
int tries = 0;
- srand(seed);
+ rb->srand(seed);
tries = make_argh(0);
if ((x == arghx[0] && y == arghy[0]) || tries < 2) {
failures ++;
}
- snprintf(buf, sizeof buf, "(%d;%d) fail%d try%d", x, y, failures, tries);
- lcd_putsxy(0, LCD_HEIGHT - 8, buf);
- lcd_update();
- lcd_invertrect(x + FIELD_RECT_X, y+ FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE);
- lcd_update();
+ rb->snprintf(buf, sizeof buf, "(%d;%d) fail%d try%d", x, y, failures, tries);
+ rb->lcd_putsxy(0, LCD_HEIGHT - 8, buf);
+ rb->lcd_update();
+ rb->lcd_invertrect(x + FIELD_RECT_X, y+ FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE);
+ rb->lcd_update();
draw_argh(0);
- lcd_update();
- lcd_invertrect(x + FIELD_RECT_X, y + FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE);
- lcd_clearrect(arghx[0] + FIELD_RECT_X, arghy[0] + FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE);
+ rb->lcd_update();
+ rb->lcd_invertrect(x + FIELD_RECT_X, y + FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE);
+ rb->lcd_clearrect(arghx[0] + FIELD_RECT_X, arghy[0] + FIELD_RECT_Y, ARGH_SIZE, ARGH_SIZE);
if (failures > last_failures) {
- button_get(true);
+ rb->button_get(true);
}
last_failures = failures;
hit ++;
@@ -1860,7 +1843,7 @@ static void test_make_argh(void){
static void test_worm_argh_collision_in_moves(void) {
int hit_count = 0;
int i;
- lcd_clear_display();
+ rb->lcd_clear_display();
init_worm(&worms[0], 10, 20);
arghx[0] = 20;
@@ -1875,12 +1858,12 @@ static void test_worm_argh_collision_in_moves(void) {
if (worm_argh_collision_in_moves(&worms[0], 0, 5)){
hit_count ++;
}
- snprintf(buf, sizeof buf, "in 5 moves hits: %d", hit_count);
- lcd_putsxy(0, LCD_HEIGHT - 8, buf);
- lcd_update();
+ rb->snprintf(buf, sizeof buf, "in 5 moves hits: %d", hit_count);
+ rb->lcd_putsxy(0, LCD_HEIGHT - 8, buf);
+ rb->lcd_update();
}
if (hit_count != ARGH_SIZE + 5) {
- button_get(true);
+ rb->button_get(true);
}
}
#endif /* DEBUG_WORMLET */
@@ -1888,14 +1871,18 @@ static void test_worm_argh_collision_in_moves(void) {
extern bool use_old_rect;
/**
- * Main entry point from the menu to start the game control.
+ * Main entry point
*/
-bool wormlet(void)
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{
bool worm_dead = false;
int button;
- lcd_setfont(FONT_SYSFIXED);
+ TEST_PLUGIN_API(api);
+ (void)(parameter);
+
+ rb = api;
+ rb->lcd_setfont(FONT_SYSFIXED);
#ifdef DEBUG_WORMLET
testline_in_rect();
@@ -1905,44 +1892,44 @@ bool wormlet(void)
test_worm_argh_collision();
test_specific_worm_collision();
#endif
- lcd_setmargins(0,0);
/* Setup screen */
do {
char buf[20];
- lcd_clear_display();
+ char* ptr;
+ rb->lcd_clear_display();
/* first line players */
- snprintf(buf, sizeof buf, str(LANG_WORMLET_PLAYERS), players);
- lcd_puts(0, 0, buf);
+ rb->snprintf(buf, sizeof buf, "%d Players UP/DN", players);
+ rb->lcd_puts(0, 0, buf);
/* second line worms */
- snprintf(buf, sizeof buf, str(LANG_WORMLET_WORMS), worm_count);
- lcd_puts(0, 1, buf);
+ rb->snprintf(buf, sizeof buf, "%d Worms L/R", worm_count);
+ rb->lcd_puts(0, 1, buf);
/* third line control */
if (players > 1) {
if (use_remote) {
- snprintf(buf, sizeof buf, str(LANG_WORMLET_REMOTE_CTRL));
+ ptr = "Remote Control F1";
} else {
- snprintf(buf, sizeof buf, str(LANG_WORMLET_NO_REM_CTRL));
+ ptr = "No Rem. Control F1";
}
} else {
if (players > 0) {
if (use_remote) {
- snprintf(buf, sizeof buf, str(LANG_WORMLET_2_KEY_CTRL));
+ ptr = "2 Key Control F1";
} else {
- snprintf(buf, sizeof buf, str(LANG_WORMLET_4_KEY_CTRL));
+ ptr = "4 Key Control F1";
}
} else {
- snprintf(buf, sizeof buf, str(LANG_WORMLET_NO_CONTROL));
+ ptr = "Out Of Control";
}
}
- lcd_puts(0, 2, buf);
- lcd_update();
+ rb->lcd_puts(0, 2, ptr);
+ rb->lcd_update();
/* user selection */
- button = button_get(true);
+ button = rb->button_get(true);
switch (button) {
case BUTTON_UP:
if (players < 3) {
@@ -1981,14 +1968,13 @@ bool wormlet(void)
break;
case SYS_USB_CONNECTED:
- usb_screen();
- lcd_setfont(FONT_UI);
- return true;
+ rb->usb_screen();
+ return PLUGIN_USB_CONNECTED;
}
} while (button != BUTTON_PLAY &&
button != BUTTON_OFF && button != BUTTON_ON);
- lcd_clear_display();
+ rb->lcd_clear_display();
/* end of setup */
do {
@@ -2008,7 +1994,7 @@ bool wormlet(void)
via BUTTON_OFF -> no need to wait for buttons. */
if (worm_dead) {
do {
- button = button_get(true);
+ button = rb->button_get(true);
}
/* BUTTON_ON -> start new game */
/* BUTTON_OFF -> back to game menu */
@@ -2017,20 +2003,7 @@ bool wormlet(void)
}
while (button != BUTTON_OFF);
- lcd_setfont(FONT_UI);
-
- return false;
+ return PLUGIN_OK;
}
-
-#endif /* USE_GAMES */
-
-
-
-
-
-
-
-
-
-
+#endif
diff --git a/apps/recorder/icons.c b/apps/recorder/icons.c
index af0352094f..25d34d7591 100644
--- a/apps/recorder/icons.c
+++ b/apps/recorder/icons.c
@@ -64,6 +64,7 @@ unsigned char bitmap_icons_6x8[LastIcon][6] =
{ 0x3e, 0x2a, 0x3e, 0x2a, 0x2a, 0x3e }, /* Language file */
{ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, /* Text file */
{ 0x4e, 0x51, 0x51, 0x40, 0x55, 0x55 }, /* Config file */
+ { 0x0a, 0x0a, 0x5f, 0x4e, 0x24, 0x18 }, /* Plugin file */
};
unsigned char bitmap_icons_7x8[][7] =
diff --git a/apps/recorder/icons.h b/apps/recorder/icons.h
index a7858cd0ae..40418468f3 100644
--- a/apps/recorder/icons.h
+++ b/apps/recorder/icons.h
@@ -29,6 +29,7 @@ enum icons_6x8 {
Folder, Directory, Playlist, Repeat,
Selected, Cursor, Wps, Mod_Ajz,
Font, Language, Text, Config,
+ Plugin,
LastIcon
};
diff --git a/apps/recorder/sokoban.c b/apps/recorder/sokoban.c
deleted file mode 100644
index d28e32f430..0000000000
--- a/apps/recorder/sokoban.c
+++ /dev/null
@@ -1,891 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * 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 "config.h"
-#include "options.h"
-
-#ifdef USE_GAMES
-
-#include <sprintf.h>
-#include "ctype.h"
-#include "sokoban.h"
-#include "lcd.h"
-#include "button.h"
-#include "kernel.h"
-#include "menu.h"
-#include "screens.h"
-#include "font.h"
-#include "file.h"
-#include "misc.h"
-#include "debug.h"
-
-#ifdef SIMULATOR
-#include <stdio.h>
-#endif
-#include <string.h>
-#include "lang.h"
-#include "sprintf.h"
-
-#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 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];
-
- current_info.level = undo->level;
- current_info.player = 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 */
- undo->level = current_info.level;
-
- /* Store our player info */
- undo->location[0] = current_info.player;
-
- /* 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 len, lastlen = 0;
- char buffer[COLS + 3]; /* COLS plus CR/LF and \0 */
-
- if ((fd = open(LEVELS_FILE, O_RDONLY)) < 0) {
- splash(0, 0, true, "Unable to open %s", LEVELS_FILE);
- return -1;
- }
-
- while(1) {
- len = 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;
- }
-
- DEBUGF("%d levels loaded\n", current_info.max_level);
- 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 len, lastlen = 0;
- int level_ct = 1;
- unsigned char buffer[SOKOBAN_LEVEL_SIZE * 2];
- bool level_found = false;
-
- /* open file */
- if ((fd = 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) {
- lseek(fd, current_info.level_offset, SEEK_SET);
- level_ct = current_info.loaded_level;
- }
-
- if(current_info.level.level > 1) {
- while(!level_found) {
- len = read_line(fd, buffer, SOKOBAN_LEVEL_SIZE);
- if(len <= 0) {
- 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 = lseek(fd, 0, SEEK_CUR);
-
- /* read a full buffer chunk from here */
- nread = read(fd, buffer, sizeof(buffer)-1);
- if (nread < 0)
- return -1;
- buffer[nread] = 0;
-
- 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 */
- lcd_drawrect(c, b, magnify, magnify);
- lcd_drawrect(c+1, b+1, 2, 2);
- break;
-
- case '#': /* this is a wall */
- lcd_drawpixel(c, b);
- lcd_drawpixel(c+2, b);
- lcd_drawpixel(c+1, b+1);
- lcd_drawpixel(c+3, b+1);
- lcd_drawpixel(c, b+2);
- lcd_drawpixel(c+2, b+2);
- lcd_drawpixel(c+1, b+3);
- lcd_drawpixel(c+3, b+3);
- break;
-
- case '.': /* this is a home location */
- lcd_drawrect(c+1, b+1, 2, 2);
- break;
-
- case '$': /* this is a box */
- lcd_drawrect(c, b, magnify, magnify);
- break;
-
- case '@': /* this is you */
- lcd_drawline(c+1, b, c+2, b);
- lcd_drawline(c, b+1, c+3, b+1);
- lcd_drawline(c+1, b+2, c+2, b+2);
-
- lcd_drawpixel(c, b+3);
- lcd_drawpixel(c+3, b+3);
- break;
-
- case '%': /* this is a box on a home spot */
- lcd_drawrect(c, b, magnify, magnify);
- lcd_drawrect(c+1, b+1, 2, 2);
- break;
- }
- }
- }
-
-
- snprintf(s, sizeof(s), "%d", current_info.level.level);
- lcd_putsxy(86, 22, s);
- snprintf(s, sizeof(s), "%d", current_info.level.moves);
- lcd_putsxy(86, 54, s);
-
- lcd_drawrect(80,0,32,32);
- lcd_drawrect(80,32,32,64);
- lcd_putsxy(81, 10, str(LANG_SOKOBAN_LEVEL));
- lcd_putsxy(81, 42, str(LANG_SOKOBAN_MOVE));
-
- /* print out the screen */
- lcd_update();
-}
-
-static void draw_level(void)
-{
- load_level();
- 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 = button_get(true);
-
- add_undo(button);
-
- switch(button)
- {
- case BUTTON_OFF:
- /* get out of here */
- return false;
-
- case BUTTON_ON:
- case BUTTON_ON | BUTTON_REPEAT:
- /* this is UNDO */
- undo();
- 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:
- usb_screen();
- return true;
-
- default:
- moved = false;
- break;
- }
-
- if (moved) {
- current_info.level.moves++;
- 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();
-
- lcd_clear_display();
-
- if (current_info.level.level > current_info.max_level) {
- lcd_putsxy(10, 20, str(LANG_SOKOBAN_WIN));
-
- for (i = 0; i < 30000 ; i++) {
- lcd_invertrect(0, 0, 111, 63);
- lcd_update();
-
- button = button_get(false);
- if (button && ((button & BUTTON_REL) != BUTTON_REL))
- break;
- }
-
- return false;
- }
-
- load_level();
- update_screen();
- }
-
- } /* end while */
-
- return false;
-}
-
-
-bool sokoban(void)
-{
- bool result;
- int w, h;
- int len;
-
- lcd_setfont(FONT_SYSFIXED);
-
- 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;
-
- lcd_clear_display();
- lcd_putsxy(LCD_WIDTH/2-len,(LCD_HEIGHT/2)-h, SOKOBAN_TITLE);
-
- lcd_update();
- sleep(HZ*2);
-
- lcd_clear_display();
-
- lcd_putsxy(3, 6, str(LANG_SOKOBAN_QUIT));
- lcd_putsxy(3, 16, str(LANG_SOKOBAN_ON));
- lcd_putsxy(3, 26, str(LANG_SOKOBAN_F1));
- lcd_putsxy(3, 36, str(LANG_SOKOBAN_F2));
- lcd_putsxy(3, 46, str(LANG_SOKOBAN_F3));
-
- lcd_update();
- sleep(HZ*2);
- lcd_clear_display();
-
- init_boards();
-
- if (get_level_count() != 0)
- return false;
-
- result = sokoban_loop();
-
- lcd_setfont(FONT_UI);
-
- return result;
-}
-
-#endif
diff --git a/apps/recorder/sokoban.h b/apps/recorder/sokoban.h
deleted file mode 100644
index f4f8fdd24f..0000000000
--- a/apps/recorder/sokoban.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2002 Robert E. Hak
- *
- * 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.
- *
- ****************************************************************************/
-
-#ifndef __SOKOBAN__
-#define __SOKOBAN__
-
-#include "menu.h"
-
-bool sokoban(void);
-
-#endif /*__SOKOBAN__ */
-
diff --git a/apps/recorder/tetris.c b/apps/recorder/tetris.c
deleted file mode 100644
index 6302e40109..0000000000
--- a/apps/recorder/tetris.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 1999 Mattis Wadman (nappe@sudac.org)
- *
- * Heavily modified for embedded use by Björn Stenberg (bjorn@haxx.se)
- *
- * 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 "config.h"
-#include "options.h"
-
-#ifdef USE_GAMES
-
-#include <stdbool.h>
-#include <string.h>
-#include "lcd.h"
-#include "button.h"
-#include "kernel.h"
-#include "menu.h"
-#include "screens.h"
-#include "font.h"
-
-#ifdef SIMULATOR
-#include <stdio.h>
-#endif
-#include "sprintf.h"
-#include "lang.h"
-#define TETRIS_TITLE "Tetris!"
-#define TETRIS_TITLE_FONT 1
-#define TETRIS_TITLE_XLOC 43
-#define TETRIS_TITLE_YLOC 15
-
-static const int start_x = 5;
-static const int start_y = 5;
-static const int max_x = 4 * 17;
-static const int max_y = 3 * 10;
-static const short level_speeds[10] = {
- 1000, 900, 800, 700, 600, 500, 400, 300, 250, 200
-};
-static const int blocks = 7;
-static const int block_frames[7] = {1,2,2,2,4,4,4};
-
-static int current_x, current_y, current_f, current_b;
-static int level, score;
-static int next_b, next_f;
-static short lines;
-static char virtual[LCD_WIDTH * LCD_HEIGHT];
-
-/*
- block_data is built up the following way
-
- first array index specifies the block number
- second array index specifies the rotation of the block
- third array index specifies:
- 0: x-coordinates of pixels
- 1: y-coordinates of pixels
- fourth array index specifies the coordinate of a pixel
-
- each block consists of four pixels whose relative coordinates are given
- with block_data
-*/
-
-static const char block_data[7][4][2][4] =
-{
- {
- {{0,1,0,1},{0,0,1,1}}
- },
- {
- {{0,1,1,2},{1,1,0,0}},
- {{0,0,1,1},{0,1,1,2}}
- },
- {
- {{0,1,1,2},{0,0,1,1}},
- {{1,1,0,0},{0,1,1,2}}
- },
- {
- {{1,1,1,1},{0,1,2,3}},
- {{0,1,2,3},{2,2,2,2}}
- },
- {
- {{1,1,1,2},{2,1,0,0}},
- {{0,1,2,2},{1,1,1,2}},
- {{0,1,1,1},{2,2,1,0}},
- {{0,0,1,2},{0,1,1,1}}
- },
- {
- {{0,1,1,1},{0,0,1,2}},
- {{0,1,2,2},{1,1,1,0}},
- {{1,1,1,2},{0,1,2,2}},
- {{0,0,1,2},{2,1,1,1}}
- },
- {
- {{1,0,1,2},{0,1,1,1}},
- {{2,1,1,1},{1,0,1,2}},
- {{1,0,1,2},{2,1,1,1}},
- {{0,1,1,1},{1,0,1,2}}
- }
-};
-
-static int t_rand(int range)
-{
- return current_tick % range;
-}
-
-static void draw_frame(int fstart_x,int fstop_x,int fstart_y,int fstop_y)
-{
- lcd_drawline(fstart_x, fstart_y, fstop_x, fstart_y);
- lcd_drawline(fstart_x, fstop_y, fstop_x, fstop_y);
-
- lcd_drawline(fstart_x, fstart_y, fstart_x, fstop_y);
- lcd_drawline(fstop_x, fstart_y, fstop_x, fstop_y);
-
- lcd_drawline(fstart_x - 1, fstart_y + 1, fstart_x - 1, fstop_y + 1);
- lcd_drawline(fstart_x - 1, fstop_y + 1, fstop_x - 1, fstop_y + 1);
-}
-
-static void draw_block(int x, int y, int block, int frame, bool clear)
-{
- int i, a, b;
- for(i=0;i < 4;i++) {
- if (clear)
- {
- for (a = 0; a < 3; a++)
- for (b = 0; b < 4; b++)
- lcd_clearpixel(start_x + x + block_data[block][frame][1][i] * 4 - b,
- start_y + y + block_data[block][frame][0][i] * 3 + a);
- }
- else
- {
- for (a = 0; a < 3; a++)
- for (b = 0; b < 4; b++)
- lcd_drawpixel(start_x+x+block_data[block][frame][1][i] * 4 - b,
- start_y+y+block_data[block][frame][0][i] * 3 + a);
- }
- }
-}
-
-static void to_virtual(void)
-{
- int i, a, b;
-
- for(i = 0; i < 4; i++)
- for (a = 0; a < 3; a++)
- for (b = 0; b < 4; b++)
- *(virtual +
- (current_y + block_data[current_b][current_f][0][i] * 3 + a) *
- max_x + current_x + block_data[current_b][current_f][1][i] *
- 4 - b) = current_b + 1;
-}
-
-static bool block_touch (int x, int y)
-{
- int a,b;
- for (a = 0; a < 4; a++)
- for (b = 0; b < 3; b++)
- if (*(virtual + (y + b) * max_x + (x - a)) != 0)
- return true;
- return false;
-}
-
-static bool gameover(void)
-{
- int i;
- int frame, block, y, x;
-
- x = current_x;
- y = current_y;
- block = current_b;
- frame = current_f;
-
- for(i = 0; i < 4; i++){
- /* Do we have blocks touching? */
- if(block_touch(x + block_data[block][frame][1][i] * 4,
- y + block_data[block][frame][0][i] * 3))
- {
- /* Are we at the top of the frame? */
- if(x + block_data[block][frame][1][i] * 4 >= max_x - 16)
- {
- /* Game over ;) */
- return true;
- }
- }
- }
- return false;
-}
-
-static bool valid_position(int x, int y, int block, int frame)
-{
- int i;
- for(i=0;i < 4;i++)
- if ((y + block_data[block][frame][0][i] * 3 > max_y - 3) ||
- (x + block_data[block][frame][1][i] * 4 > max_x - 4) ||
- (y + block_data[block][frame][0][i] * 3 < 0) ||
- (x + block_data[block][frame][1][i] * 4 < 4) ||
- block_touch (x + block_data[block][frame][1][i] * 4,
- y + block_data[block][frame][0][i] * 3))
- {
- return false;
- }
- return true;
-}
-
-static void from_virtual(void)
-{
- int x,y;
- for(y = 0; y < max_y; y++)
- for(x = 1; x < max_x - 1; x++)
- if(*(virtual + (y * max_x) + x) != 0)
- lcd_drawpixel(start_x + x, start_y + y);
- else
- lcd_clearpixel(start_x + x, start_y + y);
-}
-
-static void move_block(int x,int y,int f)
-{
- int last_frame = current_f;
- if(f != 0)
- {
- current_f += f;
- if(current_f > block_frames[current_b]-1)
- current_f = 0;
- if(current_f < 0)
- current_f = block_frames[current_b]-1;
- }
-
- if(valid_position(current_x + x, current_y + y, current_b, current_f))
- {
- draw_block(current_x,current_y,current_b,last_frame,true);
- current_x += x;
- current_y += y;
- draw_block(current_x,current_y,current_b,current_f,false);
- lcd_update();
- }
- else
- current_f = last_frame;
-}
-
-static void new_block(void)
-{
- current_b = next_b;
- current_f = next_f;
- current_x = max_x - 16;
- current_y = (int)12;
- next_b = t_rand(blocks);
- next_f = t_rand(block_frames[next_b]);
-
- lcd_drawline (max_x + 7, start_y - 1, max_x + 29, start_y - 1);
- lcd_drawline (max_x + 29, start_y, max_x + 29, start_y + 14);
- lcd_drawline (max_x + 29, start_y + 14, max_x + 7, start_y + 14);
- lcd_drawline (max_x + 7, start_y + 14, max_x + 7, start_y - 1);
- lcd_drawline (max_x + 6, start_y + 15, max_x + 6, start_y);
- lcd_drawline (max_x + 6, start_y + 15, max_x + 28, start_y + 15);
-
- draw_block(max_x + 9, start_y - 4, current_b, current_f, true);
- draw_block(max_x + 9, start_y - 4, next_b, next_f, false);
- if(!valid_position(current_x, current_y, current_b, current_f))
- {
- draw_block(current_x, current_y, current_b, current_f, false);
- lcd_update();
- }
- else
- draw_block(current_x, current_y, current_b, current_f, false);
-}
-
-static int check_lines(void)
-{
- int x,y,i,j;
- bool line;
- int lines = 0;
- for(x = 0; x < max_x; x++)
- {
- line = true;
- for(y = 0; y < max_y; y++)
- {
- if(*(virtual + y * max_x + x) == 0)
- {
- line = false;
- break;
- }
- }
-
- if(line)
- {
- lines++;
- /* move rows down */
- for(i = x; i < max_x - 1; i++)
- for (j = 0; j < max_y; j++)
- *(virtual + j * max_x + i)=*(virtual + j * max_x + (i + 1));
-
- x--; /* re-check this line */
- }
- }
-
- return lines / 4;
-}
-
-static void move_down(void)
-{
- int l;
- char s[25];
-
- if(!valid_position(current_x - 4, current_y, current_b, current_f))
- {
- to_virtual();
- l = check_lines();
- if(l)
- {
- lines += l;
- level = (int)lines/10;
- if(level > 9)
- level = 9;
- from_virtual();
- score += l*l;
- }
-
- snprintf (s, sizeof(s), "%d %s %d", lines,
- str(LANG_TETRIS_LEVEL), level);
- lcd_putsxy (2, 42, s);
-
- new_block();
- move_block(0,0,0);
- }
- else
- move_block(-4,0,0);
-}
-
-static bool game_loop(void)
-{
- while(1)
- {
- int count = 0;
- while(count * 300 < level_speeds[level])
- {
- switch(button_get_w_tmo(HZ/10))
- {
- case BUTTON_OFF:
- return false;
-
- case BUTTON_UP:
- case BUTTON_UP | BUTTON_REPEAT:
- move_block(0,-3,0);
- break;
-
- case BUTTON_DOWN:
- case BUTTON_DOWN | BUTTON_REPEAT:
- move_block(0,3,0);
- break;
-
- case BUTTON_RIGHT:
- case BUTTON_RIGHT | BUTTON_REPEAT:
- move_block(0,0,1);
- break;
-
- case BUTTON_LEFT:
- case BUTTON_LEFT | BUTTON_REPEAT:
- move_down();
- break;
-
- case SYS_USB_CONNECTED:
- usb_screen();
- return true;
- }
-
- count++;
- }
-
- if(gameover())
- {
- lcd_clearrect(0, 52, LCD_WIDTH, LCD_HEIGHT - 52);
- lcd_putsxy (2, 52, str(LANG_TETRIS_LOSE));
- lcd_update();
- sleep(HZ * 3);
- return false;
- }
-
- move_down();
- }
-
- return false;
-}
-
-static void init_tetris(void)
-{
- memset(&virtual, 0, sizeof(virtual));
-
- current_x = 0;
- current_y = 0;
- current_f = 0;
- current_b = 0;
- level = 0;
- lines = 0;
- score = 0;
- next_b = 0;
- next_f = 0;
-}
-
-bool tetris(void)
-{
- char buf[20];
- bool val;
-
- /* Lets use the default font */
- lcd_setfont(FONT_SYSFIXED);
-
- init_tetris();
-
- draw_frame(start_x, start_x + max_x - 1, start_y - 1, start_y + max_y);
- snprintf(buf, sizeof(buf), "0 %s 0", str(LANG_TETRIS_LEVEL));
- lcd_putsxy (2, 42, buf);
- lcd_update();
-
- next_b = t_rand(blocks);
- next_f = t_rand(block_frames[next_b]);
- new_block();
- val = game_loop();
-
- lcd_setfont(FONT_UI);
-
- return val;
-}
-
-#endif
-
-
-
diff --git a/apps/recorder/wormlet.h b/apps/recorder/wormlet.h
deleted file mode 100644
index 0aeea3cc77..0000000000
--- a/apps/recorder/wormlet.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * 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.
- *
- ****************************************************************************/
-
-#ifndef __WORMLET__
-#define __WORMLET__
-
-#include "menu.h"
-
-bool wormlet(void);
-
-#endif /*__WORMLET__ */
-
diff --git a/apps/screens.c b/apps/screens.c
index d12a93a4d4..6055be3a2d 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -31,6 +31,7 @@
#include "status.h"
#include "playlist.h"
#include "sprintf.h"
+#include "kernel.h"
#ifdef HAVE_LCD_BITMAP
#define BMPHEIGHT_usb_logo 32
diff --git a/apps/tree.c b/apps/tree.c
index 9935d8263d..e61fdc50cb 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -46,12 +46,12 @@
#include "rolo.h"
#include "icons.h"
#include "lang.h"
-#include "viewer.h"
#include "language.h"
#include "screens.h"
#include "keyboard.h"
#include "onplay.h"
#include "buffer.h"
+#include "plugin.h"
#ifdef HAVE_LCD_BITMAP
#include "widgets.h"
@@ -318,6 +318,8 @@ static int showdir(char *path, int start)
else if (!strcasecmp(&entry->d_name[len-4], ".mod"))
#endif
dptr->attr |= TREE_ATTR_MOD;
+ else if (!strcasecmp(&entry->d_name[len-5], ".rock"))
+ dptr->attr |= TREE_ATTR_ROCK;
}
/* filter out all non-playlist files */
@@ -468,6 +470,10 @@ static int showdir(char *path, int start)
icon_type = Mod_Ajz;
break;
+ case TREE_ATTR_ROCK:
+ icon_type = Plugin;
+ break;
+
#ifdef HAVE_LCD_BITMAP
case TREE_ATTR_FONT:
icon_type = Font;
@@ -962,7 +968,7 @@ bool dirbrowse(char *root)
break;
case TREE_ATTR_TXT:
- viewer_run(buf);
+ plugin_load("/.rockbox/rocks/viewer.rock",buf);
restore = true;
break;
@@ -998,6 +1004,14 @@ bool dirbrowse(char *root)
rolo_load(buf);
break;
#endif
+
+ /* plugin file */
+ case TREE_ATTR_ROCK:
+ if (plugin_load(buf,NULL) == PLUGIN_USB_CONNECTED)
+ reload_root = true;
+ else
+ restore = true;
+ break;
}
if ( play ) {
@@ -1194,6 +1208,7 @@ bool dirbrowse(char *root)
/* the sub-screen might've ruined the margins */
lcd_setmargins(MARGIN_X,MARGIN_Y); /* leave room for cursor and
icon */
+ lcd_setfont(FONT_UI);
#endif
numentries = showdir(currdir, dirstart);
update_all = true;
diff --git a/apps/tree.h b/apps/tree.h
index eb0aa8b98a..aa8f2127f3 100644
--- a/apps/tree.h
+++ b/apps/tree.h
@@ -30,6 +30,7 @@
#define TREE_ATTR_TXT 0x500 /* text file */
#define TREE_ATTR_FONT 0x800 /* font file */
#define TREE_ATTR_LNG 0x1000 /* binary lang file */
+#define TREE_ATTR_ROCK 0x2000 /* binary rockbox plugin */
#define TREE_ATTR_MASK 0xffd0 /* which bits tree.c uses (above + DIR) */
void tree_init(void);
diff --git a/apps/viewer.h b/apps/viewer.h
deleted file mode 100644
index ed9f64ca49..0000000000
--- a/apps/viewer.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2002 Jerome Kuptz
- *
- * 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.
- *
- ****************************************************************************/
-#ifndef _VIEWER_H
-#define _VIEWER_H
-
-bool viewer_run(char* file);
-
-#endif
diff --git a/firmware/app.lds b/firmware/app.lds
index 46a6ca70fb..34ab1adf66 100644
--- a/firmware/app.lds
+++ b/firmware/app.lds
@@ -2,15 +2,17 @@ ENTRY(start)
OUTPUT_FORMAT(elf32-sh)
INPUT(crt0.o)
+#define PLUGINSIZE 0x8000
+
#ifdef DEBUG
-#define DRAMSIZE 0x1f0000
+#define DRAMSIZE 0x1f0000 - PLUGINSIZE
#define ORIGADDR 0x09010000
-#define ENDADDR 0x09200000
+
#else
-#define DRAMSIZE (MEMORYSIZE * 0x100000)
+#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGINSIZE
#define ORIGADDR 0x09000000
-#define ENDADDR (ORIGADDR + DRAMSIZE)
#endif
+#define ENDADDR (ORIGADDR + DRAMSIZE)
MEMORY
{
@@ -91,6 +93,11 @@ SECTIONS
_topramend = .;
} > DRAM
+ .plugin ENDADDR:
+ {
+ _pluginbuf = .;
+ }
+
.iram 0xf000000 : AT ( _iramcopy )
{
_iramstart = .;
diff --git a/firmware/drivers/lcd-player-charset.c b/firmware/drivers/lcd-player-charset.c
index 523158f49f..df4f3f016d 100644
--- a/firmware/drivers/lcd-player-charset.c
+++ b/firmware/drivers/lcd-player-charset.c
@@ -47,7 +47,7 @@ unsigned short new_lcd_rocklatin1_to_xlcd[] =
RESERVED_CHAR, /* 0x01-0x17 reserved */
RESERVED_CHAR, /* 0x01-0x17 reserved */
RESERVED_CHAR, /* 0x01-0x17 reserved */
- RESERVED_CHAR, /* 0x01-0x17 reserved */
+ 0x217, /* 0x17 .. "plugin" icon */
0x218, /* 0x18 .. "folder" icon */
0x219, /* 0x19 .. "MOD/AJZ" icon (winlatin o (dote in the middle) */
0x21a, /* 0x1a .. "language" icon (winlatin - (a bit longer minus sign) */
@@ -668,7 +668,7 @@ unsigned char extended_font_player[NO_EXTENDED_LCD_CHARS][8] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 14 */
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 15 */
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 16 */
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 17 */
+ { 0x04, 0x1e, 0x07, 0x1f, 0x05, 0x01, 0x06, 0x00}, /* 17 Plugin file icon */
{ 0x0c, 0x13, 0x11, 0x11, 0x11, 0x11, 0x1f, 0x00}, /* 18 Folder icon */
{ 0x1f, 0x11, 0x1b, 0x15, 0x1b, 0x11, 0x1f, 0x00}, /* 19 MOD/AJZ icon */
{ 0x00, 0x1f, 0x15, 0x1f, 0x15, 0x1f, 0x00, 0x00}, /* 1a Language icon */