Quixe=function(){var self={};function quixe_prepare(image,all_options){game_image=image;var ls=game_image.slice(0,64);var ix,val;for(ix=0;ix>>16)&0xffff;var al=a&0xffff;var bh=(b>>>16)&0xffff;var bl=b&0xffff;return((al*bl)+(((ah*bl+al*bh)<<16)>>>0)|0);};} var bytestring_table=Array(256);var quotechar_table=Array(256);function setup_bytestring_table(){var ix,val;for(ix=0;ix<0x100;ix++){val=ix.toString(16);if(ix<0x10) val="0"+val;bytestring_table[ix]=val;} for(ix=0;ix<0x100;ix++){if(ix>=0x20&&ix<0x7f){if(ix==0x22||ix==0x27||ix==0x5c) val="\\"+String.fromCharCode(ix);else val=String.fromCharCode(ix);} else if(ix==0x0a){val="\\n";} else{val="\\x"+bytestring_table[ix];} quotechar_table[ix]=val;}} function ByteRead4(arr,addr){return(arr[addr]*0x1000000)+(arr[addr+1]*0x10000) +(arr[addr+2]*0x100)+(arr[addr+3]);} function ByteRead2(arr,addr){return(arr[addr]*0x100)+(arr[addr+1]);} function ByteRead1(arr,addr){return arr[addr];} function Mem1(addr){return memmap[addr];} function Mem2(addr){return(memmap[addr]*0x100)+(memmap[addr+1]);} function Mem4(addr){return(memmap[addr]*0x1000000)+(memmap[addr+1]*0x10000) +(memmap[addr+2]*0x100)+(memmap[addr+3]);} function MemSlice(addr,length){return memmap.slice(addr,addr+length);} function MemW1(addr,val){memmap[addr]=val&0xFF;} function MemW2(addr,val){memmap[addr]=(val>>8)&0xFF;memmap[addr+1]=val&0xFF;} function MemW4(addr,val){memmap[addr]=(val>>24)&0xFF;memmap[addr+1]=(val>>16)&0xFF;memmap[addr+2]=(val>>8)&0xFF;memmap[addr+3]=val&0xFF;} self.Mem1=Mem1;self.Mem2=Mem2;self.Mem4=Mem4;self.MemSlice=MemSlice;self.MemW1=MemW1;self.MemW2=MemW2;self.MemW4=MemW4;function BytePushString(arr,str){for(var ix=0;ix>24)&0xFF);arr.push((val>>16)&0xFF);arr.push((val>>8)&0xFF);arr.push(val&0xFF);} function BytePush2(arr,val){arr.push((val>>8)&0xFF);arr.push(val&0xFF);} function BytePush1(arr,val){arr.push(val&0xFF);} function ByteWrite4(arr,addr,val){arr[addr]=(val>>24)&0xFF;arr[addr+1]=(val>>16)&0xFF;arr[addr+2]=(val>>8)&0xFF;arr[addr+3]=val&0xFF;} function ByteReadString(arr,addr,len){return String.fromCharCode.apply(this,arr.slice(addr,addr+len));} function QuoteMem1(addr){if(memmap[addr]>=0x80) return"0xffffff"+bytestring_table[memmap[addr]];return"0x"+bytestring_table[memmap[addr]];} function QuoteMem2(addr){if(memmap[addr]>=0x80) return"0xffff"+bytestring_table[memmap[addr]]+bytestring_table[memmap[addr+1]];if(memmap[addr]) return"0x"+bytestring_table[memmap[addr]]+bytestring_table[memmap[addr+1]];return"0x"+bytestring_table[memmap[addr+1]];} function QuoteMem4(addr){if(memmap[addr]) return"0x"+bytestring_table[memmap[addr]]+bytestring_table[memmap[addr+1]]+bytestring_table[memmap[addr+2]]+bytestring_table[memmap[addr+3]];if(memmap[addr+1]) return"0x"+bytestring_table[memmap[addr+1]]+bytestring_table[memmap[addr+2]]+bytestring_table[memmap[addr+3]];if(memmap[addr+2]) return"0x"+bytestring_table[memmap[addr+2]]+bytestring_table[memmap[addr+3]];return"0x"+bytestring_table[memmap[addr+3]];} function ReadArgByte(addr){if(addr==0xffffffff) return self.frame.valstack.pop()&0xFF;else return Mem1(addr);} function WriteArgByte(addr,val){if(addr==0xffffffff) self.frame.valstack.push(val&0xFF);else MemW1(addr,val);} function ReadArgWord(addr){if(addr==0xffffffff) return self.frame.valstack.pop();else return Mem4(addr);} function WriteArgWord(addr,val){if(addr==0xffffffff) self.frame.valstack.push(val);else MemW4(addr,val);} function ReadStructField(addr,fieldnum){if(addr==0xffffffff) return self.frame.valstack.pop();else return Mem4(addr+4*fieldnum);} function WriteStructField(addr,fieldnum,val){if(addr==0xffffffff) self.frame.valstack.push(val);else MemW4(addr+4*fieldnum,val);} function SetResumeStore(val){self.resumevalue=val;} function CharToString(val){if(val<0x10000){return String.fromCharCode(val);} else{val-=0x10000;return String.fromCharCode(0xD800+(val>>10),0xDC00+(val&0x3FF));}} function QuoteCharToString(val){if(val<0x100){return quotechar_table[val];} else if(val<0x10000){val=val.toString(16);while(val.length<4) val="0"+val;return("\\u"+val);} else{var val2;val-=0x10000;val2=0xD800+(val>>10);val=0xDC00+(val&0x3FF);return("\\u"+val2.toString(16)+"\\u"+val.toString(16));}} function QuoteStr1ToString(val){return QuoteCharToString(val.charCodeAt(0));} var regexp_string_unsafe=/[^a-zA-Z0-9 .,;:?!=_+()-]/g;function QuoteEscapeString(val){val=val.replace(regexp_string_unsafe,QuoteStr1ToString);return'"'+val+'"';} function fatal_error(msg){var ix,val;if(arguments.length>1){msg+=" (";for(ix=1;ix=arr.length){qlog("Bad frameptr in serialized stack frame");return undefined;} arr=arr.splice(frameptr,arr.length);var framelen=ByteRead4(arr,0);var localspos=ByteRead4(arr,4);var rawformat=arr.slice(8,localspos);var localsformat=[];var addr=8;while(1){var loctype=ByteRead1(arr,addr);addr++;var locnum=ByteRead1(arr,addr);addr++;if(loctype==0){break;} if(loctype!=1&&loctype!=2&&loctype!=4){fatal_error("Invalid local variable size in function header.",loctype);} localsformat.push({size:loctype,count:locnum});} var vmfunc=new VMFunc(null,null,localsformat,rawformat);var frame=new StackFrame(vmfunc);frame.framestart=frameptr;for(var i=0;i>>0;context.code.push("self.pc = "+newpc+";");context.vmfunc.pathaddrs[newpc]=true;}} else{oputil_unload_offstate(context,!unconditional);context.code.push("if (("+operand+")==0 || ("+operand+")==1) {");context.code.push("if (self.leave_function()) return self.VMStopped;");context.code.push("self.pop_callstub("+operand+");");context.code.push("}");context.code.push("else {");context.code.push("self.pc = ("+context.cp+"+("+operand+")-2) >>>0;");context.code.push("}");} context.code.push("return;");} var opcode_table={0x0:function(context,operands){},0x10:function(context,operands){context.code.push(operands[2]+"(("+operands[0]+")+("+operands[1]+")) >>>0);");},0x11:function(context,operands){context.code.push(operands[2]+"(("+operands[0]+")-("+operands[1]+")) >>>0);");},0x12:function(context,operands){var sign0=oputil_signify_operand(context,operands[0]);var sign1=oputil_signify_operand(context,operands[1]);context.code.push(operands[2]+"(Math.imul(("+sign0+"),("+sign1+"))) >>>0);");},0x13:function(context,operands){var sign0=oputil_signify_operand(context,operands[0]);var sign1=oputil_signify_operand(context,operands[1]);var holdvar=alloc_holdvar(context);context.code.push(holdvar+"=(("+sign0+")/("+sign1+"));");context.code.push("if (!isFinite("+holdvar+")) self.fatal_error('Division by zero.');");context.code.push(operands[2]+"("+holdvar+">=0)?Math.floor("+holdvar+"):(-Math.floor(-"+holdvar+") >>>0));");},0x14:function(context,operands){var sign0=oputil_signify_operand(context,operands[0]);var sign1=oputil_signify_operand(context,operands[1]);var holdvar=alloc_holdvar(context);context.code.push(holdvar+"=(("+sign0+")%("+sign1+"));");context.code.push("if (!isFinite("+holdvar+")) self.fatal_error('Modulo division by zero.');");context.code.push(operands[2]+holdvar+" >>>0);");},0x15:function(context,operands){context.code.push(operands[1]+"(-("+operands[0]+")) >>>0);");},0x18:function(context,operands){context.code.push(operands[2]+"(("+operands[0]+")&("+operands[1]+")) >>>0);");},0x19:function(context,operands){context.code.push(operands[2]+"(("+operands[0]+")|("+operands[1]+")) >>>0);");},0x1a:function(context,operands){context.code.push(operands[2]+"(("+operands[0]+")^("+operands[1]+")) >>>0);");},0x1b:function(context,operands){context.code.push(operands[1]+"(~("+operands[0]+")) >>>0);");},0x1c:function(context,operands){if(quot_isconstant(operands[1])){var val=Number(operands[1]);if(val<32) context.code.push(operands[2]+"(("+operands[0]+")<<"+val+") >>>0);");else context.code.push(operands[2]+"0);");} else{context.code.push(operands[2]+"("+operands[1]+"<32) ? (("+operands[0]+"<<"+operands[1]+") >>>0) : 0);");}},0x1d:function(context,operands){if(quot_isconstant(operands[1])){var val=Number(operands[1]);if(val<32) context.code.push(operands[2]+"(("+operands[0]+")>>"+val+") >>>0);");else context.code.push(operands[2]+"(("+operands[0]+")&0x80000000) ? 0xffffffff : 0);");} else{context.code.push("if ("+operands[0]+" & 0x80000000) {");context.code.push(operands[2]+"("+operands[1]+"<32) ? (("+operands[0]+">>"+operands[1]+") >>>0) : 0xffffffff);");context.code.push("} else {");context.code.push(operands[2]+"("+operands[1]+"<32) ? (("+operands[0]+">>"+operands[1]+") >>>0) : 0);");context.code.push("}");}},0x1e:function(context,operands){if(quot_isconstant(operands[1])){var val=Number(operands[1]);if(val<32) context.code.push(operands[2]+"("+operands[0]+")>>>"+val+");");else context.code.push(operands[2]+"0);");} else{context.code.push(operands[2]+"("+operands[1]+"<32) ? ("+operands[0]+">>>"+operands[1]+") : 0);");}},0x20:function(context,operands){oputil_perform_jump(context,operands[0],true);context.path_ends=true;},0x104:function(context,operands){if(quot_isconstant(operands[0])){var newpc=Number(operands[0]);context.code.push("self.pc = "+newpc+";");context.vmfunc.pathaddrs[newpc]=true;} else{context.code.push("self.pc = "+operands[0]+";");} oputil_unload_offstate(context);context.code.push("return;");context.path_ends=true;},0x22:function(context,operands){context.code.push("if (("+operands[0]+")==0) {");oputil_perform_jump(context,operands[1]);context.code.push("}");},0x23:function(context,operands){context.code.push("if (("+operands[0]+")!=0) {");oputil_perform_jump(context,operands[1]);context.code.push("}");},0x24:function(context,operands){context.code.push("if (("+operands[0]+")==("+operands[1]+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x25:function(context,operands){context.code.push("if (("+operands[0]+")!=("+operands[1]+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x26:function(context,operands){var sign0=oputil_signify_operand(context,operands[0]);var sign1=oputil_signify_operand(context,operands[1]);context.code.push("if (("+sign0+")<("+sign1+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x27:function(context,operands){var sign0=oputil_signify_operand(context,operands[0]);var sign1=oputil_signify_operand(context,operands[1]);context.code.push("if (("+sign0+")>=("+sign1+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x28:function(context,operands){var sign0=oputil_signify_operand(context,operands[0]);var sign1=oputil_signify_operand(context,operands[1]);context.code.push("if (("+sign0+")>("+sign1+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x29:function(context,operands){var sign0=oputil_signify_operand(context,operands[0]);var sign1=oputil_signify_operand(context,operands[1]);context.code.push("if (("+sign0+")<=("+sign1+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x2a:function(context,operands){context.code.push("if (("+operands[0]+")<("+operands[1]+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x2b:function(context,operands){context.code.push("if (("+operands[0]+")>=("+operands[1]+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x2c:function(context,operands){context.code.push("if (("+operands[0]+")>("+operands[1]+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x2d:function(context,operands){context.code.push("if (("+operands[0]+")<=("+operands[1]+")) {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x30:function(context,operands){if(quot_isconstant(operands[1])){var ix;var argc=Number(operands[1]);for(ix=0;ix>>0):(val&0xffff);context.code.push(operands[1]+val+");");} else{context.code.push(operands[1]+"("+operands[0]+" & 0x8000) ? (("+operands[0]+" | 0xffff0000) >>> 0) : ("+operands[0]+" & 0xffff));");}},0x45:function(context,operands){var val;if(quot_isconstant(operands[0])){val=Number(operands[0]);val=(val&0x80)?((val|0xffffff00)>>>0):(val&0xff);context.code.push(operands[1]+val+");");} else{context.code.push(operands[1]+"("+operands[0]+" & 0x80) ? (("+operands[0]+" | 0xffffff00) >>> 0) : ("+operands[0]+" & 0xff));");}},0x48:function(context,operands){var val,addr;if(quot_isconstant(operands[1])){if(quot_isconstant(operands[0])){addr=Number(operands[0])+Number(operands[1])*4;val="self.Mem4("+(addr>>>0)+")";} else{var addr=Number(operands[1])*4;if(addr) val="self.Mem4(("+operands[0]+"+"+addr+") >>>0)";else val="self.Mem4("+operands[0]+")";}} else{val="self.Mem4(("+operands[0]+"+4*"+operands[1]+") >>>0)";} context.code.push(operands[2]+val+");");},0x49:function(context,operands){var val,addr;if(quot_isconstant(operands[1])){if(quot_isconstant(operands[0])){addr=Number(operands[0])+Number(operands[1])*2;val="self.Mem2("+(addr>>>0)+")";} else{var addr=Number(operands[1])*2;if(addr) val="self.Mem2(("+operands[0]+"+"+addr+") >>>0)";else val="self.Mem2("+operands[0]+")";}} else{val="self.Mem2(("+operands[0]+"+2*"+operands[1]+") >>>0)";} context.code.push(operands[2]+val+");");},0x4a:function(context,operands){var val,addr;if(quot_isconstant(operands[1])){if(quot_isconstant(operands[0])){addr=Number(operands[0])+Number(operands[1]);val="self.Mem1("+(addr>>>0)+")";} else{var addr=Number(operands[1]);if(addr) val="self.Mem1(("+operands[0]+"+"+addr+") >>>0)";else val="self.Mem1("+operands[0]+")";}} else{val="self.Mem1(("+operands[0]+"+"+operands[1]+") >>>0)";} context.code.push(operands[2]+val+");");},0x4c:function(context,operands){var val,addr;if(quot_isconstant(operands[1])){if(quot_isconstant(operands[0])){addr=Number(operands[0])+Number(operands[1])*4;val=(addr>>>0)+",";} else{var addr=Number(operands[1])*4;if(addr) val="("+operands[0]+"+"+addr+") >>>0"+",";else val=operands[0]+",";}} else{val="("+operands[0]+"+4*"+operands[1]+") >>>0"+",";} context.code.push("self.MemW4("+val+operands[2]+")"+";");},0x4d:function(context,operands){var val,addr;if(quot_isconstant(operands[1])){if(quot_isconstant(operands[0])){addr=Number(operands[0])+Number(operands[1])*2;val=(addr>>>0)+",";} else{var addr=Number(operands[1])*2;if(addr) val="("+operands[0]+"+"+addr+") >>>0"+",";else val=operands[0]+",";}} else{val="("+operands[0]+"+2*"+operands[1]+") >>>0"+",";} context.code.push("self.MemW2("+val+operands[2]+")"+";");},0x4e:function(context,operands){var val,addr;if(quot_isconstant(operands[1])){if(quot_isconstant(operands[0])){addr=Number(operands[0])+Number(operands[1]);val=(addr>>>0)+",";} else{var addr=Number(operands[1]);if(addr) val="("+operands[0]+"+"+addr+") >>>0"+",";else val=operands[0]+",";}} else{val="("+operands[0]+"+"+operands[1]+") >>>0"+",";} context.code.push("self.MemW1("+val+operands[2]+")"+";");},0x4b:function(context,operands){if(quot_isconstant(operands[1])){var bitx,addrx,bitnum;bitnum=Number(operands[1])&0xffffffff;bitx=bitnum&7;if(quot_isconstant(operands[0])){addrx=Number(operands[0]);if(bitnum>=0) addrx+=(bitnum>>3);else addrx-=(1+((-1-bitnum)>>3));} else{if(bitnum>=0){if(bitnum<=7) addrx=operands[0];else addrx=(operands[0]+"+"+(bitnum>>3));} else{addrx=(operands[0]+"-"+(1+((-1-bitnum)>>3)));}} context.code.push(operands[2]+"(self.Mem1("+addrx+") & "+(1<=0) addrx = "+operands[0]+" + ("+sign1+">>3);");context.code.push("else addrx = "+operands[0]+" - (1+((-1-("+sign1+"))>>3));");context.code.push(operands[2]+"(self.Mem1(addrx) & (1<=0) addrx+=(bitnum>>3);else addrx-=(1+((-1-bitnum)>>3));} else{if(bitnum>=0){if(bitnum<=7) addrx=operands[0];else addrx=(operands[0]+"+"+(bitnum>>3));} else{addrx=(operands[0]+"-"+(1+((-1-bitnum)>>3)));}} mask=(1<=0) addrx = "+operands[0]+" + ("+sign1+">>3);");context.code.push("else addrx = "+operands[0]+" - (1+((-1-("+sign1+"))>>3));");addrx="addrx";mask="(1< 0) {");context.code.push("if ("+sign1+" > 0) {");context.code.push("vals1 = "+sign1+" % "+sign0+";");context.code.push("} else {");context.code.push("vals1 = "+sign0+" - (-("+sign1+")) % "+sign0+";");context.code.push("}");context.code.push("if (vals1) {");context.code.push("pos = self.frame.valstack.length - "+sign0+";");context.code.push("roll = self.frame.valstack.slice(self.frame.valstack.length-vals1, self.frame.valstack.length).concat(self.frame.valstack.slice(pos, self.frame.valstack.length-vals1));");context.code.push("for (ix=0; ix<"+sign0+"; ix++) { self.frame.valstack[pos+ix] = roll[ix]; }");context.code.push("roll = undefined;");context.code.push("}");context.code.push("}");},0x54:function(context,operands){oputil_unload_offstate(context);if(quot_isconstant(operands[0])){var ix,holdvar;var pos=Number(operands[0]);for(ix=0;ix0) expr="Math.floor(self.random_func() * "+val+")";else expr="-Math.floor(self.random_func() * "+(-val)+")";} else{var sign0=oputil_signify_operand(context,operands[0],true);var holdvar=alloc_holdvar(context);expr=holdvar;context.code.push("if ("+sign0+" > 0)");context.code.push(holdvar+" = Math.floor(self.random_func() * "+sign0+");");context.code.push("else if ("+sign0+" < 0)");context.code.push(holdvar+" = -Math.floor(self.random_func() * -"+sign0+");");context.code.push("else");context.code.push(holdvar+" = (Math.floor(self.random_func() * 0x10000) | (Math.floor(self.random_func() * 0x10000) << 16)) >>>0;");} context.code.push(operands[1]+expr+");");},0x111:function(context,operands){context.code.push("self.set_random("+operands[0]+");");},0x120:function(context,operands){context.offstack.length=0;context.offloc.length=0;context.offlocdirty.length=0;context.code.push("return self.VMStopped;");context.path_ends=true;},0x121:function(context,operands){context.code.push(operands[0]+"self.perform_verify());");},0x122:function(context,operands){context.offstack.length=0;context.offloc.length=0;context.offlocdirty.length=0;context.code.push("self.vm_restart();");context.code.push("return;");context.path_ends=true;},0x123:function(context,operands){oputil_unload_offstate(context);context.varsused["ix"]=true;oputil_push_callstub(context,operands[1]);context.code.push("ix = self.vm_save("+operands[0]+");");context.code.push("self.pop_callstub(ix ? 0 : 1);");context.code.push("return;");context.path_ends=true;},0x124:function(context,operands){oputil_unload_offstate(context);context.code.push("if (self.vm_restore("+operands[0]+")) {");context.code.push("self.pop_callstub((-1)>>>0);");context.code.push("} else {");oputil_store(context,operands[1],"1");oputil_unload_offstate(context);context.code.push("self.pc = "+context.cp+";");context.code.push("}");context.code.push("return;");context.path_ends=true;},0x125:function(context,operands){oputil_unload_offstate(context);oputil_push_callstub(context,operands[0]);context.code.push("self.vm_saveundo();");context.code.push("self.pop_callstub(0);");context.code.push("return;");context.path_ends=true;},0x126:function(context,operands){oputil_unload_offstate(context);context.code.push("if (self.vm_restoreundo()) {");context.code.push("self.pop_callstub((-1)>>>0);");context.code.push("} else {");oputil_store(context,operands[0],"1");oputil_unload_offstate(context);context.code.push("self.pc = "+context.cp+";");context.code.push("}");context.code.push("return;");context.path_ends=true;},0x127:function(context,operands){context.code.push("self.protectstart="+operands[0]+";");context.code.push("self.protectend=self.protectstart+("+operands[1]+");");context.code.push("if (self.protectstart==self.protectend) {") context.code.push(" self.protectstart=0; self.protectend=0;");context.code.push("}");},0x170:function(context,operands){context.varsused["maddr"]=true;context.varsused["mlen"]=true;context.varsused["ix"]=true;context.code.push("mlen="+operands[0]+";");context.code.push("maddr="+operands[1]+";");context.code.push("for (ix=0; ix 0x7fffffff))");context.code.push(" res = 0x7fffffff;");context.code.push(" else");context.code.push(" res = Math.floor(valf);");context.code.push("} else {");context.code.push(" if (isNaN(valf) || !isFinite(valf) || (valf < -0x80000000))");context.code.push(" res = -0x80000000;");context.code.push(" else");context.code.push(" res = Math.ceil(valf);");context.code.push("}");context.code.push(operands[1]+"res>>>0);");},0x192:function(context,operands){context.varsused["valf"]=true;context.varsused["res"]=true;context.code.push("valf = "+oputil_decode_float(context,operands[0])+";");context.code.push("if (!("+operands[0]+" & 0x80000000)) {");context.code.push(" if (isNaN(valf) || !isFinite(valf))");context.code.push(" res = 0x7fffffff;");context.code.push(" else");context.code.push(" res = Math.round(valf);");context.code.push(" if (res > 0x7fffffff) res = 0x7fffffff;");context.code.push("} else {");context.code.push(" if (isNaN(valf) || !isFinite(valf))");context.code.push(" res = -0x80000000;");context.code.push(" else");context.code.push(" res = Math.round(valf);");context.code.push(" if (res < -0x80000000) res = -0x80000000;");context.code.push("}");context.code.push(operands[1]+"res>>>0);");},0x198:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.ceil("+valf+")));");},0x199:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.floor("+valf+")));");},0x1A0:function(context,operands){var valf0=oputil_decode_float(context,operands[0]);var valf1=oputil_decode_float(context,operands[1]);context.code.push(operands[2]+"self.encode_float("+valf0+" + "+valf1+"));");},0x1A1:function(context,operands){var valf0=oputil_decode_float(context,operands[0]);var valf1=oputil_decode_float(context,operands[1]);context.code.push(operands[2]+"self.encode_float("+valf0+" - "+valf1+"));");},0x1A2:function(context,operands){var valf0=oputil_decode_float(context,operands[0]);var valf1=oputil_decode_float(context,operands[1]);context.code.push(operands[2]+"self.encode_float("+valf0+" * "+valf1+"));");},0x1A3:function(context,operands){var valf0=oputil_decode_float(context,operands[0]);var valf1=oputil_decode_float(context,operands[1]);context.code.push(operands[2]+"self.encode_float("+valf0+" / "+valf1+"));");},0x1A4:function(context,operands){var valf0=oputil_decode_float(context,operands[0],true);var valf1=oputil_decode_float(context,operands[1],true);context.varsused["modv"]=true;context.varsused["quov"]=true;context.code.push("modv=("+valf0+" % "+valf1+");");context.code.push("quov=self.encode_float(("+valf0+" - modv) / "+valf1+");");context.code.push("if (quov == 0x0 || quov == 0x80000000) {");context.code.push(" quov = (("+operands[0]+" ^ "+operands[1]+") & 0x80000000) >>>0;");context.code.push("}");context.code.push(operands[2]+"self.encode_float(modv));");context.code.push(operands[3]+"quov);");},0x1A8:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.sqrt("+valf+")));");},0x1A9:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.exp("+valf+")));");},0x1AA:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.log("+valf+")));");},0x1AB:function(context,operands){context.varsused["valf"]=true;var valf0=oputil_decode_float(context,operands[0],true);var valf1=oputil_decode_float(context,operands[1],true);context.code.push("if ("+operands[0]+" == 0x3f800000) {");context.code.push(" valf = 0x3f800000;");context.code.push("} else if ("+operands[0]+" == 0xbf800000 && ("+operands[1]+" == 0xff800000 || "+operands[1]+" == 0x7f800000)) {");context.code.push(" valf = 0x3f800000;");context.code.push("} else {");context.code.push(" valf=self.encode_float(Math.pow("+valf0+", "+valf1+"));");context.code.push("}");context.code.push(operands[2]+"valf);");},0x1B0:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.sin("+valf+")));");},0x1B1:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.cos("+valf+")));");},0x1B2:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.tan("+valf+")));");},0x1B3:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.asin("+valf+")));");},0x1B4:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.acos("+valf+")));");},0x1B5:function(context,operands){var valf=oputil_decode_float(context,operands[0]);context.code.push(operands[1]+"self.encode_float(Math.atan("+valf+")));");},0x1B6:function(context,operands){var valf0=oputil_decode_float(context,operands[0]);var valf1=oputil_decode_float(context,operands[1]);context.code.push(operands[2]+"self.encode_float(Math.atan2("+valf0+", "+valf1+")));");},0x1C0:function(context,operands){var val,valf0,valf1,valf2;context.varsused["fequal"]=true;context.varsused["fdiff"]=true;context.code.push("if (("+operands[2]+" & 0x7f800000) == 0x7f800000 && ("+operands[2]+" & 0x007fffff) != 0) {");context.code.push(" fequal = 0;");context.code.push("} else if (("+operands[0]+" == 0xff800000 || "+operands[0]+" == 0x7f800000) && ("+operands[1]+" == 0xff800000 || "+operands[1]+" == 0x7f800000)) {");context.code.push(" fequal = ("+operands[0]+" == "+operands[1]+");");context.code.push("} else {");if(quot_isconstant(operands[2])){val=Number(operands[2]);valf2=""+decode_float(val&0x7fffffff);} else{val="self.decode_float(("+operands[2]+") & 0x7fffffff)";valf2=alloc_holdvar(context);context.code.push(valf2+"="+val+";");} valf0=oputil_decode_float(context,operands[0]);valf1=oputil_decode_float(context,operands[1]);context.code.push(" fdiff = "+valf1+" - "+valf0+";");context.code.push(" fequal = (fdiff <= "+valf2+" && fdiff >= -("+valf2+"));");context.code.push("}");context.code.push("if (fequal) {");oputil_perform_jump(context,operands[3]);context.code.push("}");},0x1C1:function(context,operands){var val,valf0,valf1,valf2;context.varsused["fequal"]=true;context.varsused["fdiff"]=true;context.code.push("if (("+operands[2]+" & 0x7f800000) == 0x7f800000 && ("+operands[2]+" & 0x007fffff) != 0) {");context.code.push(" fequal = 0;");context.code.push("} else if (("+operands[0]+" == 0xff800000 || "+operands[0]+" == 0x7f800000) && ("+operands[1]+" == 0xff800000 || "+operands[1]+" == 0x7f800000)) {");context.code.push(" fequal = ("+operands[0]+" == "+operands[1]+");");context.code.push("} else {");if(quot_isconstant(operands[2])){val=Number(operands[2]);valf2=""+decode_float(val&0x7fffffff);} else{val="self.decode_float(("+operands[2]+") & 0x7fffffff)";valf2=alloc_holdvar(context);context.code.push(valf2+"="+val+";");} valf0=oputil_decode_float(context,operands[0]);valf1=oputil_decode_float(context,operands[1]);context.code.push(" fdiff = "+valf1+" - "+valf0+";");context.code.push(" fequal = (fdiff <= "+valf2+" && fdiff >= -("+valf2+"));");context.code.push("}");context.code.push("if (!fequal) {");oputil_perform_jump(context,operands[3]);context.code.push("}");},0x1C2:function(context,operands){valf0=oputil_decode_float(context,operands[0]);valf1=oputil_decode_float(context,operands[1]);context.code.push("if ("+valf0+" < "+valf1+") {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x1C3:function(context,operands){valf0=oputil_decode_float(context,operands[0]);valf1=oputil_decode_float(context,operands[1]);context.code.push("if ("+valf0+" <= "+valf1+") {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x1C4:function(context,operands){valf0=oputil_decode_float(context,operands[0]);valf1=oputil_decode_float(context,operands[1]);context.code.push("if ("+valf0+" > "+valf1+") {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x1C5:function(context,operands){valf0=oputil_decode_float(context,operands[0]);valf1=oputil_decode_float(context,operands[1]);context.code.push("if ("+valf0+" >= "+valf1+") {");oputil_perform_jump(context,operands[2]);context.code.push("}");},0x1C8:function(context,operands){context.code.push("if (("+operands[0]+" & 0x7f800000) == 0x7f800000 && ("+operands[0]+" & 0x007fffff) != 0) {");oputil_perform_jump(context,operands[1]);context.code.push("}");},0x1C9:function(context,operands){context.code.push("if ("+operands[0]+" == 0xff800000 || "+operands[0]+" == 0x7f800000) {");oputil_perform_jump(context,operands[1]);context.code.push("}");},0x130:function(context,operands){var mayblock;if(quot_isconstant(operands[0])) mayblock=Glk.call_may_not_return(Number(operands[0]));else mayblock=true;context.code.push("self.tempglkargs.length = "+operands[1]+";");if(quot_isconstant(operands[1])){var ix;var argc=Number(operands[1]);for(ix=0;ix>1);for(ix=0;ix>4)&0x0F);modeaddr++;} var optype=oplist.formlist[ix];if(optype=="L"){switch(mode){case 8:if(context.offstack.length){operands[ix]=pop_offstack_holdvar(context);} else{holdvar=alloc_holdvar(context);context.code.push(holdvar+"=self.frame.valstack.pop();");operands[ix]=holdvar;} continue;case 0:operands[ix]="0";continue;case 1:value=QuoteMem1(cp);cp++;operands[ix]=value;continue;case 2:value=QuoteMem2(cp);cp+=2;operands[ix]=value;continue;case 3:value=QuoteMem4(cp);cp+=4;operands[ix]=value;continue;} if(mode>=9&&mode<=11){if(mode==9){addr=Mem1(cp);cp++;} else if(mode==10){addr=Mem2(cp);cp+=2;} else if(mode==11){addr=Mem4(cp);cp+=4;} if(context.offloc[addr]!==undefined){operands[ix]=context.offloc[addr];continue;} if(oplist.argsize==4){value="self.frame.locals["+addr+"]";} else if(oplist.argsize==2){value="self.frame.locals["+addr+"] & 0xffff";} else{value="self.frame.locals["+addr+"] & 0xff";} holdvar=alloc_holdvar(context,true);context.code.push(holdvar+"=("+value+");");context.offloc[addr]=holdvar;context.offlocdirty[addr]=false;operands[ix]=holdvar;continue;} switch(mode){case 15:addr=Mem4(cp)+ramstart;cp+=4;break;case 14:addr=Mem2(cp)+ramstart;cp+=2;break;case 13:addr=Mem1(cp)+ramstart;cp++;break;case 7:addr=Mem4(cp);cp+=4;break;case 6:addr=Mem2(cp);cp+=2;break;case 5:addr=Mem1(cp);cp++;break;default:fatal_error("Unknown addressing mode in load operand.");} if(oplist.argsize==4){value="self.Mem4("+addr+")";} else if(oplist.argsize==2){value="self.Mem2("+addr+")";} else{value="self.Mem1("+addr+")";} holdvar=alloc_holdvar(context);context.code.push(holdvar+"=("+value+");");operands[ix]=holdvar;continue;} else if(optype=="E"){switch(mode){case 8:if(context.offstack.length){operands[ix]=pop_offstack_holdvar(context);} else{operands[ix]="self.frame.valstack.pop()";} continue;case 0:operands[ix]="0";continue;case 1:value=QuoteMem1(cp);cp++;operands[ix]=value;continue;case 2:value=QuoteMem2(cp);cp+=2;operands[ix]=value;continue;case 3:value=QuoteMem4(cp);cp+=4;operands[ix]=value;continue;} if(mode>=9&&mode<=11){if(mode==9){addr=Mem1(cp);cp++;} else if(mode==10){addr=Mem2(cp);cp+=2;} else if(mode==11){addr=Mem4(cp);cp+=4;} if(context.offloc[addr]!==undefined){operands[ix]=context.offloc[addr];continue;} if(oplist.argsize==4){value="self.frame.locals["+addr+"]";} else if(oplist.argsize==2){value="self.frame.locals["+addr+"] & 0xffff";} else{value="self.frame.locals["+addr+"] & 0xff";} holdvar=alloc_holdvar(context,true);context.code.push(holdvar+"=("+value+");");context.offloc[addr]=holdvar;context.offlocdirty[addr]=false;operands[ix]=holdvar;continue;} switch(mode){case 15:addr=Mem4(cp)+ramstart;cp+=4;break;case 14:addr=Mem2(cp)+ramstart;cp+=2;break;case 13:addr=Mem1(cp)+ramstart;cp++;break;case 7:addr=Mem4(cp);cp+=4;break;case 6:addr=Mem2(cp);cp+=2;break;case 5:addr=Mem1(cp);cp++;break;default:fatal_error("Unknown addressing mode in load operand.");} if(oplist.argsize==4){value="self.Mem4("+addr+")";} else if(oplist.argsize==2){value="self.Mem2("+addr+")";} else{value="self.Mem1("+addr+")";} operands[ix]=value;continue;} else if(optype=="S"){switch(mode){case 8:holdvar=alloc_holdvar(context,true);context.offstack.push(holdvar);operands[ix]=holdvar+"=(";continue;case 0:operands[ix]="(";continue;} if(mode>=9&&mode<=11){if(mode==9){addr=Mem1(cp);cp++;} else if(mode==10){addr=Mem2(cp);cp+=2;} else if(mode==11){addr=Mem4(cp);cp+=4;} if(oplist.argsize==4){holdvar=alloc_holdvar(context,true);store_offloc_value(context,addr,holdvar,false);operands[ix]=holdvar+"=(";} else if(oplist.argsize==2){store_offloc_value(context,addr,undefined);operands[ix]="self.frame.locals["+addr+"]=(0xffff &";} else{store_offloc_value(context,addr,undefined);operands[ix]="self.frame.locals["+addr+"]=(0xff &";} continue;} switch(mode){case 15:addr=Mem4(cp)+ramstart;cp+=4;break;case 14:addr=Mem2(cp)+ramstart;cp+=2;break;case 13:addr=Mem1(cp)+ramstart;cp++;break;case 7:addr=Mem4(cp);cp+=4;break;case 6:addr=Mem2(cp);cp+=2;break;case 5:addr=Mem1(cp);cp++;break;default:fatal_error("Unknown addressing mode in store operand.");} if(oplist.argsize==4){value="self.MemW4("+addr+",";} else if(oplist.argsize==2){value="self.MemW2("+addr+",";} else{value="self.MemW1("+addr+",";} operands[ix]=value;continue;} else if(optype=="F"){var funcop=operands.func_store;switch(mode){case 8:funcop.mode=8;funcop.argsize=oplist.argsize;operands[ix]=funcop;continue;case 0:funcop.mode=0;funcop.argsize=oplist.argsize;operands[ix]=funcop;continue;} if(mode>=9&&mode<=11){if(mode==9){addr=Mem1(cp);cp++;} else if(mode==10){addr=Mem2(cp);cp+=2;} else if(mode==11){addr=Mem4(cp);cp+=4;} funcop.mode=11;funcop.addr=addr;funcop.argsize=oplist.argsize;operands[ix]=funcop;continue;} switch(mode){case 15:addr=Mem4(cp)+ramstart;cp+=4;break;case 14:addr=Mem2(cp)+ramstart;cp+=2;break;case 13:addr=Mem1(cp)+ramstart;cp++;break;case 7:addr=Mem4(cp);cp+=4;break;case 6:addr=Mem2(cp);cp+=2;break;case 5:addr=Mem1(cp);cp++;break;default:fatal_error("Unknown addressing mode in store operand.");} funcop.mode=15;funcop.addr=addr;funcop.argsize=oplist.argsize;operands[ix]=funcop;continue;} else if(optype=="C"){switch(mode){case 8:operands[ix]="3,0";continue;case 0:operands[ix]="0,0";continue;} if(mode>=9&&mode<=11){if(mode==9){addr=Mem1(cp);cp++;} else if(mode==10){addr=Mem2(cp);cp+=2;} else if(mode==11){addr=Mem4(cp);cp+=4;} operands[ix]="2,"+addr;continue;} switch(mode){case 15:addr=Mem4(cp)+ramstart;cp+=4;break;case 14:addr=Mem2(cp)+ramstart;cp+=2;break;case 13:addr=Mem1(cp)+ramstart;cp++;break;case 7:addr=Mem4(cp);cp+=4;break;case 6:addr=Mem2(cp);cp+=2;break;case 5:addr=Mem1(cp);cp++;break;default:fatal_error("Unknown addressing mode in store operand.");} operands[ix]="1,"+addr;continue;} else{fatal_error("Unknown operand type.",optype);}} return cp;} function compile_func(funcaddr){var addr=funcaddr;var functype=Mem1(addr);if(functype!=0xC0&&functype!=0xC1){if(functype>=0xC0&&functype<=0xDF) fatal_error("Call to unknown type of function.",addr);else fatal_error("Call to non-function.",addr);} addr++;var localsformat=[];var rawstart=addr;var ix=0;while(1){var loctype=Mem1(addr);addr++;var locnum=Mem1(addr);addr++;if(loctype==0){break;} if(loctype!=1&&loctype!=2&&loctype!=4){fatal_error("Invalid local variable size in function header.",loctype);} localsformat.push({size:loctype,count:locnum});} var rawformat=memmap.slice(rawstart,addr);while(rawformat.length%4) rawformat.push(0);return new VMFunc(funcaddr,addr,localsformat,rawformat);} function compile_path(vmfunc,startaddr,startiosys){var cp=startaddr;var opcode;var opcodecp;var key;var context={vmfunc:vmfunc,cp:null,curiosys:startiosys,code:[],holduse:{},varsused:{},offstack:[],offloc:[],offlocdirty:[],path_ends:false};var operands={};operands.func_store={};context.code.push("");while(!context.path_ends){opcodecp=cp;opcode=Mem1(cp);if(opcode===undefined) fatal_error("Tried to compile nonexistent address",cp);cp++;if(opcode&0x80){if(opcode&0x40){opcode&=0x3F;opcode=(opcode*0x100)|Mem1(cp);cp++;opcode=(opcode*0x100)|Mem1(cp);cp++;opcode=(opcode*0x100)|Mem1(cp);cp++;} else{opcode&=0x7F;opcode=(opcode*0x100)|Mem1(cp);cp++;}} var oplist=operandlist_table[opcode];if(!oplist) fatal_error("Encountered unknown opcode.",opcode);cp=parse_operands(context,cp,oplist,operands);context.cp=cp;var ophandler=opcode_table[opcode];if(!ophandler) fatal_error("Encountered unhandled opcode.",opcode);ophandler(context,operands);for(key in context.holduse){if(context.holduse[key]===true) context.holduse[key]=false;} if(vmfunc.pathaddrs[cp]&&!context.path_ends){context.code.push("self.pc="+cp+";");oputil_unload_offstate(context);context.code.push("return;");context.path_ends=true;}} if(context.offstack.length) fatal_error("Path compilation ended with nonempty offstack.",context.offstack.length);if(context.offloc.length) fatal_error("Path compilation ended with nonempty offloc.",context.offloc.length);{var ls=[];for(key in context.holduse) ls.push(key);for(key in context.varsused) ls.push(key);if(ls.length) context.code[0]="var "+ls.join(",")+";";} return make_code(context.code.join("\n"),"_func_path_"+startaddr);} function enter_function(addr,argcount){var ix;total_function_calls++;var accelfunc=accel_address_map[addr];if(accelfunc!==undefined){accel_function_calls++;var val=accelfunc(argcount,self.tempcallargs);pop_callstub(val);return;} var vmfunc=vmfunc_table[addr];if(vmfunc===undefined){vmfunc=compile_func(addr);if(addr=0;ix--) self.frame.valstack.push(self.tempcallargs[ix]);self.frame.valstack.push(argcount);} else{for(ix=0;ixval) stack.pop();if(stack.length==0) fatal_error("Stack evaporated during throw.");self.frame=stack[stack.length-1];val-=(self.frame.framestart+self.frame.framelen);if(val<0) fatal_error("Attempted to throw below the frame value stack.");if(val&3) fatal_error("Attempted to throw to an unaligned address.");val>>>=2;if(val>self.frame.valstack.length) fatal_error("Attempted to throw beyond the frame value stack.");self.frame.valstack.length=val;} self.pop_stack_to=pop_stack_to;function pop_callstub(val){var destaddr,desttype;if(isNaN(val)) fatal_error("Function returned undefined value.");var framestart=self.frame.valstack.pop();if(framestart!=self.frame.framestart) fatal_error("Call stub frameptr ("+framestart+") "+"does not match frame ("+self.frame.framestart+")");self.pc=self.frame.valstack.pop();destaddr=self.frame.valstack.pop();desttype=self.frame.valstack.pop();switch(desttype){case 0:return;case 1:MemW4(destaddr,val);return;case 2:self.frame.locals[destaddr]=val;return;case 3:self.frame.valstack.push(val);return;case 0x11:fatal_error("String-terminator call stub at end of function call.");return;case 0x10:stream_string(0,self.pc,0xE1,destaddr);return;case 0x12:stream_num(0,self.pc,true,destaddr);return;case 0x13:stream_string(0,self.pc,0xE0,destaddr);return;case 0x14:stream_string(0,self.pc,0xE2,destaddr);return;default:fatal_error("Unrecognized desttype in callstub.",desttype);}} self.pop_callstub=pop_callstub;function store_operand(desttype,destaddr,val){switch(desttype){case 0:return;case 1:MemW4(destaddr,val);return;case 2:self.frame.locals[destaddr]=val;return;case 3:self.frame.valstack.push(val);return;default:fatal_error("Unrecognized desttype in callstub.",desttype);}} self.store_operand=store_operand;function store_operand_by_funcop(funcop,val){if(!funcop) return;switch(funcop.mode){case 8:self.frame.valstack.push(val);return;case 0:return;case 11:if(funcop.argsize==4){self.frame.locals[funcop.addr]=(val);} else if(funcop.argsize==2){self.frame.locals[funcop.addr]=(0xffff&val);} else{self.frame.locals[funcop.addr]=(0xff&val);} return;case 15:if(funcop.argsize==4){MemW4(funcop.addr,val);} else if(funcop.argsize==2){MemW2(funcop.addr,val);} else{MemW1(funcop.addr,val);} return;default:fatal_error("Unknown addressing mode in store func by operand.");}} function set_random(val){if(val==0){self.random_func=Math.random;} else{srand_set_seed(val);self.random_func=srand_get_random;}} self.set_random=set_random;var srand_table=undefined;var srand_index1,srand_index2;function srand_set_seed(seed){var i,ii,k,val,loop;if(srand_table===undefined) srand_table=Array(55);srand_table[54]=seed;srand_index1=0;srand_index2=31;k=1;for(i=0;i<55;i++){ii=(21*i)%55;srand_table[ii]=k;k=(seed-k)>>>0;seed=srand_table[ii];} for(loop=0;loop<4;loop++){for(i=0;i<55;i++){val=srand_table[i]-srand_table[(1+i+30)%55];srand_table[i]=val>>>0;}}} function srand_get_random(){srand_index1=(srand_index1+1)%55;srand_index2=(srand_index2+1)%55;srand_table[srand_index1]=(srand_table[srand_index1]-srand_table[srand_index2])>>>0;return srand_table[srand_index1]/0x100000000;} var accel_address_map={};self.accel_address_map=accel_address_map;var accel_params=[0,0,0,0,0,0,0,0,0];self.accel_params=accel_params;var accel_func_map={1:function func_1_z__region(argc,argv){if(argc<1) return 0;var addr=argv[0];if(addr<36) return 0;if(addr>=self.endmem) return 0;var tb=Mem1(addr);if(tb>=0xE0){return 3;} if(tb>=0xC0){return 2;} if(tb>=0x70&&tb<=0x7F&&addr>=ramstart){return 1;} return 0;},2:function func_2_cp__tab(argc,argv){var obj=((argc>0)?argv[0]:0);var id=((argc>1)?argv[1]:0);if(accel_func_map[1](argc,argv)!=1){Glk.glk_put_jstring("\n[** Programming error: tried to find the \".\" of (something) **]\n");return 0;} var otab=Mem4(obj+16);if(!otab) return 0;var max=Mem4(otab);otab+=4;return binary_search(id,2,otab,10,max,0,0);},3:function func_3_ra__pr(argc,argv){var obj=((argc>0)?argv[0]:0);var id=((argc>1)?argv[1]:0);var prop=accel_helper_get_prop(obj,id);if(prop==0) return 0;return Mem4(prop+4);},4:function func_4_rl__pr(argc,argv){var obj=((argc>0)?argv[0]:0);var id=((argc>1)?argv[1]:0);var prop=accel_helper_get_prop(obj,id);if(prop==0) return 0;return 4*Mem2(prop+2);},5:function func_5_oc__cl(argc,argv){var zr,prop,inlist,inlistlen,jx;var obj=((argc>0)?argv[0]:0);var cla=((argc>1)?argv[1]:0);zr=accel_func_map[1](argc,argv);if(zr==3) return(cla==accel_params[5])?1:0;if(zr==2) return(cla==accel_params[4])?1:0;if(zr!=1) return 0;if(cla==accel_params[2]){if(accel_helper_obj_in_class(obj)) return 1;if(obj==accel_params[2]) return 1;if(obj==accel_params[5]) return 1;if(obj==accel_params[4]) return 1;if(obj==accel_params[3]) return 1;return 0;} if(cla==accel_params[3]){if(accel_helper_obj_in_class(obj)) return 0;if(obj==accel_params[2]) return 0;if(obj==accel_params[5]) return 0;if(obj==accel_params[4]) return 0;if(obj==accel_params[3]) return 0;return 1;} if((cla==accel_params[5])||(cla==accel_params[4])) return 0;if(!accel_helper_obj_in_class(cla)){Glk.glk_put_jstring("\n[** Programming error: tried to apply 'ofclass' with non-class **]\n");return 0;} prop=accel_helper_get_prop(obj,2);if(prop==0) return 0;inlist=Mem4(prop+4);if(inlist==0) return 0;inlistlen=Mem2(prop+2);for(jx=0;jx1)?argv[1]:0);var addr;addr=accel_func_map[3](argc,argv);if(addr==0){if((id>0)&&(id0)?argv[0]:0);var id=((argc>1)?argv[1]:0);var indiv_prop_start=accel_params[1];var zr=accel_func_map[1](argc,argv);if(zr==3){if(id==indiv_prop_start+6) return 1;if(id==indiv_prop_start+7) return 1;return 0;} if(zr==2){return((id==indiv_prop_start+5)?1:0);} if(zr!=1) return 0;if((id>=indiv_prop_start)&&(id0)?argv[0]:0);var id=((argc>1)?argv[1]:0);if(accel_func_map[1](argc,argv)!=1){Glk.glk_put_jstring("\n[** Programming error: tried to find the \".\" of (something) **]\n");return 0;} var otab=Mem4(obj+4*(3+(accel_params[7]>>2)));if(!otab) return 0;var max=Mem4(otab);otab+=4;return binary_search(id,2,otab,10,max,0,0);},9:function func_9_ra__pr(argc,argv){var obj=((argc>0)?argv[0]:0);var id=((argc>1)?argv[1]:0);var prop=accel_helper_get_prop_new(obj,id);if(prop==0) return 0;return Mem4(prop+4);},10:function func_10_rl__pr(argc,argv){var obj=((argc>0)?argv[0]:0);var id=((argc>1)?argv[1]:0);var prop=accel_helper_get_prop_new(obj,id);if(prop==0) return 0;return 4*Mem2(prop+2);},11:function func_11_oc__cl(argc,argv){var zr,prop,inlist,inlistlen,jx;var obj=((argc>0)?argv[0]:0);var cla=((argc>1)?argv[1]:0);zr=accel_func_map[1](argc,argv);if(zr==3) return(cla==accel_params[5])?1:0;if(zr==2) return(cla==accel_params[4])?1:0;if(zr!=1) return 0;if(cla==accel_params[2]){if(accel_helper_obj_in_class(obj)) return 1;if(obj==accel_params[2]) return 1;if(obj==accel_params[5]) return 1;if(obj==accel_params[4]) return 1;if(obj==accel_params[3]) return 1;return 0;} if(cla==accel_params[3]){if(accel_helper_obj_in_class(obj)) return 0;if(obj==accel_params[2]) return 0;if(obj==accel_params[5]) return 0;if(obj==accel_params[4]) return 0;if(obj==accel_params[3]) return 0;return 1;} if((cla==accel_params[5])||(cla==accel_params[4])) return 0;if(!accel_helper_obj_in_class(cla)){Glk.glk_put_jstring("\n[** Programming error: tried to apply 'ofclass' with non-class **]\n");return 0;} prop=accel_helper_get_prop_new(obj,2);if(prop==0) return 0;inlist=Mem4(prop+4);if(inlist==0) return 0;inlistlen=Mem2(prop+2);for(jx=0;jx1)?argv[1]:0);var addr;addr=accel_func_map[9](argc,argv);if(addr==0){if((id>0)&&(id0)?argv[0]:0);var id=((argc>1)?argv[1]:0);var indiv_prop_start=accel_params[1];var zr=accel_func_map[1](argc,argv);if(zr==3){if(id==indiv_prop_start+6) return 1;if(id==indiv_prop_start+7) return 1;return 0;} if(zr==2){return((id==indiv_prop_start+5)?1:0);} if(zr!=1) return 0;if((id>=indiv_prop_start)&&(id>16;obj=cla;} accel_helper_temp_args[0]=obj;accel_helper_temp_args[1]=id;prop=accel_func_map[2](2,accel_helper_temp_args);if(prop==0) return 0;if(accel_helper_obj_in_class(obj)&&(cla==0)){if((id=accel_params[1]+8)) return 0;} if(Mem4(accel_params[6])!=obj){if(Mem1(prop+9)&1) return 0;} return prop;} function accel_helper_get_prop_new(obj,id) {var cla=0;var prop;if(id&0xFFFF0000){cla=Mem4(accel_params[0]+((id&0xFFFF)*4));accel_helper_temp_args[0]=obj;accel_helper_temp_args[1]=cla;if(accel_func_map[11](2,accel_helper_temp_args)==0) return 0;id=id>>16;obj=cla;} accel_helper_temp_args[0]=obj;accel_helper_temp_args[1]=id;prop=accel_func_map[8](2,accel_helper_temp_args);if(prop==0) return 0;if(accel_helper_obj_in_class(obj)&&(cla==0)){if((id=accel_params[1]+8)) return 0;} if(Mem4(accel_params[6])!=obj){if(Mem1(prop+9)&1) return 0;} return prop;} function set_string_table(addr){if(self.stringtable==addr) return;decoding_tree=undefined;vmstring_table=undefined;self.stringtable=addr;if(self.stringtable==0){return;} var textenv=vmtextenv_table[self.stringtable];if(textenv===undefined){var dectab=undefined;var tablelen=Mem4(self.stringtable);var rootaddr=Mem4(self.stringtable+8);var cache_stringtable=(self.stringtable+tablelen<=ramstart);if(cache_stringtable){var tmparray=Array(1);build_decoding_tree(tmparray,rootaddr,4,0);dectab=tmparray[0];if(dectab===undefined) fatal_error("Failed to create decoding tree.");} textenv=new VMTextEnv(self.stringtable,dectab);vmtextenv_table[self.stringtable]=textenv;} decoding_tree=textenv.decoding_tree;vmstring_table=textenv.vmstring_tables[self.iosysmode];} self.set_string_table=set_string_table;function set_iosys(mode,rock){switch(mode){case 0:rock=0;break;case 1:break;case 2:rock=0;break;default:mode=0;rock=0;break;} self.iosysmode=mode;self.iosysrock=rock;var textenv=vmtextenv_table[self.stringtable];if(textenv===undefined) vmstring_table=undefined;else vmstring_table=textenv.vmstring_tables[self.iosysmode];} self.set_iosys=set_iosys;function build_decoding_tree(cablist,nodeaddr,depth,mask){var ix,type,cab;var depthbit;type=Mem1(nodeaddr);if(type==0&&depth==4){cab=Array(16);cab.type=0;cab.depth=4;cablist[mask]=cab;build_decoding_tree(cab,nodeaddr,0,0);return;} if(type==0){var leftaddr=Mem4(nodeaddr+1);var rightaddr=Mem4(nodeaddr+5);build_decoding_tree(cablist,leftaddr,depth+1,mask);build_decoding_tree(cablist,rightaddr,depth+1,(mask|(1<>=bitnum;numbits=(8-bitnum);readahead=false;if(!(decoding_tree instanceof Array)){done=true;} cablist=decoding_tree;while(!done){if(numbits<4){var newbyte=Mem1(addr+1);bits|=(newbyte<>=cab.depth;bitnum+=cab.depth;if(bitnum>=8){addr+=1;bitnum-=8;if(readahead){readahead=false;} else{var newbyte=Mem1(addr);bits|=(newbyte<=0x09) context.code.push("oaddr = self.Mem4(oaddr);");if(cab.type==0x0B) context.code.push("oaddr = self.Mem4(oaddr);");context.code.push("otype = self.Mem1(oaddr);");retval="retval";done=true;oputil_push_callstub(context,"0x10,"+bitnum,addr);context.code.push("if (otype >= 0xE0 && otype <= 0xFF) {");context.code.push("retval = [oaddr, 0, 0];");context.code.push("}");context.code.push("else if (otype >= 0xC0 && otype <= 0xDF) {");var argc=0;if(cab.type==0x0A||cab.type==0x0B){argc=Mem4(cab.addr+4);for(var ix=0;ix>=bitnum;node=Mem4(self.stringtable+8);while(!done){nodetype=Mem1(node);node++;switch(nodetype){case 0x00:if(byt&1) node=Mem4(node+4);else node=Mem4(node+0);if(bitnum==7){bitnum=0;addr++;byt=Mem1(addr);} else{bitnum++;byt>>=1;} break;case 0x01:retval=false;done=true;break;case 0x02:ch=Mem1(node);switch(curiosys){case 2:context.buffer.push(CharToString(ch));break;case 1:oputil_flush_string(context);oputil_push_substring_callstub(context);oputil_push_callstub(context,"0x10,"+bitnum,addr);context.code.push("self.tempcallargs[0]="+ch+";");context.code.push("self.enter_function(self.iosysrock, 1);");retval=true;done=true;break;} node=Mem4(self.stringtable+8);break;case 0x04:ch=Mem4(node);switch(curiosys){case 2:context.buffer.push(CharToString(ch));break;case 1:oputil_flush_string(context);oputil_push_substring_callstub(context);oputil_push_callstub(context,"0x10,"+bitnum,addr);context.code.push("self.tempcallargs[0]="+ch+";");context.code.push("self.enter_function(self.iosysrock, 1);");retval=true;done=true;break;} node=Mem4(self.stringtable+8);break;case 0x03:switch(curiosys){case 2:while(true){ch=Mem1(node);if(ch==0) break;context.buffer.push(CharToString(ch));node++;} break;case 1:oputil_flush_string(context);oputil_push_substring_callstub(context);oputil_push_callstub(context,"0x10,"+bitnum,addr);retval="["+node+", 0xE0, 0]";done=true;break;} node=Mem4(self.stringtable+8);break;case 0x05:switch(curiosys){case 2:while(true){ch=Mem4(node);if(ch==0) break;context.buffer.push(CharToString(ch));node+=4;} break;case 1:oputil_flush_string(context);oputil_push_substring_callstub(context);oputil_push_callstub(context,"0x10,"+bitnum,addr);retval="["+node+", 0xE2, 0]";done=true;break;} node=Mem4(self.stringtable+8);break;case 0x08:case 0x09:case 0x0A:case 0x0B:oputil_flush_string(context);oputil_push_substring_callstub(context);context.code.push("var otype, retval;");context.code.push("var oaddr = "+Mem4(node)+";");if(nodetype==0x09||nodetype==0x0B) context.code.push("oaddr = self.Mem4(oaddr);");context.code.push("otype = self.Mem1(oaddr);");retval="retval";done=true;oputil_push_callstub(context,"0x10,"+bitnum,addr);context.code.push("if (otype >= 0xE0 && otype <= 0xFF) {");context.code.push("retval = [oaddr, 0, 0];");context.code.push("}");context.code.push("else if (otype >= 0xC0 && otype <= 0xDF) {");var argc=0;if(nodetype==0x0A||nodetype==0x0B){argc=Mem4(node+4);for(var ix=0;ix=0xE0&&type<=0xFF){fatal_error("Attempt to print unknown type of string.");} else{fatal_error("Attempt to print non-string.");} if(!retval){return context.buffer.join("");} else{oputil_flush_string(context);context.code.push("return "+retval+";");return make_code(context.code.join("\n"),"_func_str_"+startaddr,"nextcp","substring");}} function do_gestalt(val,val2){var ix;switch(val){case 0:return 0x00030102;case 1:return 0x00020102;case 2:return 1;case 3:return 1;case 4:switch(val2){case 0:return 1;case 1:return 1;case 2:return 1;default:return 0;} break;case 5:return 1;case 6:return 1;case 7:return 1;case 8:return heap_get_start();case 9:return 1;case 10:if(accel_func_map[val2]) return 1;else return 0;case 11:return 1;default:return 0;}} self.do_gestalt=do_gestalt;function fetch_search_key(addr,len,options){var ix;if(options&1){return MemSlice(addr,len);} else{switch(len){case 4:return[(addr>>24)&0xFF,(addr>>16)&0xFF,(addr>>8)&0xFF,addr&0xFF];case 2:return[(addr>>8)&0xFF,addr&0xFF];case 1:return[addr&0xFF];default:throw('Direct search key must hold one, two, or four bytes.');}}} function linear_search(key,keysize,start,structsize,numstructs,keyoffset,options){var ix,count,match,bytes;var retindex=((options&4)!=0);var zeroterm=((options&2)!=0);var keybuf=fetch_search_key(key,keysize,options);for(count=0;count>1;addr=start+val*structsize;for(ix=0;(!cmp)&&ixbyt2) cmp=1;} if(!cmp){if(retindex) return val;else return addr;} if(cmp<0){bot=val+1;} else{top=val;}} if(retindex) return 0xFFFFFFFF;else return 0;} function linked_search(key,keysize,start,keyoffset,nextoffset,options){var ix,byt,match;var zeroterm=((options&2)!=0);var keybuf=fetch_search_key(key,keysize,options);while(start!=0){match=true;for(ix=0;match&&ix>23&0xff);if(expo){res=((val&0x7fffff|0x800000)/8388608*Math.pow(2,(expo-127)));} else{res=((val&0x7fffff)/8388608*Math.pow(2,-126));} if(sign) return-res;else return res;} function encode_float(val){var absval,fbits;var mant,expo,sign;if(isNaN(val)){return 0x7f800001;} if(!isFinite(val)){if(val<0) return 0xff800000;else return 0x7f800000;} if(val==0){if(1/val<0) return 0x80000000;else return 0x0;} if(val<0){sign=true;absval=-val;} else{sign=false;absval=val;} expo=Math.floor(Math.log(absval)/Math.log(2));mant=absval/Math.pow(2,expo);if(expo>=128){return(sign?0xff800000:0x7f800000);} else if(expo<-126){mant=mant*Math.pow(2,126+expo);expo=0;} else if(!(expo==0&&mant==0.0)){expo+=127;mant-=1.0;} mant=mant*8388608.0;fbits=(mant+0.4999999999999999)<<0;if(fbits>=8388608){fbits=0;expo++;if(expo>=255){return(sign?0xff800000:0x7f800000);}} if(sign) return((0x80000000)|(expo<<23)|(fbits))>>>0;else return(expo<<23)|(fbits);} self.decode_float=decode_float;self.encode_float=encode_float;var game_image=null;var game_signature=null;var opt_rethrow_exceptions=null;var memmap;var stack;self.frame=null;self.vm_started=false;self.vm_stopped=false;self.tempcallargs=null;self.tempglkargs=null;self.done_executing=null;var vmfunc_table;var vmtextenv_table;var decoding_tree;var vmstring_table;self.random_func=null;var ramstart;var endgamefile;var origendmem;var stacksize;var startfuncaddr;var origstringtable;var checksum;self.pc=null;self.stringtable=null;self.endmem=null;self.protectstart=null;self.protectend=null;self.iosysmode=null;self.iosysrock=null;var undostack;self.resumefuncop=null;self.resumevalue=null;var heapstart;var usedlist;var freelist;var total_execution_time=0;var total_function_calls=0;var accel_function_calls=0;var total_path_calls=0;var paths_cached=0;var paths_compiled=0;var strings_cached=0;var strings_compiled=0;function setup_vm(){var val,version;if(!game_image) fatal_error("There is no Glulx game file loaded.");self.vm_started=true;self.resumefuncop=null;self.resumevalue=0;memmap=null;stack=[];self.frame=null;self.pc=0;if(game_image.length<36) fatal_error("This is too short to be a valid Glulx file.");val=ByteRead4(game_image,0);if(val!=0x476c756c) fatal_error("This is not a valid Glulx file.");version=ByteRead4(game_image,4);if(version<0x20000) fatal_error("This Glulx file is too old a version to execute.");if(version>=0x30200) fatal_error("This Glulx file is too new a version to execute.");ramstart=ByteRead4(game_image,8);endgamefile=ByteRead4(game_image,12);origendmem=ByteRead4(game_image,16);stacksize=ByteRead4(game_image,20);startfuncaddr=ByteRead4(game_image,24);origstringtable=ByteRead4(game_image,28);checksum=ByteRead4(game_image,32);self.protectstart=0;self.protectend=0;if(ramstart<0x100||endgamefile0){result.push(0);result.push(zeroes-1);} while(ibytes.length){qlog("IFF chunk header is truncated");return undefined;} var key=ByteReadString(bytes,pos,4);var size=ByteRead4(bytes,pos+4);pos+=8;if((pos+size)>bytes.length){qlog(key+" chunk is truncated "+"("+size+" bytes needed, "+(bytes.length-pos)+" available");return undefined;} chunks[key]=bytes.slice(pos,pos+size);pos+=size;if(pos&1) pos+=1;} return chunks;} function vm_save(streamid){if(self.iosysmode!=2) fatal_error("Streams are only available in Glk I/O system.");var str=GiDispa.class_obj_from_id('stream',streamid);if(!str) return false;chunks=[];chunks.push({key:"IFhd",chunk:game_image.slice(0,128)});var cmem=memmap.slice(ramstart);for(var i=ramstart;i0){count=Glk.glk_get_buffer_stream(str,buffer);quetzal=quetzal.concat(buffer.slice(0,count));} quetzal=unpack_iff_chunks(quetzal);if(!quetzal){qlog("vm_restore failed: file is not Quetzal");return false;} quetzal=quetzal["FORM"];if(!quetzal||ByteReadString(quetzal,0,4)!="IFZS"){qlog("vm_restore failed: file doesn't start with FORM/IFZS header");return false;} var chunks=unpack_iff_chunks(quetzal.slice(4));if(!chunks["IFhd"]){qlog("vm_restore failed: missing required IFhd chunk");return false;} for(var i=0;i<128;i++){if(chunks["IFhd"][i]!=game_image[i]){qlog("vm_restore failed: this save image is for a different game");return false;}} if(!chunks["CMem"]){qlog("vm_restore failed: missing required CMem chunk");return false;} if(!chunks["Stks"]){qlog("vm_restore failed: missing required Stks chunk");return false;} var protect=copy_protected_range();heap_clear();var newendmem=ByteRead4(chunks["CMem"],0);var ram_xor=chunks["CMem"].slice(4);ram_xor=decompress_bytes(ram_xor);while(ram_xor.length=8){heapstart=ByteRead4(heapchunk,0);var numblocks=ByteRead4(heapchunk,4);for(var i=0;iself.endmem){fatal_error("vm_restore failed: corrupt dynamic heap");} if(addr>heapend){freelist.push(new HeapBlock(heapend,addr-heapend));} heapend=addr+size;} if(heapend10){undostack.shift();}} function vm_restoreundo(){if(undostack.length==0){return false;} var snapshot=undostack.pop();var protect=copy_protected_range();memmap=memmap.slice(0,ramstart).concat(snapshot.ram);self.endmem=snapshot.endmem;stack=snapshot.stack;self.frame=stack[stack.length-1];self.pc=snapshot.pc;heapstart=snapshot.heapstart;usedlist=snapshot.usedlist;freelist=snapshot.freelist;paste_protected_range(protect);return true;} self.vm_save=vm_save;self.vm_restore=vm_restore;self.vm_saveundo=vm_saveundo;self.vm_restoreundo=vm_restoreundo;function change_memsize(newlen,internal){var lx;if(newlen==self.endmem) return;if((!internal)&&heap_is_active()) fatal_error("Cannot resize Glulx memory space while heap is active.");if(newlenself.endmem){for(lx=self.endmem;lx=self.protectend) return null;var len=self.protectend-self.protectstart;var obj={start:self.protectstart,end:self.protectend,len:len};var arr=memmap.slice(self.protectstart,self.protectend);while(arr.lengthself.endmem) end=self.endmem;for(ix=0,addr=start;addr>>0;for(ix=0;ix>>0;} if(newsum!=checksum) return 1;return 0;} self.perform_verify=perform_verify;function quixe_get_signature(){return game_signature;} function quixe_get_statistics(){var stat={game_image_length:game_image.length,total_execution_time:total_execution_time,total_function_calls:total_function_calls,accel_function_calls:accel_function_calls,total_path_calls:total_path_calls,paths_cached:paths_cached,paths_compiled:paths_compiled,strings_cached:strings_cached,strings_compiled:strings_compiled};return stat;} function heap_clear(){heapstart=0;usedlist=[];freelist=[];} function heap_is_active(){return(usedlist.length>0);} function heap_get_start(){return heapstart;} function HeapBlock(addr,size){this.addr=addr;this.size=size;this.end=addr+size;} function heap_binary_search(list,addr){var low=0;var high=list.length;while(low>1;if(list[mid].addr=size){if(freeblock.size>size){freelist[i]=new HeapBlock(freeblock.addr+size,freeblock.size-size);}else{freelist.splice(i,1);} var pos=heap_binary_search(usedlist,freeblock.addr);usedlist.splice(pos,0,new HeapBlock(freeblock.addr,size));return freeblock.addr;}} var addr=self.endmem;var rounded_up_size=((size+0xFF)&0xFFFFFF00);change_memsize(self.endmem+rounded_up_size,true);if(rounded_up_size>size){freelist.push(new HeapBlock(addr+size,rounded_up_size-size));} usedlist.push(new HeapBlock(addr,size));return addr;} self.heap_malloc=heap_malloc;function heap_free(addr){var pos=heap_binary_search(usedlist,addr);var block=usedlist[pos];if(!block||block.addr!=addr){fatal_error("Tried to free non-existent block");} usedlist.splice(pos,1);if(usedlist.length==0){change_memsize(heapstart,true);heap_clear();return;} pos=heap_binary_search(freelist,addr);var next=freelist[pos];if(next&&next.addr==block.end){block=new HeapBlock(addr,block.size+next.size);freelist.splice(pos,1);} var prev=freelist[pos-1];if(prev&&prev.end==block.addr){block=new HeapBlock(prev.addr,prev.size+block.size);freelist.splice(pos-1,1);pos-=1;} freelist.splice(pos,0,block);} self.heap_free=heap_free;function assert_heap_valid(){if(!heap_is_active()){if(heapstart!=0) fatal_error("Heap inconsistency: heapstart nonzero");if(usedlist.length>0) fatal_error("Heap inconsistency: usedlist nonempty");if(freelist.length>0) fatal_error("Heap inconsistency: usedlist nonempty");return;} if(heapstart==0) fatal_error("Heap inconsistency: heapstart is zero");var addr=heapstart;var upos=0,fpos=0;while(upos>> 0';} if(arg instanceof ArgChar){if(!arg.signed) return val+' & 0xFF';else return'self.uncast_signed_char('+val+')'} if(arg instanceof ArgClass){return'self.class_obj_to_id("'+arg.name+'", '+val+')';} return'???';} function cast_signed_char(val){val=val&0xFF;if(val&0x80) val-=0x100;return val;} self.cast_signed_char=cast_signed_char;function uncast_signed_char(val){val=val&0xFF;if(val&0x80) val+=0xFFFFFF00;return val;} self.uncast_signed_char=uncast_signed_char;function class_obj_to_id(clas,val){if(!val) return 0;return val.disprock;} self.class_obj_to_id=class_obj_to_id;function class_obj_from_id(clas,val){if(val==0) return null;return class_map[clas][val];} self.class_obj_from_id=class_obj_from_id;function build_function(func){var ix,jx;var form,retarg,argpos,argjoin,subargs;var arg,refarg,tmpvar,val,retval,ls;var mayblock;var out=[];var locals={};var arraycount=0;out.push('// no local vars');out.push('// '+func.id+': '+func.name);form=func.proto;retarg=null;if(form.retarg) retarg=form.retarg.arg;out.push('var self = this;');mayblock=Glk.call_may_not_return(func.id);argpos=0;argjoin=[];for(ix=0;ix>>0);self.VM.WriteStructField(blocked_callargs[0],1,class_obj_to_id("window",glka0.get_field(1)));self.VM.WriteStructField(blocked_callargs[0],2,glka0.get_field(2)>>>0);self.VM.WriteStructField(blocked_callargs[0],3,glka0.get_field(3)>>>0);}} else if(blocked_selector==0x062){self.VM.SetResumeStore(class_obj_to_id("fileref",glka0));} blocked_selector=null;blocked_callargs=null;} var temp_arg_arrays=[];self.temp_arg_arrays=temp_arg_arrays;var retained_arrays=[];self.retained_arrays=retained_arrays;function make_arg_array(arr,addr,len,arg){var obj;if(!arr) return;obj={arr:arr,addr:addr,len:len,arg:arg};temp_arg_arrays.push(obj);} self.make_arg_array=make_arg_array;function retain_array(arr){var ix,obj;if(!arr) return;obj=undefined;for(ix=0;ix>>0);}} else if(obj.arg instanceof ArgChar){if(!obj.arg.signed){for(ix=0,jx=obj.addr;ix element!");return;} var script=$('