summaryrefslogtreecommitdiff
path: root/apps/plugins
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 /apps/plugins
parent9bcbe3fd723d23a709873a0855f27b86bc5c96f1 (diff)
downloadrockbox-ba371fb595affd68c823926b85718d1d613dc7d3.zip
rockbox-ba371fb595affd68c823926b85718d1d613dc7d3.tar.gz
rockbox-ba371fb595affd68c823926b85718d1d613dc7d3.tar.bz2
rockbox-ba371fb595affd68c823926b85718d1d613dc7d3.tar.xz
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
Diffstat (limited to '')
-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
10 files changed, 1343 insertions, 429 deletions
diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile
new file mode 100644
index 0000000..4c02207
--- /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 ed4885b..0c53d49 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 ad3af91..996a1a8 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 0000000..ea347fb
--- /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 bf94db1..a34aa8b 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 0000000..be6b6fd
--- /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 c4e952f..df9966e 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 0000000..2387fa9
--- /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 f653866..f8dc309 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 2937a1b..be089cd 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