JetStream should have a more rational story for jitter-oriented latency tests
[WebKit-https.git] / PerformanceTests / JetStream / Octane2 / mandreel.js
1 // Portions copyright 2012 Google, Inc.
2 // Copyright 2012 Onan Games. All rights reserved.
3 // Copyright (C) 2015 Apple Inc. All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 //       notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 //       copyright notice, this list of conditions and the following
12 //       disclaimer in the documentation and/or other materials provided
13 //       with the distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 //       contributors may be used to endorse or promote products derived
16 //       from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 var MandreelBenchmark = new BenchmarkSuite('Mandreel', [16831872, 49852],
31                                             [new Benchmark('Mandreel',
32                                                            false,
33                                                            false,
34                                                            runMandreel,
35                                                            setupMandreel,
36                                                            tearDownMandreel,
37                                                            latencyMandreel,
38                                                            4)]);
39
40 var mandreelPauseTimes = [];
41 var mandreelSampleTimeStart = 0.0;
42
43 function setupMandreel() {
44   // Check for Typed Arrays support, throw error if not.
45   if (!(typeof Uint8Array != "undefined" &&
46     typeof Float64Array != "undefined" &&
47     typeof (new Uint8Array(0)).subarray != "undefined")) {
48       throw "TypedArrayUnsupported";
49   }
50
51   my_old_constructors = mandreel_call_constructors;
52   mandreel_call_constructors = my_mandreel_call_constructors;
53   startMandreelTimer();
54   startApp();
55   _mandreelAppAudioReady();
56 }
57
58 function runMandreel() {
59   Mandreel_currentTime = 0;
60   var sp = g_stack_pointer+800*1024;
61   for (var i=0;i<mandreel_total_memory/4;i++) {
62     heap32[i] = my_heap32[i];
63   }
64   tlsf_ptr = 0;
65   heapNewPos = my_heapNewPos;
66   my_old_constructors(llvm_2E_global_ctors,5,sp);
67   heapU32[sp>>2] = 640;
68   heapU32[(sp+4)>>2] = 480;
69   __mandreel_internal_SetResolution(sp);
70   __mandreel_internal_init(g_stack_pointer+800*1024);
71   __init(g_stack_pointer+800*1024);
72   for (var i = 0; i < 20; i++) {
73     render();
74     Mandreel_flushTimeouts();
75     updateMandreelStats(performance.now());
76   }
77   Mandreel_checkState();
78 }
79
80 function updateMandreelStats(time) {
81   var pause = time - mandreelSampleTimeStart;
82   mandreelSampleTimeStart = time;
83   mandreelPauseTimes.push(pause);
84 }
85
86 function startMandreelTimer() {
87   mandreelSampleTimeStart = performance.now();
88 }
89
90 function latencyMandreel() {
91   return mandreelPauseTimes;
92 }
93
94 function tearDownMandreel() {
95   my_old_constructors = null;
96   my_heap = null;
97   my_heap8 = null;
98   my_heap32 = null;
99
100   heap = null;
101   heap8 = null;
102   heapU8 = null;
103   heap16 = null;
104   heapU16 = null;
105   heap32 = null;
106   heapU32 = null;
107   heapFloat = null;
108   heapDouble = null;
109   mandreelAppUsePackAsyncTexture = null;
110   mandreelPauseTimes = [];
111 }
112
113 // Mocks for browser functions.
114
115 function Mandreel_setTimeout(cmd, delay) {
116   timeouts.push(cmd);
117 }
118
119 function Mandreel_flushTimeouts() {
120   while (Mandreel_timeouts.length != 0) {
121     var next = Mandreel_timeouts.pop();
122     eval(next);
123   }
124 }
125
126 Mandreel_timeouts = new Array();
127
128 Mandreel_XMLHttpRequest = function() {
129   this.open = function(type, url, some_bool) {
130     this.url = url;
131   }
132   this.overrideMimeType = function() {
133   }
134   this.send = function() {
135     this.response = null;
136     this.readyState = 4;
137     this.status = 0;
138     this.onreadystatechange();
139   }
140 };
141
142 function Mandreel_Element(type) {
143   this.element_type = type;
144   this.insertBefore = function() {
145   }
146 }
147
148
149 function Mandreel_Context() {
150 }
151
152 function Mandreel_Canvas() {
153 }
154
155 function Mandreel_CanvasDiv() {
156 }
157
158 Mandreel_document = {
159   createElement : function(element_type) {
160     var element = new Mandreel_Element(element_type);
161     element.parentNode = new Mandreel_Element("dummy_parent");
162     return element;
163   },
164   getElementById : function(name) {
165     if (name === "canvas") {
166       return new Mandreel_Canvas();
167     } else if (name === "canvasDiv") {
168       return new Mandreel_CanvasDiv();
169     } else {
170       return undefined;
171     }
172   },
173   getElementsByTagName : function(element) {
174     if (element === "script") {
175       return new Array(new this.createElement(element));
176     }
177   }
178
179 };
180
181 Mandreel_window = {
182   WebGLRenderingContext: {},
183   Float64Array: Float64Array,
184   Float32Array: Float32Array,
185   Int32Array: Int32Array,
186   Uint32Array: Uint32Array,
187   Int16Array: Int16Array,
188   Uint16Array: Uint16Array,
189   Int8Array: Int8Array,
190   Uint8Array: Uint8Array,
191   setTimeout: Mandreel_setTimeout,
192   addEventListener : function () {},
193   document: Mandreel_document
194 };
195
196 function dump(x) { }
197
198 alert = typeof alert != "undefined" ? alert : function(x) {
199   print(x);
200 }
201
202 var my_old_constructors;
203 var my_heap;
204 var my_heap8;
205 var my_heap32;
206 var my_heapNewPos;
207
208 function my_mandreel_call_constructors(_ptr, size,stackPos) {
209   my_heapNewPos = heapNewPos;
210   my_heap = new ArrayBuffer(mandreel_total_memory);
211   my_heap8 = new Int8Array(my_heap);
212   my_heap32 = new Int32Array(my_heap);
213   for (var i=0;i<mandreel_total_memory/4;i++) {
214     my_heap32[i] = heap32[i];
215   }
216   my_old_constructors(_ptr,size,stackPos);
217 }
218
219
220 var Mandreel_currentTime = 0;
221
222 function Date_now() {
223    Mandreel_currentTime += 16;
224    return Mandreel_currentTime;
225 }
226
227 function Mandreel_checkState() {
228   var sum = 0;
229   for (var i = 0; i < heap32.length; i += 100) {
230     sum = (sum * 3 + heap32[i]) & 0xFFFFFF;
231   }
232   if (sum != 8001026) {
233     alert("Check sum mismatch: expected ???, actual " + sum);
234   }
235 }
236
237 // Original Mandreel code follows.
238 // Modifications for benchmarking are marked in comments.
239
240 // Start of js/main.js file:
241
242 ////////////////////////////////////////////
243 function startApp(_platform)
244 {
245         // Start mandreel
246         var params =
247         {
248                 platform : _platform,
249                 width : 1024,
250                 height : 768,
251                 webglCanvas : "canvas",
252                 flashCanvas : "FlashDiv",
253                 workingFolderFlash : "data/as3/",
254                 workingFolderWebgl : "data/js/",
255                 swfFlash : "mandreel.swf",
256                 log : true
257         };
258         mandreelAppStart(appStartState,params);
259 }
260
261 ////////////////////////////////////////////
262 function appStartState(state,param)
263 {
264         // mandreel.js program is been loaded
265         if ( state == "loadingScript" )
266         {
267         }
268
269         // mandreel.js program has been loaded
270         if ( state == "scriptLoaded" )
271         {
272         }
273
274         // loading pack data file
275         if (state == "loadingData")
276         {
277                 // param bytes loaded
278         }
279
280         // Audio system is been started
281         if ( state == "loadingAudio" )
282         {
283         }
284
285         // Audio system is ready and the default audio preloading has been done
286         if ( state == "audioLoaded" )
287         {
288         }
289
290
291
292         // Mandreel has been started, render will start automatically
293         if ( state == "ready" )
294         {
295                 // Hide loading image
296                 var canvasElement = Mandreel_document.getElementById('loading');
297                 if ( canvasElement != null )
298                         canvasElement.style.visibility = "hidden";
299         }
300
301         // An error has been produced during the start process and the app must quit
302         if ( state == "error" )
303         {
304                 if ( param == "webgl_not_found" )
305                 {
306                         window.location = "http://get.webgl.org";
307                         return;
308                 }
309                 alert(param);
310         }
311 }
312
313 // End of js/main.js file.
314
315 // Start of js/mandreelapp.js file.
316
317 var mandreelAppMandreelJs = "mandreel.js";
318 var mandreelAppMandreelJsCompressed = false;
319 var mandreelAppWorkingFolder = "data/js/";
320 var mandreelAppLog = false;
321 var mandreelAppLocalHost = "http://localhost";
322 var mandreelAppReadDataFromLocalHost = false;
323 var mandreelAppReadMandreelJsFromLocalHost = false;
324 var mandreelAppHostedAudioServer = null;
325 var mandreelAppHostedAudioUrl = null;
326 var mandrelCurrentFatVersion = "1.4";
327 var mandreelAppPlatform = "webgl";
328 var mandreelAppCanvasWidth = 1024;
329 var mandreelAppCanvasHeight = 768;
330 var mandreelAppWidthSrc = 1024;
331 var mandreelAppHeightSrc = 768;
332 var mandreelAppCanvasName = "canvas";
333 var mandreelAppCanvasDiv = "canvasDiv";
334 var mandreelAppUseFlashSockets = false;
335 var mandreelAppUsePackAsyncTexture = new Array();
336 //var mandreelBufferPackAsyncTexture = null;
337 var mandreelAppForceFocus = true;
338 var _imandreel_pause_game = false;
339
340 /* The following code was removed for benchmarking:
341 navigator.pointer = navigator.pointer || navigator.webkitPointer || navigator.mozPointer || null;*/
342
343 /* The following code was removed for benchmarking:
344  if (!Date_now) {
345    Date_now = function() {
346      return +new Date();
347    };
348  };*/
349
350 ////////////////////////////////////////////
351
352 if (Mandreel_window["console"])
353 {
354         if (!Mandreel_window["dump"]) Mandreel_window["dump"] = function dump(str){ if ( mandreelAppLog ) console.log(str) };
355 }
356 else
357 {
358         if (!Mandreel_window["dump"]) Mandreel_window["dump"] = function dump(str){ };
359 }
360
361 /* The following code is removed for benchmarking:
362 var mandreel_BrowserDetect = {
363         init: function () {
364                 this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
365                 this.version = this.searchVersion(navigator.userAgent)
366                         || this.searchVersion(navigator.appVersion)
367                         || "an unknown version";
368                 this.OS = this.searchString(this.dataOS) || "an unknown OS";
369         },
370         searchString: function (data) {
371                 for (var i=0;i<data.length;i++) {
372                         var dataString = data[i].string;
373                         var dataProp = data[i].prop;
374                         this.versionSearchString = data[i].versionSearch || data[i].identity;
375                         if (dataString) {
376                                 if (dataString.indexOf(data[i].subString) != -1)
377                                         return data[i].identity;
378                         }
379                         else if (dataProp)
380                                 return data[i].identity;
381                 }
382         },
383         searchVersion: function (dataString) {
384                 var index = dataString.indexOf(this.versionSearchString);
385                 if (index == -1) return;
386                 return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
387         },
388         dataBrowser: [
389                 {
390                         string: navigator.userAgent,
391                         subString: "Chrome",
392                         identity: "Chrome"
393                 },
394                 {       string: navigator.userAgent,
395                         subString: "OmniWeb",
396                         versionSearch: "OmniWeb/",
397                         identity: "OmniWeb"
398                 },
399                 {
400                         string: navigator.vendor,
401                         subString: "Apple",
402                         identity: "Safari",
403                         versionSearch: "Version"
404                 },
405                 {
406                         prop: window.opera,
407                         identity: "Opera",
408                         versionSearch: "Version"
409                 },
410                 {
411                         string: navigator.vendor,
412                         subString: "iCab",
413                         identity: "iCab"
414                 },
415                 {
416                         string: navigator.vendor,
417                         subString: "KDE",
418                         identity: "Konqueror"
419                 },
420                 {
421                         string: navigator.userAgent,
422                         subString: "Firefox",
423                         identity: "Firefox"
424                 },
425                 {
426                         string: navigator.vendor,
427                         subString: "Camino",
428                         identity: "Camino"
429                 },
430                 {               // for newer Netscapes (6+)
431                         string: navigator.userAgent,
432                         subString: "Netscape",
433                         identity: "Netscape"
434                 },
435                 {
436                         string: navigator.userAgent,
437                         subString: "MSIE",
438                         identity: "Explorer",
439                         versionSearch: "MSIE"
440                 },
441                 {
442                         string: navigator.userAgent,
443                         subString: "Gecko",
444                         identity: "Mozilla",
445                         versionSearch: "rv"
446                 },
447                 {               // for older Netscapes (4-)
448                         string: navigator.userAgent,
449                         subString: "Mozilla",
450                         identity: "Netscape",
451                         versionSearch: "Mozilla"
452                 }
453         ],
454         dataOS : [
455                 {
456                         string: navigator.platform,
457                         subString: "Win",
458                         identity: "Windows"
459                 },
460                 {
461                         string: navigator.platform,
462                         subString: "Mac",
463                         identity: "Mac"
464                 },
465                 {
466                            string: navigator.userAgent,
467                            subString: "iPhone",
468                            identity: "iPhone/iPod"
469             },
470                 {
471                         string: navigator.platform,
472                         subString: "Linux",
473                         identity: "Linux"
474                 }
475         ]
476
477 };
478 mandreel_BrowserDetect.init(); */
479
480 ////////////////////////////////////////////
481 var mandreel_packfiledata_name = null;
482 var mandreel_packfiledata_compressed = false;
483 var mandreel_packfiledata_size = 0;
484 var mandreel_total_packtexture_size = 0;
485 var mandreel_total_pogfile_size = 0;
486 var mandreel_loaded_packtexture_size = 0;
487 var mandreel_jslzma_size = 0;
488 var mandreel_swf_size = 0;
489
490 var mandreelJsScriptLoaded_loaded = false;
491
492 var mandreel_swf_last_total_size = 0;
493 function mandreel_swf_size_updated(str)
494 {
495         var params = str.split(',');
496         if ( mandreel_swf_size == 0 )
497         {
498                 mandreel_swf_last_loaded_size = 0;
499         }
500         mandreel_swf_size = parseInt(params[0]);
501         var loaded = parseInt(params[1]);
502         var delta_size = loaded - mandreel_swf_last_loaded_size;
503         mandreel_swf_last_loaded_size = loaded;
504
505         var percentage = ((100*loaded)/mandreel_swf_size)|0;
506         if (percentage>100)
507                 percentage = 100;
508
509         if ( mandreelAppStartStateFunc )
510                 mandreelAppStartStateFunc("loadingScriptUpdate",percentage);
511
512         imandreel_update_load(delta_size,0);
513 }
514
515 function mandreel_swf_size_loaded(str)
516 {
517         if ( mandreelAppStartStateFunc )
518                 mandreelAppStartStateFunc("scriptLoaded","");
519 }
520
521 function mandreelNextDecompress(mandreel_result_lzma)
522 {
523
524         if ( mandreelAppStartStateFunc )
525         {
526                 var totalBytesLeft = mandreel_result_lzma.totalSize - mandreel_result_lzma.remainingBytes;
527
528                 var percentage;
529
530                 if (totalBytesLeft == 0)
531                         percentage = 0;
532                 else
533                         percentage = ((100*totalBytesLeft)/mandreel_result_lzma.totalSize)|0;
534
535                 mandreelAppStartStateFunc("uncompressingDataUpdate",percentage);
536         }
537
538         var old_result = mandreel_result_lzma;
539         mandreel_result_lzma = LZMA.decompress2(mandreel_result_lzma.inStream,mandreel_result_lzma.inStream,mandreel_result_lzma.outStream,mandreel_result_lzma);
540
541         if (mandreel_result_lzma == null)
542         {
543                 //setTimeout(mandreelLoadScript,10,old_result.my_outStream.data);
544
545                 //mandreel_fs_saveFile('data.bin', old_result.my_outStream.arrayBuffer);
546                 //callback(old_result.my_outStream.arrayBuffer);
547                 //alert('done');
548                 mandreelLoadPackData(old_result.my_outStream.arrayBuffer,true);
549         }
550         else
551         {
552                 Mandreel_setTimeout(mandreelNextDecompress,10,mandreel_result_lzma);
553         }
554
555
556 }
557
558 function mandreel_load_packfile(array_buffer)
559 {
560         if (array_buffer)
561         {
562                 mandreelLoadPackData(array_buffer,false);
563                 return;
564         }
565
566         var working_folder = mandreelAppWorkingFolder;
567         if ( mandreelAppReadDataFromLocalHost )
568                 working_folder = mandreelAppLocalHost+"/"+mandreelAppWorkingFolder;
569         var packdata_request = new XMLHttpRequest();
570         var url = working_folder+mandreel_packfiledata_name;
571
572         packdata_request.open("GET", url, true);
573
574         if("responseType" in packdata_request)
575                 packdata_request.responseType="arraybuffer";
576         else
577                 packdata_request.overrideMimeType('text/plain; charset=x-user-defined');
578
579         var last_loaded_size = 0;
580
581         packdata_request.onreadystatechange = function()
582         {
583                 if (packdata_request.readyState != 4) return;
584
585                 if (packdata_request.status == 200)
586                 {
587                         var buffer;
588                         if (packdata_request.responseType=="arraybuffer")
589                                 buffer=packdata_request.response;
590                         else if (packdata_request.mozResponseArrayBuffer != null)
591                                 buffer = packdata_request.mozResponseArrayBuffer;
592                         else
593                                 buffer=packdata_request.response;
594
595                         if (mandreel_packfiledata_compressed)
596                         {
597                                 var inStream = {
598                                   data: new Uint8Array(buffer),
599                                   offset: 0,
600                                   readByte: function(){
601                                         return this.data[this.offset ++];
602                                   }
603                                 };
604
605                                 var outStream = {
606                                   data: null,
607                                   offset: 0,
608                                   binary_mode : true,
609                                   writeByte: function(value){
610                                         this.data[this.offset ++] = value;
611                                   }
612                                 };
613
614
615                                 var result = LZMA.decompress2(inStream,inStream,outStream,null);
616
617                                 if (result == null)
618                                         mandreelLoadPackData(outStream.arrayBuffer,true);
619                                 else
620                                         Mandreel_setTimeout(mandreelNextDecompress,10,result);
621                         }
622                         else
623                                 mandreelLoadPackData(buffer,true);
624                 }
625                 else
626                 {
627                         if ( mandreelAppStartStateFunc )
628                                 mandreelAppStartStateFunc("error","can't load packfile data");
629                 }
630         }
631         packdata_request.onprogress = function(e)
632         {
633                 var delta_size = e.loaded - last_loaded_size;
634                 last_loaded_size = e.loaded;
635                 var percentage = ((100*e.loaded)/mandreel_packfiledata_size)|0;
636
637
638                 imandreel_update_load(delta_size,0);
639
640                 if (percentage>100)
641                         percentage = 100;
642
643                 if ( mandreelAppStartStateFunc )
644                         mandreelAppStartStateFunc("loadingData",percentage);
645         }
646
647         packdata_request.send();
648 }
649
650 function mandreelJsScriptLoaded()
651 {
652         if (mandreelJsScriptLoaded_loaded)
653                 return;
654
655         if (typeof(mandreel_cache_files)=="undefined")
656         {
657                 Mandreel_setTimeout(mandreelJsScriptLoaded,10);
658                 return;
659         }
660
661         mandreelJsScriptLoaded_loaded = true;
662
663         if ( mandreelAppStartStateFunc )
664                 mandreelAppStartStateFunc("scriptLoaded","");
665
666         if (mandreel_packfiledata_name)
667         {
668
669                 mandreel_fs_load_binary(mandreel_packfiledata_name, mandreel_load_packfile);
670
671
672         }
673         else
674         {
675                 mandreelCacheMandreelFat();
676                 imandreelJsScriptLoaded();
677         }
678 }
679
680 function imandreelLoadAudio()
681 {
682         g_mandreel_working_folder = mandreelAppWorkingFolder;
683         if ( mandreelAppReadDataFromLocalHost )
684                 g_mandreel_working_folder = mandreelAppLocalHost+"/"+mandreelAppWorkingFolder;
685
686         // load audio
687         if ( mandreelAppStartStateFunc )
688                 mandreelAppStartStateFunc("loadingAudio","");
689         mandreel_start_audio(mandreelAppHostedAudioServer,mandreelAppHostedAudioUrl,_mandreelAppAudioReady);
690 }
691
692 var _mandreel_currentPackTexture = '';
693
694 function imandreel_packasynctexture_loaded(buffer,save_file)
695 {
696         if (save_file)
697                 mandreel_fs_saveFile(_mandreel_currentPackTexture,buffer);
698
699         //mandreelBufferPackAsyncTexture = buffer;
700         Mandreel_TextureAsync_PackBufferData[_mandreel_currentPackTexture] = buffer;
701
702         imandreelLoadNextTexturePack();
703 }
704
705 var mandreel_update_total_size = 0;
706
707 function imandreel_update_load(size, total)
708 {
709         if (total == 0)
710                 total = mandreel_packfiledata_size + mandreel_total_packtexture_size + mandreel_total_pogfile_size + mandreel_jslzma_size + mandreel_swf_size;
711
712
713         mandreel_update_total_size+=size;
714
715         var percentage = ((100*mandreel_update_total_size)/total)|0;
716
717         if (percentage>100)
718                 percentage = 100;
719         if (mandreelAppStartStateFunc)
720                 mandreelAppStartStateFunc("loadingProgress",percentage);
721
722 }
723
724
725 function imandreel_packasynctexture_load(array_buffer)
726 {
727         if (array_buffer)
728         {
729                 imandreel_packasynctexture_loaded(array_buffer, false);
730                 return;
731         }
732
733
734         var working_folder = mandreelAppWorkingFolder;
735         if ( mandreelAppReadDataFromLocalHost )
736                 working_folder = mandreelAppLocalHost+"/"+mandreelAppWorkingFolder;
737         var packdata_request = new XMLHttpRequest();
738         var url = working_folder+_mandreel_currentPackTexture;
739
740         packdata_request.open("GET", url, true);
741
742         if("responseType" in packdata_request)
743                 packdata_request.responseType="arraybuffer";
744         else
745                 packdata_request.overrideMimeType('text/plain; charset=x-user-defined');
746
747         var last_loaded_size = 0;
748
749         packdata_request.onreadystatechange = function()
750         {
751                 if (packdata_request.readyState != 4) return;
752
753                 if (packdata_request.status == 200)
754                 {
755                         var buffer;
756                         if (packdata_request.responseType=="arraybuffer")
757                                 buffer=packdata_request.response;
758                         else if (packdata_request.mozResponseArrayBuffer != null)
759                                 buffer = packdata_request.mozResponseArrayBuffer;
760                         else
761                                 buffer=packdata_request.response;
762
763                         imandreel_packasynctexture_loaded(buffer, true);
764                 }
765                 else
766                 {
767                         if ( mandreelAppStartStateFunc )
768                                 mandreelAppStartStateFunc("error","can't load textureasync pack data");
769                 }
770         }
771         packdata_request.onprogress = function(e)
772         {
773                 var delta_size = e.loaded - last_loaded_size;
774                 last_loaded_size = e.loaded;
775                 mandreel_loaded_packtexture_size+=delta_size;
776
777                 imandreel_update_load(delta_size,0);
778
779                 var percentage = ((100*mandreel_loaded_packtexture_size)/mandreel_total_packtexture_size)|0;
780
781                 if (percentage>100)
782                         percentage = 100;
783
784                 if ( mandreelAppStartStateFunc )
785                         mandreelAppStartStateFunc("loadingTextureAsyncPack",percentage);
786         }
787
788         packdata_request.send();
789
790 }
791
792 function imandreelLoadNextTexturePack()
793 {
794         if (mandreelAppUsePackAsyncTexture.length)
795         {
796                 _mandreel_currentPackTexture = mandreelAppUsePackAsyncTexture.pop();
797                 mandreel_fs_load_binary(_mandreel_currentPackTexture, imandreel_packasynctexture_load);
798         }
799         else
800                 imandreelLoadAudio();
801 }
802
803 function imandreelJsScriptLoaded()
804 {
805         imandreelLoadNextTexturePack();
806 }
807
808 ////////////////////////////////////////////
809
810 function mandreelDecompressJSReady(code, save_file)
811 {
812         if (save_file)
813                 mandreel_fs_saveFile(mandreelAppMandreelJs + ".lzma", code);
814
815         var ga = Mandreel_document.createElement('script');
816         ga.type = "text/javascript";
817         ga.text = code;
818         var s = Mandreel_document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
819         s.parentNode.removeChild(ga);
820         mandreelJsScriptLoaded();
821 }
822
823 function mandreelNextDecompressJS(mandreel_result_lzma)
824 {
825
826         if ( mandreelAppStartStateFunc )
827         {
828                 var totalBytesLeft = mandreel_result_lzma.totalSize - mandreel_result_lzma.remainingBytes;
829
830                 var percentage;
831
832                 if (totalBytesLeft == 0)
833                         percentage = 0;
834                 else
835                         percentage = ((100*totalBytesLeft)/mandreel_result_lzma.totalSize)|0;
836
837                 mandreelAppStartStateFunc("uncompressingScriptUpdate",percentage);
838         }
839
840         var old_result = mandreel_result_lzma;
841         mandreel_result_lzma = LZMA.decompress2(mandreel_result_lzma.inStream,mandreel_result_lzma.inStream,mandreel_result_lzma.outStream,mandreel_result_lzma);
842
843         if (mandreel_result_lzma == null)
844         {
845                 mandreelDecompressJSReady(old_result.my_outStream.data,true);
846         }
847         else
848         {
849                 Mandreel_setTimeout(mandreelNextDecompressJS,10,mandreel_result_lzma);
850         }
851
852
853 }
854
855 function mandreel_load_compressed_js(code_js)
856 {
857         if (code_js)
858         {
859                 mandreelDecompressJSReady(code_js,false);
860                 return;
861         }
862          var xmlhttp_get = new XMLHttpRequest();
863
864          var url = mandreelAppMandreelJs + ".lzma";
865          if ( mandreelAppReadMandreelJsFromLocalHost )
866                 url = mandreelAppLocalHost+"/"+url;
867
868          xmlhttp_get.open('GET',url);
869
870
871         if("responseType" in xmlhttp_get)
872                 xmlhttp_get.responseType="arraybuffer";
873         else
874                 xmlhttp_get.overrideMimeType('text/plain; charset=x-user-defined');
875
876         var last_loaded_size = 0;
877
878         xmlhttp_get.onreadystatechange = function()
879         {
880                 if (xmlhttp_get.readyState==4)
881                 {
882                         if (xmlhttp_get.status==200 || xmlhttp_get.status==0)
883                         {
884
885                                 var inStream = {
886                                   data: new Uint8Array(xmlhttp_get.response),
887                                   offset: 0,
888                                   readByte: function(){
889                                         return this.data[this.offset ++];
890                                   }
891                                 };
892
893                                 var outStream = {
894                                   data: new String(""),
895                                   offset: 0,
896                                   binary_mode : false,
897                                   writeByte: function(value){
898                                         this.data+=String.fromCharCode(value);
899                                   }
900                                 };
901
902
903                                 var result = LZMA.decompress2(inStream,inStream,outStream,null);
904                                 if (result == null)
905                                         mandreelDecompressJSReady(outStream.data,true);
906                                 else
907                                         Mandreel_setTimeout(mandreelNextDecompressJS,10,result);
908                         }
909                         else
910                         {
911                                 alert('error ' + xmlhttp_get.status);
912                         }
913                 }
914
915         }
916
917         xmlhttp_get.onprogress = function(e)
918         {
919                 var delta_size = e.loaded - last_loaded_size;
920                 last_loaded_size = e.loaded;
921
922                 var percentage = ((100*e.loaded)/e.total)|0;
923
924                 mandreel_jslzma_size = e.total;
925
926                 imandreel_update_load(delta_size,0);
927
928                 if (percentage>100)
929                         percentage = 100;
930
931                 if ( mandreelAppStartStateFunc )
932                         mandreelAppStartStateFunc("loadingScriptUpdate",percentage);
933         }
934
935         xmlhttp_get.send();
936
937 }
938
939 function mandreelLoadMandreelJsScript()
940 {
941         if (mandreelAppMandreelJsCompressed)
942         {
943                 mandreel_fs_load_text(mandreelAppMandreelJs + ".lzma", mandreel_load_compressed_js);
944
945         }
946         else
947         {
948                 var ga = Mandreel_document.createElement('script');
949                 ga.type = 'text/javascript';
950                 ga.async = true;
951                 ga.onload = ga.onreadystatechange = mandreelJsScriptLoaded;
952                 var url = mandreelAppMandreelJs;
953                 if ( mandreelAppReadMandreelJsFromLocalHost )
954                         ga.src = mandreelAppLocalHost+"/"+url;
955                 else
956                         ga.src = url;
957                 var s = Mandreel_document.getElementsByTagName('script')[0];
958                 if ( mandreelAppStartStateFunc )
959                         mandreelAppStartStateFunc("loadingScript","");
960                 s.parentNode.insertBefore(ga, s);
961         }
962 }
963
964 ////////////////////////////////////////////
965 function mandreelFatLoaded()
966 {
967         if ( mandreelAppPlatform == "nacl" )
968         {
969                 g_mandreel_working_folder = mandreelAppWorkingFolder;
970                 if ( mandreelAppReadDataFromLocalHost )
971                         g_mandreel_working_folder = mandreelAppLocalHost+"/"+mandreelAppWorkingFolder;
972
973                 // load audio
974                 if ( mandreelAppStartStateFunc )
975                         mandreelAppStartStateFunc("loadingAudio","");
976                 _mandreelAppAudioReady();
977         }
978         else
979                 mandreelLoadMandreelJsScript();
980 }
981
982 var mandreelFatData = "";
983 var mandreelFatPreloadRequest = 0;
984 ////////////////////////////////////////////
985
986 function mandreel_chanka_fixfile(fileName)
987 {
988         var fileNameNoExt = fileName.toLowerCase();
989         fileNameNoExt = fileNameNoExt.replace(/\\/g,"/");
990
991         fileNameNoExt =  fileNameNoExt.substr(1);
992
993         var new_fileName = '';
994
995         for(var j = 0; j < fileNameNoExt.length; j++)
996         {
997                 var data = fileNameNoExt.charCodeAt(j);
998
999                 if (data != 13)
1000                 {
1001                          var t = String.fromCharCode(data);
1002                          new_fileName+=t;
1003                 }
1004         }
1005
1006         return  new_fileName;
1007 }
1008
1009 function mandreel_removecr(my_string)
1010 {
1011         var new_string = '';
1012         for(var j = 0; j < my_string.length; j++)
1013         {
1014                 var data = my_string.charCodeAt(j);
1015
1016                 if (data != 13)
1017                 {
1018                          var t = String.fromCharCode(data);
1019                          new_string+=t;
1020                 }
1021         }
1022
1023         return  new_string;
1024 }
1025
1026 function mandreelCacheMandreelFat()
1027 {
1028         var array_mandreel_fat = new ArrayBuffer(mandreelFatData.length+1);
1029
1030
1031         {
1032                 var j;
1033                 var len = mandreelFatData.length;
1034                 var data_char;
1035
1036                 var my_bytes = new Uint8Array(array_mandreel_fat);
1037
1038                 for(j = 0; j < len; j++)
1039                 {
1040                         data_char = mandreelFatData.charCodeAt(j);
1041
1042                         my_bytes[j] = data_char;
1043                 }
1044                 my_bytes[j] = 0;
1045         }
1046
1047
1048         mandreel_cache_files['mandreel.fat'] = array_mandreel_fat;
1049 }
1050
1051 function mandreelLoadPackData(data, save_pack)
1052 {
1053         var files = mandreelFatData.split('\n');
1054
1055         var current_dir = '';
1056         var current_offset = 0;
1057
1058         if (save_pack)
1059                 mandreel_fs_saveFile(mandreel_packfiledata_name,data);
1060
1061
1062         for (var i=0;i<files.length;++i)
1063         {
1064                 var file_data = files[i].split(',');
1065
1066                 if (file_data[0] == 'dir')
1067                 {
1068                         current_dir = file_data[1];
1069                         //current_dir = current_dir.substr(0,current_dir.lengh-1);
1070                 }
1071                 else if (file_data[0] == 'file')
1072                 {
1073                         var file_name = current_dir + file_data[1];
1074                         file_name = mandreel_chanka_fixfile(file_name) ;
1075                         //dump('new file ' + file_name + ' ' + current_offset);
1076                         //dump(file_name);
1077                         var file_size = parseInt(file_data[2]);
1078
1079                         var my_array = new ArrayBuffer(file_size);
1080
1081                         var my_bytes = new Uint8Array(my_array);
1082
1083                         var data_bytes = new Uint8Array(data,current_offset,file_size);
1084
1085                         my_bytes.set(data_bytes);
1086
1087                         mandreel_cache_files[file_name] = my_array;
1088
1089
1090                         current_offset+=file_size;
1091
1092
1093                 }
1094         }
1095
1096
1097
1098         g_mandreel_datafiles_sufix = '';
1099         mandreelCacheMandreelFat();
1100
1101         imandreelJsScriptLoaded();
1102 }
1103
1104 var preCreatedWebAudioContext = null;
1105
1106 function mandreelLoadFat()
1107 {
1108         mandreelFatPreloadRequest = new Mandreel_XMLHttpRequest();
1109         var working_folder = mandreelAppWorkingFolder;
1110         if ( mandreelAppReadDataFromLocalHost )
1111                 working_folder = mandreelAppLocalHost+"/"+mandreelAppWorkingFolder;
1112         var url = working_folder+"mandreel.fat.dat";
1113         if ( mandreelAppPlatform == "nacl" )
1114                 url = working_folder+"mandreel.fat";
1115         mandreelFatPreloadRequest.open("GET", url, true);
1116         mandreelFatPreloadRequest.onreadystatechange = function()
1117         {
1118                 if (mandreelFatPreloadRequest.readyState != 4) return;
1119                 if ( mandreelFatPreloadRequest.status != 404 && mandreelFatPreloadRequest.response != null )
1120                 {
1121                         mandreelFatData = mandreelFatPreloadRequest.response;
1122                 }
1123                 if ( mandreelFatData == "" )
1124                 {
1125                         dump("error loading mandreel.fat file, Maybe the working folder is not correctly set???");
1126                 }
1127
1128                 var packfiledata = null;
1129                 var compressed = false;
1130                 var packfiledata_size = 0;
1131                 var total_packtexture_size = 0;
1132                 var pogsize = 0;
1133
1134                 // Check version
1135                 var FatLines = mandreelFatData.split('\n');
1136                 for ( var i=0;i<FatLines.length;++i )
1137                 {
1138                         var line = mandreel_removecr(FatLines[i]);
1139                         var params = line.split(',');
1140                         if ( params[0] == "version" )
1141                         {
1142                                 if ( params[1] != mandrelCurrentFatVersion )
1143                                         dump("warning: mandreel.fat version number is ("+params[1]+") and it should be ("+mandrelCurrentFatVersion+")");
1144
1145                         }
1146                         else if ( params[0] == "platform" && params[1] != "js" && (mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas")  )
1147                                 dump("warning: mandreel.fat platform is ("+params[1]+") and it should be (js)");
1148                         else if ( params[0] == "platform" && params[1] != "nacl" && mandreelAppPlatform == "nacl"  )
1149                                 dump("warning: mandreel.fat platform is ("+params[1]+") and it should be (nacl)");
1150                         else if (params[0] == 'packdata')
1151                         {
1152                                 packfiledata = params[1];
1153                                 compressed = params[2].charAt(0) == '1';
1154                                 packfiledata_size =  parseInt(params[3], 10);
1155                         }
1156                         else if (params[0] == 'flashsockets')
1157                         {
1158                                 mandreelAppUseFlashSockets = true;
1159                         }
1160                         else if (params[0] == 'packtexture')
1161                         {
1162                                 var filename = params[1];
1163                                 var size_packtexture = parseInt(params[3], 10);
1164                                 total_packtexture_size+=size_packtexture;
1165                                 mandreelAppUsePackAsyncTexture.push(filename);
1166                         }
1167                         else if (params[0] == 'audiopreloadfile')
1168                         {
1169                                 pogsize = parseInt(params[2],10);
1170                         }
1171                         else if (params[0] == 'audiodriver' && params[1] == 'webaudio')
1172                         {
1173                                 try     { preCreatedWebAudioContext = new webkitAudioContext(); } catch(err) { preCreatedWebAudioContext = null; }
1174                         }
1175                 }
1176
1177                 if ( preCreatedWebAudioContext != null )
1178                         mandreel_total_pogfile_size = pogsize;
1179                 mandreel_packfiledata_name = packfiledata;
1180                 mandreel_packfiledata_compressed = compressed;
1181                 mandreel_packfiledata_size = packfiledata_size;
1182                 mandreel_total_packtexture_size = total_packtexture_size;
1183                 mandreelFatLoaded();
1184         }
1185         mandreelFatPreloadRequest.send();
1186 }
1187
1188 var mandreelAppStartStateFunc = 0;
1189 var mandreelDisableSpaceKey = true;
1190 ////////////////////////////////////////////
1191 function mandreelAppStart(startStateFunc,params)
1192 {
1193         mandreelAppStartStateFunc = startStateFunc;
1194
1195
1196
1197
1198         if ( typeof(params.log) != 'undefined' )
1199                 mandreelAppLog = params.log;
1200
1201         if ( typeof(params.platform) != 'undefined' )
1202                 mandreelAppPlatform = params.platform;
1203
1204         if (typeof(params.mandreelJSCompressed) != 'undefined' )
1205                 mandreelAppMandreelJsCompressed = params.mandreelJSCompressed;
1206
1207
1208 /*       The following code is removed for benchmarking:
1209         if ((mandreel_BrowserDetect.browser == 'Chrome' || mandreel_BrowserDetect.browser == 'Safari') && mandreel_BrowserDetect.OS == 'Mac' && mandreelAppPlatform == "flash")
1210                 mandreelDisableSpaceKey = false; */
1211
1212         if ( mandreelAppPlatform != "webgl" && mandreelAppPlatform != "flash" && mandreelAppPlatform != "nacl" && mandreelAppPlatform != "canvas" && mandreelAppPlatform != "plugin")
1213         {
1214                 mandreelAppStartStateFunc("error",'platform ('+mandreelAppPlatform+') not supported');
1215                 return;
1216         }
1217
1218         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
1219         {
1220                 mandreelAppWorkingFolder = "data/js/";
1221                 if ( typeof(params.workingFolderWebgl) != 'undefined' )
1222                         mandreelAppWorkingFolder = params.workingFolderWebgl;
1223                 // Check Float64Array availability
1224                 if ( !Mandreel_window["Float64Array"] )
1225                 {
1226                         mandreelAppStartStateFunc("error",'Browser unsupported: Float64Array not available');
1227                         return;
1228                 }
1229
1230                 var flashElement = Mandreel_document.getElementById('FlashWrapper');
1231                 if ( flashElement != null )
1232                 {
1233                         flashElement.style.visibility = "hidden";
1234                         flashElement.style.width = "0px";
1235                         flashElement.style.height = "0px";
1236                 }
1237                 var flashElement = Mandreel_document.getElementById('FlashDiv');
1238                 if ( flashElement != null )
1239                 {
1240                         flashElement.style.visibility = "hidden";
1241                         flashElement.style.width = "0px";
1242                         flashElement.style.height = "0px";
1243                 }
1244
1245                 // Setup WebGL
1246                 if ( typeof(params.webglCanvas) == 'undefined' )
1247                 {
1248                         mandreelAppStartStateFunc("error",'canvas parameter not found');
1249                         return;
1250                 }
1251                 var canvas = Mandreel_document.getElementById(params.webglCanvas);
1252                 if ( canvas == null )
1253                 {
1254                         mandreelAppStartStateFunc("error",'canvas object ('+params.webglCanvas+') not found');
1255                         return;
1256                 }
1257                 if ( params.width != null )
1258                 {
1259                         canvas.width = params.width;
1260                         mandreelAppWidthSrc = params.width;
1261                 }
1262                 if ( params.height != null )
1263                 {
1264                         canvas.height = params.height;
1265                         mandreelAppHeightSrc = params.height;
1266                 }
1267                 if ( mandreelAppPlatform == "webgl" )
1268                 {
1269                         // The following code is removed for benchmarking:
1270                         // imandreel_gl = WebGLUtils.setupWebGL(canvas,{premultipliedAlpha:false,alpha:false});
1271                         // if (imandreel_gl == null)
1272                         // {
1273                         //      mandreelAppStartStateFunc("error","webgl_not_found");
1274                         //      return;
1275                         // }
1276                 }
1277
1278                 if ( mandreelAppPlatform == "canvas" )
1279                 {
1280                         imandreel_ctx_canvas = canvas.getContext('2d');
1281                         if ( imandreel_ctx_canvas == null )
1282                         {
1283                                 mandreelAppStartStateFunc("error","canvas context 2d not found");
1284                                 return;
1285                         }
1286                 }
1287
1288                 if (params.cache != null)
1289                 {
1290                         //alert( params.cache.size + params.cache.url);
1291                         mandreel_fs_init(function() { if ( mandreelAppStartStateFunc )
1292                                 mandreelAppStartStateFunc("loadingFat","");
1293                         mandreelLoadFat();}, params.cache.size,params.cache.url);
1294                 }
1295                 else
1296                 {
1297                         // load Fat
1298                         if ( mandreelAppStartStateFunc )
1299                                 mandreelAppStartStateFunc("loadingFat","");
1300                         mandreelLoadFat();
1301                 }
1302         }
1303
1304         if ( mandreelAppPlatform == "flash" )
1305         {
1306                 mandreelAppWorkingFolder = "data/as3/";
1307                 if ( typeof(params.workingFolderFlash) != 'undefined' )
1308                         mandreelAppWorkingFolder = params.workingFolderFlash;
1309                 if (!swfobject.hasFlashPlayerVersion('11.2.0'))
1310                 {
1311                         mandreelAppStartStateFunc("error","flash 11 not found");
1312                         return;
1313                 }
1314
1315                 if ( typeof(params.flashCanvas) == 'undefined' )
1316                 {
1317                         mandreelAppStartStateFunc("error",'canvas parameter not found');
1318                         return;
1319                 }
1320
1321                 if ( true ) // hide webgl canvas
1322                 {
1323                         var canvas = Mandreel_document.getElementById(mandreelAppCanvasDiv);
1324                         if ( canvas != null )
1325                         {
1326                                 canvas.style.visibility = "hidden";
1327                                 canvas.style.width = "0px";
1328                                 canvas.style.height = "0px";
1329                         }
1330                 }
1331
1332                 if ( params.width != null )
1333                 {
1334                         mandreelAppCanvasWidth = params.width;
1335                 }
1336                 if ( params.height != null )
1337                 {
1338                         mandreelAppCanvasHeight = params.height;
1339                 }
1340
1341                 mandreelAppCanvasDiv = params.flashCanvas;
1342
1343                 try
1344                 {
1345                         var mandreelSocketsSwf = "mandreel.swf";
1346                         if ( typeof(params.swfFlash) != 'undefined' )
1347                                 mandreelSocketsSwf = params.swfFlash;
1348
1349                         var my_flashvars = "workingFolder=" + encodeURIComponent(mandreelAppWorkingFolder);
1350                         if ( typeof(params.log) != 'undefined' && params.log == true)
1351                           my_flashvars += "&log=true"
1352                         my_flashvars += "&width=" + params.width;
1353                         my_flashvars += "&height=" + params.height;
1354                         my_flashvars += "&swfloader=" + mandreelSocketsSwf;
1355
1356                         if (typeof(params.restore_context) != 'undefined' && params.restore_context == true)
1357                                 my_flashvars += "&restore_context=1";
1358
1359                         if (typeof(params.antialiasing) != 'undefined')
1360                                 my_flashvars += "&antialiasing=" + params.antialiasing;
1361
1362                         if (typeof(params.right_click_enable) != 'undefined' && params.right_click_enable == true)
1363                                 my_flashvars += "&right_click=1";
1364
1365                         if (typeof(params.disable_depth) != 'undefined' && params.disable_depth == true)
1366                                 my_flashvars += "&disable_depth=1";
1367
1368                         var swfname = "mandreelloader.swf";
1369                         if ( typeof(params.swfPreloader) != 'undefined' && params.swfPreloader == false)
1370                                 swfname = mandreelSocketsSwf;
1371
1372                         var swf = swfobject.createSWF({ data:swfname, width:"100%", height:"100%" }, { menu:"false",allowScriptAccess:"always",allowFullScreen:"true",wmode:"direct",scale:"noscale",salign :"tl",bgcolor:"#000000",flashvars:my_flashvars}, params.flashCanvas);
1373                         if ( !swf )
1374                         {
1375                                 mandreelAppStartStateFunc("error","error loading " + swfname);
1376                                 return;
1377                         }
1378                         else
1379                         {
1380                                 if ( mandreelAppStartStateFunc )
1381                                         mandreelAppStartStateFunc("loadingScript","");
1382                         }
1383                 }
1384                 catch(err)
1385                 {
1386                         mandreelAppStartStateFunc("error","exception " + err + " while loading " + mandreelSocketsSwf);
1387                         return;
1388                 }
1389
1390                 appStartState('loadingScript');
1391         }
1392
1393         if ( mandreelAppPlatform == "nacl" )
1394         {
1395                 mandreelAppWorkingFolder = "data/nacl/";
1396
1397                 // load Fat
1398                 if ( mandreelAppStartStateFunc )
1399                         mandreelAppStartStateFunc("loadingFat","");
1400                 mandreelLoadFat();
1401
1402         }
1403
1404         if ( mandreelAppPlatform == "plugin" )
1405         {
1406                 mandreelInitPluginPlatform(params);
1407         }
1408 }
1409
1410
1411 ////////////////////////////////////////////
1412 function MandreelAudioStartedNacl()
1413 {
1414         var helloWorldModule = null;
1415         helloWorldModule = Mandreel_document.getElementById('hello_world');
1416         helloWorldModule.postMessage('init');
1417         var flashElement = Mandreel_document.getElementById('FlashWrapper');
1418         if ( flashElement != null )
1419                 flashElement.style.visibility = "hidden";
1420         mandreelAppStartStateFunc("ready",mandreelAppCanvasWidth,mandreelAppCanvasHeight);
1421 }
1422
1423 ////////////////////////////////////////////
1424 function _mandreelAppStartReady()
1425 {
1426         if ( mandreelAppPlatform == "nacl" )
1427         {
1428                 wa_initWebAudio();
1429                 mandreel_webAudio_PreloadAssets();
1430         }
1431         else
1432         {
1433                 if ( mandreelAppStartStateFunc )
1434                 {
1435                         mandreelAppStartRenderWebGL();
1436                         mandreelAppStartStateFunc("ready",mandreelAppCanvasWidth,mandreelAppCanvasHeight);
1437                 }
1438         }
1439 }
1440 ////////////////////////////////////////////
1441 function _mandreelAppAudioReady()
1442 {
1443         if ( mandreelAppStartStateFunc )
1444                 mandreelAppStartStateFunc("audioLoaded","");
1445
1446         if ( mandreelAppUseFlashSockets )
1447                 mandreel_flash_sockets_load_flash(_mandreelAppStartReady);
1448         else
1449                 _mandreelAppStartReady();
1450 }
1451
1452 ////////////////////////////////////////////
1453 function mandreelAppInit()
1454 {
1455         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
1456         {
1457                 global_init(g_stack_pointer+800*1024);
1458
1459                 //Mandreel_TextureAsync_PackBufferData[_mandreel_currentPackTexture] = mandreelBufferPackAsyncTexture;
1460                 //mandreelBufferPackAsyncTexture = null;
1461                 var sp = g_stack_pointer+800*1024;
1462                 heapU32[sp>>2] = mandreelAppCanvasWidth;
1463                 heapU32[(sp+4)>>2] = mandreelAppCanvasHeight;
1464                 __mandreel_internal_SetResolution(sp);
1465                 __mandreel_internal_init(g_stack_pointer+800*1024);
1466                 __init(g_stack_pointer+800*1024);
1467         }
1468 }
1469
1470 ////////////////////////////////////////////
1471 function mandreelAppDraw(elapsed)
1472 {
1473         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
1474         {
1475                 if ( mandreelAppPlatform == "canvas" && imandreel_ctx_canvas != null )
1476                 {
1477                         var canvas = Mandreel_document.getElementById(mandreelAppCanvasName);
1478                         imandreel_ctx_canvas.clearRect(0,0,canvas.width,canvas.height);
1479                 }
1480                 var sp = g_stack_pointer+800*1024;
1481                 __mandreel_internal_preupdate(sp);
1482                 heapU32[sp>>2] = elapsed;
1483                 __draw(sp);
1484                 __mandreel_internal_update(sp);
1485                 __mandreel_process_async_calls();
1486         }
1487 }
1488
1489 ////////////////////////////////////////////
1490 function mandreelAppMouseWheel(delta)
1491 {
1492         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
1493         {
1494                 var i7 = MandreelLockFrame();
1495                 heap32[(i7+0)>>2] = delta;
1496                 __mouseWheelDelta(i7);
1497                 MandreelUnlockFrame();
1498         }
1499 }
1500
1501 ////////////////////////////////////////////
1502 function mandreelAppMouseMove(x,y)
1503 {
1504         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
1505         {
1506                 var i7 = MandreelLockFrame();
1507                 heap32[(i7+0)>>2] = x;
1508                 heap32[(i7+4)>>2] = y;
1509                 __mouseMove(i7);
1510                 MandreelUnlockFrame();
1511         }
1512 }
1513
1514 ////////////////////////////////////////////
1515 function mandreelAppResize(x,y)
1516 {
1517         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
1518         {
1519                 var i7 = MandreelLockFrame();
1520                 heap32[(i7+0)>>2] = x;
1521                 heap32[(i7+4)>>2] = y;
1522                 __resize(i7);
1523                 heap32[(i7+0)>>2] = x;
1524                 heap32[(i7+4)>>2] = y;
1525                 __mandreel_internal_SetResolution(i7);
1526                 MandreelUnlockFrame();
1527         }
1528 }
1529
1530 ////////////////////////////////////////////
1531 function mandreelAppMouseButton(down,x,y)
1532 {
1533         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
1534         {
1535                 var i7 = MandreelLockFrame();
1536                 heap32[(i7+0)>>2] = down;
1537                 heap32[(i7+4)>>2] = x;
1538                 heap32[(i7+8)>>2] = y;
1539                 __mouseButton(i7);
1540                 MandreelUnlockFrame();
1541         }
1542 }
1543
1544 ////////////////////////////////////////////
1545 function mandreelAppMouseDblClick(x,y)
1546 {
1547         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
1548         {
1549                 var i7 = MandreelLockFrame();
1550                 heap32[(i7+0)>>2] = x;
1551                 heap32[(i7+4)>>2] = y;
1552                 __mouseDoubleClick(i7);
1553                 MandreelUnlockFrame();
1554         }
1555 }
1556
1557 ////////////////////////////////////////////
1558 function mandreelAppKeyEvent(down,keyId)
1559 {
1560         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
1561         {
1562                 var i7 = MandreelLockFrame();
1563                 heap32[(i7+0)>>2] = down;
1564                 heap32[(i7+4)>>2] = keyId;
1565                 __keyEvent(i7);
1566                 MandreelUnlockFrame();
1567         }
1568 }
1569
1570 ////////////////////////////////////////////
1571 function mandreelAppGetPlatform()
1572 {
1573         return mandreelAppPlatform;
1574 }
1575
1576 ////////////////////////////////////////////
1577 function mandreelAppGetElementAbsolutePos(elementName)
1578 {
1579         var element = Mandreel_document.getElementById(elementName);
1580         var res = new Object();
1581         res.x = 0; res.y = 0;
1582         if (element !== null)
1583         {
1584                 if (element.getBoundingClientRect)
1585                 {
1586                         var viewportElement = Mandreel_document.documentElement;
1587                         var box = element.getBoundingClientRect();
1588                         var scrollLeft = viewportElement.scrollLeft;
1589                         var scrollTop = viewportElement.scrollTop;
1590                         res.x = box.left + scrollLeft;
1591                         res.y = box.top + scrollTop;
1592                 }
1593                 else
1594                 { //for old browsers
1595                         res.x = element.offsetLeft;
1596                         res.y = element.offsetTop;
1597                         var parentNode = element.parentNode;
1598                         var borderWidth = null;
1599                         while (offsetParent != null)
1600                         {
1601                                 res.x += offsetParent.offsetLeft;
1602                                 res.y += offsetParent.offsetTop;
1603                                 var parentTagName = offsetParent.tagName.toLowerCase();
1604                                 if ((__isIEOld && parentTagName != "table") ||
1605                                         ((__isFireFoxNew || __isChrome) &&
1606                                                 parentTagName == "td"))
1607                                 {
1608                                         borderWidth = kGetBorderWidth(offsetParent);
1609                                         res.x += borderWidth.left;
1610                                         res.y += borderWidth.top;
1611                                 }
1612
1613                                 if (offsetParent != Mandreel_document.body &&
1614                                 offsetParent != Mandreel_document.documentElement)
1615                                 {
1616                                         res.x -= offsetParent.scrollLeft;
1617                                         res.y -= offsetParent.scrollTop;
1618                                 }
1619
1620                                 //next lines are necessary to fix the problem
1621                                 //with offsetParent
1622                                 if (!__isIE && !__isOperaOld || __isIENew)
1623                                 {
1624                                         while (offsetParent != parentNode &&
1625                                                 parentNode !== null) {
1626                                                 res.x -= parentNode.scrollLeft;
1627                                                 res.y -= parentNode.scrollTop;
1628                                                 if (__isFireFoxOld || __isWebKit)
1629                                                 {
1630                                                     borderWidth =
1631                                                      kGetBorderWidth(parentNode);
1632                                                     res.x += borderWidth.left;
1633                                                     res.y += borderWidth.top;
1634                                                 }
1635                                                 parentNode = parentNode.parentNode;
1636                                         }
1637                                 }
1638
1639                                 parentNode = offsetParent.parentNode;
1640                                 offsetParent = offsetParent.offsetParent;
1641                         }
1642                 }
1643         }
1644         return res;
1645 }
1646 function __getIEVersion()
1647 {
1648         var rv = -1; // Return value assumes failure.
1649         if (navigator.appName == 'Microsoft Internet Explorer')
1650         {
1651                 var ua = navigator.userAgent;
1652                 var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
1653                 if (re.exec(ua) != null)
1654                         rv = parseFloat(RegExp.$1);
1655         }
1656         return rv;
1657 }
1658 function __getOperaVersion()
1659 {
1660         var rv = 0; // Default value
1661         if (Mandreel_window.opera)
1662         {
1663                 var sver = Mandreel_window.opera.version();
1664                 rv = parseFloat(sver);
1665         }
1666         return rv;
1667 }
1668 /* The following code was removed for benchmarking:
1669 var __userAgent = navigator.userAgent;
1670 var __isIE =  navigator.appVersion.match(/MSIE/) != null;
1671 var __IEVersion = __getIEVersion();
1672 var __isIENew = __isIE && __IEVersion >= 8;
1673 var __isIEOld = __isIE && !__isIENew;
1674 var __isFireFox = __userAgent.match(/firefox/i) != null;
1675 var __isFireFoxOld = __isFireFox && ((__userAgent.match(/firefox\/2./i) != null) || (__userAgent.match(/firefox\/1./i) != null));
1676 var __isFireFoxNew = __isFireFox && !__isFireFoxOld;
1677 var __isWebKit =  navigator.appVersion.match(/WebKit/) != null;
1678 var __isChrome =  navigator.appVersion.match(/Chrome/) != null;
1679 var __isOpera =  Mandreel_window.opera != null;
1680 var __operaVersion = __getOperaVersion();
1681 var __isOperaOld = __isOpera && (__operaVersion < 10); */
1682 function __parseBorderWidth(width)
1683 {
1684         var res = 0;
1685         if (typeof(width) == "string" && width != null && width != "" )
1686         {
1687                 var p = width.indexOf("px");
1688                 if (p >= 0)
1689                 {
1690                         res = parseInt(width.substring(0, p));
1691                 }
1692                 else
1693                 {
1694                         //do not know how to calculate other values (such as 0.5em or 0.1cm) correctly now so just set the width to 1 pixel
1695                         res = 1;
1696                 }
1697         }
1698         return res;
1699 }
1700 function __getBorderWidth(element)
1701 {
1702         var res = new Object();
1703         res.left = 0; res.top = 0; res.right = 0; res.bottom = 0;
1704         if (Mandreel_window.getComputedStyle)
1705         {
1706                 //for Firefox
1707                 var elStyle = Mandreel_window.getComputedStyle(element, null);
1708                 res.left = parseInt(elStyle.borderLeftWidth.slice(0, -2));
1709                 res.top = parseInt(elStyle.borderTopWidth.slice(0, -2));
1710                 res.right = parseInt(elStyle.borderRightWidth.slice(0, -2));
1711                 res.bottom = parseInt(elStyle.borderBottomWidth.slice(0, -2));
1712         }
1713         else
1714         {
1715                 //for other browsers
1716                 res.left = __parseBorderWidth(element.style.borderLeftWidth);
1717                 res.top = __parseBorderWidth(element.style.borderTopWidth);
1718                 res.right = __parseBorderWidth(element.style.borderRightWidth);
1719                 res.bottom = __parseBorderWidth(element.style.borderBottomWidth);
1720         }
1721         return res;
1722 }
1723
1724
1725 ////////////////////////////////////////////
1726 // WebGL
1727 ////////////////////////////////////////////
1728         var imandreel_gl = null;
1729         var imandreel_ctx_canvas = null;
1730         var imandreel_is_ready = 0;
1731         var imandreel_oldTime = Date_now();
1732
1733         function mandreel_wheel(event) { imandreel_onMouseWheel(event);event.preventDefault(); event.returnValue=false; }
1734
1735         ////////////////////////////////////////////
1736         function mandreelAppStartRenderWebGL()
1737         {
1738 /* The following code was removed for benchmarking:
1739                 var canvas = document.getElementById(mandreelAppCanvasName);
1740
1741                 mandreelAppCanvasWidth = canvas.width;
1742                 mandreelAppCanvasHeight = canvas.height;
1743
1744                 // Register event handlers
1745                 if(window.addEventListener){ window.addEventListener('DOMMouseScroll',mandreel_wheel,false); }  window.onmousewheel=document.onmousewheel=mandreel_wheel;
1746
1747                 window.addEventListener('mousedown',imandreel_onMouseDown,false);
1748                 window.addEventListener('mouseup',imandreel_onMouseUp,false);
1749                 window.addEventListener('mousemove',imandreel_onMouseMove,false);
1750                 window.addEventListener('dblclick',imandreel_onMouseDblClick,false);
1751
1752                 document.body.oncontextmenu = function() { return false;};
1753
1754                 var canvasDiv = document.getElementById(mandreelAppCanvasDiv);
1755                 canvasDiv.addEventListener('keydown',imandreel_onKeyDown,false);
1756                 canvasDiv.addEventListener('keyup',imandreel_onKeyUp,false);
1757                 canvasDiv.focus();*/
1758
1759                 // Call mandreel app init funtion (__init())
1760                 mandreelAppInit();
1761
1762                 // Start rendering
1763                 imandreel_is_ready = 1;
1764                 //imandreel_render();
1765         }
1766
1767         ////////////////////////////////////////////
1768         function imandreel_render()
1769         {
1770                 if( ABORT )
1771                         return;
1772
1773                 var canvas = Mandreel_document.getElementById(mandreelAppCanvasName);
1774                 WebGLUtils.requestAnimationFrame(canvas, imandreel_render);
1775
1776
1777                 // Reshape
1778                 if (canvas.clientWidth != mandreelAppCanvasWidth || canvas.clientHeight != mandreelAppCanvasHeight)
1779                 {
1780                         mandreelAppCanvasWidth = canvas.clientWidth;
1781                         mandreelAppCanvasHeight = canvas.clientHeight;
1782                         imandreel_gl.viewport(0, 0, mandreelAppCanvasWidth, mandreelAppCanvasHeight);
1783                 }
1784
1785                 // Set the focus to the canvas div
1786                 if (mandreelAppForceFocus)
1787                 {
1788                         var canvasDiv = Mandreel_document.getElementById(mandreelAppCanvasDiv);
1789                         canvasDiv.focus();
1790                 }
1791
1792                 // Call mandreel app draw funtion (__draw())
1793                 var nowTime = Date_now();
1794                 if (!g_mandreel_frame_locked)
1795                 {
1796                         g_mandreel_frame_inframe = true;
1797                         if (!_imandreel_pause_game)
1798                                 mandreelAppDraw(nowTime-imandreel_oldTime);
1799                         g_mandreel_frame_inframe = false;
1800                 }
1801                 imandreel_oldTime = nowTime;
1802         }
1803
1804         function render()
1805         {
1806                 // Call mandreel app draw funtion (__draw())
1807                 var nowTime = Date_now();
1808                 if (!g_mandreel_frame_locked)
1809                 {
1810                         g_mandreel_frame_inframe = true;
1811                         if (!_imandreel_pause_game)
1812                                 mandreelAppDraw(nowTime-imandreel_oldTime);
1813                         g_mandreel_frame_inframe = false;
1814                 }
1815                 imandreel_oldTime = nowTime;
1816         }
1817
1818         var imandreel_last_movex = 0;
1819         var imandreel_last_movey = 0;
1820
1821         ////////////////////////////////////////////
1822         function imandreel_onMouseMove(e)
1823         {
1824                 if (!imandreel_is_ready)
1825                         return;
1826
1827                 if (_imandreel_pause_game)
1828                         return;
1829
1830                 var pos = mandreelAppGetElementAbsolutePos(mandreelAppCanvasName);
1831                 var setX = e.clientX - pos.x;
1832                 var setY = e.clientY - pos.y;
1833
1834                   if(navigator.pointer && navigator.pointer.isLocked) {
1835             var deltaX = event.movementX || event.webkitMovementX || event.mozMovementX || 0;
1836             var deltaY = event.movementY || event.webkitMovementY || event.mozMovementX || 0;
1837
1838                         setX = imandreel_last_movex+deltaX;
1839                         setY = imandreel_last_movey+deltaY;
1840                         }
1841
1842
1843                 imandreel_last_movex = setX;
1844                 imandreel_last_movey = setY;
1845                 mandreelAppMouseMove(setX,setY);
1846         }
1847
1848         ////////////////////////////////////////////
1849         function imandreel_onMouseDblClick(e)
1850         {
1851                 if (!imandreel_is_ready)
1852                         return;
1853
1854                 if (_imandreel_pause_game)
1855                         return;
1856
1857                 var pos = mandreelAppGetElementAbsolutePos(mandreelAppCanvasName);
1858                 var setX = e.clientX - pos.x;
1859                 var setY = e.clientY - pos.y;
1860                 mandreelAppMouseDblClick(setX,setY);
1861         }
1862
1863         ////////////////////////////////////////////
1864         var mandreel_mouse_down = false;
1865         var mandreel_rmouse_down = false;
1866         function imandreel_onMouseDown(e)
1867         {
1868                 if (!imandreel_is_ready)
1869                         return;
1870
1871                 if (_imandreel_pause_game)
1872                         return;
1873
1874                 var rightclick;
1875                 if (!e) var e = Mandreel_window.event;
1876                 if (e.which) rightclick = (e.which == 3);
1877                 else if (e.button) rightclick = (e.button == 2);
1878
1879                 var pos = mandreelAppGetElementAbsolutePos(mandreelAppCanvasName);
1880                 var setX = e.clientX - pos.x;
1881                 var setY = e.clientY - pos.y;
1882
1883                 if (!rightclick)
1884                 {
1885                         if (mandreel_mouse_down)
1886                                 return;
1887
1888                         mandreel_mouse_down = true;
1889                         mandreelAppMouseButton(1,setX,setY);
1890                 }
1891                 else
1892                 {
1893                         if (mandreel_rmouse_down)
1894                                 return;
1895
1896                         mandreel_rmouse_down = true;
1897                         mandreelAppMouseButton(3,setX,setY);
1898                 }
1899         }
1900
1901         ////////////////////////////////////////////
1902         function imandreel_onMouseUp(e)
1903         {
1904                 if (!imandreel_is_ready)
1905                         return;
1906
1907                 if (_imandreel_pause_game)
1908                         return;
1909
1910                 var rightclick;
1911                 if (!e) var e = Mandreel_window.event;
1912                 if (e.which) rightclick = (e.which == 3);
1913                 else if (e.button) rightclick = (e.button == 2);
1914
1915                 var pos = mandreelAppGetElementAbsolutePos(mandreelAppCanvasName);
1916                 var setX = e.clientX - pos.x;
1917                 var setY = e.clientY - pos.y;
1918
1919
1920                 if (!rightclick)
1921                 {
1922                         if (mandreel_mouse_down == false)
1923                                 return;
1924
1925                         mandreel_mouse_down = false;
1926                         mandreelAppMouseButton(0,setX,setY);
1927                 }
1928                 else
1929                 {
1930                         if (mandreel_rmouse_down == false)
1931                                 return;
1932
1933                         mandreel_rmouse_down = false;
1934                         mandreelAppMouseButton(2,setX,setY);
1935                 }
1936         }
1937
1938         ////////////////////////////////////////////
1939         function imandreel_onMouseWheel(e)
1940         {
1941                 if (!imandreel_is_ready)
1942                         return;
1943
1944                 if (_imandreel_pause_game)
1945                         return;
1946
1947                 mandreelAppMouseWheel(e.wheelDelta);
1948         }
1949
1950         ////////////////////////////////////////////
1951         function imandreel_onKeyUp(e)
1952         {
1953                 if (!imandreel_is_ready)
1954                         return;
1955
1956                 if (_imandreel_pause_game)
1957                         return;
1958
1959                 var KeyID = e.keyCode;
1960                 mandreelAppKeyEvent(0,KeyID);
1961         }
1962
1963         ////////////////////////////////////////////
1964         Mandreel_window.onkeydown = function(e)
1965         {
1966                 if (mandreelDisableSpaceKey == false && e.keyCode == 32)
1967                         return;
1968                 return !(e.keyCode == 32 || e.keyCode == 9);
1969         };
1970
1971         ////////////////////////////////////////////
1972         function imandreel_onKeyDown(e)
1973         {
1974                 if (e.which === 8) // disable back button on browser
1975         {
1976                 e.preventDefault();
1977             }
1978                 if (!imandreel_is_ready)
1979                         return;
1980
1981                 if (_imandreel_pause_game)
1982                         return;
1983
1984                 var KeyID = e.keyCode;
1985                 mandreelAppKeyEvent(1,KeyID);
1986         }
1987
1988
1989 ////////////////////////////////////////////
1990 // Flash
1991 ////////////////////////////////////////////
1992
1993 (function(){
1994                 try {
1995                         // Disabling SWFObject's Autohide feature
1996                         if (typeof swfobject.switchOffAutoHideShow === "function") {
1997                                 swfobject.switchOffAutoHideShow();
1998                         }
1999                 } catch(e) {}
2000         })();
2001
2002 var imandreel_flash_global_sp = 0;
2003 var imandreel_flash_global_sp2 = 0;
2004 var imandreel_flash_current_sp = 0;
2005
2006 function MandreelInterSwfLoaded2()
2007 {
2008 }
2009 function MandreelInterSwfLoaded()
2010 {
2011         appStartState('scriptLoaded');
2012         var flashMovie = swfobject.getObjectById(mandreelAppCanvasDiv)
2013         dump(flashMovie.width);
2014         flashMovie.MandreelInit();
2015
2016         imandreel_flash_global_sp = MandreelInterGetSWF().MandreelInterGetGlobalStack();
2017         imandreel_flash_global_sp2 = MandreelInterGetSWF().MandreelInterGetGlobalStack2();
2018         if ( mandreelAppStartStateFunc )
2019                 mandreelAppStartStateFunc("ready",mandreelAppCanvasWidth,mandreelAppCanvasHeight);
2020 }
2021
2022
2023
2024 var g_mandreel_swf = null;
2025
2026 function MandreelInterGetSWF()
2027 {
2028         if (g_mandreel_swf)
2029                 return g_mandreel_swf;
2030
2031         g_mandreel_swf = swfobject.getObjectById(mandreelAppCanvasDiv)
2032         return g_mandreel_swf;
2033 }
2034
2035 function MandreelInterWriteInt(ptr, value)
2036 {
2037         MandreelInterGetSWF().MandreelInterWriteInt(ptr,value);
2038 }
2039
2040 function MandreelInterWriteFloat(ptr, value)
2041 {
2042         MandreelInterGetSWF().MandreelInterWriteFloat(ptr,value);
2043 }
2044
2045 function MandreelInterWriteString(ptr, value)
2046 {
2047         MandreelInterGetSWF().MandreelInterWriteString(ptr,value);
2048 }
2049
2050 function MandreelInterWriteWString(ptr, value)
2051 {
2052         MandreelInterGetSWF().MandreelInterWriteWString(ptr,value);
2053 }
2054
2055 function MandreelInterCallFunctionRaw(sp, func_name, returnType)
2056 {
2057         return MandreelInterGetSWF().MandreelInterCallFunctionRaw(sp,func_name,returnType);
2058 }
2059
2060
2061 function assert(condition, _text) {
2062 //console.assert(condition, _text);
2063     if (!condition) {
2064       var text = "Assertion failed: " + _text;
2065       alert(text + ':\n' + (new Error).stack);
2066       ABORT = true;
2067       throw "Assertion: " + text;
2068     }
2069   }
2070
2071
2072
2073 function MandreelLockFrame()
2074 {
2075         MandreelInterGetSWF().MandreelLockFrame();
2076
2077         imandreel_flash_current_sp += 300*1024;
2078
2079         assert(imandreel_flash_current_sp<1024*1024);
2080
2081         return imandreel_flash_current_sp;
2082 }
2083
2084 function MandreelPause()
2085 {
2086         MandreelInterGetSWF().MandreelPause();
2087 }
2088
2089 function MandreelResume()
2090 {
2091         MandreelInterGetSWF().MandreelResume();
2092 }
2093
2094
2095 function MandreelUnlockFrame()
2096 {
2097         imandreel_flash_current_sp -= 300*1024;
2098         MandreelInterGetSWF().MandreelUnlockFrame();
2099 }
2100
2101
2102
2103 function MandreelInterCallFunctionAsync(func_name,param)
2104 {
2105         return MandreelInterGetSWF().MandreelInterCallFunctionAsync(func_name, param);
2106 }
2107
2108
2109 function MandreelInterCallFunction(returnType,func_name)
2110 {
2111         var size_params = 0;
2112
2113         var i;
2114         var num_params = (arguments.length-2)/2;
2115         num_params|=0;
2116         for (i=2;i<num_params*2+2;i+=2)
2117         {
2118                 var type = arguments[i];
2119
2120                 var size_arg = 0;
2121                 switch(type)
2122                 {
2123                         case 'int':
2124                                 size_arg = 4;
2125                                 break;
2126                         case 'float':
2127                                 size_arg = 4;
2128                                 break;
2129                         case 'string':
2130                                 size_arg = 4;
2131                                 size_arg += ((arguments[i+1].length + 4) & 0xfffffffc);
2132                                 break;
2133                         case 'wstring':
2134                                 size_arg = 4;
2135                                 size_arg += ((arguments[i+1].length*2 + 4) & 0xfffffffc);
2136                                 break;
2137                         default:
2138                                 assert(false);
2139                 }
2140
2141                 size_params += size_arg;
2142         }
2143
2144         // stack always 8 byte aligned
2145         size_params=((size_params+7)& 0xfffffff8);
2146
2147         var sp = 0;
2148
2149         if (i<(arguments.length))
2150                 sp = arguments[i];
2151         else
2152         {
2153                 assert(false);
2154         }
2155
2156
2157         sp-=size_params;
2158
2159         MandreelLockFrame();
2160
2161         var offset = 0;
2162         var ptr_data = num_params*4+sp;
2163     for (i=2;i<num_params*2+2;i+=2)
2164         {
2165                 var type = arguments[i];
2166
2167
2168                 var size_arg = 0;
2169                 switch(type)
2170                 {
2171                         case 'int':
2172                                 MandreelInterWriteInt((sp+offset),arguments[i+1]);
2173                                 break;
2174                         case 'float':
2175                                 MandreelInterWriteFloat((sp+offset),arguments[i+1]);
2176                                 break;
2177                         case 'string':
2178                                 {
2179                                         MandreelInterWriteInt((sp+offset),ptr_data);
2180                                         var string = arguments[i+1];
2181                                         MandreelInterWriteString(ptr_data,string);
2182
2183                                         ptr_data += ((string.length + 4) & 0xfffffffc);
2184                                 }
2185                                 break;
2186                         case 'wstring':
2187                                 {
2188                                         MandreelInterWriteInt((sp+offset),ptr_data);
2189                                         var string = arguments[i+1];
2190                                         MandreelInterWriteWString(ptr_data,string);
2191
2192                                         ptr_data += ((string.length*2 + 4) & 0xfffffffc);
2193                                 }
2194                                 break;
2195                         default:
2196                                 assert(false);
2197                 }
2198                 offset+=4;
2199         }
2200
2201         return_value = MandreelInterCallFunctionRaw(sp, func_name, returnType);
2202
2203         MandreelUnlockFrame();
2204
2205         if (returnType == 'int')
2206                 return parseInt(return_value);
2207         else if (returnType == 'float')
2208                 return parseFloat(return_value);
2209
2210         return;
2211 }
2212
2213
2214
2215 // file system
2216
2217 var g_mandreel_timestamp_fs = 0;
2218 var g_mandreel_fs = null;
2219
2220 function onMandreelQuotaOk(fs)
2221 {
2222         g_mandreel_fs = fs;
2223         dump('onMandreelQuotaOk');
2224 }
2225
2226
2227 function MandreelFsErrorHandler(e) {
2228   var msg = '';
2229
2230   switch (e.code) {
2231     case FileError.QUOTA_EXCEEDED_ERR:
2232       msg = 'QUOTA_EXCEEDED_ERR';
2233       break;
2234     case FileError.NOT_FOUND_ERR:
2235       msg = 'NOT_FOUND_ERR';
2236       break;
2237     case FileError.SECURITY_ERR:
2238       msg = 'SECURITY_ERR';
2239       break;
2240     case FileError.INVALID_MODIFICATION_ERR:
2241       msg = 'INVALID_MODIFICATION_ERR';
2242       break;
2243     case FileError.INVALID_STATE_ERR:
2244       msg = 'INVALID_STATE_ERR';
2245       break;
2246     default:
2247       msg = 'Unknown Error';
2248       break;
2249   };
2250
2251   dump('Error: ' + msg);
2252   dump(e);
2253 }
2254
2255 var indexedDB = Mandreel_window.indexedDB || Mandreel_window.webkitIndexedDB ||
2256                 Mandreel_window.mozIndexedDB;
2257
2258 if ('webkitIndexedDB' in Mandreel_window) {
2259   Mandreel_window.IDBTransaction = Mandreel_window.webkitIDBTransaction;
2260   Mandreel_window.IDBKeyRange = Mandreel_window.webkitIDBKeyRange;
2261 }
2262
2263
2264 var mandreel_indexedDB = {};
2265 mandreel_indexedDB.db = null;
2266 mandreel_indexedDB.callback_init = false;
2267
2268 mandreel_indexedDB.onerror = function(e) {
2269   dump(e);
2270 };
2271
2272 mandreel_indexedDB.init = function(callback)
2273 {
2274  try {
2275         var request = indexedDB.open('my_cache', 2);
2276
2277         request.onerror = function(event) {
2278                 callback(false);
2279                 };
2280         request.onupgradeneeded = function(event) {
2281         dump('onupgradeneeded\n');
2282         mandreel_indexedDB.db = event.target.result;
2283     var db = mandreel_indexedDB.db;
2284         var objectStore = db.createObjectStore("cache",{keyPath: "fileName"});
2285         }
2286
2287   request.onsuccess = function(event) {
2288   dump('onsuccess\n');
2289     mandreel_indexedDB.db = event.target.result;
2290         callback(true);
2291
2292   };
2293   }
2294   catch(e)
2295   {
2296         callback(false);
2297   }
2298
2299 }
2300
2301 function mandreel_fs_init(callback, size_bytes, url_time)
2302 {
2303
2304         g_mandreel_timestamp_fs = 99999999999999;
2305
2306
2307
2308
2309         var aux = null;
2310         try     { aux = webkitStorageInfo; } catch(err) { aux = null; }
2311         if (aux == null)
2312         {
2313                 //callback(false);
2314
2315                 var time_request = new XMLHttpRequest();
2316         time_request.open('GET',url_time);
2317         time_request.onreadystatechange = function()
2318         {
2319                 if (time_request.readyState==4)
2320                 {
2321                         if (time_request.status==200 || time_request.status==0)
2322                         {
2323
2324                                 if (time_request.responseText)
2325                                 {
2326                                         g_mandreel_timestamp_fs = parseFloat(time_request.responseText);
2327                                         dump('mandreel_init_fs time ' + g_mandreel_timestamp_fs);
2328                                 }
2329                         }
2330
2331                         mandreel_indexedDB.init(callback);
2332                 }
2333         }
2334         time_request.send();
2335
2336
2337                 return;
2338         }
2339
2340         webkitStorageInfo.requestQuota(
2341                 webkitStorageInfo.PERSISTENT ,   // or PERSISTENT
2342                 size_bytes,
2343                 function(bytes) {  dump('request quota succeed');},
2344                 function () { dump('request quota failed');} );
2345
2346
2347 //      g_mandreel_timestamp_fs =0;
2348
2349         var time_request = new XMLHttpRequest();
2350         time_request.open('GET',url_time);
2351         time_request.onreadystatechange = function()
2352         {
2353                 if (time_request.readyState==4)
2354                 {
2355                         if (time_request.status==200 || time_request.status==0)
2356                         {
2357
2358                                 if (time_request.responseText)
2359                                 {
2360                                         g_mandreel_timestamp_fs = parseFloat(time_request.responseText);
2361                                         dump('mandreel_init_fs time ' + g_mandreel_timestamp_fs);
2362                                 }
2363                         }
2364
2365                         var my_requestFileSystem  = Mandreel_window.requestFileSystem || Mandreel_window.webkitRequestFileSystem;
2366
2367                         my_requestFileSystem(Mandreel_window.PERSISTENT, size_bytes,
2368                                 function(result)
2369                                 {
2370                                         onMandreelQuotaOk(result);
2371
2372
2373                                         if (callback)
2374                                                 Mandreel_setTimeout(callback, 100, true);
2375                                 } , function(e) { MandreelFsErrorHandler(e); if (callback) callback(false); } );
2376                 }
2377         }
2378         time_request.send();
2379 }
2380
2381
2382 mandreel_indexedDB.load = function(file_name, callback)
2383 {
2384         var db = mandreel_indexedDB.db;
2385         var trans = db.transaction(["cache"]);
2386         var store = trans.objectStore("cache");
2387
2388         var key = file_name;
2389
2390          var getReq = store.get(key);
2391            getReq.onsuccess = function (ev) {
2392                         if (getReq.result)
2393         {
2394         dump('chanka ' + g_mandreel_timestamp_fs + ' ' + getReq.result.timeStamp + '\n');
2395                                 if (getReq.result.timeStamp>=g_mandreel_timestamp_fs)
2396                                         callback(getReq.result.data);
2397                                 else
2398                                         callback(null);
2399                         }
2400                         else
2401                                 callback(null);
2402            }
2403            getReq.onerror = function (ev) {
2404                    console.log("index.get failed. Error: " + ev.message);
2405            }
2406 }
2407
2408 function mandreel_fs_get_url(file_name, callback)
2409 {
2410         if (mandreel_indexedDB.db)
2411         {
2412                 callback(null);
2413                 return;
2414         }
2415
2416
2417         if (g_mandreel_fs == null)
2418         {
2419                 callback(null);
2420                 return;
2421         }
2422
2423         g_mandreel_fs.root.getFile(file_name, {}, function(fileEntry) {
2424
2425         fileEntry.getMetadata(function(metaData){
2426         var my_seconds = metaData.modificationTime.getTime()/1000;
2427
2428         if (g_mandreel_timestamp_fs>my_seconds)
2429         {
2430                 callback(null);
2431         }
2432         else
2433         {
2434                 //alert('mandreel_fscachefile2');
2435
2436
2437                 if (Mandreel_window.localStorage.getItem(mandreel_fs_get_key(file_name)) != null)
2438                         callback(fileEntry.toURL());
2439                 else
2440                         callback(null);
2441
2442         }
2443
2444
2445                 }, MandreelFsErrorHandler);
2446
2447
2448   }, function(error) {callback(null);});
2449
2450          return;
2451
2452 }
2453
2454 function mandreel_fs_load_binary(file_name, callback)
2455  {
2456         if (mandreel_indexedDB.db)
2457         {
2458                 mandreel_indexedDB.load(file_name,callback);
2459                 return;
2460         }
2461
2462
2463         if (g_mandreel_fs == null)
2464         {
2465                 callback(null);
2466                 return;
2467         }
2468
2469
2470         g_mandreel_fs.root.getFile(file_name, {}, function(fileEntry) {
2471
2472         fileEntry.getMetadata(function(metaData){
2473         var my_seconds = metaData.modificationTime.getTime()/1000;
2474
2475         if (g_mandreel_timestamp_fs>my_seconds)
2476         {
2477                 dump('mandreel_fscachefile1');
2478                 Mandreel_window.localStorage.removeItem(mandreel_fs_get_key(file_name));
2479                 fileEntry.remove(function() {
2480                                 callback(null);
2481                         }, MandreelFsErrorHandler);
2482
2483         }
2484         else
2485         {
2486                 //alert('mandreel_fscachefile2');
2487                 dump('mandreel_fscachefile2 ' + my_seconds);
2488
2489                 fileEntry.file(function(file) {
2490
2491                                 var reader = new FileReader();
2492
2493
2494                            reader.onloadend = function(e) {
2495
2496                                    if (this.result.byteLength && Mandreel_window.localStorage.getItem(mandreel_fs_get_key(file_name)) != null)
2497                                    {
2498                                                 dump('mandreel_fs_loadFile ' + file_name);
2499                                                 callback(this.result);
2500                                         }
2501                                         else
2502                                                 callback(null);
2503
2504                            };
2505
2506
2507                                  reader.readAsArrayBuffer(file);
2508
2509
2510                         }, MandreelFsErrorHandler);
2511
2512         }
2513
2514
2515                 }, MandreelFsErrorHandler);
2516
2517
2518   }, function(error) {dump('mandreel_fscachefile3');    callback(null);});
2519
2520          return;
2521  }
2522
2523
2524  mandreel_indexedDB.save = function(file_name, data)
2525 {
2526         var db = mandreel_indexedDB.db;
2527
2528
2529   var trans = db.transaction(["cache"], IDBTransaction.READ_WRITE);
2530   var store = trans.objectStore("cache");
2531   var request = store.put({
2532     "data": data,
2533         "timeStamp" : Date_now()/1000,
2534     "fileName" : file_name
2535   });
2536
2537   request.onsuccess = function(e) {
2538     // Re-render all the todo's
2539    // html5rocks.indexedDB.getAllTodoItems();
2540    dump('mandreel_indexedDB.save ok ');
2541   };
2542
2543   request.onerror = function(e) {
2544     dump('mandreel_indexedDB.save onerror ' + file_name);
2545         dump(e);
2546   };
2547 }
2548
2549 function mandreel_fs_get_key(name)
2550 {
2551         return 'mandreel_fs_' + name;
2552 }
2553
2554 function mandreel_is_filesystem()
2555 {
2556         if (mandreel_indexedDB.db)
2557                 return false;
2558
2559         if (!g_mandreel_fs)
2560                 return false;
2561
2562         return true;
2563 }
2564
2565 function mandreel_is_indexeddb()
2566 {
2567         if (mandreel_indexedDB.db)
2568                 return true;
2569
2570         return false;
2571 }
2572
2573  function mandreel_fs_saveFile(name, my_arrayBuffer)
2574 {
2575         if (mandreel_indexedDB.db)
2576         {
2577                 mandreel_indexedDB.save(name,my_arrayBuffer);
2578                 return;
2579         }
2580
2581         if (!g_mandreel_fs)
2582                 return;
2583
2584         Mandreel_window.localStorage.removeItem(mandreel_fs_get_key(name));
2585         g_mandreel_fs.root.getFile(name, {create: true}, function(fileEntry) {
2586
2587     // Create a FileWriter object for our FileEntry (log.txt).
2588     fileEntry.createWriter(function(fileWriter) {
2589
2590       fileWriter.onwriteend = function(e) {
2591                 Mandreel_window.localStorage.setItem(mandreel_fs_get_key(name),'valid');
2592         dump('Write completed.');
2593       };
2594
2595       fileWriter.onerror = function(e) {
2596         dump('Write failed: ' + e.toString());
2597       };
2598
2599           var my_BlobBuilder = Mandreel_window.MozBlobBuilder || Mandreel_window.WebKitBlobBuilder || Mandreel_window.BlobBuilder;
2600
2601           var bb = new my_BlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12.
2602       bb.append(my_arrayBuffer);
2603       fileWriter.write(bb.getBlob('text/plain'));
2604
2605
2606
2607     }, MandreelFsErrorHandler);
2608
2609   }, MandreelFsErrorHandler);
2610 }
2611
2612
2613 function mandreel_fs_load_text(file_name, callback)
2614  {
2615
2616         if (mandreel_indexedDB.db)
2617         {
2618                 mandreel_indexedDB.load(file_name,callback);
2619                 return;
2620         }
2621
2622         if (g_mandreel_fs == null)
2623         {
2624                 callback(null);
2625                 return;
2626         }
2627
2628
2629         g_mandreel_fs.root.getFile(file_name, {}, function(fileEntry) {
2630
2631         fileEntry.getMetadata(function(metaData){
2632         var my_seconds = metaData.modificationTime.getTime()/1000;
2633
2634         if (g_mandreel_timestamp_fs>my_seconds)
2635         {
2636                 dump('mandreel_fscachefile1');
2637                 Mandreel_window.localStorage.removeItem(mandreel_fs_get_key(file_name));
2638                 fileEntry.remove(function() {
2639                                 callback(null);
2640                         }, MandreelFsErrorHandler);
2641
2642         }
2643         else
2644         {
2645                 //alert('mandreel_fscachefile2');
2646                 dump('mandreel_fscachefile2 ' + my_seconds);
2647
2648                 fileEntry.file(function(file) {
2649
2650                                 var reader = new FileReader();
2651
2652
2653                            reader.onloadend = function(e) {
2654
2655
2656                                    if (this.result.length && Mandreel_window.localStorage.getItem(mandreel_fs_get_key(file_name)) != null)
2657                                    {
2658                                                 dump('mandreel_fs_loadFile ' + file_name);
2659                                                 callback(this.result);
2660                                         }
2661                                         else
2662                                                 callback(null);
2663
2664                            };
2665
2666
2667                                  reader.readAsText(file);
2668
2669
2670                         }, MandreelFsErrorHandler);
2671
2672         }
2673
2674
2675                 }, MandreelFsErrorHandler);
2676
2677
2678   }, function(error) {dump('mandreel_fscachefile3');    callback(null);});
2679
2680          return;
2681  }
2682
2683
2684  // full screen
2685
2686
2687 /* The following code was removed for benchmarking:
2688  var __screen = screen; */
2689
2690         try
2691         {
2692         (function(global) {
2693     "use strict";
2694         var elementPrototype = (global.HTMLElement || global.Element)["prototype"];
2695
2696          // document.isFullScreen
2697     if(!Mandreel_document.hasOwnProperty("fullscreenEnabled")) {
2698         var getter = (function() {
2699             // These are the functions that match the spec, and should be preferred
2700             if("webkitIsFullScreen" in Mandreel_document) {
2701                 return function() { return Mandreel_document.webkitIsFullScreen; }
2702             }
2703             if("mozFullScreen" in Mandreel_document) {
2704                 return function() { return Mandreel_document.mozFullScreen; }
2705             }
2706             return function() { return false }; // not supported, never fullscreen
2707         })();
2708
2709         Object.defineProperty(Mandreel_document, "fullscreenEnabled", {
2710             enumerable: true, configurable: false, writeable: false,
2711             get: getter
2712         });
2713     }
2714
2715     if(!Mandreel_document.hasOwnProperty("fullscreenElement")) {
2716         var getter = (function() {
2717             // These are the functions that match the spec, and should be preferred
2718             if("webkitFullscreenElement" in Mandreel_document) {
2719                 return function() { return Mandreel_document.webkitFullscreenElement; }
2720             }
2721             if("mozFullscreenElemen" in Mandreel_document) {
2722                 return function() { return Mandreel_document.mozFullscreenElemen; }
2723             }
2724             return function() { return null }; // not supported
2725         })();
2726
2727         Object.defineProperty(Mandreel_document, "fullscreenElement", {
2728             enumerable: true, configurable: false, writeable: false,
2729             get: getter
2730         });
2731     }
2732
2733     // Document event: fullscreenchange
2734     function fullscreenchange(oldEvent) {
2735         var newEvent = Mandreel_document.createEvent("CustomEvent");
2736         newEvent.initCustomEvent("fullscreenchange", true, false, null);
2737         // TODO: Any need for variable copy?
2738         Mandreel_document.dispatchEvent(newEvent);
2739     }
2740     Mandreel_document.addEventListener("webkitfullscreenchange", fullscreenchange, false);
2741     Mandreel_document.addEventListener("mozfullscreenchange", fullscreenchange, false);
2742
2743     // Document event: fullscreenerror
2744     function fullscreenerror(oldEvent) {
2745         var newEvent = Mandreel_document.createEvent("CustomEvent");
2746         newEvent.initCustomEvent("fullscreenerror", true, false, null);
2747         // TODO: Any need for variable copy?
2748         Mandreel_document.dispatchEvent(newEvent);
2749     }
2750     Mandreel_document.addEventListener("webkitfullscreenerror", fullscreenerror, false);
2751     Mandreel_document.addEventListener("mozfullscreenerror", fullscreenerror, false);
2752
2753     // element.requestFullScreen
2754     if(!elementPrototype.requestFullScreen) {
2755         elementPrototype.requestFullScreen = (function() {
2756             if(elementPrototype.webkitRequestFullScreen) {
2757                 return function() {
2758                     this.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
2759                 }
2760             }
2761
2762             return  elementPrototype.mozRequestFullScreen    ||
2763                     function(){ /* unsupported, fail silently */ };
2764         })();
2765     }
2766
2767     // document.cancelFullscreen
2768     if(!Mandreel_document.cancelFullScreen) {
2769         Mandreel_document.cancelFullScreen = (function() {
2770             return  Mandreel_document.webkitCancelFullScreen ||
2771                     Mandreel_document.mozCancelFullScreen ||
2772                     function(){ /* unsupported, fail silently */ };
2773         })();
2774     }
2775         })((typeof(exports) != 'undefined') ? global : Mandreel_window);
2776         }
2777         catch(e)
2778         {
2779         }
2780
2781
2782 try
2783         {
2784 var __onErrorFullscreen = function() {
2785   dump("Mouse lock was not successful.");
2786 };
2787
2788 Mandreel_document.addEventListener('fullscreenchange', function(e) {
2789
2790 var width;
2791 var height;
2792  var canvas = Mandreel_document.getElementById(mandreelAppCanvasName);
2793  if(Mandreel_document.fullscreenEnabled) {
2794
2795
2796             width = __screen.width;
2797             height = __screen.height;
2798
2799         } else {
2800             width = mandreelAppWidthSrc;
2801             height = mandreelAppHeightSrc;
2802         }
2803
2804                 canvas.width = width;
2805                 canvas.height = height;
2806                 mandreelAppResize(width, height);
2807
2808   if (Mandreel_document.fullscreenEnabled && navigator.pointer) {
2809     navigator.pointer.lock(Mandreel_document.body, function() {
2810       // Locked and ready to play.
2811     }, __onErrorFullscreen);
2812   }
2813 }, false);
2814
2815 }
2816 catch(e)
2817 {
2818 }
2819
2820
2821
2822 function mandreelAppFullscreen(enable)
2823 {
2824         var canvas = Mandreel_document.getElementById(mandreelAppCanvasName);
2825         if ( mandreelAppPlatform == "webgl" || mandreelAppPlatform == "canvas" )
2826         {
2827                 if (canvas)
2828                 {
2829                         if (enable)
2830                                 canvas.requestFullScreen();
2831                         else
2832                                 Mandreel_document.cancelFullScreen();
2833                 }
2834         }
2835 }
2836
2837
2838 function mandreelAppDisableForceFocus()
2839 {
2840         mandreelAppForceFocus = false;
2841 }
2842
2843 function mandreelAppEnableForceFocus()
2844 {
2845         mandreelAppForceFocus = true;
2846 }
2847
2848 var imandreel_base64 = {};
2849 imandreel_base64.PADCHAR = '=';
2850 imandreel_base64.ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
2851
2852 imandreel_base64.makeDOMException = function() {
2853     // sadly in FF,Safari,Chrome you can't make a DOMException
2854     var e, tmp;
2855
2856     try {
2857         return new DOMException(DOMException.INVALID_CHARACTER_ERR);
2858     } catch (tmp) {
2859         // not available, just passback a duck-typed equiv
2860         // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error
2861         // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error/prototype
2862         var ex = new Error("DOM Exception 5");
2863
2864         // ex.number and ex.description is IE-specific.
2865         ex.code = ex.number = 5;
2866         ex.name = ex.description = "INVALID_CHARACTER_ERR";
2867
2868         // Safari/Chrome output format
2869         ex.toString = function() { return 'Error: ' + ex.name + ': ' + ex.message; };
2870         return ex;
2871     }
2872 }
2873
2874 imandreel_base64.getbyte64 = function(s,i) {
2875     // This is oddly fast, except on Chrome/V8.
2876     //  Minimal or no improvement in performance by using a
2877     //   object with properties mapping chars to value (eg. 'A': 0)
2878     var idx = imandreel_base64.ALPHA.indexOf(s.charAt(i));
2879     if (idx === -1) {
2880         throw imandreel_base64.makeDOMException();
2881     }
2882     return idx;
2883 }
2884
2885 imandreel_base64.decode = function(s) {
2886     // convert to string
2887     s = '' + s;
2888     var getbyte64 = imandreel_base64.getbyte64;
2889     var pads, i, b10;
2890     var imax = s.length
2891     if (imax === 0) {
2892         return s;
2893     }
2894
2895     if (imax % 4 !== 0) {
2896         throw imandreel_base64.makeDOMException();
2897     }
2898
2899     pads = 0
2900     if (s.charAt(imax - 1) === imandreel_base64.PADCHAR) {
2901         pads = 1;
2902         if (s.charAt(imax - 2) === imandreel_base64.PADCHAR) {
2903             pads = 2;
2904         }
2905         // either way, we want to ignore this last block
2906         imax -= 4;
2907     }
2908
2909     var x = [];
2910     for (i = 0; i < imax; i += 4) {
2911         b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) |
2912             (getbyte64(s,i+2) << 6) | getbyte64(s,i+3);
2913         x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff, b10 & 0xff));
2914     }
2915
2916     switch (pads) {
2917     case 1:
2918         b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | (getbyte64(s,i+2) << 6);
2919         x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff));
2920         break;
2921     case 2:
2922         b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12);
2923         x.push(String.fromCharCode(b10 >> 16));
2924         break;
2925     }
2926     return x.join('');
2927 }
2928
2929 if (!Mandreel_window.atob) {
2930 Mandreel_window.atob = function(a) { return  imandreel_base64.decode(a); }
2931 }
2932
2933
2934 function imandreel_interop_callbridge(new_method, sp)
2935 {
2936
2937         var n = new Array();
2938
2939         for( var i = 2; i < arguments.length; i++ )
2940         {
2941
2942                 if (typeof arguments[i] == 'string')
2943                         n.push(atob(arguments[i]));
2944                 else
2945                         n.push(arguments[i]);
2946         }
2947
2948         var total_args = arguments.length-2;
2949
2950         switch(total_args)
2951         {
2952                 case 0:
2953                         return Mandreel_window[new_method](sp);
2954                 case 1:
2955                         return Mandreel_window[new_method](sp, n[0]);
2956                 case 2:
2957                         return Mandreel_window[new_method](sp, n[0], n[1]);
2958                 case 3:
2959                         return Mandreel_window[new_method](sp, n[0], n[1], n[2]);
2960                 case 4:
2961                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3]);
2962                 case 5:
2963                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4]);
2964                 case 6:
2965                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5]);
2966                 case 7:
2967                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6]);
2968                 case 8:
2969                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]);
2970                 case 9:
2971                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8]);
2972                 case 10:
2973                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9]);
2974                 case 11:
2975                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10]);
2976                 case 12:
2977                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11]);
2978                 case 13:
2979                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11], n[12]);
2980                 case 14:
2981                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11], n[12], n[13]);
2982                 case 15:
2983                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11], n[12], n[13], n[14]);
2984                 case 16:
2985                         return Mandreel_window[new_method](sp, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11], n[12], n[13], n[14], n[15]);
2986                 break;
2987         }
2988
2989 }
2990 function imandreel_as3_dump(param)
2991 {
2992         dump(atob(param));
2993 }
2994
2995
2996 var mandreel_embed_plugin;
2997
2998 function PluginMandreelInterWriteInt(ptr, value)
2999 {
3000         mandreel_embed_plugin.MandreelInterCalls("WriteInt", ptr,value);
3001 }
3002
3003 function PluginMandreelInterWriteFloat(ptr, value)
3004 {
3005         mandreel_embed_plugin.MandreelInterCalls("WriteFloat", ptr,value);
3006 }
3007
3008 function PluginMandreelInterWriteString(ptr, value)
3009 {
3010         mandreel_embed_plugin.MandreelInterCalls("WriteString", ptr,value);
3011 }
3012
3013 function PluginMandreelInterWriteWString(ptr, value)
3014 {
3015         mandreel_embed_plugin.MandreelInterCalls("WriteWString", ptr,value);
3016 }
3017
3018 var mandreel_plugin_current_sp = 0;
3019
3020 function PluginMandreelLockFrame()
3021 {
3022         var result = mandreel_embed_plugin.MandreelInterCalls("LockFrame");
3023
3024         mandreel_plugin_current_sp+=300*1024;
3025
3026         assert(mandreel_plugin_current_sp<1024*1024);
3027
3028         return result+mandreel_plugin_current_sp;
3029 }
3030
3031 function PluginMandreelPause()
3032 {
3033         mandreel_embed_plugin.MandreelInterCalls("Pause");
3034 }
3035
3036 function PluginMandreelResume()
3037 {
3038         mandreel_embed_plugin.MandreelInterCalls("Resume");
3039 }
3040
3041
3042 function PluginMandreelUnlockFrame()
3043 {
3044         mandreel_embed_plugin.MandreelInterCalls("UnlockFrame");
3045
3046         mandreel_plugin_current_sp-=300*1024;
3047 }
3048
3049 function PluginMandreelInterCallFunction()
3050 {
3051         var total_args = arguments.length;
3052
3053         switch(total_args)
3054         {
3055                 case 0:
3056                         return mandreel_embed_plugin.MandreelInterCallFunction();
3057                 case 1:
3058                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0]);
3059                 case 2:
3060                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1]);
3061                 case 3:
3062                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2]);
3063                 case 4:
3064                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3]);
3065                 case 5:
3066                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
3067                 case 6:
3068                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
3069                 case 7:
3070                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
3071                 case 8:
3072                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]);
3073                 case 9:
3074                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8]);
3075                 case 10:
3076                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]);
3077                 case 11:
3078                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10]);
3079                 case 12:
3080                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11]);
3081                 case 13:
3082                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11], arguments[12]);
3083                 case 14:
3084                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11], arguments[12], arguments[13]);
3085                 case 15:
3086                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11], arguments[12], arguments[13], arguments[14]);
3087                 case 16:
3088                         return mandreel_embed_plugin.MandreelInterCallFunction(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11], arguments[12], arguments[13], arguments[14], arguments[15]);
3089                 break;
3090         }
3091 }
3092
3093 function mandreel_plugin_draw()
3094 {
3095         var canvas = Mandreel_document.getElementById('canvasDiv');
3096         WebGLUtils.requestAnimationFrame(canvas, mandreel_plugin_draw);
3097         mandreel_embed_plugin.MandreelInterCalls("AppDraw");
3098
3099 }
3100
3101 function mandreelInitPluginPlatform(params)
3102 {
3103
3104         if ( params.width != null )
3105                 mandreelAppWidthSrc = params.width;
3106
3107         if ( params.height != null )
3108                 mandreelAppHeightSrc = params.height;
3109
3110
3111         mandreel_embed_plugin = Mandreel_document.createElement('embed');
3112         mandreel_embed_plugin.setAttribute('width',mandreelAppWidthSrc);
3113         mandreel_embed_plugin.setAttribute('height',mandreelAppHeightSrc);
3114         mandreel_embed_plugin.setAttribute('type',"application/halfbrick-npruntime-scriptable-plugin");
3115
3116         var div = Mandreel_document.getElementById('canvasDiv');
3117
3118
3119         var oChild=div.firstChild;
3120
3121         div.replaceChild(mandreel_embed_plugin, oChild);
3122
3123         var flashElement = Mandreel_document.getElementById('FlashWrapper');
3124         if ( flashElement != null )
3125         {
3126                 flashElement.style.visibility = "hidden";
3127                 flashElement.style.width = "0px";
3128                 flashElement.style.height = "0px";
3129         }
3130
3131
3132
3133
3134
3135         Mandreel_window.MandreelInterWriteInt     = PluginMandreelInterWriteInt;
3136         Mandreel_window.MandreelInterWriteFloat   = PluginMandreelInterWriteInt;
3137         Mandreel_window.MandreelInterWriteString  = PluginMandreelInterWriteString;
3138         Mandreel_window.MandreelInterWriteWString = PluginMandreelInterWriteWString;
3139         Mandreel_window.MandreelLockFrame         = PluginMandreelLockFrame;
3140         Mandreel_window.MandreelUnlockFrame       = PluginMandreelUnlockFrame;
3141         Mandreel_window.MandreelInterCallFunction = PluginMandreelInterCallFunction;
3142         Mandreel_window.MandreelPause                    = PluginMandreelPause;
3143         Mandreel_window.MandreelResume                   = PluginMandreelResume;
3144
3145         Mandreel_setTimeout(function () {
3146
3147         if ( typeof(params.pluginSolutionName) != 'undefined' )
3148                 mandreel_embed_plugin.init(params.pluginDLL, params.pluginWorkingFolder,params.pluginSolutionName);
3149         else