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 @@
1bank.c 1bank.c
2engine.c 2engine.c
3file.c 3file.c
4intern.c
5mixer.c 4mixer.c
6parts.c 5parts.c
7resource.c 6resource.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) {
61 engine_processInput(e); 61 engine_processInput(e);
62 62
63 vm_hostFrame(&e->vm); 63 vm_hostFrame(&e->vm);
64
65 /* only yield() in the whole game :P */
66 rb->yield();
64 } 67 }
65 68
66} 69}
@@ -259,11 +262,11 @@ void engine_init(struct Engine* e) {
259 player_init(&e->player); 262 player_init(&e->player);
260 263
261 /* Init virtual machine, legacy way */ 264 /* Init virtual machine, legacy way */
262 /* vm_initForPart(&e->vm, GAME_PART_FIRST); // This game part is the protection screen */ 265 vm_initForPart(&e->vm, GAME_PART_FIRST); // This game part is the protection screen */
263 266
264 /* Try to cheat here. You can jump anywhere but the VM crashes afterward. */ 267 /* Try to cheat here. You can jump anywhere but the VM crashes afterward. */
265 /* Starting somewhere is probably not enough, the variables and calls return are probably missing. */ 268 /* Starting somewhere is probably not enough, the variables and calls return are probably missing. */
266 /* vm_initForPart(&e->vm, GAME_PART2); Skip protection screen and go directly to intro */ 269 /* vm_initForPart(&e->vm, GAME_PART2); Skip protection screen and go directly to intro */
267 /* vm_initForPart(&e->vm, GAME_PART3); CRASH */ 270 /* vm_initForPart(&e->vm, GAME_PART3); CRASH */
268 /* vm_initForPart(&e->vm, GAME_PART4); Start directly in jail but then crash */ 271 /* vm_initForPart(&e->vm, GAME_PART4); Start directly in jail but then crash */
269 /* vm->initForPart(&e->vm, GAME_PART5); CRASH */ 272 /* 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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 Franklin Wei, Benjamin Brown
11 * Copyright (C) 2004 Gregory Montoir
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "intern.h"
24#include "awendian.h"
25
26uint8_t ICODE_ATTR scriptPtr_fetchByte(struct Ptr* p) {
27 return *p->pc++;
28}
29
30uint16_t ICODE_ATTR scriptPtr_fetchWord(struct Ptr* p) {
31 uint16_t i = READ_BE_UINT16(p->pc);
32 p->pc += 2;
33 return i;
34}
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 {
34 uint8_t* pc; 34 uint8_t* pc;
35}; 35};
36 36
37uint8_t scriptPtr_fetchByte(struct Ptr* p) ICODE_ATTR;
38uint16_t scriptPtr_fetchWord(struct Ptr* p) ICODE_ATTR;
39
40struct Point { 37struct Point {
41 int16_t x, y; 38 int16_t x, y;
42}; 39};
43 40
41static inline uint8_t scriptPtr_fetchByte(struct Ptr* p) {
42 return *p->pc++;
43}
44
45static inline uint16_t scriptPtr_fetchWord(struct Ptr* p) {
46 uint16_t i = READ_BE_UINT16(p->pc);
47 p->pc += 2;
48 return i;
49}
50
44#endif 51#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 @@
24#include "serializer.h" 24#include "serializer.h"
25#include "sys.h" 25#include "sys.h"
26 26
27static int8_t ICODE_ATTR addclamp(int a, int b) { 27static int8_t addclamp(int a, int b) {
28 int add = a + b; 28 int add = a + b;
29 if (add < -128) { 29 if (add < -128) {
30 add = -128; 30 add = -128;
@@ -121,11 +121,11 @@ void mixer_stopAll(struct Mixer* mx) {
121/* Since there is no way to know when SDL will ask for a buffer fill, we need */ 121/* Since there is no way to know when SDL will ask for a buffer fill, we need */
122/* to synchronize with a mutex so the channels remain stable during the execution */ 122/* to synchronize with a mutex so the channels remain stable during the execution */
123/* of this method. */ 123/* of this method. */
124static void ICODE_ATTR mixer_mix(struct Mixer* mx, int8_t *buf, int len) { 124static void mixer_mix(struct Mixer* mx, int8_t *buf, int len) {
125 int8_t *pBuf; 125 int8_t *pBuf;
126 126
127 struct MutexStack_t ms; 127 /* disabled because this will be called in IRQ */
128 MutexStack(&ms, mx->sys, mx->_mutex); 128 /*sys_lockMutex(mx->sys, mx->_mutex);*/
129 129
130 /* Clear the buffer since nothing guarantees we are receiving clean memory. */ 130 /* Clear the buffer since nothing guarantees we are receiving clean memory. */
131 rb->memset(buf, 0, len); 131 rb->memset(buf, 0, len);
@@ -170,11 +170,10 @@ static void ICODE_ATTR mixer_mix(struct Mixer* mx, int8_t *buf, int len) {
170 170
171 } 171 }
172 172
173 MutexStack_destroy(&ms); 173 /*sys_unlockMutex(mx->sys, mx->_mutex);*/
174} 174}
175 175
176static void ICODE_ATTR mixer_mixCallback(void *param, uint8_t *buf, int len) { 176static void mixer_mixCallback(void *param, uint8_t *buf, int len) {
177 debug(DBG_SND, "mixer_mixCallback");
178 mixer_mix((struct Mixer*)param, (int8_t *)buf, len); 177 mixer_mix((struct Mixer*)param, (int8_t *)buf, len);
179} 178}
180 179
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) {
354 rb->audio_stop(); 354 rb->audio_stop();
355 /* steal the audio buffer */ 355 /* steal the audio buffer */
356 size_t sz; 356 size_t sz;
357 /* memory usage is as follows: 357 /* memory usage is first statically allocated, then the remainder is used dynamically:
358 [VM memory - 600K] 358 * static:
359 [Framebuffers - 128K] 359 * [VM memory - 600K]
360 [Temporary framebuffer - 192K] 360 * [Framebuffers - 128K]
361 [String table buffer] 361 * [Temporary framebuffer - 192K]
362 */ 362 * dynamic:
363 * [String table buffer]
364 */
363 res->_memPtrStart = rb->plugin_get_audio_buffer(&sz); 365 res->_memPtrStart = rb->plugin_get_audio_buffer(&sz);
364 if(sz < MEM_BLOCK_SIZE + (4 * VID_PAGE_SIZE) + 320 * 200 * sizeof(fb_data)) 366 if(sz < MEM_BLOCK_SIZE + (4 * VID_PAGE_SIZE) + 320 * 200 * sizeof(fb_data))
365 { 367 {
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)
130 rb->lcd_set_background(LCD_BLACK); 130 rb->lcd_set_background(LCD_BLACK);
131#endif 131#endif
132 rb->lcd_setfont(FONT_UI); 132 rb->lcd_setfont(FONT_UI);
133 char* help_text[] = {"XWorld", "", 133 char *help_text[] = {
134 "XWorld", "is", "an", "interpreter", "for", "Another", "World,", "a", "fantastic", "game", "by", "Eric", "Chahi." 134 "XWorld", "",
135 }; 135 "XWorld", "is", "a", "port", "of", "a", "bytecode", "interpreter", "for", "`Another", "World',", "a", "cinematic", "adventure", "game", "by", "Eric", "Chahi.",
136 "",
137 "",
138 "Level", "Codes:", "",
139 "Level", "1:", "LDKD", "",
140 "Level", "2:", "HTDC", "",
141 "Level", "3:", "CLLD", "",
142 "Level", "4:", "LBKG", "",
143 "Level", "5:", "XDDJ", "",
144 "Level", "6:", "FXLC", "",
145 "Level", "7:", "KRFK", "",
146 "Level", "8:", "KFLB", "",
147 "Level", "9:", "DDRX", "",
148 "Level", "10:", "BFLX", "",
149 "Level", "11:", "BRTD", "",
150 "Level", "12:", "TFBB", "",
151 "Level", "13:", "TXHF", "",
152 "Level", "14:", "CKJL", "",
153 "Level", "15:", "LFCK", "",
154 };
136 struct style_text style[] = { 155 struct style_text style[] = {
137 {0, TEXT_CENTER | TEXT_UNDERLINE}, 156 { 0, TEXT_CENTER | TEXT_UNDERLINE },
138 LAST_STYLE_ITEM
139 }; 157 };
158
140 return display_text(ARRAYLEN(help_text), help_text, style, NULL, true); 159 return display_text(ARRAYLEN(help_text), help_text, style, NULL, true);
141} 160}
142 161
@@ -149,19 +168,22 @@ static const struct opt_items scaling_settings[3] = {
149}; 168};
150 169
151static const struct opt_items rotation_settings[3] = { 170static const struct opt_items rotation_settings[3] = {
152 { "Disabled" , -1 }, 171 { "Disabled" , -1 },
153 { "Clockwise" , -1 }, 172 { "Clockwise" , -1 },
154 { "Anticlockwise", -1 } 173 { "Counterclockwise", -1 }
155}; 174};
156 175
157static void do_video_settings(struct System* sys) 176static void do_video_settings(struct System* sys)
158{ 177{
159 MENUITEM_STRINGLIST(menu, "Video Settings", NULL, 178 MENUITEM_STRINGLIST(menu, "Video Settings", NULL,
160 "Negative", 179 "Negative",
180#ifdef SYS_MOTION_BLUR
181 "Motion Blur",
182#endif
161 "Scaling", 183 "Scaling",
162 "Rotation", 184 "Rotation",
163 "Show FPS", 185 "Show FPS",
164 "Zoom on code", 186 "Zoom on Code",
165 "Back"); 187 "Back");
166 int sel = 0; 188 int sel = 0;
167 while(1) 189 while(1)
@@ -171,7 +193,16 @@ static void do_video_settings(struct System* sys)
171 case 0: 193 case 0:
172 rb->set_bool("Negative", &sys->settings.negative_enabled); 194 rb->set_bool("Negative", &sys->settings.negative_enabled);
173 break; 195 break;
196#ifdef SYS_MOTION_BLUR
197 case 1:
198 rb->set_bool("Motion Blur", &sys->settings.blur);
199 break;
200#endif
201#ifndef SYS_MOTION_BLUR
174 case 1: 202 case 1:
203#else
204 case 2:
205#endif
175 rb->set_option("Scaling", &sys->settings.scaling_quality, INT, scaling_settings, 206 rb->set_option("Scaling", &sys->settings.scaling_quality, INT, scaling_settings,
176#ifdef HAVE_LCD_COLOR 207#ifdef HAVE_LCD_COLOR
177 3 208 3
@@ -186,7 +217,11 @@ static void do_video_settings(struct System* sys)
186 sys->settings.zoom = false; 217 sys->settings.zoom = false;
187 } 218 }
188 break; 219 break;
220#ifndef SYS_MOTION_BLUR
189 case 2: 221 case 2:
222#else
223 case 3:
224#endif
190 rb->set_option("Rotation", &sys->settings.rotation_option, INT, rotation_settings, 3, NULL); 225 rb->set_option("Rotation", &sys->settings.rotation_option, INT, rotation_settings, 3, NULL);
191 if(sys->settings.rotation_option && 226 if(sys->settings.rotation_option &&
192 sys->settings.zoom) 227 sys->settings.zoom)
@@ -196,45 +231,42 @@ static void do_video_settings(struct System* sys)
196 } 231 }
197 sys_rotate_keymap(sys); 232 sys_rotate_keymap(sys);
198 break; 233 break;
234#ifndef SYS_MOTION_BLUR
199 case 3: 235 case 3:
236#else
237 case 4:
238#endif
200 rb->set_bool("Show FPS", &sys->settings.showfps); 239 rb->set_bool("Show FPS", &sys->settings.showfps);
201 break; 240 break;
241#ifndef SYS_MOTION_BLUR
202 case 4: 242 case 4:
203 rb->set_bool("Zoom on code", &sys->settings.zoom); 243#else
244 case 5:
245#endif
246 rb->set_bool("Zoom on Code", &sys->settings.zoom);
204 /* zoom only works with scaling and rotation disabled */ 247 /* zoom only works with scaling and rotation disabled */
205 if(sys->settings.zoom && 248 if(sys->settings.zoom && (sys->settings.scaling_quality || sys->settings.rotation_option))
206 ( sys->settings.scaling_quality |
207 sys->settings.rotation_option))
208 { 249 {
209 rb->splash(HZ*2, "Scaling and rotation automatically disabled."); 250 rb->splash(HZ*2, "Scaling and rotation automatically disabled.");
210 sys->settings.scaling_quality = 0; 251 sys->settings.scaling_quality = 0;
211 sys->settings.rotation_option = 0; 252 sys->settings.rotation_option = 0;
212 } 253 }
213 break; 254 break;
214 case 5: 255 default:
215 rb->lcd_clear_display();
216 sys_save_settings(sys); 256 sys_save_settings(sys);
217 return; 257 return;
218 } 258 }
219 } 259 }
220} 260}
221 261
222#define MAX_SOUNDBUF_SIZE 512 262#define MAX_SOUNDBUF_SIZE 256
223const struct opt_items sound_bufsize_options[] = {
224 {"8 samples" , 8},
225 {"16 samples" , 16},
226 {"32 samples" , 32},
227 {"64 samples" , 64},
228 {"128 samples", 128},
229 {"256 samples", 256},
230 {"512 samples", 512},
231};
232 263
233static void do_sound_settings(struct System* sys) 264static void do_sound_settings(struct System* sys)
234{ 265{
235 MENUITEM_STRINGLIST(menu, "Sound Settings", NULL, 266 MENUITEM_STRINGLIST(menu, "Sound Settings", NULL,
236 "Enabled", 267 "Enabled",
237 "Buffer Level", 268 "Buffer Level",
269 "Volume",
238 "Back", 270 "Back",
239 ); 271 );
240 int sel = 0; 272 int sel = 0;
@@ -246,10 +278,17 @@ static void do_sound_settings(struct System* sys)
246 rb->set_bool("Enabled", &sys->settings.sound_enabled); 278 rb->set_bool("Enabled", &sys->settings.sound_enabled);
247 break; 279 break;
248 case 1: 280 case 1:
249 rb->set_option("Buffer Level", &sys->settings.sound_bufsize, INT, 281 rb->set_int("Buffer Level", "samples", UNIT_INT, &sys->settings.sound_bufsize, NULL, 16, 16, MAX_SOUNDBUF_SIZE, NULL);
250 sound_bufsize_options, ARRAYLEN(sound_bufsize_options), NULL);
251 break; 282 break;
252 case 2: 283 case 2:
284 {
285 const struct settings_list* vol =
286 rb->find_setting(&rb->global_settings->volume, NULL);
287 rb->option_screen((struct settings_list*)vol, NULL, false, "Volume");
288 break;
289 }
290 case 3:
291 default:
253 sys_save_settings(sys); 292 sys_save_settings(sys);
254 return; 293 return;
255 } 294 }
@@ -259,12 +298,13 @@ static void do_sound_settings(struct System* sys)
259static void sys_reset_settings(struct System* sys) 298static void sys_reset_settings(struct System* sys)
260{ 299{
261 sys->settings.negative_enabled = false; 300 sys->settings.negative_enabled = false;
262 sys->settings.rotation_option = 0; 301 sys->settings.rotation_option = 0; // off
263 sys->settings.scaling_quality = 1; 302 sys->settings.scaling_quality = 1; // fast
264 sys->settings.sound_enabled = true; 303 sys->settings.sound_enabled = true;
265 sys->settings.sound_bufsize = 64; 304 sys->settings.sound_bufsize = 32; /* keep this low */
266 sys->settings.showfps = true; 305 sys->settings.showfps = false;
267 sys->settings.zoom = false; 306 sys->settings.zoom = false;
307 sys->settings.blur = false;
268 sys_rotate_keymap(sys); 308 sys_rotate_keymap(sys);
269} 309}
270 310
@@ -278,18 +318,32 @@ static int mainmenu_cb(int action, const struct menu_item_ex *this_item)
278 return action; 318 return action;
279} 319}
280 320
281static AudioCallback audio_callback; 321static AudioCallback audio_callback = NULL;
322static void get_more(const void** start, size_t* size);
282static void* audio_param; 323static void* audio_param;
283static struct System* audio_sys; 324static struct System* audio_sys;
284 325
285/************************************** MAIN MENU ***************************************/ 326/************************************** MAIN MENU ***************************************/
327/* called after game init */
286 328
287void sys_menu(struct System* sys) 329void sys_menu(struct System* sys)
288{ 330{
289 sys_stopAudio(sys); 331 sys_stopAudio(sys);
332
333#ifdef HAVE_ADJUSTABLE_CPU_FREQ
334 /* boost for load */
335 rb->cpu_boost(true);
336#endif
337
290 rb->splash(0, "Loading..."); 338 rb->splash(0, "Loading...");
291 sys->loaded = engine_loadGameState(sys->e, 0); 339 sys->loaded = engine_loadGameState(sys->e, 0);
340
341#ifdef HAVE_ADJUSTABLE_CPU_FREQ
342 rb->cpu_boost(false);
343#endif
344
292 rb->lcd_update(); 345 rb->lcd_update();
346
293 mainmenu_sysptr = sys; 347 mainmenu_sysptr = sys;
294 MENUITEM_STRINGLIST(menu, "XWorld Menu", mainmenu_cb, 348 MENUITEM_STRINGLIST(menu, "XWorld Menu", mainmenu_cb,
295 "Resume Game", /* 0 */ 349 "Resume Game", /* 0 */
@@ -352,19 +406,21 @@ void sys_menu(struct System* sys)
352 exit(PLUGIN_OK); 406 exit(PLUGIN_OK);
353 break; 407 break;
354 default: 408 default:
355 error("sys_menu: fall-through!"); 409 break;
356 } 410 }
357 } 411 }
358 rb->lcd_clear_display(); 412
413#ifdef HAVE_ADJUSTABLE_CPU_FREQ
414 /* boost for game */
415 rb->cpu_boost(true);
416#endif
417
359 sys_startAudio(sys, audio_callback, audio_param); 418 sys_startAudio(sys, audio_callback, audio_param);
360} 419}
361 420
362void sys_init(struct System* sys, const char* title) 421void sys_init(struct System* sys, const char* title)
363{ 422{
364 (void) title; 423 (void) title;
365#ifdef HAVE_ADJUSTABLE_CPU_FREQ
366 rb->cpu_boost(true);
367#endif
368 backlight_ignore_timeout(); 424 backlight_ignore_timeout();
369 rb_atexit(exit_handler); 425 rb_atexit(exit_handler);
370 save_sys = sys; 426 save_sys = sys;
@@ -565,9 +621,9 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
565 int r, g, b; 621 int r, g, b;
566 fb_data pix = rb->lcd_framebuffer[y * LCD_WIDTH + x]; 622 fb_data pix = rb->lcd_framebuffer[y * LCD_WIDTH + x];
567#if (LCD_DEPTH == 24) 623#if (LCD_DEPTH == 24)
568 r = pix.r; 624 r = 0xff - pix.r;
569 g = pix.g; 625 g = 0xff - pix.g;
570 b = pix.b; 626 b = 0xff - pix.b;
571 rb->lcd_framebuffer[y * LCD_WIDTH + x] = (fb_data) { b, g, r }; 627 rb->lcd_framebuffer[y * LCD_WIDTH + x] = (fb_data) { b, g, r };
572#else 628#else
573 r = RGB_UNPACK_RED (pix); 629 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
582 } 638 }
583 } 639 }
584 640
641#ifdef SYS_MOTION_BLUR
642 if(sys->settings.blur)
643 {
644 static fb_data *prev_frames = NULL;
645 static fb_data *orig_fb = NULL;
646 static int prev_baseidx = 0; /* circular buffer */
647 if(!prev_frames)
648 {
649 prev_frames = sys_get_buffer(sys, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT * BLUR_FRAMES);
650 orig_fb = sys_get_buffer(sys, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
651
652 rb->memset(prev_frames, 0, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT * BLUR_FRAMES);
653 }
654 if(prev_frames && orig_fb)
655 {
656
657 rb->memcpy(orig_fb, rb->lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
658 /* fancy useless slow motion blur */
659 for(int y = 0; y < LCD_HEIGHT; ++y)
660 {
661 for(int x = 0; x < LCD_WIDTH; ++x)
662 {
663 int r, g, b;
664 fb_data pix = rb->lcd_framebuffer[y * LCD_WIDTH + x];
665 r = RGB_UNPACK_RED (pix);
666 g = RGB_UNPACK_GREEN(pix);
667 b = RGB_UNPACK_BLUE (pix);
668 r *= BLUR_FRAMES + 1;
669 g *= BLUR_FRAMES + 1;
670 b *= BLUR_FRAMES + 1;
671 for(int i = 0; i < BLUR_FRAMES; ++i)
672 {
673 fb_data prev_pix = prev_frames[ (prev_baseidx + i * (LCD_WIDTH * LCD_HEIGHT)) % (LCD_WIDTH * LCD_HEIGHT * BLUR_FRAMES) + y * LCD_WIDTH + x];
674 r += (BLUR_FRAMES-i) * RGB_UNPACK_RED(prev_pix);
675 g += (BLUR_FRAMES-i) * RGB_UNPACK_GREEN(prev_pix);
676 b += (BLUR_FRAMES-i) * RGB_UNPACK_BLUE(prev_pix);
677 }
678 r /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1);
679 g /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1);
680 b /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1);
681 rb->lcd_framebuffer[y * LCD_WIDTH + x] = LCD_RGBPACK(r, g, b);
682 }
683 }
684 prev_baseidx -= LCD_WIDTH * LCD_HEIGHT;
685 if(prev_baseidx < 0)
686 prev_baseidx += BLUR_FRAMES * LCD_WIDTH * LCD_HEIGHT;
687 rb->memcpy(prev_frames + prev_baseidx, orig_fb, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
688 }
689 }
690#endif
691
585 /*********************** SHOW FPS *************************/ 692 /*********************** SHOW FPS *************************/
586 693
587 int current_time = sys_getTimeStamp(sys); 694 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
599static void do_pause_menu(struct System* sys) 706static void do_pause_menu(struct System* sys)
600{ 707{
601 sys_stopAudio(sys); 708 sys_stopAudio(sys);
709
710#ifdef HAVE_ADJUSTABLE_CPU_FREQ
711 rb->cpu_boost(false);
712#endif
713
602 int sel = 0; 714 int sel = 0;
603 MENUITEM_STRINGLIST(menu, "XWorld Menu", NULL, 715 MENUITEM_STRINGLIST(menu, "XWorld Menu", NULL,
604 "Resume Game", /* 0 */ 716 "Resume Game", /* 0 */
@@ -663,52 +775,130 @@ static void do_pause_menu(struct System* sys)
663 break; 775 break;
664 } 776 }
665 } 777 }
666 rb->lcd_clear_display(); 778
779#ifdef HAVE_ADJUSTABLE_CPU_FREQ
780 rb->cpu_boost(true);
781#endif
782
667 sys_startAudio(sys, audio_callback, audio_param); 783 sys_startAudio(sys, audio_callback, audio_param);
668} 784}
669 785
670void sys_processEvents(struct System* sys) 786void sys_processEvents(struct System* sys)
671{ 787{
672 int btn = rb->button_get(false); 788 int btn = rb->button_status();
673 btn &= ~BUTTON_REDRAW; 789 rb->button_clear_queue();
790
791 static int oldbuttonstate = 0;
792
674 debug(DBG_SYS, "button is 0x%08x", btn); 793 debug(DBG_SYS, "button is 0x%08x", btn);
675 794
676 /* exit early if we can */ 795 /* exit early if we can */
677 if(btn == BUTTON_NONE) 796 if(btn == oldbuttonstate)
678 { 797 {
679 return; 798 return;
680 } 799 }
681 800
801 /* handle special keys first */
802 switch(btn)
803 {
804 case BTN_PAUSE:
805 do_pause_menu(sys);
806 sys->input.dirMask = 0;
807 sys->input.button = false;
808 /* exit early to avoid unwanted button presses being detected */
809 return;
810 default:
811 exit_on_usb(btn);
812 break;
813 }
814
682 /* Ignore some buttons that cause errant input */ 815 /* Ignore some buttons that cause errant input */
816
817 btn &= ~BUTTON_REDRAW;
818
683#if (CONFIG_KEYPAD == IPOD_4G_PAD) || \ 819#if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
684 (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 820 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
685 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 821 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
686 if(btn & 0x80000000) 822 if(btn & 0x80000000)
687 return; 823 return;
688#endif 824#endif
825
689#if (CONFIG_KEYPAD == SANSA_E200_PAD) 826#if (CONFIG_KEYPAD == SANSA_E200_PAD)
690 if(btn == (BUTTON_SCROLL_FWD || BUTTON_SCROLL_BACK)) 827 if(btn == (BUTTON_SCROLL_FWD || BUTTON_SCROLL_BACK))
691 return; 828 return;
692#endif 829#endif
830
693#if (CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD) 831#if (CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD)
694 if(btn == (BUTTON_SELECT)) 832 if(btn == (BUTTON_SELECT))
695 return; 833 return;
696#endif 834#endif
697 835
698 /* handle special keys first */ 836 /* copied from doom which was copied from rockboy... */
699 switch(btn) 837 unsigned released = ~btn & oldbuttonstate;
838 unsigned pressed = btn & ~oldbuttonstate;
839 oldbuttonstate = btn;
840
841 if(released)
700 { 842 {
701 case BTN_PAUSE: 843 if(released & BTN_FIRE)
702 do_pause_menu(sys); 844 sys->input.button = false;
703 sys->input.dirMask = 0; 845 if(released & sys->keymap.up)
704 sys->input.button = false; 846 sys->input.dirMask &= ~DIR_UP;
705 /* exit early to avoid unwanted button presses being detected */ 847 if(released & sys->keymap.down)
706 return; 848 sys->input.dirMask &= ~DIR_DOWN;
707 default: 849 if(released & sys->keymap.left)
708 exit_on_usb(btn); 850 sys->input.dirMask &= ~DIR_LEFT;
709 break; 851 if(released & sys->keymap.right)
852 sys->input.dirMask &= ~DIR_RIGHT;
853#ifdef BTN_DOWN_LEFT
854 if(released & sys->keymap.downleft)
855 sys->input.dirMask &= ~(DIR_DOWN | DIR_LEFT);
856#endif
857#ifdef BTN_DOWN_RIGHT
858 if(released & sys->keymap.downright)
859 sys->input.dirMask &= ~(DIR_DOWN | DIR_RIGHT);
860#endif
861#ifdef BTN_UP_LEFT
862 if(released & sys->keymap.upleft)
863 sys->input.dirMask &= ~(DIR_UP | DIR_LEFT);
864#endif
865#ifdef BTN_UP_RIGHT
866 if(released & sys->keymap.upright)
867 sys->input.dirMask &= ~(DIR_UP | DIR_RIGHT);
868#endif
869 }
870
871 if(pressed)
872 {
873 if(pressed & BTN_FIRE)
874 sys->input.button = true;
875 if(pressed & sys->keymap.up)
876 sys->input.dirMask |= DIR_UP;
877 if(pressed & sys->keymap.down)
878 sys->input.dirMask |= DIR_DOWN;
879 if(pressed & sys->keymap.left)
880 sys->input.dirMask |= DIR_LEFT;
881 if(pressed & sys->keymap.right)
882 sys->input.dirMask |= DIR_RIGHT;
883#ifdef BTN_DOWN_LEFT
884 if(pressed & sys->keymap.downleft)
885 sys->input.dirMask |= (DIR_DOWN | DIR_LEFT);
886#endif
887#ifdef BTN_DOWN_RIGHT
888 if(pressed & sys->keymap.downright)
889 sys->input.dirMask |= (DIR_DOWN | DIR_RIGHT);
890#endif
891#ifdef BTN_UP_LEFT
892 if(pressed & sys->keymap.upleft)
893 sys->input.dirMask |= (DIR_UP | DIR_LEFT);
894#endif
895#ifdef BTN_UP_RIGHT
896 if(pressed & sys->keymap.upright)
897 sys->input.dirMask |= (DIR_UP | DIR_RIGHT);
898#endif
710 } 899 }
711 900
901#if 0
712 /* handle releases */ 902 /* handle releases */
713 if(btn & BUTTON_REL) 903 if(btn & BUTTON_REL)
714 { 904 {
@@ -774,6 +964,7 @@ void sys_processEvents(struct System* sys)
774 } 964 }
775 debug(DBG_SYS, "dirMask is 0x%02x", sys->input.dirMask); 965 debug(DBG_SYS, "dirMask is 0x%02x", sys->input.dirMask);
776 debug(DBG_SYS, "button is %s", sys->input.button == true ? "true" : "false"); 966 debug(DBG_SYS, "button is %s", sys->input.button == true ? "true" : "false");
967#endif
777} 968}
778 969
779void sys_sleep(struct System* sys, uint32_t duration) 970void sys_sleep(struct System* sys, uint32_t duration)
@@ -789,26 +980,28 @@ uint32_t sys_getTimeStamp(struct System* sys)
789 return (uint32_t) (*rb->current_tick * (1000/HZ)); 980 return (uint32_t) (*rb->current_tick * (1000/HZ));
790} 981}
791 982
792static int16_t rb_soundbuf [MAX_SOUNDBUF_SIZE] IBSS_ATTR; 983/* game provides us mono samples, we need stereo */
793static int8_t temp_soundbuf[MAX_SOUNDBUF_SIZE] IBSS_ATTR; 984static int16_t rb_soundbuf[MAX_SOUNDBUF_SIZE * 2];
794static void ICODE_ATTR get_more(const void** start, size_t* size) 985static int8_t temp_soundbuf[MAX_SOUNDBUF_SIZE];
986
987static void get_more(const void** start, size_t* size)
795{ 988{
796 if(audio_sys->settings.sound_enabled) 989 if(audio_sys->settings.sound_enabled && audio_callback)
797 { 990 {
798 audio_callback(audio_param, temp_soundbuf, audio_sys->settings.sound_bufsize); 991 audio_callback(audio_param, temp_soundbuf, audio_sys->settings.sound_bufsize);
799 /* convert xworld format (signed 8-bit) to rockbox format (signed 16-bit) */ 992
993 /* convert xworld format (signed 8-bit) to rockbox format (stereo signed 16-bit) */
800 for(int i = 0; i < audio_sys->settings.sound_bufsize; ++i) 994 for(int i = 0; i < audio_sys->settings.sound_bufsize; ++i)
801 { 995 {
802 rb_soundbuf[i] = temp_soundbuf[i] * 0x100; 996 rb_soundbuf[2*i] = rb_soundbuf[2*i+1] = temp_soundbuf[i] * 256;
803 } 997 }
804 *start = rb_soundbuf;
805 *size = audio_sys->settings.sound_bufsize;
806 } 998 }
807 else 999 else
808 { 1000 {
809 *start = NULL; 1001 rb->memset(rb_soundbuf, 0, audio_sys->settings.sound_bufsize * 2 * sizeof(int16_t));
810 *size = 0;
811 } 1002 }
1003 *start = rb_soundbuf;
1004 *size = audio_sys->settings.sound_bufsize * 2 * sizeof(int16_t);
812} 1005}
813 1006
814void sys_startAudio(struct System* sys, AudioCallback callback, void *param) 1007void sys_startAudio(struct System* sys, AudioCallback callback, void *param)
@@ -817,6 +1010,7 @@ void sys_startAudio(struct System* sys, AudioCallback callback, void *param)
817 audio_callback = callback; 1010 audio_callback = callback;
818 audio_param = param; 1011 audio_param = param;
819 audio_sys = sys; 1012 audio_sys = sys;
1013
820 rb->pcm_play_data(get_more, NULL, NULL, 0); 1014 rb->pcm_play_data(get_more, NULL, NULL, 0);
821} 1015}
822 1016
@@ -872,13 +1066,18 @@ void *sys_createMutex(struct System* sys)
872{ 1066{
873 if(!sys) 1067 if(!sys)
874 error("sys is NULL!"); 1068 error("sys is NULL!");
1069
1070 debug(DBG_SYS, "allocating mutex");
1071
1072 /* this bitfield works as follows: bit set = free, unset = in use */
875 for(int i = 0; i < MAX_MUTEXES; ++i) 1073 for(int i = 0; i < MAX_MUTEXES; ++i)
876 { 1074 {
1075 /* check that the corresponding bit is 1 (free) */
877 if(sys->mutex_bitfield & (1 << i)) 1076 if(sys->mutex_bitfield & (1 << i))
878 { 1077 {
879 rb->mutex_init(&sys->mutex_memory[i]); 1078 rb->mutex_init(sys->mutex_memory + i);
880 sys->mutex_bitfield |= (1 << i); 1079 sys->mutex_bitfield &= ~(1 << i);
881 return &sys->mutex_memory[i]; 1080 return sys->mutex_memory + i;
882 } 1081 }
883 } 1082 }
884 warning("Out of mutexes!"); 1083 warning("Out of mutexes!");
@@ -888,20 +1087,18 @@ void *sys_createMutex(struct System* sys)
888void sys_destroyMutex(struct System* sys, void *mutex) 1087void sys_destroyMutex(struct System* sys, void *mutex)
889{ 1088{
890 int mutex_number = ((char*)mutex - (char*)sys->mutex_memory) / sizeof(struct mutex); /* pointer arithmetic! check for bugs! */ 1089 int mutex_number = ((char*)mutex - (char*)sys->mutex_memory) / sizeof(struct mutex); /* pointer arithmetic! check for bugs! */
891 sys->mutex_bitfield &= ~(1 << mutex_number); 1090 sys->mutex_bitfield |= 1 << mutex_number;
892} 1091}
893 1092
894void sys_lockMutex(struct System* sys, void *mutex) 1093void sys_lockMutex(struct System* sys, void *mutex)
895{ 1094{
896 (void) sys; 1095 (void) sys;
897 debug(DBG_SYS, "calling mutex_lock");
898 rb->mutex_lock((struct mutex*) mutex); 1096 rb->mutex_lock((struct mutex*) mutex);
899} 1097}
900 1098
901void sys_unlockMutex(struct System* sys, void *mutex) 1099void sys_unlockMutex(struct System* sys, void *mutex)
902{ 1100{
903 (void) sys; 1101 (void) sys;
904 debug(DBG_SYS, "calling mutex_unlock");
905 rb->mutex_unlock((struct mutex*) mutex); 1102 rb->mutex_unlock((struct mutex*) mutex);
906} 1103}
907 1104
@@ -937,4 +1134,5 @@ void MutexStack(struct MutexStack_t* s, struct System *stub, void *mutex)
937void MutexStack_destroy(struct MutexStack_t* s) 1134void MutexStack_destroy(struct MutexStack_t* s)
938{ 1135{
939 sys_unlockMutex(s->sys, s->_mutex); 1136 sys_unlockMutex(s->sys, s->_mutex);
1137
940} 1138}
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 @@
23#ifndef __XWORLD_SYS_H__ 23#ifndef __XWORLD_SYS_H__
24#define __XWORLD_SYS_H__ 24#define __XWORLD_SYS_H__
25 25
26#include "plugin.h"
26#include "intern.h" 27#include "intern.h"
27 28
28#define SYS_NEGATIVE_COLOR 29#if (PLUGIN_BUFFER_SIZE >= 0x80000 && defined(HAVE_LCD_COLOR) && LCD_DEPTH < 24)
30#define SYS_MOTION_BLUR
31/* must be odd */
32#define BLUR_FRAMES 3
33#else
34#error lol
35#endif
36
29#define NUM_COLORS 16 37#define NUM_COLORS 16
30#define MAX_MUTEXES 16 38#define MAX_MUTEXES 16
31#define SETTINGS_FILE "settings.xfg" 39#define SETTINGS_FILE "settings.zfg" /* change when backwards-compatibility is broken */
32#define CODE_X 80 40#define CODE_X 80
33#define CODE_Y 36 41#define CODE_Y 36
34 42
@@ -103,6 +111,7 @@ struct System {
103 bool sound_enabled; 111 bool sound_enabled;
104 int sound_bufsize; 112 int sound_bufsize;
105 bool zoom; 113 bool zoom;
114 bool blur;
106 } settings; 115 } settings;
107}; 116};
108 117
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] = {
126 0x00, 0xA0, 0x10, 0x80, 0x10, 0x80, 0x50, 0x00, /* DEL */ 126 0x00, 0xA0, 0x10, 0x80, 0x10, 0x80, 0x50, 0x00, /* DEL */
127}; 127};
128 128
129/* default bogus strings */
129struct StrEntry video_stringsTableEng[MAX_STRING_TABLE_SIZE] = { 130struct StrEntry video_stringsTableEng[MAX_STRING_TABLE_SIZE] = {
130 { 0x001, "B A N A N A 2000" }, 131 { 0x001, "B A N A N A 2000" },
131 { 0x002, "Copyright } 2014 Banana Corporation \nGPLv2\n\nBUNIX Revision 3.14" }, 132 { 0x002, "Copyright } 2016 Franklin Wei\nGPLv2\n\nBUNIX Revision 3.14" },
132 { 0x003, "1" }, 133 { 0x003, "1" },
133 { 0x004, "3" }, 134 { 0x004, "3" },
134 { 0x005, "." }, 135 { 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) {
52 52
53 rb->memset(m->vmVariables, 0, sizeof(m->vmVariables)); 53 rb->memset(m->vmVariables, 0, sizeof(m->vmVariables));
54 m->vmVariables[0x54] = 0x81; 54 m->vmVariables[0x54] = 0x81;
55 m->vmVariables[VM_VARIABLE_RANDOM_SEED] = *rb->current_tick; 55 m->vmVariables[VM_VARIABLE_RANDOM_SEED] = *rb->current_tick % 0x10000;
56
57 /* rawgl has these, but they don't seem to do anything */
58 //m->vmVariables[0xBC] = 0x10;
59 //m->vmVariables[0xC6] = 0x80;
60 //m->vmVariables[0xF2] = 4000;
61 //m->vmVariables[0xDC] = 33;
56 62
57 m->_fastMode = false; 63 m->_fastMode = false;
58 m->player->_markVar = &m->vmVariables[VM_VARIABLE_MUS_MARK]; 64 m->player->_markVar = &m->vmVariables[VM_VARIABLE_MUS_MARK];
@@ -81,7 +87,7 @@ void vm_op_add(struct VirtualMachine* m) {
81 87
82void vm_op_addConst(struct VirtualMachine* m) { 88void vm_op_addConst(struct VirtualMachine* m) {
83 if (m->res->currentPartId == 0x3E86 && m->_scriptPtr.pc == m->res->segBytecode + 0x6D48) { 89 if (m->res->currentPartId == 0x3E86 && m->_scriptPtr.pc == m->res->segBytecode + 0x6D48) {
84 warning("vm_op_addConst() hack for non-stop looping gun sound bug"); 90 //warning("vm_op_addConst() hack for non-stop looping gun sound bug");
85 // the script 0x27 slot 0x17 doesn't stop the gun sound from looping, I 91 // the script 0x27 slot 0x17 doesn't stop the gun sound from looping, I
86 // don't really know why ; for now, let's play the 'stopping sound' like 92 // don't really know why ; for now, let's play the 'stopping sound' like
87 // the other scripts do 93 // the other scripts do
@@ -152,10 +158,9 @@ void vm_op_jnz(struct VirtualMachine* m) {
152#define BYPASS_PROTECTION 158#define BYPASS_PROTECTION
153void vm_op_condJmp(struct VirtualMachine* m) { 159void vm_op_condJmp(struct VirtualMachine* m) {
154 160
155 //printf("Jump : %X \n",m->_scriptPtr.pc-m->res->segBytecode); 161 //debug(DBG_VM, "Jump : %X \n",m->_scriptPtr.pc-m->res->segBytecode);
156//FCS Whoever wrote this is patching the bytecode on the fly. This is ballzy !! 162//FCS Whoever wrote this is patching the bytecode on the fly. This is ballzy !!
157#ifdef BYPASS_PROTECTION 163#if 0
158
159 if (m->res->currentPartId == GAME_PART_FIRST && m->_scriptPtr.pc == m->res->segBytecode + 0xCB9) { 164 if (m->res->currentPartId == GAME_PART_FIRST && m->_scriptPtr.pc == m->res->segBytecode + 0xCB9) {
160 165
161 // (0x0CB8) condJmp(0x80, VAR(41), VAR(30), 0xCD3) 166 // (0x0CB8) condJmp(0x80, VAR(41), VAR(30), 0xCD3)
@@ -168,6 +173,8 @@ void vm_op_condJmp(struct VirtualMachine* m) {
168 debug(DBG_VM, "vm_op_condJmp() bypassing protection"); 173 debug(DBG_VM, "vm_op_condJmp() bypassing protection");
169 debug(DBG_VM, "bytecode has been patched"); 174 debug(DBG_VM, "bytecode has been patched");
170 175
176 //warning("bypassing protection");
177
171 //vm_bypassProtection(m); 178 //vm_bypassProtection(m);
172 } 179 }
173 180
@@ -175,7 +182,8 @@ void vm_op_condJmp(struct VirtualMachine* m) {
175#endif 182#endif
176 183
177 uint8_t opcode = scriptPtr_fetchByte(&m->_scriptPtr); 184 uint8_t opcode = scriptPtr_fetchByte(&m->_scriptPtr);
178 int16_t b = m->vmVariables[scriptPtr_fetchByte(&m->_scriptPtr)]; 185 uint8_t var = scriptPtr_fetchByte(&m->_scriptPtr);
186 int16_t b = m->vmVariables[var];
179 uint8_t c = scriptPtr_fetchByte(&m->_scriptPtr); 187 uint8_t c = scriptPtr_fetchByte(&m->_scriptPtr);
180 int16_t a; 188 int16_t a;
181 189
@@ -193,6 +201,22 @@ void vm_op_condJmp(struct VirtualMachine* m) {
193 switch (opcode & 7) { 201 switch (opcode & 7) {
194 case 0: // jz 202 case 0: // jz
195 expr = (b == a); 203 expr = (b == a);
204
205#ifdef BYPASS_PROTECTION
206 /* always succeed in code wheel verification */
207 if (m->res->currentPartId == GAME_PART_FIRST && var == 0x29 && (opcode & 0x80) != 0) {
208
209 m->vmVariables[0x29] = m->vmVariables[0x1E];
210 m->vmVariables[0x2A] = m->vmVariables[0x1F];
211 m->vmVariables[0x2B] = m->vmVariables[0x20];
212 m->vmVariables[0x2C] = m->vmVariables[0x21];
213 // counters
214 m->vmVariables[0x32] = 6;
215 m->vmVariables[0x64] = 20;
216 expr = true;
217 //warning("Script::op_condJmp() bypassing protection");
218 }
219#endif
196 break; 220 break;
197 case 1: // jnz 221 case 1: // jnz
198 expr = (b != a); 222 expr = (b != a);
@@ -605,8 +629,6 @@ void vm_executeThread(struct VirtualMachine* m) {
605 { 629 {
606 (vm_opcodeTable[opcode])(m); 630 (vm_opcodeTable[opcode])(m);
607 } 631 }
608
609 rb->yield();
610 } 632 }
611} 633}
612 634