Added plugin loader. Moved games, demos and the text viewer to loadable plugins. Copy your *.rock files to /.rockbox/rocks/
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3769 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
9bcbe3fd72
commit
ba371fb595
|
@ -20,7 +20,7 @@ DOCSDIR := ../docs
|
|||
|
||||
INCLUDES= -I$(FIRMWARE)/include -I$(FIRMWARE)/export -I. -I$(OBJDIR)
|
||||
|
||||
CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(TARGET) $(DEFINES) -DAPPSVERSION=\"$(VERSION)\" $(EXTRA_DEFINES) -DMEM=${MEM}
|
||||
CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(TARGET) $(DEFINES) -DAPPSVERSION=\"$(VERSION)\" $(EXTRA_DEFINES) -DMEM=${MEM} -DPLUGIN=1
|
||||
AFLAGS += -small -relax
|
||||
|
||||
# Check if this is a kind of Recorder
|
||||
|
@ -71,7 +71,10 @@ ifndef TOOLSDIR
|
|||
TOOLSDIR=../tools
|
||||
endif
|
||||
|
||||
all : $(OBJDIR)/$(OUTNAME)
|
||||
all : $(OBJDIR)/$(OUTNAME) rocks
|
||||
|
||||
rocks:
|
||||
$(MAKE) -C plugins TARGET=$(TARGET) DEBUG=$(DEBUG) OBJDIR=$(OBJDIR) VERSION=$(VERSION) EXTRA_DEFINES="$(EXTRA_DEFINES)"
|
||||
|
||||
$(OBJDIR)/librockbox.a:
|
||||
make -C $(FIRMWARE) TARGET=$(TARGET) DEBUG=$(DEBUG) OBJDIR=$(OBJDIR)
|
||||
|
@ -117,6 +120,7 @@ clean:
|
|||
$(OBJDIR)/lang.o $(OBJDIR)/build.lang $(OBJDIR)/lang.[ch] \
|
||||
$(OBJDIR)/credits.raw $(LINKFILE)
|
||||
-$(RM) -r $(OBJDIR)/$(DEPS)
|
||||
$(MAKE) -C plugins clean
|
||||
|
||||
DEPS:=.deps
|
||||
DEPDIRS:=$(DEPS)
|
||||
|
|
|
@ -24,19 +24,38 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "lcd.h"
|
||||
#include "menu.h"
|
||||
#include "demo_menu.h"
|
||||
#include "button.h"
|
||||
#include "kernel.h"
|
||||
#include "sprintf.h"
|
||||
|
||||
#include "lang.h"
|
||||
#include "plugin.h"
|
||||
|
||||
extern bool bounce(void);
|
||||
extern bool snow(void);
|
||||
extern bool cube(void);
|
||||
extern bool oscillograph(void);
|
||||
static bool bounce(void)
|
||||
{
|
||||
if (plugin_load("/.rockbox/rocks/bounce.rock",NULL)==PLUGIN_USB_CONNECTED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool snow(void)
|
||||
{
|
||||
if (plugin_load("/.rockbox/rocks/snow.rock",NULL) == PLUGIN_USB_CONNECTED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool cube(void)
|
||||
{
|
||||
if (plugin_load("/.rockbox/rocks/cube.rock",NULL) == PLUGIN_USB_CONNECTED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool oscillograph(void)
|
||||
{
|
||||
if (plugin_load("/.rockbox/rocks/oscillograph.rock",NULL)==PLUGIN_USB_CONNECTED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool demo_menu(void)
|
||||
{
|
||||
|
|
|
@ -25,18 +25,31 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "lcd.h"
|
||||
#include "menu.h"
|
||||
#include "games_menu.h"
|
||||
#include "button.h"
|
||||
#include "kernel.h"
|
||||
#include "sprintf.h"
|
||||
|
||||
#include "sokoban.h"
|
||||
#include "wormlet.h"
|
||||
#include "lang.h"
|
||||
#include "plugin.h"
|
||||
|
||||
extern bool tetris(void);
|
||||
static bool tetris(void)
|
||||
{
|
||||
if (plugin_load("/.rockbox/rocks/tetris.rock",NULL)==PLUGIN_USB_CONNECTED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sokoban(void)
|
||||
{
|
||||
if (plugin_load("/.rockbox/rocks/sokoban.rock",NULL)==PLUGIN_USB_CONNECTED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool wormlet(void)
|
||||
{
|
||||
if (plugin_load("/.rockbox/rocks/wormlet.rock",NULL)==PLUGIN_USB_CONNECTED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool games_menu(void)
|
||||
{
|
||||
|
|
|
@ -677,37 +677,37 @@ new:
|
|||
|
||||
id: LANG_SOKOBAN_LEVEL
|
||||
desc: must be smaller than 6 characters
|
||||
eng: "Level"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_SOKOBAN_MOVE
|
||||
desc: must be smaller than 6 characters
|
||||
eng: "Moves"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_SOKOBAN_WIN
|
||||
desc: displayed when you win
|
||||
eng: "YOU WIN!!"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_SOKOBAN_QUIT
|
||||
desc: how to quit game
|
||||
eng: "[OFF] To Stop"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_SOKOBAN_F1
|
||||
desc: what does F1 do
|
||||
eng: "[F1] - Level"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_SOKOBAN_F2
|
||||
desc: what does F2 do
|
||||
eng: "[F2] Same Level"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_SOKOBAN_F3
|
||||
desc: what does F3 do
|
||||
eng: "[F3] + Level"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
# Next ids are for Worlmet Game.
|
||||
|
@ -717,37 +717,37 @@ new:
|
|||
|
||||
id: LANG_WORMLET_LENGTH
|
||||
desc: wormlet game
|
||||
eng: "Len:%d"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_GROWING
|
||||
desc: wormlet game
|
||||
eng: "Growing"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_HUNGRY
|
||||
desc: wormlet game
|
||||
eng: "Hungry"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_WORMED
|
||||
desc: wormlet game
|
||||
eng: "Wormed"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_ARGH
|
||||
desc: wormlet game
|
||||
eng: "Argh"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_CRASHED
|
||||
desc: wormlet game
|
||||
eng: "Crashed"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_HIGHSCORE
|
||||
desc: wormlet game
|
||||
eng: "Hs: %d"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
# Length restrictions for wormlet config screen strings (LANG_CS_XXX)
|
||||
|
@ -756,49 +756,49 @@ new:
|
|||
|
||||
id: LANG_WORMLET_PLAYERS
|
||||
desc: wormlet game
|
||||
eng: "%d Players UP/DN"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_WORMS
|
||||
desc: wormlet game
|
||||
eng: "%d Worms L/R"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_REMOTE_CTRL
|
||||
desc: wormlet game
|
||||
eng: "Remote Control F1"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_NO_REM_CTRL
|
||||
desc: wormlet game
|
||||
eng: "No Rem. Control F1"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_2_KEY_CTRL
|
||||
desc: wormlet game
|
||||
eng: "2 Key Control F1"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_4_KEY_CTRL
|
||||
desc: wormlet game
|
||||
eng: "4 Key Control F1"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_WORMLET_NO_CONTROL
|
||||
desc: wormlet game
|
||||
eng: "Out Of Control"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
# Wormlet game ids ended
|
||||
|
||||
id: LANG_TETRIS_LOSE
|
||||
desc: tetris game
|
||||
eng: "You Lose!"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_TETRIS_LEVEL
|
||||
desc: tetris game
|
||||
eng: "Rows - Level"
|
||||
eng: ""
|
||||
new:
|
||||
|
||||
id: LANG_POWEROFF_IDLE
|
||||
|
@ -1569,3 +1569,33 @@ id: LANG_CANCEL_WITH_ANY_RECORDER
|
|||
desc: Generic recorder string to use to cancel
|
||||
eng: "Any Other = No"
|
||||
new:
|
||||
|
||||
##
|
||||
## Strings used in the plugin loader:
|
||||
##
|
||||
|
||||
id: LANG_PLUGIN_CANT_OPEN
|
||||
desc: Plugin open error message
|
||||
eng: "Can't open %s"
|
||||
new:
|
||||
|
||||
id: LANG_READ_FAILED
|
||||
desc: There was an error reading a file
|
||||
eng: "Failed reading %s"
|
||||
new:
|
||||
|
||||
id: LANG_PLUGIN_WRONG_MODEL
|
||||
desc: The plugin is not compatible with the archos model trying to run it
|
||||
eng: "Incompatible model"
|
||||
new:
|
||||
|
||||
id: LANG_PLUGIN_WRONG_VERSION
|
||||
desc: The plugin is not compatible with the rockbox version trying to run it
|
||||
eng: "Incompatible version"
|
||||
new:
|
||||
|
||||
id: LANG_PLUGIN_ERROR
|
||||
desc: The plugin return an error code
|
||||
eng: "Plugin returned error"
|
||||
new:
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
|
||||
enum {
|
||||
Unknown=0x90,
|
||||
Folder=0x18, Mod_Ajz, Language, File, Wps, Playlist, Text, Config
|
||||
Plugin = 0x17,
|
||||
Folder, Mod_Ajz, Language, File, Wps, Playlist, Text, Config,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
221
apps/plugin.c
Normal file
221
apps/plugin.c
Normal file
|
@ -0,0 +1,221 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Björn Stenberg
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "button.h"
|
||||
#include "lcd.h"
|
||||
#include "dir.h"
|
||||
#include "file.h"
|
||||
#include "kernel.h"
|
||||
#include "sprintf.h"
|
||||
#include "screens.h"
|
||||
#include "misc.h"
|
||||
#include "mas.h"
|
||||
#include "plugin.h"
|
||||
#include "lang.h"
|
||||
|
||||
#ifdef SIMULATOR
|
||||
#include <dlfcn.h>
|
||||
#define PREFIX(_x_) x11_ ## _x_
|
||||
#else
|
||||
#define PREFIX(_x_) _x_
|
||||
#endif
|
||||
|
||||
static int plugin_test(int api_version, int model);
|
||||
|
||||
static struct plugin_api rockbox_api = {
|
||||
PLUGIN_API_VERSION,
|
||||
|
||||
plugin_test,
|
||||
|
||||
/* lcd */
|
||||
lcd_clear_display,
|
||||
lcd_puts,
|
||||
lcd_puts_scroll,
|
||||
lcd_stop_scroll,
|
||||
#ifdef HAVE_LCD_CHARCELLS
|
||||
lcd_define_pattern,
|
||||
#else
|
||||
lcd_putsxy,
|
||||
lcd_bitmap,
|
||||
lcd_drawline,
|
||||
lcd_clearline,
|
||||
lcd_drawpixel,
|
||||
lcd_clearpixel,
|
||||
lcd_setfont,
|
||||
lcd_clearrect,
|
||||
lcd_fillrect,
|
||||
lcd_drawrect,
|
||||
lcd_invertrect,
|
||||
lcd_getstringsize,
|
||||
lcd_update,
|
||||
lcd_update_rect,
|
||||
#ifndef SIMULATOR
|
||||
lcd_roll,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* button */
|
||||
button_get,
|
||||
button_get_w_tmo,
|
||||
|
||||
/* file */
|
||||
PREFIX(open),
|
||||
PREFIX(close),
|
||||
read,
|
||||
lseek,
|
||||
PREFIX(creat),
|
||||
write,
|
||||
remove,
|
||||
rename,
|
||||
ftruncate,
|
||||
PREFIX(filesize),
|
||||
fprintf,
|
||||
read_line,
|
||||
|
||||
/* dir */
|
||||
PREFIX(opendir),
|
||||
PREFIX(closedir),
|
||||
PREFIX(readdir),
|
||||
|
||||
/* kernel */
|
||||
PREFIX(sleep),
|
||||
usb_screen,
|
||||
¤t_tick,
|
||||
|
||||
/* strings and memory */
|
||||
snprintf,
|
||||
strcpy,
|
||||
strlen,
|
||||
memset,
|
||||
memcpy,
|
||||
|
||||
/* sound */
|
||||
#ifndef SIMULATOR
|
||||
#ifdef HAVE_MAS3587F
|
||||
mas_codec_readreg,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* misc */
|
||||
srand,
|
||||
rand,
|
||||
splash,
|
||||
};
|
||||
|
||||
int plugin_load(char* plugin, void* parameter)
|
||||
{
|
||||
enum plugin_status (*plugin_start)(struct plugin_api* api, void* param);
|
||||
int rc;
|
||||
char buf[64];
|
||||
#ifdef SIMULATOR
|
||||
void* pd;
|
||||
char path[256];
|
||||
#else
|
||||
extern unsigned char pluginbuf[];
|
||||
int fd;
|
||||
#endif
|
||||
|
||||
lcd_clear_display();
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
lcd_setmargins(0,0);
|
||||
lcd_update();
|
||||
#endif
|
||||
#ifdef SIMULATOR
|
||||
snprintf(path, sizeof path, "archos%s", plugin);
|
||||
pd = dlopen(path, RTLD_NOW);
|
||||
if (!pd) {
|
||||
snprintf(buf, sizeof buf, "Can't open %s", plugin);
|
||||
splash(HZ*2, 0, true, buf);
|
||||
dlclose(pd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
plugin_start = dlsym(pd, "plugin_start");
|
||||
if (!plugin_start) {
|
||||
plugin_start = dlsym(pd, "_plugin_start");
|
||||
if (!plugin_start) {
|
||||
splash(HZ*2, 0, true, "Can't find entry point");
|
||||
dlclose(pd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
fd = open(plugin, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
snprintf(buf, sizeof buf, str(LANG_PLUGIN_CANT_OPEN), plugin);
|
||||
splash(HZ*2, 0, true, buf);
|
||||
return fd;
|
||||
}
|
||||
|
||||
plugin_start = (void*)&pluginbuf;
|
||||
rc = read(fd, plugin_start, 0x8000);
|
||||
close(fd);
|
||||
if (rc < 0) {
|
||||
/* read error */
|
||||
snprintf(buf, sizeof buf, str(LANG_READ_FAILED), plugin);
|
||||
splash(HZ*2, 0, true, buf);
|
||||
return -1;
|
||||
}
|
||||
if (rc == 0) {
|
||||
/* loaded a 0-byte plugin, implying it's not for this model */
|
||||
splash(HZ*2, 0, true, str(LANG_PLUGIN_WRONG_MODEL));
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = plugin_start(&rockbox_api, parameter);
|
||||
switch (rc) {
|
||||
case PLUGIN_OK:
|
||||
break;
|
||||
|
||||
case PLUGIN_USB_CONNECTED:
|
||||
return PLUGIN_USB_CONNECTED;
|
||||
|
||||
case PLUGIN_WRONG_API_VERSION:
|
||||
splash(HZ*2, 0, true, str(LANG_PLUGIN_WRONG_VERSION));
|
||||
break;
|
||||
|
||||
case PLUGIN_WRONG_MODEL:
|
||||
splash(HZ*2, 0, true, str(LANG_PLUGIN_WRONG_MODEL));
|
||||
break;
|
||||
|
||||
default:
|
||||
splash(HZ*2, 0, true, str(LANG_PLUGIN_ERROR));
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SIMULATOR
|
||||
dlclose(pd);
|
||||
#endif
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
int plugin_test(int api_version, int model)
|
||||
{
|
||||
if (api_version != PLUGIN_API_VERSION)
|
||||
return PLUGIN_WRONG_API_VERSION;
|
||||
|
||||
if (model != MODEL)
|
||||
return PLUGIN_WRONG_MODEL;
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
161
apps/plugin.h
Normal file
161
apps/plugin.h
Normal file
|
@ -0,0 +1,161 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Björn Stenberg
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef _PLUGIN_H_
|
||||
#define _PLUGIN_H_
|
||||
|
||||
/* instruct simulator code to not redefine any symbols when compiling plugins.
|
||||
(the PLUGIN macro is defined in apps/plugins/Makefile) */
|
||||
#ifdef PLUGIN
|
||||
#define NO_REDEFINES_PLEASE
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include "dir.h"
|
||||
#include "kernel.h"
|
||||
#include "button.h"
|
||||
#include "font.h"
|
||||
#include "system.h"
|
||||
#include "lcd.h"
|
||||
|
||||
/* increase this every time the api struct changes */
|
||||
#define PLUGIN_API_VERSION 1
|
||||
|
||||
/* plugin return codes */
|
||||
enum plugin_status {
|
||||
PLUGIN_OK = 0,
|
||||
PLUGIN_USB_CONNECTED,
|
||||
|
||||
PLUGIN_WRONG_API_VERSION = -1,
|
||||
PLUGIN_WRONG_MODEL = -2,
|
||||
PLUGIN_ERROR = -3,
|
||||
};
|
||||
|
||||
/* different (incompatible) plugin models */
|
||||
enum model {
|
||||
PLAYER,
|
||||
RECORDER
|
||||
};
|
||||
|
||||
#ifdef HAVE_LCD_CHARCELLS
|
||||
#define MODEL PLAYER
|
||||
#else
|
||||
#define MODEL RECORDER
|
||||
#endif
|
||||
|
||||
/* compatibility test macro */
|
||||
#define TEST_PLUGIN_API(_api_) \
|
||||
do { \
|
||||
int _rc_ = _api_->plugin_test(PLUGIN_API_VERSION, MODEL); \
|
||||
if (_rc_<0) \
|
||||
return _rc_; \
|
||||
} while(0)
|
||||
|
||||
struct plugin_api {
|
||||
/* these two fields must always be first, to ensure
|
||||
TEST_PLUGIN_API will always work */
|
||||
int version;
|
||||
int (*plugin_test)(int api_version, int model);
|
||||
|
||||
/* lcd */
|
||||
void (*lcd_clear_display)(void);
|
||||
void (*lcd_puts)(int x, int y, unsigned char *string);
|
||||
void (*lcd_puts_scroll)(int x, int y, unsigned char* string);
|
||||
void (*lcd_stop_scroll)(void);
|
||||
#ifdef HAVE_LCD_CHARCELLS
|
||||
void (*lcd_define_pattern)(int which,char *pattern);
|
||||
#else
|
||||
void (*lcd_putsxy)(int x, int y, unsigned char *string);
|
||||
void (*lcd_bitmap)(unsigned char *src, int x, int y,
|
||||
int nx, int ny, bool clear);
|
||||
void (*lcd_drawline)(int x1, int y1, int x2, int y2);
|
||||
void (*lcd_clearline)(int x1, int y1, int x2, int y2);
|
||||
void (*lcd_drawpixel)(int x, int y);
|
||||
void (*lcd_clearpixel)(int x, int y);
|
||||
void (*lcd_setfont)(int font);
|
||||
void (*lcd_clearrect)(int x, int y, int nx, int ny);
|
||||
void (*lcd_fillrect)(int x, int y, int nx, int ny);
|
||||
void (*lcd_drawrect)(int x, int y, int nx, int ny);
|
||||
void (*lcd_invertrect)(int x, int y, int nx, int ny);
|
||||
int (*lcd_getstringsize)(unsigned char *str, int *w, int *h);
|
||||
void (*lcd_update)(void);
|
||||
void (*lcd_update_rect)(int x, int y, int width, int height);
|
||||
#ifndef SIMULATOR
|
||||
void (*lcd_roll)(int pixels);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* button */
|
||||
int (*button_get)(bool block);
|
||||
int (*button_get_w_tmo)(int ticks);
|
||||
|
||||
/* file */
|
||||
int (*open)(const char* pathname, int flags);
|
||||
int (*close)(int fd);
|
||||
int (*read)(int fd, void* buf, int count);
|
||||
int (*lseek)(int fd, int offset, int whence);
|
||||
int (*creat)(const char *pathname, int mode);
|
||||
int (*write)(int fd, void* buf, int count);
|
||||
int (*remove)(const char* pathname);
|
||||
int (*rename)(const char* path, const char* newname);
|
||||
int (*ftruncate)(int fd, unsigned int size);
|
||||
int (*filesize)(int fd);
|
||||
int (*fprintf)(int fd, const char *fmt, ...);
|
||||
int (*read_line)(int fd, char* buffer, int buffer_size);
|
||||
|
||||
/* dir */
|
||||
DIR* (*opendir)(char* name);
|
||||
int (*closedir)(DIR* dir);
|
||||
struct dirent* (*readdir)(DIR* dir);
|
||||
|
||||
/* kernel */
|
||||
void (*sleep)(int ticks);
|
||||
void (*usb_screen)(void);
|
||||
long* current_tick;
|
||||
|
||||
/* strings and memory */
|
||||
int (*snprintf)(char *buf, size_t size, const char *fmt, ...);
|
||||
char* (*strcpy)(char *dst, const char *src);
|
||||
size_t (*strlen)(const char *str);
|
||||
void* (*memset)(void *dst, int c, size_t length);
|
||||
void* (*memcpy)(void *out, const void *in, size_t n);
|
||||
|
||||
/* sound */
|
||||
#ifndef SIMULATOR
|
||||
#ifdef HAVE_MAS3587F
|
||||
int (*mas_codec_readreg)(int reg);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* misc */
|
||||
void (*srand)(unsigned int seed);
|
||||
int (*rand)(void);
|
||||
void (*splash)(int ticks, int keymask, bool center, char *fmt, ...);
|
||||
};
|
||||
|
||||
/* defined by the plugin loader (plugin.c) */
|
||||
int plugin_load(char* plugin, void* parameter);
|
||||
|
||||
/* defined by the plugin */
|
||||
enum plugin_status plugin_start(struct plugin_api* rockbox, void* parameter)
|
||||
__attribute__ ((section (".entry")));
|
||||
|
||||
#endif
|
45
apps/plugins/Makefile
Normal file
45
apps/plugins/Makefile
Normal file
|
@ -0,0 +1,45 @@
|
|||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
# $Id$
|
||||
#
|
||||
|
||||
CC = sh-elf-gcc
|
||||
OC = sh-elf-objcopy
|
||||
|
||||
FIRMWARE = ../../firmware
|
||||
|
||||
INCLUDES = -I$(FIRMWARE)/include -I$(FIRMWARE)/export -I$(FIRMWARE)/common -I$(FIRMWARE)/drivers -I..
|
||||
CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes $(INCLUDES) $(TARGET) $(EXTRA_DEFINES)
|
||||
|
||||
LINKFILE = plugin.lds
|
||||
|
||||
SRC := $(wildcard *.c)
|
||||
ROCKS := $(SRC:%.c=$(OBJDIR)/%.rock)
|
||||
|
||||
ifndef OBJDIR
|
||||
no_configure:
|
||||
@echo "Don't run make here. Run the tools/configure script from your own build"
|
||||
@echo "directory, then run make there."
|
||||
@echo
|
||||
@echo "More help on how to build rockbox can be found here:"
|
||||
@echo "http://rockbox.haxx.se/docs/how_to_compile.html"
|
||||
endif
|
||||
|
||||
$(OBJDIR)/%.elf: $(OBJDIR)/%.o $(LINKFILE)
|
||||
$(CC) -O -nostdlib -o $@ $< -lgcc -T$(LINKFILE) -Wl,-Map,$*.map
|
||||
|
||||
$(OBJDIR)/%.rock : $(OBJDIR)/%.elf
|
||||
$(OC) -O binary $< $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c ../plugin.h Makefile
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
all: $(ROCKS)
|
||||
@echo done
|
||||
|
||||
clean:
|
||||
-rm -f $(ROCKS)
|
|
@ -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;
|
||||
}
|
|
@ -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
|
48
apps/plugins/helloworld.c
Normal file
48
apps/plugins/helloworld.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Björn Stenberg
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "plugin.h"
|
||||
|
||||
/* welcome to the example rockbox plugin */
|
||||
|
||||
/* here is a global api struct pointer. while not strictly necessary,
|
||||
it's nice not to have to pass the api pointer in all function calls
|
||||
in the plugin */
|
||||
static struct plugin_api* rb;
|
||||
|
||||
/* this is the plugin entry point */
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||
{
|
||||
/* this macro should be called as the first thing you do in the plugin.
|
||||
it test that the api version and model the plugin was compiled for
|
||||
matches the machine it is running on */
|
||||
TEST_PLUGIN_API(api);
|
||||
|
||||
/* if you don't use the parameter, you can do like
|
||||
this to avoid the compiler warning about it */
|
||||
(void)parameter;
|
||||
|
||||
/* if you are using a global api pointer, don't forget to copy it!
|
||||
otherwise you will get lovely "I04: IllInstr" errors... :-) */
|
||||
rb = api;
|
||||
|
||||
/* now go ahead and have fun! */
|
||||
rb->splash(HZ*2, 0, true, "Hello world!");
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
|
@ -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
|
26
apps/plugins/plugin.lds
Normal file
26
apps/plugins/plugin.lds
Normal file
|
@ -0,0 +1,26 @@
|
|||
OUTPUT_FORMAT(elf32-sh)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
PLUGIN_RAM : ORIGIN = 0x091f8000, LENGTH = 0x8000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
*(.entry)
|
||||
*(.text)
|
||||
} > PLUGIN_RAM
|
||||
|
||||
.data : {
|
||||
*(.data)
|
||||
} > PLUGIN_RAM
|
||||
|
||||
.bss : {
|
||||
*(.bss)
|
||||
} > PLUGIN_RAM
|
||||
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
} > PLUGIN_RAM
|
||||
}
|
|
@ -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
|
868
apps/plugins/sokoban.c
Normal file
868
apps/plugins/sokoban.c
Normal file
|
@ -0,0 +1,868 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Eric Linenberg
|
||||
* February 2003: Robert Hak performs a cleanup/rewrite/feature addition.
|
||||
* Eric smiles. Bjorn cries. Linus say 'huh?'.
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "plugin.h"
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
|
||||
#define SOKOBAN_TITLE "Sokoban"
|
||||
#define SOKOBAN_TITLE_FONT 2
|
||||
|
||||
#define LEVELS_FILE "/.rockbox/sokoban/levels.txt"
|
||||
|
||||
#define ROWS 16
|
||||
#define COLS 20
|
||||
#define MAX_UNDOS 5
|
||||
|
||||
#define SOKOBAN_LEVEL_SIZE (ROWS*COLS)
|
||||
|
||||
static void init_undo(void);
|
||||
static void undo(void);
|
||||
static void add_undo(int button);
|
||||
|
||||
static int get_level(char *level, int level_size);
|
||||
static int get_level_count(void);
|
||||
static int load_level(void);
|
||||
static void draw_level(void);
|
||||
|
||||
static void init_boards(void);
|
||||
static void update_screen(void);
|
||||
static bool sokoban_loop(void);
|
||||
|
||||
/* The Location, Undo and LevelInfo structs are OO-flavored.
|
||||
* (oooh!-flavored as Schnueff puts it.) It makes more you have to know,
|
||||
* but the overall data layout becomes more manageable. */
|
||||
|
||||
/* We use the same three values in 2 structs. Makeing them a struct
|
||||
* hopefully ensures that if you change things in one, the other changes
|
||||
* as well. */
|
||||
struct LevelInfo {
|
||||
short level;
|
||||
short moves;
|
||||
short boxes_to_go;
|
||||
};
|
||||
|
||||
/* What a given location on the board looks like at a given time */
|
||||
struct Location {
|
||||
char spot;
|
||||
short row;
|
||||
short col;
|
||||
};
|
||||
|
||||
/* A single level of undo. Each undo move can affect upto,
|
||||
* but not more then, 3 spots on the board */
|
||||
struct Undo {
|
||||
struct LevelInfo level;
|
||||
struct Location location[3];
|
||||
};
|
||||
|
||||
/* Our full undo history */
|
||||
static struct UndoInfo {
|
||||
short count; /* How many undos are there in history */
|
||||
short current; /* Which history is the current undo */
|
||||
struct Undo history[MAX_UNDOS];
|
||||
} undo_info;
|
||||
|
||||
/* Our playing board */
|
||||
static struct BoardInfo {
|
||||
char board[ROWS][COLS];
|
||||
struct LevelInfo level;
|
||||
struct Location player;
|
||||
int max_level; /* How many levels do we have? */
|
||||
int level_offset; /* Where in the level file is this level */
|
||||
int loaded_level; /* Which level is in memory */
|
||||
} current_info;
|
||||
|
||||
static struct plugin_api* rb;
|
||||
|
||||
static void init_undo(void)
|
||||
{
|
||||
undo_info.count = 0;
|
||||
undo_info.current = 0;
|
||||
}
|
||||
|
||||
static void undo(void)
|
||||
{
|
||||
struct Undo *undo;
|
||||
int i = 0;
|
||||
short row, col;
|
||||
|
||||
if (undo_info.count == 0)
|
||||
return;
|
||||
|
||||
/* Update board info */
|
||||
undo = &undo_info.history[undo_info.current];
|
||||
|
||||
rb->memcpy(¤t_info.level, &undo->level, sizeof(undo->level));
|
||||
rb->memcpy(¤t_info.player, &undo->location[0], sizeof(undo->location[0]));
|
||||
|
||||
row = undo->location[0].row;
|
||||
col = undo->location[0].col;
|
||||
current_info.board[row][col] = '@';
|
||||
|
||||
/* Update the two other possible spots */
|
||||
for (i = 1; i < 3; i++) {
|
||||
if (undo->location[i].spot != '\0') {
|
||||
row = undo->location[i].row;
|
||||
col = undo->location[i].col;
|
||||
current_info.board[row][col] = undo->location[i].spot;
|
||||
undo->location[i].spot = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove this undo from the list */
|
||||
if (undo_info.current == 0) {
|
||||
if (undo_info.count > 1)
|
||||
undo_info.current = MAX_UNDOS - 1;
|
||||
} else {
|
||||
undo_info.current--;
|
||||
}
|
||||
|
||||
undo_info.count--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void add_undo(int button)
|
||||
{
|
||||
struct Undo *undo;
|
||||
int row, col, i;
|
||||
bool storable;
|
||||
|
||||
if ((button != BUTTON_LEFT) && (button != BUTTON_RIGHT) &&
|
||||
(button != BUTTON_UP) && (button != BUTTON_DOWN))
|
||||
return;
|
||||
|
||||
if (undo_info.count != 0) {
|
||||
if (undo_info.current < (MAX_UNDOS - 1))
|
||||
undo_info.current++;
|
||||
else
|
||||
undo_info.current = 0;
|
||||
}
|
||||
|
||||
/* Make what follows more readable */
|
||||
undo = &undo_info.history[undo_info.current];
|
||||
|
||||
/* Store our level info */
|
||||
rb->memcpy(&undo->level, ¤t_info.level, sizeof(undo->level));
|
||||
|
||||
/* Store our player info */
|
||||
rb->memcpy(&undo->location[0], ¤t_info.player, sizeof(undo->location[0]));
|
||||
|
||||
/* Now we need to store upto 2 blocks that may be affected.
|
||||
* If player.spot is NULL, then there is no info stored
|
||||
* for that block */
|
||||
|
||||
row = current_info.player.row;
|
||||
col = current_info.player.col;
|
||||
|
||||
/* This must stay as _1_ because the first block (0) is the player */
|
||||
for (i = 1; i < 3; i++) {
|
||||
storable = true;
|
||||
|
||||
switch (button) {
|
||||
case BUTTON_LEFT:
|
||||
col--;
|
||||
if (col < 0)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
case BUTTON_RIGHT:
|
||||
col++;
|
||||
if (col >= COLS)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
case BUTTON_UP:
|
||||
row--;
|
||||
if (row < 0)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
row++;
|
||||
if (row >= ROWS)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (storable) {
|
||||
undo->location[i].col = col;
|
||||
undo->location[i].row = row;
|
||||
undo->location[i].spot = current_info.board[row][col];
|
||||
} else {
|
||||
undo->location[i].spot = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (undo_info.count < MAX_UNDOS)
|
||||
undo_info.count++;
|
||||
}
|
||||
|
||||
static void init_boards(void)
|
||||
{
|
||||
current_info.level.level = 0;
|
||||
current_info.level.moves = 0;
|
||||
current_info.level.boxes_to_go = 0;
|
||||
current_info.player.row = 0;
|
||||
current_info.player.col = 0;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.max_level = 0;
|
||||
current_info.level_offset = 0;
|
||||
current_info.loaded_level = 0;
|
||||
|
||||
init_undo();
|
||||
}
|
||||
|
||||
static int get_level_count(void)
|
||||
{
|
||||
int fd = 0;
|
||||
int lastlen = 0;
|
||||
char buffer[COLS + 3]; /* COLS plus CR/LF and \0 */
|
||||
|
||||
if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0) {
|
||||
rb->splash(0, 0, true, "Unable to open %s", LEVELS_FILE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
int len = rb->read_line(fd, buffer, sizeof(buffer));
|
||||
if(len <= 0)
|
||||
break;
|
||||
|
||||
/* Two short lines in a row means new level */
|
||||
if(len < 3 && lastlen < 3)
|
||||
current_info.max_level++;
|
||||
|
||||
lastlen = len;
|
||||
}
|
||||
|
||||
rb->close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_level(char *level, int level_size)
|
||||
{
|
||||
int fd = 0, i = 0;
|
||||
int nread = 0;
|
||||
int count = 0;
|
||||
int lastlen = 0;
|
||||
int level_ct = 1;
|
||||
unsigned char buffer[SOKOBAN_LEVEL_SIZE * 2];
|
||||
bool level_found = false;
|
||||
|
||||
/* open file */
|
||||
if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0)
|
||||
return -1;
|
||||
|
||||
/* Lets not reparse the full file if we can avoid it */
|
||||
if (current_info.loaded_level < current_info.level.level) {
|
||||
rb->lseek(fd, current_info.level_offset, SEEK_SET);
|
||||
level_ct = current_info.loaded_level;
|
||||
}
|
||||
|
||||
if(current_info.level.level > 1) {
|
||||
while(!level_found) {
|
||||
int len = rb->read_line(fd, buffer, SOKOBAN_LEVEL_SIZE);
|
||||
if(len <= 0) {
|
||||
rb->close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Two short lines in a row means new level */
|
||||
if(len < 3 && lastlen < 3) {
|
||||
level_ct++;
|
||||
if(level_ct == current_info.level.level)
|
||||
level_found = true;
|
||||
}
|
||||
lastlen = len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the current offset */
|
||||
current_info.level_offset = rb->lseek(fd, 0, SEEK_CUR);
|
||||
|
||||
/* read a full buffer chunk from here */
|
||||
nread = rb->read(fd, buffer, sizeof(buffer)-1);
|
||||
if (nread < 0)
|
||||
return -1;
|
||||
buffer[nread] = 0;
|
||||
|
||||
rb->close(fd);
|
||||
|
||||
/* If we read less then a level, error */
|
||||
if (nread < level_size)
|
||||
return -1;
|
||||
|
||||
/* Load our new level */
|
||||
for(i=0, count=0; (count < nread) && (i<level_size);) {
|
||||
if (buffer[count] != '\n' && buffer[count] != '\r')
|
||||
level[i++] = buffer[count];
|
||||
count++;
|
||||
}
|
||||
level[i] = 0;
|
||||
|
||||
current_info.loaded_level = current_info.level.level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return non-zero on error */
|
||||
static int load_level(void)
|
||||
{
|
||||
short c = 0;
|
||||
short r = 0;
|
||||
short i = 0;
|
||||
char level[ROWS*COLS+1];
|
||||
int x = 0;
|
||||
|
||||
current_info.player.spot=' ';
|
||||
current_info.level.boxes_to_go = 0;
|
||||
current_info.level.moves = 0;
|
||||
|
||||
if (get_level(level, sizeof(level)) != 0)
|
||||
return -1;
|
||||
|
||||
i = 0;
|
||||
for (r = 0; r < ROWS; r++) {
|
||||
x++;
|
||||
for (c = 0; c < COLS; c++, i++) {
|
||||
current_info.board[r][c] = level[i];
|
||||
|
||||
if (current_info.board[r][c] == '.')
|
||||
current_info.level.boxes_to_go++;
|
||||
|
||||
else if (current_info.board[r][c] == '@') {
|
||||
current_info.player.row = r;
|
||||
current_info.player.col = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_screen(void)
|
||||
{
|
||||
short b = 0, c = 0;
|
||||
short rows = 0, cols = 0;
|
||||
char s[25];
|
||||
|
||||
short magnify = 4;
|
||||
|
||||
/* load the board to the screen */
|
||||
for (rows=0 ; rows < ROWS ; rows++) {
|
||||
for (cols = 0 ; cols < COLS ; cols++) {
|
||||
c = cols * magnify;
|
||||
b = rows * magnify;
|
||||
|
||||
switch(current_info.board[rows][cols]) {
|
||||
case 'X': /* black space */
|
||||
rb->lcd_drawrect(c, b, magnify, magnify);
|
||||
rb->lcd_drawrect(c+1, b+1, 2, 2);
|
||||
break;
|
||||
|
||||
case '#': /* this is a wall */
|
||||
rb->lcd_drawpixel(c, b);
|
||||
rb->lcd_drawpixel(c+2, b);
|
||||
rb->lcd_drawpixel(c+1, b+1);
|
||||
rb->lcd_drawpixel(c+3, b+1);
|
||||
rb->lcd_drawpixel(c, b+2);
|
||||
rb->lcd_drawpixel(c+2, b+2);
|
||||
rb->lcd_drawpixel(c+1, b+3);
|
||||
rb->lcd_drawpixel(c+3, b+3);
|
||||
break;
|
||||
|
||||
case '.': /* this is a home location */
|
||||
rb->lcd_drawrect(c+1, b+1, 2, 2);
|
||||
break;
|
||||
|
||||
case '$': /* this is a box */
|
||||
rb->lcd_drawrect(c, b, magnify, magnify);
|
||||
break;
|
||||
|
||||
case '@': /* this is you */
|
||||
rb->lcd_drawline(c+1, b, c+2, b);
|
||||
rb->lcd_drawline(c, b+1, c+3, b+1);
|
||||
rb->lcd_drawline(c+1, b+2, c+2, b+2);
|
||||
|
||||
rb->lcd_drawpixel(c, b+3);
|
||||
rb->lcd_drawpixel(c+3, b+3);
|
||||
break;
|
||||
|
||||
case '%': /* this is a box on a home spot */
|
||||
rb->lcd_drawrect(c, b, magnify, magnify);
|
||||
rb->lcd_drawrect(c+1, b+1, 2, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rb->snprintf(s, sizeof(s), "%d", current_info.level.level);
|
||||
rb->lcd_putsxy(86, 22, s);
|
||||
rb->snprintf(s, sizeof(s), "%d", current_info.level.moves);
|
||||
rb->lcd_putsxy(86, 54, s);
|
||||
|
||||
rb->lcd_drawrect(80,0,32,32);
|
||||
rb->lcd_drawrect(80,32,32,64);
|
||||
rb->lcd_putsxy(81, 10, "Level");
|
||||
rb->lcd_putsxy(81, 42, "Moves");
|
||||
|
||||
/* print out the screen */
|
||||
rb->lcd_update();
|
||||
}
|
||||
|
||||
static void draw_level(void)
|
||||
{
|
||||
load_level();
|
||||
rb->lcd_clear_display();
|
||||
update_screen();
|
||||
}
|
||||
|
||||
static bool sokoban_loop(void)
|
||||
{
|
||||
char new_spot;
|
||||
bool moved = true;
|
||||
int i = 0, button = 0;
|
||||
short r = 0, c = 0;
|
||||
|
||||
current_info.level.level = 1;
|
||||
|
||||
load_level();
|
||||
update_screen();
|
||||
|
||||
while (1) {
|
||||
moved = true;
|
||||
|
||||
r = current_info.player.row;
|
||||
c = current_info.player.col;
|
||||
|
||||
button = rb->button_get(true);
|
||||
|
||||
add_undo(button);
|
||||
|
||||
switch(button)
|
||||
{
|
||||
case BUTTON_OFF:
|
||||
/* get out of here */
|
||||
return PLUGIN_OK;
|
||||
|
||||
case BUTTON_ON:
|
||||
case BUTTON_ON | BUTTON_REPEAT:
|
||||
/* this is UNDO */
|
||||
undo();
|
||||
rb->lcd_clear_display();
|
||||
update_screen();
|
||||
moved = false;
|
||||
break;
|
||||
|
||||
case BUTTON_F3:
|
||||
case BUTTON_F3 | BUTTON_REPEAT:
|
||||
/* increase level */
|
||||
init_undo();
|
||||
current_info.level.boxes_to_go=0;
|
||||
moved = true;
|
||||
break;
|
||||
|
||||
case BUTTON_F1:
|
||||
case BUTTON_F1 | BUTTON_REPEAT:
|
||||
/* previous level */
|
||||
init_undo();
|
||||
if (current_info.level.level > 1)
|
||||
current_info.level.level--;
|
||||
|
||||
draw_level();
|
||||
moved = false;
|
||||
break;
|
||||
|
||||
case BUTTON_F2:
|
||||
case BUTTON_F2 | BUTTON_REPEAT:
|
||||
/* same level */
|
||||
init_undo();
|
||||
draw_level();
|
||||
moved = false;
|
||||
break;
|
||||
|
||||
case BUTTON_LEFT:
|
||||
switch(current_info.board[r][c-1])
|
||||
{
|
||||
case ' ': /* if it is a blank spot */
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r][c-1];
|
||||
current_info.board[r][c-1] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r][c-2])
|
||||
{
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r][c-2] = current_info.board[r][c-1];
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r][c-2] = '%';
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r][c-2]) {
|
||||
case ' ': /* we are going from a home to a blank */
|
||||
current_info.board[r][c-2] = '$';
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.': /* if we are going from a home to home */
|
||||
current_info.board[r][c-2] = '%';
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.col--;
|
||||
break;
|
||||
|
||||
case BUTTON_RIGHT: /* if it is a blank spot */
|
||||
switch(current_info.board[r][c+1]) {
|
||||
case ' ':
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r][c+1];
|
||||
current_info.board[r][c+1] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r][c+2]) {
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r][c+2] = current_info.board[r][c+1];
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r][c+2] = '%';
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r][c+2]) {
|
||||
case ' ': /* going from a home to a blank */
|
||||
current_info.board[r][c+2] = '$';
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
current_info.board[r][c+2] = '%';
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.col++;
|
||||
break;
|
||||
|
||||
case BUTTON_UP:
|
||||
switch(current_info.board[r-1][c]) {
|
||||
case ' ': /* if it is a blank spot */
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r-1][c];
|
||||
current_info.board[r-1][c] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r-2][c]) {
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r-2][c] = current_info.board[r-1][c];
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r-2][c] = '%';
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r-2][c]) {
|
||||
case ' ': /* we are going from a home to a blank */
|
||||
current_info.board[r-2][c] = '$';
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.': /* if we are going from a home to home */
|
||||
current_info.board[r-2][c] = '%';
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.row--;
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
switch(current_info.board[r+1][c]) {
|
||||
case ' ': /* if it is a blank spot */
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r+1][c];
|
||||
current_info.board[r+1][c] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r+2][c]) {
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r+2][c] = current_info.board[r+1][c];
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r+2][c] = '%';
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r+2][c]) {
|
||||
case ' ': /* going from a home to a blank */
|
||||
current_info.board[r+2][c] = '$';
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.': /* going from a home to home */
|
||||
current_info.board[r+2][c] = '%';
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.row++;
|
||||
break;
|
||||
|
||||
case SYS_USB_CONNECTED:
|
||||
rb->usb_screen();
|
||||
return PLUGIN_USB_CONNECTED;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved) {
|
||||
current_info.level.moves++;
|
||||
rb->lcd_clear_display();
|
||||
update_screen();
|
||||
}
|
||||
|
||||
/* We have completed this level */
|
||||
if (current_info.level.boxes_to_go == 0) {
|
||||
current_info.level.level++;
|
||||
|
||||
/* clear undo stats */
|
||||
init_undo();
|
||||
|
||||
rb->lcd_clear_display();
|
||||
|
||||
if (current_info.level.level > current_info.max_level) {
|
||||
rb->lcd_putsxy(10, 20, "You WIN!!");
|
||||
|
||||
for (i = 0; i < 30000 ; i++) {
|
||||
rb->lcd_invertrect(0, 0, 111, 63);
|
||||
rb->lcd_update();
|
||||
|
||||
button = rb->button_get(false);
|
||||
if (button && ((button & BUTTON_REL) != BUTTON_REL))
|
||||
break;
|
||||
}
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
load_level();
|
||||
update_screen();
|
||||
}
|
||||
|
||||
} /* end while */
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||
{
|
||||
int w, h;
|
||||
int len;
|
||||
|
||||
TEST_PLUGIN_API(api);
|
||||
(void)(parameter);
|
||||
rb = api;
|
||||
|
||||
rb->lcd_setfont(FONT_SYSFIXED);
|
||||
rb->lcd_getstringsize(SOKOBAN_TITLE, &w, &h);
|
||||
|
||||
/* Get horizontel centering for text */
|
||||
len = w;
|
||||
if (len%2 != 0)
|
||||
len =((len+1)/2)+(w/2);
|
||||
else
|
||||
len /= 2;
|
||||
|
||||
if (h%2 != 0)
|
||||
h = (h/2)+1;
|
||||
else
|
||||
h /= 2;
|
||||
|
||||
rb->lcd_clear_display();
|
||||
rb->lcd_putsxy(LCD_WIDTH/2-len,(LCD_HEIGHT/2)-h, SOKOBAN_TITLE);
|
||||
rb->lcd_update();
|
||||
rb->sleep(HZ*2);
|
||||
|
||||
rb->lcd_clear_display();
|
||||
|
||||
rb->lcd_putsxy(3, 6, "[OFF] To Stop");
|
||||
rb->lcd_putsxy(3, 16, "[ON] To Undo");
|
||||
rb->lcd_putsxy(3, 26, "[F1] - Level");
|
||||
rb->lcd_putsxy(3, 36, "[F2] Same Level");
|
||||
rb->lcd_putsxy(3, 46, "[F3] + Level");
|
||||
|
||||
rb->lcd_update();
|
||||
rb->sleep(HZ*2);
|
||||
rb->lcd_clear_display();
|
||||
|
||||
init_boards();
|
||||
|
||||
if (get_level_count() != 0) {
|
||||
rb->splash(HZ*2,0,true,"Failed loading levels!");
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
return sokoban_loop();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -64,6 +64,7 @@ unsigned char bitmap_icons_6x8[LastIcon][6] =
|
|||
{ 0x3e, 0x2a, 0x3e, 0x2a, 0x2a, 0x3e }, /* Language file */
|
||||
{ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, /* Text file */
|
||||
{ 0x4e, 0x51, 0x51, 0x40, 0x55, 0x55 }, /* Config file */
|
||||
{ 0x0a, 0x0a, 0x5f, 0x4e, 0x24, 0x18 }, /* Plugin file */
|
||||
};
|
||||
|
||||
unsigned char bitmap_icons_7x8[][7] =
|
||||
|
|
|
@ -29,6 +29,7 @@ enum icons_6x8 {
|
|||
Folder, Directory, Playlist, Repeat,
|
||||
Selected, Cursor, Wps, Mod_Ajz,
|
||||
Font, Language, Text, Config,
|
||||
Plugin,
|
||||
LastIcon
|
||||
};
|
||||
|
||||
|
|
|
@ -1,891 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Eric Linenberg
|
||||
* February 2003: Robert Hak performs a cleanup/rewrite/feature addition.
|
||||
* Eric smiles. Bjorn cries. Linus say 'huh?'.
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include "options.h"
|
||||
|
||||
#ifdef USE_GAMES
|
||||
|
||||
#include <sprintf.h>
|
||||
#include "ctype.h"
|
||||
#include "sokoban.h"
|
||||
#include "lcd.h"
|
||||
#include "button.h"
|
||||
#include "kernel.h"
|
||||
#include "menu.h"
|
||||
#include "screens.h"
|
||||
#include "font.h"
|
||||
#include "file.h"
|
||||
#include "misc.h"
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef SIMULATOR
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "lang.h"
|
||||
#include "sprintf.h"
|
||||
|
||||
#define SOKOBAN_TITLE "Sokoban"
|
||||
#define SOKOBAN_TITLE_FONT 2
|
||||
|
||||
#define LEVELS_FILE "/.rockbox/sokoban/levels.txt"
|
||||
|
||||
#define ROWS 16
|
||||
#define COLS 20
|
||||
#define MAX_UNDOS 5
|
||||
|
||||
#define SOKOBAN_LEVEL_SIZE (ROWS*COLS)
|
||||
|
||||
static void init_undo(void);
|
||||
static void undo(void);
|
||||
static void add_undo(int button);
|
||||
|
||||
static int get_level(char *level, int level_size);
|
||||
static int get_level_count(void);
|
||||
static int load_level(void);
|
||||
static void draw_level(void);
|
||||
|
||||
static void init_boards(void);
|
||||
static void update_screen(void);
|
||||
static bool sokoban_loop(void);
|
||||
|
||||
/* The Location, Undo and LevelInfo structs are OO-flavored.
|
||||
* (oooh!-flavored as Schnueff puts it.) It makes more you have to know,
|
||||
* but the overall data layout becomes more manageable. */
|
||||
|
||||
/* We use the same three values in 2 structs. Makeing them a struct
|
||||
* hopefully ensures that if you change things in one, the other changes
|
||||
* as well. */
|
||||
struct LevelInfo {
|
||||
short level;
|
||||
short moves;
|
||||
short boxes_to_go;
|
||||
};
|
||||
|
||||
/* What a given location on the board looks like at a given time */
|
||||
struct Location {
|
||||
char spot;
|
||||
short row;
|
||||
short col;
|
||||
};
|
||||
|
||||
/* A single level of undo. Each undo move can affect upto,
|
||||
* but not more then, 3 spots on the board */
|
||||
struct Undo {
|
||||
struct LevelInfo level;
|
||||
struct Location location[3];
|
||||
};
|
||||
|
||||
/* Our full undo history */
|
||||
static struct UndoInfo {
|
||||
short count; /* How many undos are there in history */
|
||||
short current; /* Which history is the current undo */
|
||||
struct Undo history[MAX_UNDOS];
|
||||
} undo_info;
|
||||
|
||||
/* Our playing board */
|
||||
static struct BoardInfo {
|
||||
char board[ROWS][COLS];
|
||||
struct LevelInfo level;
|
||||
struct Location player;
|
||||
int max_level; /* How many levels do we have? */
|
||||
int level_offset; /* Where in the level file is this level */
|
||||
int loaded_level; /* Which level is in memory */
|
||||
} current_info;
|
||||
|
||||
|
||||
static void init_undo(void)
|
||||
{
|
||||
undo_info.count = 0;
|
||||
undo_info.current = 0;
|
||||
}
|
||||
|
||||
static void undo(void)
|
||||
{
|
||||
struct Undo *undo;
|
||||
int i = 0;
|
||||
short row, col;
|
||||
|
||||
if (undo_info.count == 0)
|
||||
return;
|
||||
|
||||
/* Update board info */
|
||||
undo = &undo_info.history[undo_info.current];
|
||||
|
||||
current_info.level = undo->level;
|
||||
current_info.player = undo->location[0];
|
||||
|
||||
row = undo->location[0].row;
|
||||
col = undo->location[0].col;
|
||||
current_info.board[row][col] = '@';
|
||||
|
||||
/* Update the two other possible spots */
|
||||
for (i = 1; i < 3; i++) {
|
||||
if (undo->location[i].spot != '\0') {
|
||||
row = undo->location[i].row;
|
||||
col = undo->location[i].col;
|
||||
current_info.board[row][col] = undo->location[i].spot;
|
||||
undo->location[i].spot = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove this undo from the list */
|
||||
if (undo_info.current == 0) {
|
||||
if (undo_info.count > 1)
|
||||
undo_info.current = MAX_UNDOS - 1;
|
||||
} else {
|
||||
undo_info.current--;
|
||||
}
|
||||
|
||||
undo_info.count--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void add_undo(int button)
|
||||
{
|
||||
struct Undo *undo;
|
||||
int row, col, i;
|
||||
bool storable;
|
||||
|
||||
if ((button != BUTTON_LEFT) && (button != BUTTON_RIGHT) &&
|
||||
(button != BUTTON_UP) && (button != BUTTON_DOWN))
|
||||
return;
|
||||
|
||||
if (undo_info.count != 0) {
|
||||
if (undo_info.current < (MAX_UNDOS - 1))
|
||||
undo_info.current++;
|
||||
else
|
||||
undo_info.current = 0;
|
||||
}
|
||||
|
||||
/* Make what follows more readable */
|
||||
undo = &undo_info.history[undo_info.current];
|
||||
|
||||
/* Store our level info */
|
||||
undo->level = current_info.level;
|
||||
|
||||
/* Store our player info */
|
||||
undo->location[0] = current_info.player;
|
||||
|
||||
/* Now we need to store upto 2 blocks that may be affected.
|
||||
* If player.spot is NULL, then there is no info stored
|
||||
* for that block */
|
||||
|
||||
row = current_info.player.row;
|
||||
col = current_info.player.col;
|
||||
|
||||
/* This must stay as _1_ because the first block (0) is the player */
|
||||
for (i = 1; i < 3; i++) {
|
||||
storable = true;
|
||||
|
||||
switch (button) {
|
||||
case BUTTON_LEFT:
|
||||
col--;
|
||||
if (col < 0)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
case BUTTON_RIGHT:
|
||||
col++;
|
||||
if (col >= COLS)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
case BUTTON_UP:
|
||||
row--;
|
||||
if (row < 0)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
row++;
|
||||
if (row >= ROWS)
|
||||
storable = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (storable) {
|
||||
undo->location[i].col = col;
|
||||
undo->location[i].row = row;
|
||||
undo->location[i].spot = current_info.board[row][col];
|
||||
} else {
|
||||
undo->location[i].spot = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (undo_info.count < MAX_UNDOS)
|
||||
undo_info.count++;
|
||||
}
|
||||
|
||||
static void init_boards(void)
|
||||
{
|
||||
current_info.level.level = 0;
|
||||
current_info.level.moves = 0;
|
||||
current_info.level.boxes_to_go = 0;
|
||||
current_info.player.row = 0;
|
||||
current_info.player.col = 0;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.max_level = 0;
|
||||
current_info.level_offset = 0;
|
||||
current_info.loaded_level = 0;
|
||||
|
||||
init_undo();
|
||||
}
|
||||
|
||||
static int get_level_count(void)
|
||||
{
|
||||
int fd = 0;
|
||||
int len, lastlen = 0;
|
||||
char buffer[COLS + 3]; /* COLS plus CR/LF and \0 */
|
||||
|
||||
if ((fd = open(LEVELS_FILE, O_RDONLY)) < 0) {
|
||||
splash(0, 0, true, "Unable to open %s", LEVELS_FILE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
len = read_line(fd, buffer, sizeof(buffer));
|
||||
if(len <= 0)
|
||||
break;
|
||||
|
||||
/* Two short lines in a row means new level */
|
||||
if(len < 3 && lastlen < 3)
|
||||
current_info.max_level++;
|
||||
|
||||
lastlen = len;
|
||||
}
|
||||
|
||||
DEBUGF("%d levels loaded\n", current_info.max_level);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_level(char *level, int level_size)
|
||||
{
|
||||
int fd = 0, i = 0;
|
||||
int nread = 0;
|
||||
int count = 0;
|
||||
int len, lastlen = 0;
|
||||
int level_ct = 1;
|
||||
unsigned char buffer[SOKOBAN_LEVEL_SIZE * 2];
|
||||
bool level_found = false;
|
||||
|
||||
/* open file */
|
||||
if ((fd = open(LEVELS_FILE, O_RDONLY)) < 0)
|
||||
return -1;
|
||||
|
||||
/* Lets not reparse the full file if we can avoid it */
|
||||
if (current_info.loaded_level < current_info.level.level) {
|
||||
lseek(fd, current_info.level_offset, SEEK_SET);
|
||||
level_ct = current_info.loaded_level;
|
||||
}
|
||||
|
||||
if(current_info.level.level > 1) {
|
||||
while(!level_found) {
|
||||
len = read_line(fd, buffer, SOKOBAN_LEVEL_SIZE);
|
||||
if(len <= 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Two short lines in a row means new level */
|
||||
if(len < 3 && lastlen < 3) {
|
||||
level_ct++;
|
||||
if(level_ct == current_info.level.level)
|
||||
level_found = true;
|
||||
}
|
||||
lastlen = len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the current offset */
|
||||
current_info.level_offset = lseek(fd, 0, SEEK_CUR);
|
||||
|
||||
/* read a full buffer chunk from here */
|
||||
nread = read(fd, buffer, sizeof(buffer)-1);
|
||||
if (nread < 0)
|
||||
return -1;
|
||||
buffer[nread] = 0;
|
||||
|
||||
close(fd);
|
||||
|
||||
/* If we read less then a level, error */
|
||||
if (nread < level_size)
|
||||
return -1;
|
||||
|
||||
/* Load our new level */
|
||||
for(i=0, count=0; (count < nread) && (i<level_size);) {
|
||||
if (buffer[count] != '\n' && buffer[count] != '\r')
|
||||
level[i++] = buffer[count];
|
||||
count++;
|
||||
}
|
||||
level[i] = 0;
|
||||
|
||||
current_info.loaded_level = current_info.level.level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return non-zero on error */
|
||||
static int load_level(void)
|
||||
{
|
||||
short c = 0;
|
||||
short r = 0;
|
||||
short i = 0;
|
||||
char level[ROWS*COLS+1];
|
||||
int x = 0;
|
||||
|
||||
current_info.player.spot=' ';
|
||||
current_info.level.boxes_to_go = 0;
|
||||
current_info.level.moves = 0;
|
||||
|
||||
if (get_level(level, sizeof(level)) != 0)
|
||||
return -1;
|
||||
|
||||
i = 0;
|
||||
for (r = 0; r < ROWS; r++) {
|
||||
x++;
|
||||
for (c = 0; c < COLS; c++, i++) {
|
||||
current_info.board[r][c] = level[i];
|
||||
|
||||
if (current_info.board[r][c] == '.')
|
||||
current_info.level.boxes_to_go++;
|
||||
|
||||
else if (current_info.board[r][c] == '@') {
|
||||
current_info.player.row = r;
|
||||
current_info.player.col = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void update_screen(void)
|
||||
{
|
||||
short b = 0, c = 0;
|
||||
short rows = 0, cols = 0;
|
||||
char s[25];
|
||||
|
||||
short magnify = 4;
|
||||
|
||||
/* load the board to the screen */
|
||||
for (rows=0 ; rows < ROWS ; rows++) {
|
||||
for (cols = 0 ; cols < COLS ; cols++) {
|
||||
c = cols * magnify;
|
||||
b = rows * magnify;
|
||||
|
||||
switch(current_info.board[rows][cols]) {
|
||||
case 'X': /* black space */
|
||||
lcd_drawrect(c, b, magnify, magnify);
|
||||
lcd_drawrect(c+1, b+1, 2, 2);
|
||||
break;
|
||||
|
||||
case '#': /* this is a wall */
|
||||
lcd_drawpixel(c, b);
|
||||
lcd_drawpixel(c+2, b);
|
||||
lcd_drawpixel(c+1, b+1);
|
||||
lcd_drawpixel(c+3, b+1);
|
||||
lcd_drawpixel(c, b+2);
|
||||
lcd_drawpixel(c+2, b+2);
|
||||
lcd_drawpixel(c+1, b+3);
|
||||
lcd_drawpixel(c+3, b+3);
|
||||
break;
|
||||
|
||||
case '.': /* this is a home location */
|
||||
lcd_drawrect(c+1, b+1, 2, 2);
|
||||
break;
|
||||
|
||||
case '$': /* this is a box */
|
||||
lcd_drawrect(c, b, magnify, magnify);
|
||||
break;
|
||||
|
||||
case '@': /* this is you */
|
||||
lcd_drawline(c+1, b, c+2, b);
|
||||
lcd_drawline(c, b+1, c+3, b+1);
|
||||
lcd_drawline(c+1, b+2, c+2, b+2);
|
||||
|
||||
lcd_drawpixel(c, b+3);
|
||||
lcd_drawpixel(c+3, b+3);
|
||||
break;
|
||||
|
||||
case '%': /* this is a box on a home spot */
|
||||
lcd_drawrect(c, b, magnify, magnify);
|
||||
lcd_drawrect(c+1, b+1, 2, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
snprintf(s, sizeof(s), "%d", current_info.level.level);
|
||||
lcd_putsxy(86, 22, s);
|
||||
snprintf(s, sizeof(s), "%d", current_info.level.moves);
|
||||
lcd_putsxy(86, 54, s);
|
||||
|
||||
lcd_drawrect(80,0,32,32);
|
||||
lcd_drawrect(80,32,32,64);
|
||||
lcd_putsxy(81, 10, str(LANG_SOKOBAN_LEVEL));
|
||||
lcd_putsxy(81, 42, str(LANG_SOKOBAN_MOVE));
|
||||
|
||||
/* print out the screen */
|
||||
lcd_update();
|
||||
}
|
||||
|
||||
static void draw_level(void)
|
||||
{
|
||||
load_level();
|
||||
lcd_clear_display();
|
||||
update_screen();
|
||||
}
|
||||
|
||||
static bool sokoban_loop(void)
|
||||
{
|
||||
char new_spot;
|
||||
bool moved = true;
|
||||
int i = 0, button = 0;
|
||||
short r = 0, c = 0;
|
||||
|
||||
current_info.level.level = 1;
|
||||
|
||||
load_level();
|
||||
update_screen();
|
||||
|
||||
while (1) {
|
||||
moved = true;
|
||||
|
||||
r = current_info.player.row;
|
||||
c = current_info.player.col;
|
||||
|
||||
button = button_get(true);
|
||||
|
||||
add_undo(button);
|
||||
|
||||
switch(button)
|
||||
{
|
||||
case BUTTON_OFF:
|
||||
/* get out of here */
|
||||
return false;
|
||||
|
||||
case BUTTON_ON:
|
||||
case BUTTON_ON | BUTTON_REPEAT:
|
||||
/* this is UNDO */
|
||||
undo();
|
||||
lcd_clear_display();
|
||||
update_screen();
|
||||
moved = false;
|
||||
break;
|
||||
|
||||
case BUTTON_F3:
|
||||
case BUTTON_F3 | BUTTON_REPEAT:
|
||||
/* increase level */
|
||||
init_undo();
|
||||
current_info.level.boxes_to_go=0;
|
||||
moved = true;
|
||||
break;
|
||||
|
||||
case BUTTON_F1:
|
||||
case BUTTON_F1 | BUTTON_REPEAT:
|
||||
/* previous level */
|
||||
init_undo();
|
||||
if (current_info.level.level > 1)
|
||||
current_info.level.level--;
|
||||
|
||||
draw_level();
|
||||
moved = false;
|
||||
break;
|
||||
|
||||
case BUTTON_F2:
|
||||
case BUTTON_F2 | BUTTON_REPEAT:
|
||||
/* same level */
|
||||
init_undo();
|
||||
draw_level();
|
||||
moved = false;
|
||||
break;
|
||||
|
||||
case BUTTON_LEFT:
|
||||
switch(current_info.board[r][c-1])
|
||||
{
|
||||
case ' ': /* if it is a blank spot */
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r][c-1];
|
||||
current_info.board[r][c-1] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r][c-2])
|
||||
{
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r][c-2] = current_info.board[r][c-1];
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r][c-2] = '%';
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r][c-2]) {
|
||||
case ' ': /* we are going from a home to a blank */
|
||||
current_info.board[r][c-2] = '$';
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.': /* if we are going from a home to home */
|
||||
current_info.board[r][c-2] = '%';
|
||||
current_info.board[r][c-1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.col--;
|
||||
break;
|
||||
|
||||
case BUTTON_RIGHT: /* if it is a blank spot */
|
||||
switch(current_info.board[r][c+1]) {
|
||||
case ' ':
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r][c+1];
|
||||
current_info.board[r][c+1] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r][c+2]) {
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r][c+2] = current_info.board[r][c+1];
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r][c+2] = '%';
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r][c+2]) {
|
||||
case ' ': /* going from a home to a blank */
|
||||
current_info.board[r][c+2] = '$';
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
current_info.board[r][c+2] = '%';
|
||||
current_info.board[r][c+1] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.col++;
|
||||
break;
|
||||
|
||||
case BUTTON_UP:
|
||||
switch(current_info.board[r-1][c]) {
|
||||
case ' ': /* if it is a blank spot */
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r-1][c];
|
||||
current_info.board[r-1][c] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r-2][c]) {
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r-2][c] = current_info.board[r-1][c];
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r-2][c] = '%';
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r-2][c]) {
|
||||
case ' ': /* we are going from a home to a blank */
|
||||
current_info.board[r-2][c] = '$';
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.': /* if we are going from a home to home */
|
||||
current_info.board[r-2][c] = '%';
|
||||
current_info.board[r-1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.row--;
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
switch(current_info.board[r+1][c]) {
|
||||
case ' ': /* if it is a blank spot */
|
||||
case '.': /* if it is a home spot */
|
||||
new_spot = current_info.board[r+1][c];
|
||||
current_info.board[r+1][c] = '@';
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = new_spot;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
switch(current_info.board[r+2][c]) {
|
||||
case ' ': /* going from blank to blank */
|
||||
current_info.board[r+2][c] = current_info.board[r+1][c];
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
break;
|
||||
|
||||
case '.': /* going from a blank to home */
|
||||
current_info.board[r+2][c] = '%';
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = ' ';
|
||||
current_info.level.boxes_to_go--;
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%':
|
||||
switch(current_info.board[r+2][c]) {
|
||||
case ' ': /* going from a home to a blank */
|
||||
current_info.board[r+2][c] = '$';
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
current_info.level.boxes_to_go++;
|
||||
break;
|
||||
|
||||
case '.': /* going from a home to home */
|
||||
current_info.board[r+2][c] = '%';
|
||||
current_info.board[r+1][c] = current_info.board[r][c];
|
||||
current_info.board[r][c] = current_info.player.spot;
|
||||
current_info.player.spot = '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
current_info.player.row++;
|
||||
break;
|
||||
|
||||
case SYS_USB_CONNECTED:
|
||||
usb_screen();
|
||||
return true;
|
||||
|
||||
default:
|
||||
moved = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved) {
|
||||
current_info.level.moves++;
|
||||
lcd_clear_display();
|
||||
update_screen();
|
||||
}
|
||||
|
||||
/* We have completed this level */
|
||||
if (current_info.level.boxes_to_go == 0) {
|
||||
current_info.level.level++;
|
||||
|
||||
/* clear undo stats */
|
||||
init_undo();
|
||||
|
||||
lcd_clear_display();
|
||||
|
||||
if (current_info.level.level > current_info.max_level) {
|
||||
lcd_putsxy(10, 20, str(LANG_SOKOBAN_WIN));
|
||||
|
||||
for (i = 0; i < 30000 ; i++) {
|
||||
lcd_invertrect(0, 0, 111, 63);
|
||||
lcd_update();
|
||||
|
||||
button = button_get(false);
|
||||
if (button && ((button & BUTTON_REL) != BUTTON_REL))
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
load_level();
|
||||
update_screen();
|
||||
}
|
||||
|
||||
} /* end while */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool sokoban(void)
|
||||
{
|
||||
bool result;
|
||||
int w, h;
|
||||
int len;
|
||||
|
||||
lcd_setfont(FONT_SYSFIXED);
|
||||
|
||||
lcd_getstringsize(SOKOBAN_TITLE, &w, &h);
|
||||
|
||||
/* Get horizontel centering for text */
|
||||
len = w;
|
||||
if (len%2 != 0)
|
||||
len =((len+1)/2)+(w/2);
|
||||
else
|
||||
len /= 2;
|
||||
|
||||
if (h%2 != 0)
|
||||
h = (h/2)+1;
|
||||
else
|
||||
h /= 2;
|
||||
|
||||
lcd_clear_display();
|
||||
lcd_putsxy(LCD_WIDTH/2-len,(LCD_HEIGHT/2)-h, SOKOBAN_TITLE);
|
||||
|
||||
lcd_update();
|
||||
sleep(HZ*2);
|
||||
|
||||
lcd_clear_display();
|
||||
|
||||
lcd_putsxy(3, 6, str(LANG_SOKOBAN_QUIT));
|
||||
lcd_putsxy(3, 16, str(LANG_SOKOBAN_ON));
|
||||
lcd_putsxy(3, 26, str(LANG_SOKOBAN_F1));
|
||||
lcd_putsxy(3, 36, str(LANG_SOKOBAN_F2));
|
||||
lcd_putsxy(3, 46, str(LANG_SOKOBAN_F3));
|
||||
|
||||
lcd_update();
|
||||
sleep(HZ*2);
|
||||
lcd_clear_display();
|
||||
|
||||
init_boards();
|
||||
|
||||
if (get_level_count() != 0)
|
||||
return false;
|
||||
|
||||
result = sokoban_loop();
|
||||
|
||||
lcd_setfont(FONT_UI);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Robert E. Hak
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __SOKOBAN__
|
||||
#define __SOKOBAN__
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
bool sokoban(void);
|
||||
|
||||
#endif /*__SOKOBAN__ */
|
||||
|
|
@ -1,438 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 1999 Mattis Wadman (nappe@sudac.org)
|
||||
*
|
||||
* Heavily modified for embedded use by Björn Stenberg (bjorn@haxx.se)
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include "options.h"
|
||||
|
||||
#ifdef USE_GAMES
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "lcd.h"
|
||||
#include "button.h"
|
||||
#include "kernel.h"
|
||||
#include "menu.h"
|
||||
#include "screens.h"
|
||||
#include "font.h"
|
||||
|
||||
#ifdef SIMULATOR
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "sprintf.h"
|
||||
#include "lang.h"
|
||||
#define TETRIS_TITLE "Tetris!"
|
||||
#define TETRIS_TITLE_FONT 1
|
||||
#define TETRIS_TITLE_XLOC 43
|
||||
#define TETRIS_TITLE_YLOC 15
|
||||
|
||||
static const int start_x = 5;
|
||||
static const int start_y = 5;
|
||||
static const int max_x = 4 * 17;
|
||||
static const int max_y = 3 * 10;
|
||||
static const short level_speeds[10] = {
|
||||
1000, 900, 800, 700, 600, 500, 400, 300, 250, 200
|
||||
};
|
||||
static const int blocks = 7;
|
||||
static const int block_frames[7] = {1,2,2,2,4,4,4};
|
||||
|
||||
static int current_x, current_y, current_f, current_b;
|
||||
static int level, score;
|
||||
static int next_b, next_f;
|
||||
static short lines;
|
||||
static char virtual[LCD_WIDTH * LCD_HEIGHT];
|
||||
|
||||
/*
|
||||
block_data is built up the following way
|
||||
|
||||
first array index specifies the block number
|
||||
second array index specifies the rotation of the block
|
||||
third array index specifies:
|
||||
0: x-coordinates of pixels
|
||||
1: y-coordinates of pixels
|
||||
fourth array index specifies the coordinate of a pixel
|
||||
|
||||
each block consists of four pixels whose relative coordinates are given
|
||||
with block_data
|
||||
*/
|
||||
|
||||
static const char block_data[7][4][2][4] =
|
||||
{
|
||||
{
|
||||
{{0,1,0,1},{0,0,1,1}}
|
||||
},
|
||||
{
|
||||
{{0,1,1,2},{1,1,0,0}},
|
||||
{{0,0,1,1},{0,1,1,2}}
|
||||
},
|
||||
{
|
||||
{{0,1,1,2},{0,0,1,1}},
|
||||
{{1,1,0,0},{0,1,1,2}}
|
||||
},
|
||||
{
|
||||
{{1,1,1,1},{0,1,2,3}},
|
||||
{{0,1,2,3},{2,2,2,2}}
|
||||
},
|
||||
{
|
||||
{{1,1,1,2},{2,1,0,0}},
|
||||
{{0,1,2,2},{1,1,1,2}},
|
||||
{{0,1,1,1},{2,2,1,0}},
|
||||
{{0,0,1,2},{0,1,1,1}}
|
||||
},
|
||||
{
|
||||
{{0,1,1,1},{0,0,1,2}},
|
||||
{{0,1,2,2},{1,1,1,0}},
|
||||
{{1,1,1,2},{0,1,2,2}},
|
||||
{{0,0,1,2},{2,1,1,1}}
|
||||
},
|
||||
{
|
||||
{{1,0,1,2},{0,1,1,1}},
|
||||
{{2,1,1,1},{1,0,1,2}},
|
||||
{{1,0,1,2},{2,1,1,1}},
|
||||
{{0,1,1,1},{1,0,1,2}}
|
||||
}
|
||||
};
|
||||
|
||||
static int t_rand(int range)
|
||||
{
|
||||
return current_tick % range;
|
||||
}
|
||||
|
||||
static void draw_frame(int fstart_x,int fstop_x,int fstart_y,int fstop_y)
|
||||
{
|
||||
lcd_drawline(fstart_x, fstart_y, fstop_x, fstart_y);
|
||||
lcd_drawline(fstart_x, fstop_y, fstop_x, fstop_y);
|
||||
|
||||
lcd_drawline(fstart_x, fstart_y, fstart_x, fstop_y);
|
||||
lcd_drawline(fstop_x, fstart_y, fstop_x, fstop_y);
|
||||
|
||||
lcd_drawline(fstart_x - 1, fstart_y + 1, fstart_x - 1, fstop_y + 1);
|
||||
lcd_drawline(fstart_x - 1, fstop_y + 1, fstop_x - 1, fstop_y + 1);
|
||||
}
|
||||
|
||||
static void draw_block(int x, int y, int block, int frame, bool clear)
|
||||
{
|
||||
int i, a, b;
|
||||
for(i=0;i < 4;i++) {
|
||||
if (clear)
|
||||
{
|
||||
for (a = 0; a < 3; a++)
|
||||
for (b = 0; b < 4; b++)
|
||||
lcd_clearpixel(start_x + x + block_data[block][frame][1][i] * 4 - b,
|
||||
start_y + y + block_data[block][frame][0][i] * 3 + a);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (a = 0; a < 3; a++)
|
||||
for (b = 0; b < 4; b++)
|
||||
lcd_drawpixel(start_x+x+block_data[block][frame][1][i] * 4 - b,
|
||||
start_y+y+block_data[block][frame][0][i] * 3 + a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void to_virtual(void)
|
||||
{
|
||||
int i, a, b;
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
for (a = 0; a < 3; a++)
|
||||
for (b = 0; b < 4; b++)
|
||||
*(virtual +
|
||||
(current_y + block_data[current_b][current_f][0][i] * 3 + a) *
|
||||
max_x + current_x + block_data[current_b][current_f][1][i] *
|
||||
4 - b) = current_b + 1;
|
||||
}
|
||||
|
||||
static bool block_touch (int x, int y)
|
||||
{
|
||||
int a,b;
|
||||
for (a = 0; a < 4; a++)
|
||||
for (b = 0; b < 3; b++)
|
||||
if (*(virtual + (y + b) * max_x + (x - a)) != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gameover(void)
|
||||
{
|
||||
int i;
|
||||
int frame, block, y, x;
|
||||
|
||||
x = current_x;
|
||||
y = current_y;
|
||||
block = current_b;
|
||||
frame = current_f;
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
/* Do we have blocks touching? */
|
||||
if(block_touch(x + block_data[block][frame][1][i] * 4,
|
||||
y + block_data[block][frame][0][i] * 3))
|
||||
{
|
||||
/* Are we at the top of the frame? */
|
||||
if(x + block_data[block][frame][1][i] * 4 >= max_x - 16)
|
||||
{
|
||||
/* Game over ;) */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool valid_position(int x, int y, int block, int frame)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i < 4;i++)
|
||||
if ((y + block_data[block][frame][0][i] * 3 > max_y - 3) ||
|
||||
(x + block_data[block][frame][1][i] * 4 > max_x - 4) ||
|
||||
(y + block_data[block][frame][0][i] * 3 < 0) ||
|
||||
(x + block_data[block][frame][1][i] * 4 < 4) ||
|
||||
block_touch (x + block_data[block][frame][1][i] * 4,
|
||||
y + block_data[block][frame][0][i] * 3))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void from_virtual(void)
|
||||
{
|
||||
int x,y;
|
||||
for(y = 0; y < max_y; y++)
|
||||
for(x = 1; x < max_x - 1; x++)
|
||||
if(*(virtual + (y * max_x) + x) != 0)
|
||||
lcd_drawpixel(start_x + x, start_y + y);
|
||||
else
|
||||
lcd_clearpixel(start_x + x, start_y + y);
|
||||
}
|
||||
|
||||
static void move_block(int x,int y,int f)
|
||||
{
|
||||
int last_frame = current_f;
|
||||
if(f != 0)
|
||||
{
|
||||
current_f += f;
|
||||
if(current_f > block_frames[current_b]-1)
|
||||
current_f = 0;
|
||||
if(current_f < 0)
|
||||
current_f = block_frames[current_b]-1;
|
||||
}
|
||||
|
||||
if(valid_position(current_x + x, current_y + y, current_b, current_f))
|
||||
{
|
||||
draw_block(current_x,current_y,current_b,last_frame,true);
|
||||
current_x += x;
|
||||
current_y += y;
|
||||
draw_block(current_x,current_y,current_b,current_f,false);
|
||||
lcd_update();
|
||||
}
|
||||
else
|
||||
current_f = last_frame;
|
||||
}
|
||||
|
||||
static void new_block(void)
|
||||
{
|
||||
current_b = next_b;
|
||||
current_f = next_f;
|
||||
current_x = max_x - 16;
|
||||
current_y = (int)12;
|
||||
next_b = t_rand(blocks);
|
||||
next_f = t_rand(block_frames[next_b]);
|
||||
|
||||
lcd_drawline (max_x + 7, start_y - 1, max_x + 29, start_y - 1);
|
||||
lcd_drawline (max_x + 29, start_y, max_x + 29, start_y + 14);
|
||||
lcd_drawline (max_x + 29, start_y + 14, max_x + 7, start_y + 14);
|
||||
lcd_drawline (max_x + 7, start_y + 14, max_x + 7, start_y - 1);
|
||||
lcd_drawline (max_x + 6, start_y + 15, max_x + 6, start_y);
|
||||
lcd_drawline (max_x + 6, start_y + 15, max_x + 28, start_y + 15);
|
||||
|
||||
draw_block(max_x + 9, start_y - 4, current_b, current_f, true);
|
||||
draw_block(max_x + 9, start_y - 4, next_b, next_f, false);
|
||||
if(!valid_position(current_x, current_y, current_b, current_f))
|
||||
{
|
||||
draw_block(current_x, current_y, current_b, current_f, false);
|
||||
lcd_update();
|
||||
}
|
||||
else
|
||||
draw_block(current_x, current_y, current_b, current_f, false);
|
||||
}
|
||||
|
||||
static int check_lines(void)
|
||||
{
|
||||
int x,y,i,j;
|
||||
bool line;
|
||||
int lines = 0;
|
||||
for(x = 0; x < max_x; x++)
|
||||
{
|
||||
line = true;
|
||||
for(y = 0; y < max_y; y++)
|
||||
{
|
||||
if(*(virtual + y * max_x + x) == 0)
|
||||
{
|
||||
line = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(line)
|
||||
{
|
||||
lines++;
|
||||
/* move rows down */
|
||||
for(i = x; i < max_x - 1; i++)
|
||||
for (j = 0; j < max_y; j++)
|
||||
*(virtual + j * max_x + i)=*(virtual + j * max_x + (i + 1));
|
||||
|
||||
x--; /* re-check this line */
|
||||
}
|
||||
}
|
||||
|
||||
return lines / 4;
|
||||
}
|
||||
|
||||
static void move_down(void)
|
||||
{
|
||||
int l;
|
||||
char s[25];
|
||||
|
||||
if(!valid_position(current_x - 4, current_y, current_b, current_f))
|
||||
{
|
||||
to_virtual();
|
||||
l = check_lines();
|
||||
if(l)
|
||||
{
|
||||
lines += l;
|
||||
level = (int)lines/10;
|
||||
if(level > 9)
|
||||
level = 9;
|
||||
from_virtual();
|
||||
score += l*l;
|
||||
}
|
||||
|
||||
snprintf (s, sizeof(s), "%d %s %d", lines,
|
||||
str(LANG_TETRIS_LEVEL), level);
|
||||
lcd_putsxy (2, 42, s);
|
||||
|
||||
new_block();
|
||||
move_block(0,0,0);
|
||||
}
|
||||
else
|
||||
move_block(-4,0,0);
|
||||
}
|
||||
|
||||
static bool game_loop(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
int count = 0;
|
||||
while(count * 300 < level_speeds[level])
|
||||
{
|
||||
switch(button_get_w_tmo(HZ/10))
|
||||
{
|
||||
case BUTTON_OFF:
|
||||
return false;
|
||||
|
||||
case BUTTON_UP:
|
||||
case BUTTON_UP | BUTTON_REPEAT:
|
||||
move_block(0,-3,0);
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
case BUTTON_DOWN | BUTTON_REPEAT:
|
||||
move_block(0,3,0);
|
||||
break;
|
||||
|
||||
case BUTTON_RIGHT:
|
||||
case BUTTON_RIGHT | BUTTON_REPEAT:
|
||||
move_block(0,0,1);
|
||||
break;
|
||||
|
||||
case BUTTON_LEFT:
|
||||
case BUTTON_LEFT | BUTTON_REPEAT:
|
||||
move_down();
|
||||
break;
|
||||
|
||||
case SYS_USB_CONNECTED:
|
||||
usb_screen();
|
||||
return true;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if(gameover())
|
||||
{
|
||||
lcd_clearrect(0, 52, LCD_WIDTH, LCD_HEIGHT - 52);
|
||||
lcd_putsxy (2, 52, str(LANG_TETRIS_LOSE));
|
||||
lcd_update();
|
||||
sleep(HZ * 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
move_down();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void init_tetris(void)
|
||||
{
|
||||
memset(&virtual, 0, sizeof(virtual));
|
||||
|
||||
current_x = 0;
|
||||
current_y = 0;
|
||||
current_f = 0;
|
||||
current_b = 0;
|
||||
level = 0;
|
||||
lines = 0;
|
||||
score = 0;
|
||||
next_b = 0;
|
||||
next_f = 0;
|
||||
}
|
||||
|
||||
bool tetris(void)
|
||||
{
|
||||
char buf[20];
|
||||
bool val;
|
||||
|
||||
/* Lets use the default font */
|
||||
lcd_setfont(FONT_SYSFIXED);
|
||||
|
||||
init_tetris();
|
||||
|
||||
draw_frame(start_x, start_x + max_x - 1, start_y - 1, start_y + max_y);
|
||||
snprintf(buf, sizeof(buf), "0 %s 0", str(LANG_TETRIS_LEVEL));
|
||||
lcd_putsxy (2, 42, buf);
|
||||
lcd_update();
|
||||
|
||||
next_b = t_rand(blocks);
|
||||
next_f = t_rand(block_frames[next_b]);
|
||||
new_block();
|
||||
val = game_loop();
|
||||
|
||||
lcd_setfont(FONT_UI);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Philipp Pertermann
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __WORMLET__
|
||||
#define __WORMLET__
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
bool wormlet(void);
|
||||
|
||||
#endif /*__WORMLET__ */
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include "status.h"
|
||||
#include "playlist.h"
|
||||
#include "sprintf.h"
|
||||
#include "kernel.h"
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
#define BMPHEIGHT_usb_logo 32
|
||||
|
|
19
apps/tree.c
19
apps/tree.c
|
@ -46,12 +46,12 @@
|
|||
#include "rolo.h"
|
||||
#include "icons.h"
|
||||
#include "lang.h"
|
||||
#include "viewer.h"
|
||||
#include "language.h"
|
||||
#include "screens.h"
|
||||
#include "keyboard.h"
|
||||
#include "onplay.h"
|
||||
#include "buffer.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
#include "widgets.h"
|
||||
|
@ -318,6 +318,8 @@ static int showdir(char *path, int start)
|
|||
else if (!strcasecmp(&entry->d_name[len-4], ".mod"))
|
||||
#endif
|
||||
dptr->attr |= TREE_ATTR_MOD;
|
||||
else if (!strcasecmp(&entry->d_name[len-5], ".rock"))
|
||||
dptr->attr |= TREE_ATTR_ROCK;
|
||||
}
|
||||
|
||||
/* filter out all non-playlist files */
|
||||
|
@ -468,6 +470,10 @@ static int showdir(char *path, int start)
|
|||
icon_type = Mod_Ajz;
|
||||
break;
|
||||
|
||||
case TREE_ATTR_ROCK:
|
||||
icon_type = Plugin;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
case TREE_ATTR_FONT:
|
||||
icon_type = Font;
|
||||
|
@ -962,7 +968,7 @@ bool dirbrowse(char *root)
|
|||
break;
|
||||
|
||||
case TREE_ATTR_TXT:
|
||||
viewer_run(buf);
|
||||
plugin_load("/.rockbox/rocks/viewer.rock",buf);
|
||||
restore = true;
|
||||
break;
|
||||
|
||||
|
@ -998,6 +1004,14 @@ bool dirbrowse(char *root)
|
|||
rolo_load(buf);
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* plugin file */
|
||||
case TREE_ATTR_ROCK:
|
||||
if (plugin_load(buf,NULL) == PLUGIN_USB_CONNECTED)
|
||||
reload_root = true;
|
||||
else
|
||||
restore = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( play ) {
|
||||
|
@ -1194,6 +1208,7 @@ bool dirbrowse(char *root)
|
|||
/* the sub-screen might've ruined the margins */
|
||||
lcd_setmargins(MARGIN_X,MARGIN_Y); /* leave room for cursor and
|
||||
icon */
|
||||
lcd_setfont(FONT_UI);
|
||||
#endif
|
||||
numentries = showdir(currdir, dirstart);
|
||||
update_all = true;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define TREE_ATTR_TXT 0x500 /* text file */
|
||||
#define TREE_ATTR_FONT 0x800 /* font file */
|
||||
#define TREE_ATTR_LNG 0x1000 /* binary lang file */
|
||||
#define TREE_ATTR_ROCK 0x2000 /* binary rockbox plugin */
|
||||
#define TREE_ATTR_MASK 0xffd0 /* which bits tree.c uses (above + DIR) */
|
||||
|
||||
void tree_init(void);
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 Jerome Kuptz
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef _VIEWER_H
|
||||
#define _VIEWER_H
|
||||
|
||||
bool viewer_run(char* file);
|
||||
|
||||
#endif
|
|
@ -2,15 +2,17 @@ ENTRY(start)
|
|||
OUTPUT_FORMAT(elf32-sh)
|
||||
INPUT(crt0.o)
|
||||
|
||||
#define PLUGINSIZE 0x8000
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DRAMSIZE 0x1f0000
|
||||
#define DRAMSIZE 0x1f0000 - PLUGINSIZE
|
||||
#define ORIGADDR 0x09010000
|
||||
#define ENDADDR 0x09200000
|
||||
|
||||
#else
|
||||
#define DRAMSIZE (MEMORYSIZE * 0x100000)
|
||||
#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGINSIZE
|
||||
#define ORIGADDR 0x09000000
|
||||
#define ENDADDR (ORIGADDR + DRAMSIZE)
|
||||
#endif
|
||||
#define ENDADDR (ORIGADDR + DRAMSIZE)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
|
@ -91,6 +93,11 @@ SECTIONS
|
|||
_topramend = .;
|
||||
} > DRAM
|
||||
|
||||
.plugin ENDADDR:
|
||||
{
|
||||
_pluginbuf = .;
|
||||
}
|
||||
|
||||
.iram 0xf000000 : AT ( _iramcopy )
|
||||
{
|
||||
_iramstart = .;
|
||||
|
|
|
@ -47,7 +47,7 @@ unsigned short new_lcd_rocklatin1_to_xlcd[] =
|
|||
RESERVED_CHAR, /* 0x01-0x17 reserved */
|
||||
RESERVED_CHAR, /* 0x01-0x17 reserved */
|
||||
RESERVED_CHAR, /* 0x01-0x17 reserved */
|
||||
RESERVED_CHAR, /* 0x01-0x17 reserved */
|
||||
0x217, /* 0x17 .. "plugin" icon */
|
||||
0x218, /* 0x18 .. "folder" icon */
|
||||
0x219, /* 0x19 .. "MOD/AJZ" icon (winlatin o (dote in the middle) */
|
||||
0x21a, /* 0x1a .. "language" icon (winlatin - (a bit longer minus sign) */
|
||||
|
@ -668,7 +668,7 @@ unsigned char extended_font_player[NO_EXTENDED_LCD_CHARS][8] = {
|
|||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 14 */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 15 */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 16 */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 17 */
|
||||
{ 0x04, 0x1e, 0x07, 0x1f, 0x05, 0x01, 0x06, 0x00}, /* 17 Plugin file icon */
|
||||
{ 0x0c, 0x13, 0x11, 0x11, 0x11, 0x11, 0x1f, 0x00}, /* 18 Folder icon */
|
||||
{ 0x1f, 0x11, 0x1b, 0x15, 0x1b, 0x11, 0x1f, 0x00}, /* 19 MOD/AJZ icon */
|
||||
{ 0x00, 0x1f, 0x15, 0x1f, 0x15, 0x1f, 0x00, 0x00}, /* 1a Language icon */
|
||||
|
|
Loading…
Reference in New Issue
Block a user