summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranklin Wei <frankhwei536@gmail.com>2016-11-03 22:27:01 -0400
committerGerrit Rockbox <gerrit@rockbox.org>2016-11-19 19:17:14 +0100
commit05733649bce2623acfad7b163501c6fdefea985a (patch)
tree8db235af25ae7e72f9793879bd1119db90990cf4
parentdeaeb73912c1bb9fd4d3498e59d1789761f3e322 (diff)
downloadrockbox-05733649bce2623acfad7b163501c6fdefea985a.tar.gz
rockbox-05733649bce2623acfad7b163501c6fdefea985a.zip
XWorld: some fixes
Fixes sound on most platforms, original root cause was bad menu code as well as DMA callbacks taking too long. Worked around with smaller chunk sizes. Permanent fix would include moving mixing out of the callback. Rewrites input with code from rockboy/doom. Cherry-picks a change from Gregory Montoir's `rawgl' to patch the code wheel screen. Finally, adds a motion blur filter on select targets. Change-Id: I8df549c923c5075800c6625c36c8202e53de1d27
-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