summaryrefslogtreecommitdiff
path: root/apps/plugins/xworld/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/xworld/sys.c')
-rw-r--r--apps/plugins/xworld/sys.c340
1 files changed, 269 insertions, 71 deletions
diff --git a/apps/plugins/xworld/sys.c b/apps/plugins/xworld/sys.c
index 03b032c055..b13d4fb9ed 100644
--- a/apps/plugins/xworld/sys.c
+++ b/apps/plugins/xworld/sys.c
@@ -130,13 +130,32 @@ static bool sys_do_help(void)
rb->lcd_set_background(LCD_BLACK);
#endif
rb->lcd_setfont(FONT_UI);
- char* help_text[] = {"XWorld", "",
- "XWorld", "is", "an", "interpreter", "for", "Another", "World,", "a", "fantastic", "game", "by", "Eric", "Chahi."
- };
+ char *help_text[] = {
+ "XWorld", "",
+ "XWorld", "is", "a", "port", "of", "a", "bytecode", "interpreter", "for", "`Another", "World',", "a", "cinematic", "adventure", "game", "by", "Eric", "Chahi.",
+ "",
+ "",
+ "Level", "Codes:", "",
+ "Level", "1:", "LDKD", "",
+ "Level", "2:", "HTDC", "",
+ "Level", "3:", "CLLD", "",
+ "Level", "4:", "LBKG", "",
+ "Level", "5:", "XDDJ", "",
+ "Level", "6:", "FXLC", "",
+ "Level", "7:", "KRFK", "",
+ "Level", "8:", "KFLB", "",
+ "Level", "9:", "DDRX", "",
+ "Level", "10:", "BFLX", "",
+ "Level", "11:", "BRTD", "",
+ "Level", "12:", "TFBB", "",
+ "Level", "13:", "TXHF", "",
+ "Level", "14:", "CKJL", "",
+ "Level", "15:", "LFCK", "",
+ };
struct style_text style[] = {
- {0, TEXT_CENTER | TEXT_UNDERLINE},
- LAST_STYLE_ITEM
+ { 0, TEXT_CENTER | TEXT_UNDERLINE },
};
+
return display_text(ARRAYLEN(help_text), help_text, style, NULL, true);
}
@@ -149,19 +168,22 @@ static const struct opt_items scaling_settings[3] = {
};
static const struct opt_items rotation_settings[3] = {
- { "Disabled" , -1 },
- { "Clockwise" , -1 },
- { "Anticlockwise", -1 }
+ { "Disabled" , -1 },
+ { "Clockwise" , -1 },
+ { "Counterclockwise", -1 }
};
static void do_video_settings(struct System* sys)
{
MENUITEM_STRINGLIST(menu, "Video Settings", NULL,
"Negative",
+#ifdef SYS_MOTION_BLUR
+ "Motion Blur",
+#endif
"Scaling",
"Rotation",
"Show FPS",
- "Zoom on code",
+ "Zoom on Code",
"Back");
int sel = 0;
while(1)
@@ -171,7 +193,16 @@ static void do_video_settings(struct System* sys)
case 0:
rb->set_bool("Negative", &sys->settings.negative_enabled);
break;
+#ifdef SYS_MOTION_BLUR
+ case 1:
+ rb->set_bool("Motion Blur", &sys->settings.blur);
+ break;
+#endif
+#ifndef SYS_MOTION_BLUR
case 1:
+#else
+ case 2:
+#endif
rb->set_option("Scaling", &sys->settings.scaling_quality, INT, scaling_settings,
#ifdef HAVE_LCD_COLOR
3
@@ -186,7 +217,11 @@ static void do_video_settings(struct System* sys)
sys->settings.zoom = false;
}
break;
+#ifndef SYS_MOTION_BLUR
case 2:
+#else
+ case 3:
+#endif
rb->set_option("Rotation", &sys->settings.rotation_option, INT, rotation_settings, 3, NULL);
if(sys->settings.rotation_option &&
sys->settings.zoom)
@@ -196,45 +231,42 @@ static void do_video_settings(struct System* sys)
}
sys_rotate_keymap(sys);
break;
+#ifndef SYS_MOTION_BLUR
case 3:
+#else
+ case 4:
+#endif
rb->set_bool("Show FPS", &sys->settings.showfps);
break;
+#ifndef SYS_MOTION_BLUR
case 4:
- rb->set_bool("Zoom on code", &sys->settings.zoom);
+#else
+ case 5:
+#endif
+ rb->set_bool("Zoom on Code", &sys->settings.zoom);
/* zoom only works with scaling and rotation disabled */
- if(sys->settings.zoom &&
- ( sys->settings.scaling_quality |
- sys->settings.rotation_option))
+ if(sys->settings.zoom && (sys->settings.scaling_quality || sys->settings.rotation_option))
{
rb->splash(HZ*2, "Scaling and rotation automatically disabled.");
sys->settings.scaling_quality = 0;
sys->settings.rotation_option = 0;
}
break;
- case 5:
- rb->lcd_clear_display();
+ default:
sys_save_settings(sys);
return;
}
}
}
-#define MAX_SOUNDBUF_SIZE 512
-const struct opt_items sound_bufsize_options[] = {
- {"8 samples" , 8},
- {"16 samples" , 16},
- {"32 samples" , 32},
- {"64 samples" , 64},
- {"128 samples", 128},
- {"256 samples", 256},
- {"512 samples", 512},
-};
+#define MAX_SOUNDBUF_SIZE 256
static void do_sound_settings(struct System* sys)
{
MENUITEM_STRINGLIST(menu, "Sound Settings", NULL,
"Enabled",
"Buffer Level",
+ "Volume",
"Back",
);
int sel = 0;
@@ -246,10 +278,17 @@ static void do_sound_settings(struct System* sys)
rb->set_bool("Enabled", &sys->settings.sound_enabled);
break;
case 1:
- rb->set_option("Buffer Level", &sys->settings.sound_bufsize, INT,
- sound_bufsize_options, ARRAYLEN(sound_bufsize_options), NULL);
+ rb->set_int("Buffer Level", "samples", UNIT_INT, &sys->settings.sound_bufsize, NULL, 16, 16, MAX_SOUNDBUF_SIZE, NULL);
break;
case 2:
+ {
+ const struct settings_list* vol =
+ rb->find_setting(&rb->global_settings->volume, NULL);
+ rb->option_screen((struct settings_list*)vol, NULL, false, "Volume");
+ break;
+ }
+ case 3:
+ default:
sys_save_settings(sys);
return;
}
@@ -259,12 +298,13 @@ static void do_sound_settings(struct System* sys)
static void sys_reset_settings(struct System* sys)
{
sys->settings.negative_enabled = false;
- sys->settings.rotation_option = 0;
- sys->settings.scaling_quality = 1;
+ sys->settings.rotation_option = 0; // off
+ sys->settings.scaling_quality = 1; // fast
sys->settings.sound_enabled = true;
- sys->settings.sound_bufsize = 64;
- sys->settings.showfps = true;
+ sys->settings.sound_bufsize = 32; /* keep this low */
+ sys->settings.showfps = false;
sys->settings.zoom = false;
+ sys->settings.blur = false;
sys_rotate_keymap(sys);
}
@@ -278,18 +318,32 @@ static int mainmenu_cb(int action, const struct menu_item_ex *this_item)
return action;
}
-static AudioCallback audio_callback;
+static AudioCallback audio_callback = NULL;
+static void get_more(const void** start, size_t* size);
static void* audio_param;
static struct System* audio_sys;
/************************************** MAIN MENU ***************************************/
+/* called after game init */
void sys_menu(struct System* sys)
{
sys_stopAudio(sys);
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ /* boost for load */
+ rb->cpu_boost(true);
+#endif
+
rb->splash(0, "Loading...");
sys->loaded = engine_loadGameState(sys->e, 0);
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(false);
+#endif
+
rb->lcd_update();
+
mainmenu_sysptr = sys;
MENUITEM_STRINGLIST(menu, "XWorld Menu", mainmenu_cb,
"Resume Game", /* 0 */
@@ -352,19 +406,21 @@ void sys_menu(struct System* sys)
exit(PLUGIN_OK);
break;
default:
- error("sys_menu: fall-through!");
+ break;
}
}
- rb->lcd_clear_display();
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ /* boost for game */
+ rb->cpu_boost(true);
+#endif
+
sys_startAudio(sys, audio_callback, audio_param);
}
void sys_init(struct System* sys, const char* title)
{
(void) title;
-#ifdef HAVE_ADJUSTABLE_CPU_FREQ
- rb->cpu_boost(true);
-#endif
backlight_ignore_timeout();
rb_atexit(exit_handler);
save_sys = sys;
@@ -565,9 +621,9 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
int r, g, b;
fb_data pix = rb->lcd_framebuffer[y * LCD_WIDTH + x];
#if (LCD_DEPTH == 24)
- r = pix.r;
- g = pix.g;
- b = pix.b;
+ r = 0xff - pix.r;
+ g = 0xff - pix.g;
+ b = 0xff - pix.b;
rb->lcd_framebuffer[y * LCD_WIDTH + x] = (fb_data) { b, g, r };
#else
r = RGB_UNPACK_RED (pix);
@@ -582,6 +638,57 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
}
}
+#ifdef SYS_MOTION_BLUR
+ if(sys->settings.blur)
+ {
+ static fb_data *prev_frames = NULL;
+ static fb_data *orig_fb = NULL;
+ static int prev_baseidx = 0; /* circular buffer */
+ if(!prev_frames)
+ {
+ prev_frames = sys_get_buffer(sys, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT * BLUR_FRAMES);
+ orig_fb = sys_get_buffer(sys, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
+
+ rb->memset(prev_frames, 0, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT * BLUR_FRAMES);
+ }
+ if(prev_frames && orig_fb)
+ {
+
+ rb->memcpy(orig_fb, rb->lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
+ /* fancy useless slow motion blur */
+ for(int y = 0; y < LCD_HEIGHT; ++y)
+ {
+ for(int x = 0; x < LCD_WIDTH; ++x)
+ {
+ int r, g, b;
+ fb_data pix = rb->lcd_framebuffer[y * LCD_WIDTH + x];
+ r = RGB_UNPACK_RED (pix);
+ g = RGB_UNPACK_GREEN(pix);
+ b = RGB_UNPACK_BLUE (pix);
+ r *= BLUR_FRAMES + 1;
+ g *= BLUR_FRAMES + 1;
+ b *= BLUR_FRAMES + 1;
+ for(int i = 0; i < BLUR_FRAMES; ++i)
+ {
+ fb_data prev_pix = prev_frames[ (prev_baseidx + i * (LCD_WIDTH * LCD_HEIGHT)) % (LCD_WIDTH * LCD_HEIGHT * BLUR_FRAMES) + y * LCD_WIDTH + x];
+ r += (BLUR_FRAMES-i) * RGB_UNPACK_RED(prev_pix);
+ g += (BLUR_FRAMES-i) * RGB_UNPACK_GREEN(prev_pix);
+ b += (BLUR_FRAMES-i) * RGB_UNPACK_BLUE(prev_pix);
+ }
+ r /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1);
+ g /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1);
+ b /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1);
+ rb->lcd_framebuffer[y * LCD_WIDTH + x] = LCD_RGBPACK(r, g, b);
+ }
+ }
+ prev_baseidx -= LCD_WIDTH * LCD_HEIGHT;
+ if(prev_baseidx < 0)
+ prev_baseidx += BLUR_FRAMES * LCD_WIDTH * LCD_HEIGHT;
+ rb->memcpy(prev_frames + prev_baseidx, orig_fb, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
+ }
+ }
+#endif
+
/*********************** SHOW FPS *************************/
int current_time = sys_getTimeStamp(sys);
@@ -599,6 +706,11 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
static void do_pause_menu(struct System* sys)
{
sys_stopAudio(sys);
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(false);
+#endif
+
int sel = 0;
MENUITEM_STRINGLIST(menu, "XWorld Menu", NULL,
"Resume Game", /* 0 */
@@ -663,52 +775,130 @@ static void do_pause_menu(struct System* sys)
break;
}
}
- rb->lcd_clear_display();
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(true);
+#endif
+
sys_startAudio(sys, audio_callback, audio_param);
}
void sys_processEvents(struct System* sys)
{
- int btn = rb->button_get(false);
- btn &= ~BUTTON_REDRAW;
+ int btn = rb->button_status();
+ rb->button_clear_queue();
+
+ static int oldbuttonstate = 0;
+
debug(DBG_SYS, "button is 0x%08x", btn);
/* exit early if we can */
- if(btn == BUTTON_NONE)
+ if(btn == oldbuttonstate)
{
return;
}
+ /* handle special keys first */
+ switch(btn)
+ {
+ case BTN_PAUSE:
+ do_pause_menu(sys);
+ sys->input.dirMask = 0;
+ sys->input.button = false;
+ /* exit early to avoid unwanted button presses being detected */
+ return;
+ default:
+ exit_on_usb(btn);
+ break;
+ }
+
/* Ignore some buttons that cause errant input */
+
+ btn &= ~BUTTON_REDRAW;
+
#if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
if(btn & 0x80000000)
return;
#endif
+
#if (CONFIG_KEYPAD == SANSA_E200_PAD)
if(btn == (BUTTON_SCROLL_FWD || BUTTON_SCROLL_BACK))
return;
#endif
+
#if (CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD)
if(btn == (BUTTON_SELECT))
return;
#endif
- /* handle special keys first */
- switch(btn)
+ /* copied from doom which was copied from rockboy... */
+ unsigned released = ~btn & oldbuttonstate;
+ unsigned pressed = btn & ~oldbuttonstate;
+ oldbuttonstate = btn;
+
+ if(released)
{
- case BTN_PAUSE:
- do_pause_menu(sys);
- sys->input.dirMask = 0;
- sys->input.button = false;
- /* exit early to avoid unwanted button presses being detected */
- return;
- default:
- exit_on_usb(btn);
- break;
+ if(released & BTN_FIRE)
+ sys->input.button = false;
+ if(released & sys->keymap.up)
+ sys->input.dirMask &= ~DIR_UP;
+ if(released & sys->keymap.down)
+ sys->input.dirMask &= ~DIR_DOWN;
+ if(released & sys->keymap.left)
+ sys->input.dirMask &= ~DIR_LEFT;
+ if(released & sys->keymap.right)
+ sys->input.dirMask &= ~DIR_RIGHT;
+#ifdef BTN_DOWN_LEFT
+ if(released & sys->keymap.downleft)
+ sys->input.dirMask &= ~(DIR_DOWN | DIR_LEFT);
+#endif
+#ifdef BTN_DOWN_RIGHT
+ if(released & sys->keymap.downright)
+ sys->input.dirMask &= ~(DIR_DOWN | DIR_RIGHT);
+#endif
+#ifdef BTN_UP_LEFT
+ if(released & sys->keymap.upleft)
+ sys->input.dirMask &= ~(DIR_UP | DIR_LEFT);
+#endif
+#ifdef BTN_UP_RIGHT
+ if(released & sys->keymap.upright)
+ sys->input.dirMask &= ~(DIR_UP | DIR_RIGHT);
+#endif
+ }
+
+ if(pressed)
+ {
+ if(pressed & BTN_FIRE)
+ sys->input.button = true;
+ if(pressed & sys->keymap.up)
+ sys->input.dirMask |= DIR_UP;
+ if(pressed & sys->keymap.down)
+ sys->input.dirMask |= DIR_DOWN;
+ if(pressed & sys->keymap.left)
+ sys->input.dirMask |= DIR_LEFT;
+ if(pressed & sys->keymap.right)
+ sys->input.dirMask |= DIR_RIGHT;
+#ifdef BTN_DOWN_LEFT
+ if(pressed & sys->keymap.downleft)
+ sys->input.dirMask |= (DIR_DOWN | DIR_LEFT);
+#endif
+#ifdef BTN_DOWN_RIGHT
+ if(pressed & sys->keymap.downright)
+ sys->input.dirMask |= (DIR_DOWN | DIR_RIGHT);
+#endif
+#ifdef BTN_UP_LEFT
+ if(pressed & sys->keymap.upleft)
+ sys->input.dirMask |= (DIR_UP | DIR_LEFT);
+#endif
+#ifdef BTN_UP_RIGHT
+ if(pressed & sys->keymap.upright)
+ sys->input.dirMask |= (DIR_UP | DIR_RIGHT);
+#endif
}
+#if 0
/* handle releases */
if(btn & BUTTON_REL)
{
@@ -774,6 +964,7 @@ void sys_processEvents(struct System* sys)
}
debug(DBG_SYS, "dirMask is 0x%02x", sys->input.dirMask);
debug(DBG_SYS, "button is %s", sys->input.button == true ? "true" : "false");
+#endif
}
void sys_sleep(struct System* sys, uint32_t duration)
@@ -789,26 +980,28 @@ uint32_t sys_getTimeStamp(struct System* sys)
return (uint32_t) (*rb->current_tick * (1000/HZ));
}
-static int16_t rb_soundbuf [MAX_SOUNDBUF_SIZE] IBSS_ATTR;
-static int8_t temp_soundbuf[MAX_SOUNDBUF_SIZE] IBSS_ATTR;
-static void ICODE_ATTR get_more(const void** start, size_t* size)
+/* game provides us mono samples, we need stereo */
+static int16_t rb_soundbuf[MAX_SOUNDBUF_SIZE * 2];
+static int8_t temp_soundbuf[MAX_SOUNDBUF_SIZE];
+
+static void get_more(const void** start, size_t* size)
{
- if(audio_sys->settings.sound_enabled)
+ if(audio_sys->settings.sound_enabled && audio_callback)
{
audio_callback(audio_param, temp_soundbuf, audio_sys->settings.sound_bufsize);
- /* convert xworld format (signed 8-bit) to rockbox format (signed 16-bit) */
+
+ /* convert xworld format (signed 8-bit) to rockbox format (stereo signed 16-bit) */
for(int i = 0; i < audio_sys->settings.sound_bufsize; ++i)
{
- rb_soundbuf[i] = temp_soundbuf[i] * 0x100;
+ rb_soundbuf[2*i] = rb_soundbuf[2*i+1] = temp_soundbuf[i] * 256;
}
- *start = rb_soundbuf;
- *size = audio_sys->settings.sound_bufsize;
}
else
{
- *start = NULL;
- *size = 0;
+ rb->memset(rb_soundbuf, 0, audio_sys->settings.sound_bufsize * 2 * sizeof(int16_t));
}
+ *start = rb_soundbuf;
+ *size = audio_sys->settings.sound_bufsize * 2 * sizeof(int16_t);
}
void sys_startAudio(struct System* sys, AudioCallback callback, void *param)
@@ -817,6 +1010,7 @@ void sys_startAudio(struct System* sys, AudioCallback callback, void *param)
audio_callback = callback;
audio_param = param;
audio_sys = sys;
+
rb->pcm_play_data(get_more, NULL, NULL, 0);
}
@@ -872,13 +1066,18 @@ void *sys_createMutex(struct System* sys)
{
if(!sys)
error("sys is NULL!");
+
+ debug(DBG_SYS, "allocating mutex");
+
+ /* this bitfield works as follows: bit set = free, unset = in use */
for(int i = 0; i < MAX_MUTEXES; ++i)
{
+ /* check that the corresponding bit is 1 (free) */
if(sys->mutex_bitfield & (1 << i))
{
- rb->mutex_init(&sys->mutex_memory[i]);
- sys->mutex_bitfield |= (1 << i);
- return &sys->mutex_memory[i];
+ rb->mutex_init(sys->mutex_memory + i);
+ sys->mutex_bitfield &= ~(1 << i);
+ return sys->mutex_memory + i;
}
}
warning("Out of mutexes!");
@@ -888,20 +1087,18 @@ void *sys_createMutex(struct System* sys)
void sys_destroyMutex(struct System* sys, void *mutex)
{
int mutex_number = ((char*)mutex - (char*)sys->mutex_memory) / sizeof(struct mutex); /* pointer arithmetic! check for bugs! */
- sys->mutex_bitfield &= ~(1 << mutex_number);
+ sys->mutex_bitfield |= 1 << mutex_number;
}
void sys_lockMutex(struct System* sys, void *mutex)
{
(void) sys;
- debug(DBG_SYS, "calling mutex_lock");
rb->mutex_lock((struct mutex*) mutex);
}
void sys_unlockMutex(struct System* sys, void *mutex)
{
(void) sys;
- debug(DBG_SYS, "calling mutex_unlock");
rb->mutex_unlock((struct mutex*) mutex);
}
@@ -937,4 +1134,5 @@ void MutexStack(struct MutexStack_t* s, struct System *stub, void *mutex)
void MutexStack_destroy(struct MutexStack_t* s)
{
sys_unlockMutex(s->sys, s->_mutex);
+
}