summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/xworld/SOURCES1
-rw-r--r--apps/plugins/xworld/engine.c7
-rw-r--r--apps/plugins/xworld/intern.c34
-rw-r--r--apps/plugins/xworld/intern.h13
-rw-r--r--apps/plugins/xworld/mixer.c13
-rw-r--r--apps/plugins/xworld/resource.c14
-rw-r--r--apps/plugins/xworld/sys.c340
-rw-r--r--apps/plugins/xworld/sys.h13
-rw-r--r--apps/plugins/xworld/video_data.c3
-rw-r--r--apps/plugins/xworld/vm.c38
10 files changed, 341 insertions, 135 deletions
diff --git a/apps/plugins/xworld/SOURCES b/apps/plugins/xworld/SOURCES
index 98b5f14fb8..eb331b18f5 100644
--- a/apps/plugins/xworld/SOURCES
+++ b/apps/plugins/xworld/SOURCES
@@ -1,7 +1,6 @@
bank.c
engine.c
file.c
-intern.c
mixer.c
parts.c
resource.c
diff --git a/apps/plugins/xworld/engine.c b/apps/plugins/xworld/engine.c
index 0d1c1bfa61..3a4ddfbf4e 100644
--- a/apps/plugins/xworld/engine.c
+++ b/apps/plugins/xworld/engine.c
@@ -61,6 +61,9 @@ void engine_run(struct Engine* e) {
engine_processInput(e);
vm_hostFrame(&e->vm);
+
+ /* only yield() in the whole game :P */
+ rb->yield();
}
}
@@ -259,11 +262,11 @@ void engine_init(struct Engine* e) {
player_init(&e->player);
/* Init virtual machine, legacy way */
- /* vm_initForPart(&e->vm, GAME_PART_FIRST); // This game part is the protection screen */
+ vm_initForPart(&e->vm, GAME_PART_FIRST); // This game part is the protection screen */
/* Try to cheat here. You can jump anywhere but the VM crashes afterward. */
/* Starting somewhere is probably not enough, the variables and calls return are probably missing. */
- /* vm_initForPart(&e->vm, GAME_PART2); Skip protection screen and go directly to intro */
+ /* vm_initForPart(&e->vm, GAME_PART2); Skip protection screen and go directly to intro */
/* vm_initForPart(&e->vm, GAME_PART3); CRASH */
/* vm_initForPart(&e->vm, GAME_PART4); Start directly in jail but then crash */
/* vm->initForPart(&e->vm, GAME_PART5); CRASH */
diff --git a/apps/plugins/xworld/intern.c b/apps/plugins/xworld/intern.c
deleted file mode 100644
index 0d58100f37..0000000000
--- a/apps/plugins/xworld/intern.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2014 Franklin Wei, Benjamin Brown
- * Copyright (C) 2004 Gregory Montoir
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#include "intern.h"
-#include "awendian.h"
-
-uint8_t ICODE_ATTR scriptPtr_fetchByte(struct Ptr* p) {
- return *p->pc++;
-}
-
-uint16_t ICODE_ATTR scriptPtr_fetchWord(struct Ptr* p) {
- uint16_t i = READ_BE_UINT16(p->pc);
- p->pc += 2;
- return i;
-}
diff --git a/apps/plugins/xworld/intern.h b/apps/plugins/xworld/intern.h
index 3355f28eb1..90b640858d 100644
--- a/apps/plugins/xworld/intern.h
+++ b/apps/plugins/xworld/intern.h
@@ -34,11 +34,18 @@ struct Ptr {
uint8_t* pc;
};
-uint8_t scriptPtr_fetchByte(struct Ptr* p) ICODE_ATTR;
-uint16_t scriptPtr_fetchWord(struct Ptr* p) ICODE_ATTR;
-
struct Point {
int16_t x, y;
};
+static inline uint8_t scriptPtr_fetchByte(struct Ptr* p) {
+ return *p->pc++;
+}
+
+static inline uint16_t scriptPtr_fetchWord(struct Ptr* p) {
+ uint16_t i = READ_BE_UINT16(p->pc);
+ p->pc += 2;
+ return i;
+}
+
#endif
diff --git a/apps/plugins/xworld/mixer.c b/apps/plugins/xworld/mixer.c
index de7536cd36..6035045239 100644
--- a/apps/plugins/xworld/mixer.c
+++ b/apps/plugins/xworld/mixer.c
@@ -24,7 +24,7 @@
#include "serializer.h"
#include "sys.h"
-static int8_t ICODE_ATTR addclamp(int a, int b) {
+static int8_t addclamp(int a, int b) {
int add = a + b;
if (add < -128) {
add = -128;
@@ -121,11 +121,11 @@ void mixer_stopAll(struct Mixer* mx) {
/* Since there is no way to know when SDL will ask for a buffer fill, we need */
/* to synchronize with a mutex so the channels remain stable during the execution */
/* of this method. */
-static void ICODE_ATTR mixer_mix(struct Mixer* mx, int8_t *buf, int len) {
+static void mixer_mix(struct Mixer* mx, int8_t *buf, int len) {
int8_t *pBuf;
- struct MutexStack_t ms;
- MutexStack(&ms, mx->sys, mx->_mutex);
+ /* disabled because this will be called in IRQ */
+ /*sys_lockMutex(mx->sys, mx->_mutex);*/
/* Clear the buffer since nothing guarantees we are receiving clean memory. */
rb->memset(buf, 0, len);
@@ -170,11 +170,10 @@ static void ICODE_ATTR mixer_mix(struct Mixer* mx, int8_t *buf, int len) {
}
- MutexStack_destroy(&ms);
+ /*sys_unlockMutex(mx->sys, mx->_mutex);*/
}
-static void ICODE_ATTR mixer_mixCallback(void *param, uint8_t *buf, int len) {
- debug(DBG_SND, "mixer_mixCallback");
+static void mixer_mixCallback(void *param, uint8_t *buf, int len) {
mixer_mix((struct Mixer*)param, (int8_t *)buf, len);
}
diff --git a/apps/plugins/xworld/resource.c b/apps/plugins/xworld/resource.c
index 2820dcb998..4bd93f0616 100644
--- a/apps/plugins/xworld/resource.c
+++ b/apps/plugins/xworld/resource.c
@@ -354,12 +354,14 @@ void res_allocMemBlock(struct Resource* res) {
rb->audio_stop();
/* steal the audio buffer */
size_t sz;
- /* memory usage is as follows:
- [VM memory - 600K]
- [Framebuffers - 128K]
- [Temporary framebuffer - 192K]
- [String table buffer]
- */
+ /* memory usage is first statically allocated, then the remainder is used dynamically:
+ * static:
+ * [VM memory - 600K]
+ * [Framebuffers - 128K]
+ * [Temporary framebuffer - 192K]
+ * dynamic:
+ * [String table buffer]
+ */
res->_memPtrStart = rb->plugin_get_audio_buffer(&sz);
if(sz < MEM_BLOCK_SIZE + (4 * VID_PAGE_SIZE) + 320 * 200 * sizeof(fb_data))
{
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);
+
}
diff --git a/apps/plugins/xworld/sys.h b/apps/plugins/xworld/sys.h
index f1920acf37..20c6e859c4 100644
--- a/apps/plugins/xworld/sys.h
+++ b/apps/plugins/xworld/sys.h
@@ -23,12 +23,20 @@
#ifndef __XWORLD_SYS_H__
#define __XWORLD_SYS_H__
+#include "plugin.h"
#include "intern.h"
-#define SYS_NEGATIVE_COLOR
+#if (PLUGIN_BUFFER_SIZE >= 0x80000 && defined(HAVE_LCD_COLOR) && LCD_DEPTH < 24)
+#define SYS_MOTION_BLUR
+/* must be odd */
+#define BLUR_FRAMES 3
+#else
+#error lol
+#endif
+
#define NUM_COLORS 16
#define MAX_MUTEXES 16
-#define SETTINGS_FILE "settings.xfg"
+#define SETTINGS_FILE "settings.zfg" /* change when backwards-compatibility is broken */
#define CODE_X 80
#define CODE_Y 36
@@ -103,6 +111,7 @@ struct System {
bool sound_enabled;
int sound_bufsize;
bool zoom;
+ bool blur;
} settings;
};
diff --git a/apps/plugins/xworld/video_data.c b/apps/plugins/xworld/video_data.c
index e658c175d9..afed9e06ea 100644
--- a/apps/plugins/xworld/video_data.c
+++ b/apps/plugins/xworld/video_data.c
@@ -126,9 +126,10 @@ uint8_t video_font[FONT_SIZE] = {
0x00, 0xA0, 0x10, 0x80, 0x10, 0x80, 0x50, 0x00, /* DEL */
};
+/* default bogus strings */
struct StrEntry video_stringsTableEng[MAX_STRING_TABLE_SIZE] = {
{ 0x001, "B A N A N A 2000" },
- { 0x002, "Copyright } 2014 Banana Corporation \nGPLv2\n\nBUNIX Revision 3.14" },
+ { 0x002, "Copyright } 2016 Franklin Wei\nGPLv2\n\nBUNIX Revision 3.14" },
{ 0x003, "1" },
{ 0x004, "3" },
{ 0x005, "." },
diff --git a/apps/plugins/xworld/vm.c b/apps/plugins/xworld/vm.c
index de632d710d..10c3957ad7 100644
--- a/apps/plugins/xworld/vm.c
+++ b/apps/plugins/xworld/vm.c
@@ -52,7 +52,13 @@ void vm_init(struct VirtualMachine* m) {
rb->memset(m->vmVariables, 0, sizeof(m->vmVariables));
m->vmVariables[0x54] = 0x81;
- m->vmVariables[VM_VARIABLE_RANDOM_SEED] = *rb->current_tick;
+ m->vmVariables[VM_VARIABLE_RANDOM_SEED] = *rb->current_tick % 0x10000;
+
+ /* rawgl has these, but they don't seem to do anything */
+ //m->vmVariables[0xBC] = 0x10;
+ //m->vmVariables[0xC6] = 0x80;
+ //m->vmVariables[0xF2] = 4000;
+ //m->vmVariables[0xDC] = 33;
m->_fastMode = false;
m->player->_markVar = &m->vmVariables[VM_VARIABLE_MUS_MARK];
@@ -81,7 +87,7 @@ void vm_op_add(struct VirtualMachine* m) {
void vm_op_addConst(struct VirtualMachine* m) {
if (m->res->currentPartId == 0x3E86 && m->_scriptPtr.pc == m->res->segBytecode + 0x6D48) {
- warning("vm_op_addConst() hack for non-stop looping gun sound bug");
+ //warning("vm_op_addConst() hack for non-stop looping gun sound bug");
// the script 0x27 slot 0x17 doesn't stop the gun sound from looping, I
// don't really know why ; for now, let's play the 'stopping sound' like
// the other scripts do
@@ -152,10 +158,9 @@ void vm_op_jnz(struct VirtualMachine* m) {
#define BYPASS_PROTECTION
void vm_op_condJmp(struct VirtualMachine* m) {
- //printf("Jump : %X \n",m->_scriptPtr.pc-m->res->segBytecode);
+ //debug(DBG_VM, "Jump : %X \n",m->_scriptPtr.pc-m->res->segBytecode);
//FCS Whoever wrote this is patching the bytecode on the fly. This is ballzy !!
-#ifdef BYPASS_PROTECTION
-
+#if 0
if (m->res->currentPartId == GAME_PART_FIRST && m->_scriptPtr.pc == m->res->segBytecode + 0xCB9) {
// (0x0CB8) condJmp(0x80, VAR(41), VAR(30), 0xCD3)
@@ -168,6 +173,8 @@ void vm_op_condJmp(struct VirtualMachine* m) {
debug(DBG_VM, "vm_op_condJmp() bypassing protection");
debug(DBG_VM, "bytecode has been patched");
+ //warning("bypassing protection");
+
//vm_bypassProtection(m);
}
@@ -175,7 +182,8 @@ void vm_op_condJmp(struct VirtualMachine* m) {
#endif
uint8_t opcode = scriptPtr_fetchByte(&m->_scriptPtr);
- int16_t b = m->vmVariables[scriptPtr_fetchByte(&m->_scriptPtr)];
+ uint8_t var = scriptPtr_fetchByte(&m->_scriptPtr);
+ int16_t b = m->vmVariables[var];
uint8_t c = scriptPtr_fetchByte(&m->_scriptPtr);
int16_t a;
@@ -193,6 +201,22 @@ void vm_op_condJmp(struct VirtualMachine* m) {
switch (opcode & 7) {
case 0: // jz
expr = (b == a);
+
+#ifdef BYPASS_PROTECTION
+ /* always succeed in code wheel verification */
+ if (m->res->currentPartId == GAME_PART_FIRST && var == 0x29 && (opcode & 0x80) != 0) {
+
+ m->vmVariables[0x29] = m->vmVariables[0x1E];
+ m->vmVariables[0x2A] = m->vmVariables[0x1F];
+ m->vmVariables[0x2B] = m->vmVariables[0x20];
+ m->vmVariables[0x2C] = m->vmVariables[0x21];
+ // counters
+ m->vmVariables[0x32] = 6;
+ m->vmVariables[0x64] = 20;
+ expr = true;
+ //warning("Script::op_condJmp() bypassing protection");
+ }
+#endif
break;
case 1: // jnz
expr = (b != a);
@@ -605,8 +629,6 @@ void vm_executeThread(struct VirtualMachine* m) {
{
(vm_opcodeTable[opcode])(m);
}
-
- rb->yield();
}
}