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