diff options
| author | Björn Stenberg <bjorn@haxx.se> | 2003-06-29 16:33:04 +0000 |
|---|---|---|
| committer | Björn Stenberg <bjorn@haxx.se> | 2003-06-29 16:33:04 +0000 |
| commit | ba371fb595affd68c823926b85718d1d613dc7d3 (patch) | |
| tree | cfda303d0603d623cdb12f3928905d3ae02f1d87 /apps/plugins | |
| parent | 9bcbe3fd723d23a709873a0855f27b86bc5c96f1 (diff) | |
| download | rockbox-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/Makefile | 45 | ||||
| -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.c | 48 | ||||
| -rw-r--r-- | apps/plugins/oscillograph.c (renamed from apps/recorder/oscillograph.c) | 82 | ||||
| -rw-r--r-- | apps/plugins/plugin.lds | 26 | ||||
| -rw-r--r-- | apps/plugins/snow.c (renamed from apps/recorder/snow.c) | 46 | ||||
| -rw-r--r-- | apps/plugins/sokoban.c | 868 | ||||
| -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(¤t_info.level, &undo->level, sizeof(undo->level)); + rb->memcpy(¤t_info.player, &undo->location[0], sizeof(undo->location[0])); + + row = undo->location[0].row; + col = undo->location[0].col; + current_info.board[row][col] = '@'; + + /* Update the two other possible spots */ + for (i = 1; i < 3; i++) { + if (undo->location[i].spot != '\0') { + row = undo->location[i].row; + col = undo->location[i].col; + current_info.board[row][col] = undo->location[i].spot; + undo->location[i].spot = '\0'; + } + } + + /* Remove this undo from the list */ + if (undo_info.current == 0) { + if (undo_info.count > 1) + undo_info.current = MAX_UNDOS - 1; + } else { + undo_info.current--; + } + + undo_info.count--; + + return; +} + +static void add_undo(int button) +{ + struct Undo *undo; + int row, col, i; + bool storable; + + if ((button != BUTTON_LEFT) && (button != BUTTON_RIGHT) && + (button != BUTTON_UP) && (button != BUTTON_DOWN)) + return; + + if (undo_info.count != 0) { + if (undo_info.current < (MAX_UNDOS - 1)) + undo_info.current++; + else + undo_info.current = 0; + } + + /* Make what follows more readable */ + undo = &undo_info.history[undo_info.current]; + + /* Store our level info */ + rb->memcpy(&undo->level, ¤t_info.level, sizeof(undo->level)); + + /* Store our player info */ + rb->memcpy(&undo->location[0], ¤t_info.player, sizeof(undo->location[0])); + + /* Now we need to store upto 2 blocks that may be affected. + * If player.spot is NULL, then there is no info stored + * for that block */ + + row = current_info.player.row; + col = current_info.player.col; + + /* This must stay as _1_ because the first block (0) is the player */ + for (i = 1; i < 3; i++) { + storable = true; + + switch (button) { + case BUTTON_LEFT: + col--; + if (col < 0) + storable = false; + break; + + case BUTTON_RIGHT: + col++; + if (col >= COLS) + storable = false; + break; + + case BUTTON_UP: + row--; + if (row < 0) + storable = false; + break; + + case BUTTON_DOWN: + row++; + if (row >= ROWS) + storable = false; + break; + + default: + return; + } + + if (storable) { + undo->location[i].col = col; + undo->location[i].row = row; + undo->location[i].spot = current_info.board[row][col]; + } else { + undo->location[i].spot = '\0'; + } + } + + if (undo_info.count < MAX_UNDOS) + undo_info.count++; +} + +static void init_boards(void) +{ + current_info.level.level = 0; + current_info.level.moves = 0; + current_info.level.boxes_to_go = 0; + current_info.player.row = 0; + current_info.player.col = 0; + current_info.player.spot = ' '; + current_info.max_level = 0; + current_info.level_offset = 0; + current_info.loaded_level = 0; + + init_undo(); +} + +static int get_level_count(void) +{ + int fd = 0; + int lastlen = 0; + char buffer[COLS + 3]; /* COLS plus CR/LF and \0 */ + + if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0) { + rb->splash(0, 0, true, "Unable to open %s", LEVELS_FILE); + return -1; + } + + while(1) { + int len = rb->read_line(fd, buffer, sizeof(buffer)); + if(len <= 0) + break; + + /* Two short lines in a row means new level */ + if(len < 3 && lastlen < 3) + current_info.max_level++; + + lastlen = len; + } + + rb->close(fd); + return 0; +} + +static int get_level(char *level, int level_size) +{ + int fd = 0, i = 0; + int nread = 0; + int count = 0; + int lastlen = 0; + int level_ct = 1; + unsigned char buffer[SOKOBAN_LEVEL_SIZE * 2]; + bool level_found = false; + + /* open file */ + if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0) + return -1; + + /* Lets not reparse the full file if we can avoid it */ + if (current_info.loaded_level < current_info.level.level) { + rb->lseek(fd, current_info.level_offset, SEEK_SET); + level_ct = current_info.loaded_level; + } + + if(current_info.level.level > 1) { + while(!level_found) { + int len = rb->read_line(fd, buffer, SOKOBAN_LEVEL_SIZE); + if(len <= 0) { + rb->close(fd); + return -1; + } + + /* Two short lines in a row means new level */ + if(len < 3 && lastlen < 3) { + level_ct++; + if(level_ct == current_info.level.level) + level_found = true; + } + lastlen = len; + } + } + + /* Remember the current offset */ + current_info.level_offset = rb->lseek(fd, 0, SEEK_CUR); + + /* read a full buffer chunk from here */ + nread = rb->read(fd, buffer, sizeof(buffer)-1); + if (nread < 0) + return -1; + buffer[nread] = 0; + + rb->close(fd); + + /* If we read less then a level, error */ + if (nread < level_size) + return -1; + + /* Load our new level */ + for(i=0, count=0; (count < nread) && (i<level_size);) { + if (buffer[count] != '\n' && buffer[count] != '\r') + level[i++] = buffer[count]; + count++; + } + level[i] = 0; + + current_info.loaded_level = current_info.level.level; + return 0; +} + +/* return non-zero on error */ +static int load_level(void) +{ + short c = 0; + short r = 0; + short i = 0; + char level[ROWS*COLS+1]; + int x = 0; + + current_info.player.spot=' '; + current_info.level.boxes_to_go = 0; + current_info.level.moves = 0; + + if (get_level(level, sizeof(level)) != 0) + return -1; + + i = 0; + for (r = 0; r < ROWS; r++) { + x++; + for (c = 0; c < COLS; c++, i++) { + current_info.board[r][c] = level[i]; + + if (current_info.board[r][c] == '.') + current_info.level.boxes_to_go++; + + else if (current_info.board[r][c] == '@') { + current_info.player.row = r; + current_info.player.col = c; + } + } + } + + return 0; +} + +static void update_screen(void) +{ + short b = 0, c = 0; + short rows = 0, cols = 0; + char s[25]; + + short magnify = 4; + + /* load the board to the screen */ + for (rows=0 ; rows < ROWS ; rows++) { + for (cols = 0 ; cols < COLS ; cols++) { + c = cols * magnify; + b = rows * magnify; + + switch(current_info.board[rows][cols]) { + case 'X': /* black space */ + rb->lcd_drawrect(c, b, magnify, magnify); + rb->lcd_drawrect(c+1, b+1, 2, 2); + break; + + case '#': /* this is a wall */ + rb->lcd_drawpixel(c, b); + rb->lcd_drawpixel(c+2, b); + rb->lcd_drawpixel(c+1, b+1); + rb->lcd_drawpixel(c+3, b+1); + rb->lcd_drawpixel(c, b+2); + rb->lcd_drawpixel(c+2, b+2); + rb->lcd_drawpixel(c+1, b+3); + rb->lcd_drawpixel(c+3, b+3); + break; + + case '.': /* this is a home location */ + rb->lcd_drawrect(c+1, b+1, 2, 2); + break; + + case '$': /* this is a box */ + rb->lcd_drawrect(c, b, magnify, magnify); + break; + + case '@': /* this is you */ + rb->lcd_drawline(c+1, b, c+2, b); + rb->lcd_drawline(c, b+1, c+3, b+1); + rb->lcd_drawline(c+1, b+2, c+2, b+2); + + rb->lcd_drawpixel(c, b+3); + rb->lcd_drawpixel(c+3, b+3); + break; + + case '%': /* this is a box on a home spot */ + rb->lcd_drawrect(c, b, magnify, magnify); + rb->lcd_drawrect(c+1, b+1, 2, 2); + break; + } + } + } + + + rb->snprintf(s, sizeof(s), "%d", current_info.level.level); + rb->lcd_putsxy(86, 22, s); + rb->snprintf(s, sizeof(s), "%d", current_info.level.moves); + rb->lcd_putsxy(86, 54, s); + + rb->lcd_drawrect(80,0,32,32); + rb->lcd_drawrect(80,32,32,64); + rb->lcd_putsxy(81, 10, "Level"); + rb->lcd_putsxy(81, 42, "Moves"); + + /* print out the screen */ + rb->lcd_update(); +} + +static void draw_level(void) +{ + load_level(); + rb->lcd_clear_display(); + update_screen(); +} + +static bool sokoban_loop(void) +{ + char new_spot; + bool moved = true; + int i = 0, button = 0; + short r = 0, c = 0; + + current_info.level.level = 1; + + load_level(); + update_screen(); + + while (1) { + moved = true; + + r = current_info.player.row; + c = current_info.player.col; + + button = rb->button_get(true); + + add_undo(button); + + switch(button) + { + case BUTTON_OFF: + /* get out of here */ + return PLUGIN_OK; + + case BUTTON_ON: + case BUTTON_ON | BUTTON_REPEAT: + /* this is UNDO */ + undo(); + rb->lcd_clear_display(); + update_screen(); + moved = false; + break; + + case BUTTON_F3: + case BUTTON_F3 | BUTTON_REPEAT: + /* increase level */ + init_undo(); + current_info.level.boxes_to_go=0; + moved = true; + break; + + case BUTTON_F1: + case BUTTON_F1 | BUTTON_REPEAT: + /* previous level */ + init_undo(); + if (current_info.level.level > 1) + current_info.level.level--; + + draw_level(); + moved = false; + break; + + case BUTTON_F2: + case BUTTON_F2 | BUTTON_REPEAT: + /* same level */ + init_undo(); + draw_level(); + moved = false; + break; + + case BUTTON_LEFT: + switch(current_info.board[r][c-1]) + { + case ' ': /* if it is a blank spot */ + case '.': /* if it is a home spot */ + new_spot = current_info.board[r][c-1]; + current_info.board[r][c-1] = '@'; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = new_spot; + break; + + case '$': + switch(current_info.board[r][c-2]) + { + case ' ': /* going from blank to blank */ + current_info.board[r][c-2] = current_info.board[r][c-1]; + current_info.board[r][c-1] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = ' '; + break; + + case '.': /* going from a blank to home */ + current_info.board[r][c-2] = '%'; + current_info.board[r][c-1] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = ' '; + current_info.level.boxes_to_go--; + break; + + default: + moved = false; + break; + } + break; + + case '%': + switch(current_info.board[r][c-2]) { + case ' ': /* we are going from a home to a blank */ + current_info.board[r][c-2] = '$'; + current_info.board[r][c-1] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = '.'; + current_info.level.boxes_to_go++; + break; + + case '.': /* if we are going from a home to home */ + current_info.board[r][c-2] = '%'; + current_info.board[r][c-1] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = '.'; + break; + + default: + moved = false; + break; + } + break; + + default: + moved = false; + break; + } + + if (moved) + current_info.player.col--; + break; + + case BUTTON_RIGHT: /* if it is a blank spot */ + switch(current_info.board[r][c+1]) { + case ' ': + case '.': /* if it is a home spot */ + new_spot = current_info.board[r][c+1]; + current_info.board[r][c+1] = '@'; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = new_spot; + break; + + case '$': + switch(current_info.board[r][c+2]) { + case ' ': /* going from blank to blank */ + current_info.board[r][c+2] = current_info.board[r][c+1]; + current_info.board[r][c+1] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = ' '; + break; + + case '.': /* going from a blank to home */ + current_info.board[r][c+2] = '%'; + current_info.board[r][c+1] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = ' '; + current_info.level.boxes_to_go--; + break; + + default: + moved = false; + break; + } + break; + + case '%': + switch(current_info.board[r][c+2]) { + case ' ': /* going from a home to a blank */ + current_info.board[r][c+2] = '$'; + current_info.board[r][c+1] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = '.'; + current_info.level.boxes_to_go++; + break; + + case '.': + current_info.board[r][c+2] = '%'; + current_info.board[r][c+1] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = '.'; + break; + + default: + moved = false; + break; + } + break; + + default: + moved = false; + break; + } + + if (moved) + current_info.player.col++; + break; + + case BUTTON_UP: + switch(current_info.board[r-1][c]) { + case ' ': /* if it is a blank spot */ + case '.': /* if it is a home spot */ + new_spot = current_info.board[r-1][c]; + current_info.board[r-1][c] = '@'; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = new_spot; + break; + + case '$': + switch(current_info.board[r-2][c]) { + case ' ': /* going from blank to blank */ + current_info.board[r-2][c] = current_info.board[r-1][c]; + current_info.board[r-1][c] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = ' '; + break; + + case '.': /* going from a blank to home */ + current_info.board[r-2][c] = '%'; + current_info.board[r-1][c] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = ' '; + current_info.level.boxes_to_go--; + break; + + default: + moved = false; + break; + } + break; + + case '%': + switch(current_info.board[r-2][c]) { + case ' ': /* we are going from a home to a blank */ + current_info.board[r-2][c] = '$'; + current_info.board[r-1][c] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = '.'; + current_info.level.boxes_to_go++; + break; + + case '.': /* if we are going from a home to home */ + current_info.board[r-2][c] = '%'; + current_info.board[r-1][c] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = '.'; + break; + + default: + moved = false; + break; + } + break; + + default: + moved = false; + break; + } + + if (moved) + current_info.player.row--; + break; + + case BUTTON_DOWN: + switch(current_info.board[r+1][c]) { + case ' ': /* if it is a blank spot */ + case '.': /* if it is a home spot */ + new_spot = current_info.board[r+1][c]; + current_info.board[r+1][c] = '@'; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = new_spot; + break; + + case '$': + switch(current_info.board[r+2][c]) { + case ' ': /* going from blank to blank */ + current_info.board[r+2][c] = current_info.board[r+1][c]; + current_info.board[r+1][c] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = ' '; + break; + + case '.': /* going from a blank to home */ + current_info.board[r+2][c] = '%'; + current_info.board[r+1][c] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = ' '; + current_info.level.boxes_to_go--; + break; + + default: + moved = false; + break; + } + break; + + case '%': + switch(current_info.board[r+2][c]) { + case ' ': /* going from a home to a blank */ + current_info.board[r+2][c] = '$'; + current_info.board[r+1][c] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = '.'; + current_info.level.boxes_to_go++; + break; + + case '.': /* going from a home to home */ + current_info.board[r+2][c] = '%'; + current_info.board[r+1][c] = current_info.board[r][c]; + current_info.board[r][c] = current_info.player.spot; + current_info.player.spot = '.'; + break; + + default: + moved = false; + break; + } + break; + + default: + moved = false; + break; + } + + if (moved) + current_info.player.row++; + break; + + case SYS_USB_CONNECTED: + rb->usb_screen(); + return PLUGIN_USB_CONNECTED; + + default: + moved = false; + break; + } + + if (moved) { + current_info.level.moves++; + rb->lcd_clear_display(); + update_screen(); + } + + /* We have completed this level */ + if (current_info.level.boxes_to_go == 0) { + current_info.level.level++; + + /* clear undo stats */ + init_undo(); + + rb->lcd_clear_display(); + + if (current_info.level.level > current_info.max_level) { + rb->lcd_putsxy(10, 20, "You WIN!!"); + + for (i = 0; i < 30000 ; i++) { + rb->lcd_invertrect(0, 0, 111, 63); + rb->lcd_update(); + + button = rb->button_get(false); + if (button && ((button & BUTTON_REL) != BUTTON_REL)) + break; + } + + return PLUGIN_OK; + } + + load_level(); + update_screen(); + } + + } /* end while */ + + return PLUGIN_OK; +} + + +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + int w, h; + int len; + + TEST_PLUGIN_API(api); + (void)(parameter); + rb = api; + + rb->lcd_setfont(FONT_SYSFIXED); + rb->lcd_getstringsize(SOKOBAN_TITLE, &w, &h); + + /* Get horizontel centering for text */ + len = w; + if (len%2 != 0) + len =((len+1)/2)+(w/2); + else + len /= 2; + + if (h%2 != 0) + h = (h/2)+1; + else + h /= 2; + + rb->lcd_clear_display(); + rb->lcd_putsxy(LCD_WIDTH/2-len,(LCD_HEIGHT/2)-h, SOKOBAN_TITLE); + rb->lcd_update(); + rb->sleep(HZ*2); + + rb->lcd_clear_display(); + + rb->lcd_putsxy(3, 6, "[OFF] To Stop"); + rb->lcd_putsxy(3, 16, "[ON] To Undo"); + rb->lcd_putsxy(3, 26, "[F1] - Level"); + rb->lcd_putsxy(3, 36, "[F2] Same Level"); + rb->lcd_putsxy(3, 46, "[F3] + Level"); + + rb->lcd_update(); + rb->sleep(HZ*2); + rb->lcd_clear_display(); + + init_boards(); + + if (get_level_count() != 0) { + rb->splash(HZ*2,0,true,"Failed loading levels!"); + return PLUGIN_OK; + } + + return sokoban_loop(); +} + +#endif 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 |