Skip to content

Instantly share code, notes, and snippets.

@bwhite
Last active August 29, 2015 14:00
Show Gist options
  • Save bwhite/11346068 to your computer and use it in GitHub Desktop.
Save bwhite/11346068 to your computer and use it in GitHub Desktop.
/*
JSNES, based on Jamie Sanders' vNES
Copyright (C) 2010 Ben Firshman
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
JSNES.CPU = function(nes) {
this.nes = nes;
// Keep Chrome happy
this.mem = null;
this.REG_ACC = null;
this.REG_X = null;
this.REG_Y = null;
this.REG_SP = null;
this.REG_PC = null;
this.REG_PC_NEW = null;
this.REG_STATUS = null;
this.F_CARRY = null;
this.F_DECIMAL = null;
this.F_INTERRUPT = null;
this.F_INTERRUPT_NEW = null;
this.F_OVERFLOW = null;
this.F_SIGN = null;
this.F_ZERO = null;
this.F_NOTUSED = null;
this.F_NOTUSED_NEW = null;
this.F_BRK = null;
this.F_BRK_NEW = null;
this.opdata = null;
this.cyclesToHalt = null;
this.crash = null;
this.irqRequested = null;
this.irqType = null;
this.reset();
};
JSNES.CPU.prototype = {
// IRQ Types
IRQ_NORMAL: 0,
IRQ_NMI: 1,
IRQ_RESET: 2,
reset: function() {
// Main memory
this.mem = new Array(0x10000);
for (var i=0; i < 0x2000; i++) {
this.mem[i] = 0xFF;
}
for (var p=0; p < 4; p++) {
var i = p*0x800;
this.mem[i+0x008] = 0xF7;
this.mem[i+0x009] = 0xEF;
this.mem[i+0x00A] = 0xDF;
this.mem[i+0x00F] = 0xBF;
}
for (var i=0x2001; i < this.mem.length; i++) {
this.mem[i] = 0;
}
// CPU Registers:
this.REG_ACC = 0;
this.REG_X = 0;
this.REG_Y = 0;
// Reset Stack pointer:
this.REG_SP = 0x01FF;
// Reset Program counter:
this.REG_PC = 0x8000-1;
this.REG_PC_NEW = 0x8000-1;
// Reset Status register:
this.REG_STATUS = 0x28;
this.setStatus(0x28);
// Set flags:
this.F_CARRY = 0;
this.F_DECIMAL = 0;
this.F_INTERRUPT = 1;
this.F_INTERRUPT_NEW = 1;
this.F_OVERFLOW = 0;
this.F_SIGN = 0;
this.F_ZERO = 1;
this.F_NOTUSED = 1;
this.F_NOTUSED_NEW = 1;
this.F_BRK = 1;
this.F_BRK_NEW = 1;
this.opdata = new JSNES.CPU.OpData().opdata;
this.cyclesToHalt = 0;
// Reset crash flag:
this.crash = false;
// Interrupt notification:
this.irqRequested = false;
this.irqType = null;
},
// Emulates a single CPU instruction, returns the number of cycles
emulate: function() {
var temp;
var add;
// Check interrupts:
if(this.irqRequested){
temp =
(this.F_CARRY)|
((this.F_ZERO===0?1:0)<<1)|
(this.F_INTERRUPT<<2)|
(this.F_DECIMAL<<3)|
(this.F_BRK<<4)|
(this.F_NOTUSED<<5)|
(this.F_OVERFLOW<<6)|
(this.F_SIGN<<7);
this.REG_PC_NEW = this.REG_PC;
this.F_INTERRUPT_NEW = this.F_INTERRUPT;
switch(this.irqType){
case 0: {
// Normal IRQ:
if(this.F_INTERRUPT!=0){
////System.out.println("Interrupt was masked.");
break;
}
this.doIrq(temp);
////System.out.println("Did normal IRQ. I="+this.F_INTERRUPT);
break;
}case 1:{
// NMI:
this.doNonMaskableInterrupt(temp);
break;
}case 2:{
// Reset:
this.doResetInterrupt();
break;
}
}
this.REG_PC = this.REG_PC_NEW;
this.F_INTERRUPT = this.F_INTERRUPT_NEW;
this.F_BRK = this.F_BRK_NEW;
this.irqRequested = false;
}
var opinf = this.opdata[this.nes.mmap.load(this.REG_PC+1)];
var cycleCount = (opinf>>24);
var cycleAdd = 0;
// Find address mode:
var addrMode = (opinf >> 8) & 0xFF;
// Increment PC by number of op bytes:
var opaddr = this.REG_PC;
this.REG_PC += ((opinf >> 16) & 0xFF);
var addr = 0;
switch(addrMode){
case 0:{
// Zero Page mode. Use the address given after the opcode,
// but without high byte.
addr = this.load(opaddr+2);
break;
}case 1:{
// Relative mode.
addr = this.load(opaddr+2);
if(addr<0x80){
addr += this.REG_PC;
}else{
addr += this.REG_PC-256;
}
break;
}case 2:{
// Ignore. Address is implied in instruction.
break;
}case 3:{
// Absolute mode. Use the two bytes following the opcode as
// an address.
addr = this.load16bit(opaddr+2);
break;
}case 4:{
// Accumulator mode. The address is in the accumulator
// register.
addr = this.REG_ACC;
break;
}case 5:{
// Immediate mode. The value is given after the opcode.
addr = this.REG_PC;
break;
}case 6:{
// Zero Page Indexed mode, X as index. Use the address given
// after the opcode, then add the
// X register to it to get the final address.
addr = (this.load(opaddr+2)+this.REG_X)&0xFF;
break;
}case 7:{
// Zero Page Indexed mode, Y as index. Use the address given
// after the opcode, then add the
// Y register to it to get the final address.
addr = (this.load(opaddr+2)+this.REG_Y)&0xFF;
break;
}case 8:{
// Absolute Indexed Mode, X as index. Same as zero page
// indexed, but with the high byte.
addr = this.load16bit(opaddr+2);
if((addr&0xFF00)!=((addr+this.REG_X)&0xFF00)){
cycleAdd = 1;
}
addr+=this.REG_X;
break;
}case 9:{
// Absolute Indexed Mode, Y as index. Same as zero page
// indexed, but with the high byte.
addr = this.load16bit(opaddr+2);
if((addr&0xFF00)!=((addr+this.REG_Y)&0xFF00)){
cycleAdd = 1;
}
addr+=this.REG_Y;
break;
}case 10:{
// Pre-indexed Indirect mode. Find the 16-bit address
// starting at the given location plus
// the current X register. The value is the contents of that
// address.
addr = this.load(opaddr+2);
if((addr&0xFF00)!=((addr+this.REG_X)&0xFF00)){
cycleAdd = 1;
}
addr+=this.REG_X;
addr&=0xFF;
addr = this.load16bit(addr);
break;
}case 11:{
// Post-indexed Indirect mode. Find the 16-bit address
// contained in the given location
// (and the one following). Add to that address the contents
// of the Y register. Fetch the value
// stored at that adress.
addr = this.load16bit(this.load(opaddr+2));
if((addr&0xFF00)!=((addr+this.REG_Y)&0xFF00)){
cycleAdd = 1;
}
addr+=this.REG_Y;
break;
}case 12:{
// Indirect Absolute mode. Find the 16-bit address contained
// at the given location.
addr = this.load16bit(opaddr+2);// Find op
if(addr < 0x1FFF) {
addr = this.mem[addr] + (this.mem[(addr & 0xFF00) | (((addr & 0xFF) + 1) & 0xFF)] << 8);// Read from address given in op
}
else{
addr = this.nes.mmap.load(addr) + (this.nes.mmap.load((addr & 0xFF00) | (((addr & 0xFF) + 1) & 0xFF)) << 8);
}
break;
}
}
// Wrap around for addresses above 0xFFFF:
addr&=0xFFFF;
// ----------------------------------------------------------------------------------------------------
// Decode & execute instruction:
// ----------------------------------------------------------------------------------------------------
// This should be compiled to a jump table.
switch(opinf&0xFF){
case 0:{
// *******
// * ADC *
// *******
// Add with carry.
temp = this.REG_ACC + this.load(addr) + this.F_CARRY;
this.F_OVERFLOW = ((!(((this.REG_ACC ^ this.load(addr)) & 0x80)!=0) && (((this.REG_ACC ^ temp) & 0x80))!=0)?1:0);
this.F_CARRY = (temp>255?1:0);
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp&0xFF;
this.REG_ACC = (temp&255);
cycleCount+=cycleAdd;
break;
}case 1:{
// *******
// * AND *
// *******
// AND memory with accumulator.
this.REG_ACC = this.REG_ACC & this.load(addr);
this.F_SIGN = (this.REG_ACC>>7)&1;
this.F_ZERO = this.REG_ACC;
//this.REG_ACC = temp;
if(addrMode!=11)cycleCount+=cycleAdd; // PostIdxInd = 11
break;
}case 2:{
// *******
// * ASL *
// *******
// Shift left one bit
if(addrMode == 4){ // ADDR_ACC = 4
this.F_CARRY = (this.REG_ACC>>7)&1;
this.REG_ACC = (this.REG_ACC<<1)&255;
this.F_SIGN = (this.REG_ACC>>7)&1;
this.F_ZERO = this.REG_ACC;
}else{
temp = this.load(addr);
this.F_CARRY = (temp>>7)&1;
temp = (temp<<1)&255;
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp;
this.write(addr, temp);
}
break;
}case 3:{
// *******
// * BCC *
// *******
// Branch on carry clear
if(this.F_CARRY == 0){
cycleCount += ((opaddr&0xFF00)!=(addr&0xFF00)?2:1);
this.REG_PC = addr;
}
break;
}case 4:{
// *******
// * BCS *
// *******
// Branch on carry set
if(this.F_CARRY == 1){
cycleCount += ((opaddr&0xFF00)!=(addr&0xFF00)?2:1);
this.REG_PC = addr;
}
break;
}case 5:{
// *******
// * BEQ *
// *******
// Branch on zero
if(this.F_ZERO == 0){
cycleCount += ((opaddr&0xFF00)!=(addr&0xFF00)?2:1);
this.REG_PC = addr;
}
break;
}case 6:{
// *******
// * BIT *
// *******
temp = this.load(addr);
this.F_SIGN = (temp>>7)&1;
this.F_OVERFLOW = (temp>>6)&1;
temp &= this.REG_ACC;
this.F_ZERO = temp;
break;
}case 7:{
// *******
// * BMI *
// *******
// Branch on negative result
if(this.F_SIGN == 1){
cycleCount++;
this.REG_PC = addr;
}
break;
}case 8:{
// *******
// * BNE *
// *******
// Branch on not zero
if(this.F_ZERO != 0){
cycleCount += ((opaddr&0xFF00)!=(addr&0xFF00)?2:1);
this.REG_PC = addr;
}
break;
}case 9:{
// *******
// * BPL *
// *******
// Branch on positive result
if(this.F_SIGN == 0){
cycleCount += ((opaddr&0xFF00)!=(addr&0xFF00)?2:1);
this.REG_PC = addr;
}
break;
}case 10:{
// *******
// * BRK *
// *******
this.REG_PC+=2;
this.push((this.REG_PC>>8)&255);
this.push(this.REG_PC&255);
this.F_BRK = 1;
this.push(
(this.F_CARRY)|
((this.F_ZERO==0?1:0)<<1)|
(this.F_INTERRUPT<<2)|
(this.F_DECIMAL<<3)|
(this.F_BRK<<4)|
(this.F_NOTUSED<<5)|
(this.F_OVERFLOW<<6)|
(this.F_SIGN<<7)
);
this.F_INTERRUPT = 1;
//this.REG_PC = load(0xFFFE) | (load(0xFFFF) << 8);
this.REG_PC = this.load16bit(0xFFFE);
this.REG_PC--;
break;
}case 11:{
// *******
// * BVC *
// *******
// Branch on overflow clear
if(this.F_OVERFLOW == 0){
cycleCount += ((opaddr&0xFF00)!=(addr&0xFF00)?2:1);
this.REG_PC = addr;
}
break;
}case 12:{
// *******
// * BVS *
// *******
// Branch on overflow set
if(this.F_OVERFLOW == 1){
cycleCount += ((opaddr&0xFF00)!=(addr&0xFF00)?2:1);
this.REG_PC = addr;
}
break;
}case 13:{
// *******
// * CLC *
// *******
// Clear carry flag
this.F_CARRY = 0;
break;
}case 14:{
// *******
// * CLD *
// *******
// Clear decimal flag
this.F_DECIMAL = 0;
break;
}case 15:{
// *******
// * CLI *
// *******
// Clear interrupt flag
this.F_INTERRUPT = 0;
break;
}case 16:{
// *******
// * CLV *
// *******
// Clear overflow flag
this.F_OVERFLOW = 0;
break;
}case 17:{
// *******
// * CMP *
// *******
// Compare memory and accumulator:
temp = this.REG_ACC - this.load(addr);
this.F_CARRY = (temp>=0?1:0);
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp&0xFF;
cycleCount+=cycleAdd;
break;
}case 18:{
// *******
// * CPX *
// *******
// Compare memory and index X:
temp = this.REG_X - this.load(addr);
this.F_CARRY = (temp>=0?1:0);
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp&0xFF;
break;
}case 19:{
// *******
// * CPY *
// *******
// Compare memory and index Y:
temp = this.REG_Y - this.load(addr);
this.F_CARRY = (temp>=0?1:0);
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp&0xFF;
break;
}case 20:{
// *******
// * DEC *
// *******
// Decrement memory by one:
temp = (this.load(addr)-1)&0xFF;
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp;
this.write(addr, temp);
break;
}case 21:{
// *******
// * DEX *
// *******
// Decrement index X by one:
this.REG_X = (this.REG_X-1)&0xFF;
this.F_SIGN = (this.REG_X>>7)&1;
this.F_ZERO = this.REG_X;
break;
}case 22:{
// *******
// * DEY *
// *******
// Decrement index Y by one:
this.REG_Y = (this.REG_Y-1)&0xFF;
this.F_SIGN = (this.REG_Y>>7)&1;
this.F_ZERO = this.REG_Y;
break;
}case 23:{
// *******
// * EOR *
// *******
// XOR Memory with accumulator, store in accumulator:
this.REG_ACC = (this.load(addr)^this.REG_ACC)&0xFF;
this.F_SIGN = (this.REG_ACC>>7)&1;
this.F_ZERO = this.REG_ACC;
cycleCount+=cycleAdd;
break;
}case 24:{
// *******
// * INC *
// *******
// Increment memory by one:
temp = (this.load(addr)+1)&0xFF;
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp;
this.write(addr, temp&0xFF);
break;
}case 25:{
// *******
// * INX *
// *******
// Increment index X by one:
this.REG_X = (this.REG_X+1)&0xFF;
this.F_SIGN = (this.REG_X>>7)&1;
this.F_ZERO = this.REG_X;
break;
}case 26:{
// *******
// * INY *
// *******
// Increment index Y by one:
this.REG_Y++;
this.REG_Y &= 0xFF;
this.F_SIGN = (this.REG_Y>>7)&1;
this.F_ZERO = this.REG_Y;
break;
}case 27:{
// *******
// * JMP *
// *******
// Jump to new location:
this.REG_PC = addr-1;
break;
}case 28:{
// *******
// * JSR *
// *******
// Jump to new location, saving return address.
// Push return address on stack:
this.push((this.REG_PC>>8)&255);
this.push(this.REG_PC&255);
this.REG_PC = addr-1;
break;
}case 29:{
// *******
// * LDA *
// *******
// Load accumulator with memory:
this.REG_ACC = this.load(addr);
this.F_SIGN = (this.REG_ACC>>7)&1;
this.F_ZERO = this.REG_ACC;
cycleCount+=cycleAdd;
break;
}case 30:{
// *******
// * LDX *
// *******
// Load index X with memory:
this.REG_X = this.load(addr);
this.F_SIGN = (this.REG_X>>7)&1;
this.F_ZERO = this.REG_X;
cycleCount+=cycleAdd;
break;
}case 31:{
// *******
// * LDY *
// *******
// Load index Y with memory:
this.REG_Y = this.load(addr);
this.F_SIGN = (this.REG_Y>>7)&1;
this.F_ZERO = this.REG_Y;
cycleCount+=cycleAdd;
break;
}case 32:{
// *******
// * LSR *
// *******
// Shift right one bit:
if(addrMode == 4){ // ADDR_ACC
temp = (this.REG_ACC & 0xFF);
this.F_CARRY = temp&1;
temp >>= 1;
this.REG_ACC = temp;
}else{
temp = this.load(addr) & 0xFF;
this.F_CARRY = temp&1;
temp >>= 1;
this.write(addr, temp);
}
this.F_SIGN = 0;
this.F_ZERO = temp;
break;
}case 33:{
// *******
// * NOP *
// *******
// No OPeration.
// Ignore.
break;
}case 34:{
// *******
// * ORA *
// *******
// OR memory with accumulator, store in accumulator.
temp = (this.load(addr)|this.REG_ACC)&255;
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp;
this.REG_ACC = temp;
if(addrMode!=11)cycleCount+=cycleAdd; // PostIdxInd = 11
break;
}case 35:{
// *******
// * PHA *
// *******
// Push accumulator on stack
this.push(this.REG_ACC);
break;
}case 36:{
// *******
// * PHP *
// *******
// Push processor status on stack
this.F_BRK = 1;
this.push(
(this.F_CARRY)|
((this.F_ZERO==0?1:0)<<1)|
(this.F_INTERRUPT<<2)|
(this.F_DECIMAL<<3)|
(this.F_BRK<<4)|
(this.F_NOTUSED<<5)|
(this.F_OVERFLOW<<6)|
(this.F_SIGN<<7)
);
break;
}case 37:{
// *******
// * PLA *
// *******
// Pull accumulator from stack
this.REG_ACC = this.pull();
this.F_SIGN = (this.REG_ACC>>7)&1;
this.F_ZERO = this.REG_ACC;
break;
}case 38:{
// *******
// * PLP *
// *******
// Pull processor status from stack
temp = this.pull();
this.F_CARRY = (temp )&1;
this.F_ZERO = (((temp>>1)&1)==1)?0:1;
this.F_INTERRUPT = (temp>>2)&1;
this.F_DECIMAL = (temp>>3)&1;
this.F_BRK = (temp>>4)&1;
this.F_NOTUSED = (temp>>5)&1;
this.F_OVERFLOW = (temp>>6)&1;
this.F_SIGN = (temp>>7)&1;
this.F_NOTUSED = 1;
break;
}case 39:{
// *******
// * ROL *
// *******
// Rotate one bit left
if(addrMode == 4){ // ADDR_ACC = 4
temp = this.REG_ACC;
add = this.F_CARRY;
this.F_CARRY = (temp>>7)&1;
temp = ((temp<<1)&0xFF)+add;
this.REG_ACC = temp;
}else{
temp = this.load(addr);
add = this.F_CARRY;
this.F_CARRY = (temp>>7)&1;
temp = ((temp<<1)&0xFF)+add;
this.write(addr, temp);
}
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp;
break;
}case 40:{
// *******
// * ROR *
// *******
// Rotate one bit right
if(addrMode == 4){ // ADDR_ACC = 4
add = this.F_CARRY<<7;
this.F_CARRY = this.REG_ACC&1;
temp = (this.REG_ACC>>1)+add;
this.REG_ACC = temp;
}else{
temp = this.load(addr);
add = this.F_CARRY<<7;
this.F_CARRY = temp&1;
temp = (temp>>1)+add;
this.write(addr, temp);
}
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp;
break;
}case 41:{
// *******
// * RTI *
// *******
// Return from interrupt. Pull status and PC from stack.
temp = this.pull();
this.F_CARRY = (temp )&1;
this.F_ZERO = ((temp>>1)&1)==0?1:0;
this.F_INTERRUPT = (temp>>2)&1;
this.F_DECIMAL = (temp>>3)&1;
this.F_BRK = (temp>>4)&1;
this.F_NOTUSED = (temp>>5)&1;
this.F_OVERFLOW = (temp>>6)&1;
this.F_SIGN = (temp>>7)&1;
this.REG_PC = this.pull();
this.REG_PC += (this.pull()<<8);
if(this.REG_PC==0xFFFF){
return;
}
this.REG_PC--;
this.F_NOTUSED = 1;
break;
}case 42:{
// *******
// * RTS *
// *******
// Return from subroutine. Pull PC from stack.
this.REG_PC = this.pull();
this.REG_PC += (this.pull()<<8);
if(this.REG_PC==0xFFFF){
return; // return from NSF play routine:
}
break;
}case 43:{
// *******
// * SBC *
// *******
temp = this.REG_ACC-this.load(addr)-(1-this.F_CARRY);
this.F_SIGN = (temp>>7)&1;
this.F_ZERO = temp&0xFF;
this.F_OVERFLOW = ((((this.REG_ACC^temp)&0x80)!=0 && ((this.REG_ACC^this.load(addr))&0x80)!=0)?1:0);
this.F_CARRY = (temp<0?0:1);
this.REG_ACC = (temp&0xFF);
if(addrMode!=11)cycleCount+=cycleAdd; // PostIdxInd = 11
break;
}case 44:{
// *******
// * SEC *
// *******
// Set carry flag
this.F_CARRY = 1;
break;
}case 45:{
// *******
// * SED *
// *******
// Set decimal mode
this.F_DECIMAL = 1;
break;
}case 46:{
// *******
// * SEI *
// *******
// Set interrupt disable status
this.F_INTERRUPT = 1;
break;
}case 47:{
// *******
// * STA *
// *******
// Store accumulator in memory
this.write(addr, this.REG_ACC);
break;
}case 48:{
// *******
// * STX *
// *******
// Store index X in memory
this.write(addr, this.REG_X);
break;
}case 49:{
// *******
// * STY *
// *******
// Store index Y in memory:
this.write(addr, this.REG_Y);
break;
}case 50:{
// *******
// * TAX *
// *******
// Transfer accumulator to index X:
this.REG_X = this.REG_ACC;
this.F_SIGN = (this.REG_ACC>>7)&1;
this.F_ZERO = this.REG_ACC;
break;
}case 51:{
// *******
// * TAY *
// *******
// Transfer accumulator to index Y:
this.REG_Y = this.REG_ACC;
this.F_SIGN = (this.REG_ACC>>7)&1;
this.F_ZERO = this.REG_ACC;
break;
}case 52:{
// *******
// * TSX *
// *******
// Transfer stack pointer to index X:
this.REG_X = (this.REG_SP-0x0100);
this.F_SIGN = (this.REG_SP>>7)&1;
this.F_ZERO = this.REG_X;
break;
}case 53:{
// *******
// * TXA *
// *******
// Transfer index X to accumulator:
this.REG_ACC = this.REG_X;
this.F_SIGN = (this.REG_X>>7)&1;
this.F_ZERO = this.REG_X;
break;
}case 54:{
// *******
// * TXS *
// *******
// Transfer index X to stack pointer:
this.REG_SP = (this.REG_X+0x0100);
this.stackWrap();
break;
}case 55:{
// *******
// * TYA *
// *******
// Transfer index Y to accumulator:
this.REG_ACC = this.REG_Y;
this.F_SIGN = (this.REG_Y>>7)&1;
this.F_ZERO = this.REG_Y;
break;
}default:{
// *******
// * ??? *
// *******
this.nes.stop();
this.nes.crashMessage = "Game crashed, invalid opcode at address $"+opaddr.toString(16);
break;
}
}// end of switch
return cycleCount;
},
load: function(addr){
if (addr < 0x2000) {
return this.mem[addr & 0x7FF];
}
else {
return this.nes.mmap.load(addr);
}
},
load16bit: function(addr){
if (addr < 0x1FFF) {
return this.mem[addr&0x7FF]
| (this.mem[(addr+1)&0x7FF]<<8);
}
else {
return this.nes.mmap.load(addr) | (this.nes.mmap.load(addr+1) << 8);
}
},
write: function(addr, val){
if(addr < 0x2000) {
this.mem[addr&0x7FF] = val;
}
else {
this.nes.mmap.write(addr,val);
}
},
requestIrq: function(type){
if(this.irqRequested){
if(type == this.IRQ_NORMAL){
return;
}
////System.out.println("too fast irqs. type="+type);
}
this.irqRequested = true;
this.irqType = type;
},
push: function(value){
this.nes.mmap.write(this.REG_SP, value);
this.REG_SP--;
this.REG_SP = 0x0100 | (this.REG_SP&0xFF);
},
stackWrap: function(){
this.REG_SP = 0x0100 | (this.REG_SP&0xFF);
},
pull: function(){
this.REG_SP++;
this.REG_SP = 0x0100 | (this.REG_SP&0xFF);
return this.nes.mmap.load(this.REG_SP);
},
pageCrossed: function(addr1, addr2){
return ((addr1&0xFF00) != (addr2&0xFF00));
},
haltCycles: function(cycles){
this.cyclesToHalt += cycles;
},
doNonMaskableInterrupt: function(status){
if((this.nes.mmap.load(0x2000) & 128) != 0) { // Check whether VBlank Interrupts are enabled
this.REG_PC_NEW++;
this.push((this.REG_PC_NEW>>8)&0xFF);
this.push(this.REG_PC_NEW&0xFF);
//this.F_INTERRUPT_NEW = 1;
this.push(status);
this.REG_PC_NEW = this.nes.mmap.load(0xFFFA) | (this.nes.mmap.load(0xFFFB) << 8);
this.REG_PC_NEW--;
}
},
doResetInterrupt: function(){
this.REG_PC_NEW = this.nes.mmap.load(0xFFFC) | (this.nes.mmap.load(0xFFFD) << 8);
this.REG_PC_NEW--;
},
doIrq: function(status){
this.REG_PC_NEW++;
this.push((this.REG_PC_NEW>>8)&0xFF);
this.push(this.REG_PC_NEW&0xFF);
this.push(status);
this.F_INTERRUPT_NEW = 1;
this.F_BRK_NEW = 0;
this.REG_PC_NEW = this.nes.mmap.load(0xFFFE) | (this.nes.mmap.load(0xFFFF) << 8);
this.REG_PC_NEW--;
},
getStatus: function(){
return (this.F_CARRY)
|(this.F_ZERO<<1)
|(this.F_INTERRUPT<<2)
|(this.F_DECIMAL<<3)
|(this.F_BRK<<4)
|(this.F_NOTUSED<<5)
|(this.F_OVERFLOW<<6)
|(this.F_SIGN<<7);
},
setStatus: function(st){
this.F_CARRY = (st )&1;
this.F_ZERO = (st>>1)&1;
this.F_INTERRUPT = (st>>2)&1;
this.F_DECIMAL = (st>>3)&1;
this.F_BRK = (st>>4)&1;
this.F_NOTUSED = (st>>5)&1;
this.F_OVERFLOW = (st>>6)&1;
this.F_SIGN = (st>>7)&1;
},
JSON_PROPERTIES: [
'mem', 'cyclesToHalt', 'irqRequested', 'irqType',
// Registers
'REG_ACC', 'REG_X', 'REG_Y', 'REG_SP', 'REG_PC', 'REG_PC_NEW',
'REG_STATUS',
// Status
'F_CARRY', 'F_DECIMAL', 'F_INTERRUPT', 'F_INTERRUPT_NEW', 'F_OVERFLOW',
'F_SIGN', 'F_ZERO', 'F_NOTUSED', 'F_NOTUSED_NEW', 'F_BRK', 'F_BRK_NEW'
],
toJSON: function() {
return JSNES.Utils.toJSON(this);
},
fromJSON: function(s) {
JSNES.Utils.fromJSON(this, s);
}
}
// Generates and provides an array of details about instructions
JSNES.CPU.OpData = function() {
this.opdata = new Array(256);
// Set all to invalid instruction (to detect crashes):
for(var i=0;i<256;i++) this.opdata[i]=0xFF;
// Now fill in all valid opcodes:
// ADC:
this.setOp(this.INS_ADC,0x69,this.ADDR_IMM,2,2);
this.setOp(this.INS_ADC,0x65,this.ADDR_ZP,2,3);
this.setOp(this.INS_ADC,0x75,this.ADDR_ZPX,2,4);
this.setOp(this.INS_ADC,0x6D,this.ADDR_ABS,3,4);
this.setOp(this.INS_ADC,0x7D,this.ADDR_ABSX,3,4);
this.setOp(this.INS_ADC,0x79,this.ADDR_ABSY,3,4);
this.setOp(this.INS_ADC,0x61,this.ADDR_PREIDXIND,2,6);
this.setOp(this.INS_ADC,0x71,this.ADDR_POSTIDXIND,2,5);
// AND:
this.setOp(this.INS_AND,0x29,this.ADDR_IMM,2,2);
this.setOp(this.INS_AND,0x25,this.ADDR_ZP,2,3);
this.setOp(this.INS_AND,0x35,this.ADDR_ZPX,2,4);
this.setOp(this.INS_AND,0x2D,this.ADDR_ABS,3,4);
this.setOp(this.INS_AND,0x3D,this.ADDR_ABSX,3,4);
this.setOp(this.INS_AND,0x39,this.ADDR_ABSY,3,4);
this.setOp(this.INS_AND,0x21,this.ADDR_PREIDXIND,2,6);
this.setOp(this.INS_AND,0x31,this.ADDR_POSTIDXIND,2,5);
// ASL:
this.setOp(this.INS_ASL,0x0A,this.ADDR_ACC,1,2);
this.setOp(this.INS_ASL,0x06,this.ADDR_ZP,2,5);
this.setOp(this.INS_ASL,0x16,this.ADDR_ZPX,2,6);
this.setOp(this.INS_ASL,0x0E,this.ADDR_ABS,3,6);
this.setOp(this.INS_ASL,0x1E,this.ADDR_ABSX,3,7);
// BCC:
this.setOp(this.INS_BCC,0x90,this.ADDR_REL,2,2);
// BCS:
this.setOp(this.INS_BCS,0xB0,this.ADDR_REL,2,2);
// BEQ:
this.setOp(this.INS_BEQ,0xF0,this.ADDR_REL,2,2);
// BIT:
this.setOp(this.INS_BIT,0x24,this.ADDR_ZP,2,3);
this.setOp(this.INS_BIT,0x2C,this.ADDR_ABS,3,4);
// BMI:
this.setOp(this.INS_BMI,0x30,this.ADDR_REL,2,2);
// BNE:
this.setOp(this.INS_BNE,0xD0,this.ADDR_REL,2,2);
// BPL:
this.setOp(this.INS_BPL,0x10,this.ADDR_REL,2,2);
// BRK:
this.setOp(this.INS_BRK,0x00,this.ADDR_IMP,1,7);
// BVC:
this.setOp(this.INS_BVC,0x50,this.ADDR_REL,2,2);
// BVS:
this.setOp(this.INS_BVS,0x70,this.ADDR_REL,2,2);
// CLC:
this.setOp(this.INS_CLC,0x18,this.ADDR_IMP,1,2);
// CLD:
this.setOp(this.INS_CLD,0xD8,this.ADDR_IMP,1,2);
// CLI:
this.setOp(this.INS_CLI,0x58,this.ADDR_IMP,1,2);
// CLV:
this.setOp(this.INS_CLV,0xB8,this.ADDR_IMP,1,2);
// CMP:
this.setOp(this.INS_CMP,0xC9,this.ADDR_IMM,2,2);
this.setOp(this.INS_CMP,0xC5,this.ADDR_ZP,2,3);
this.setOp(this.INS_CMP,0xD5,this.ADDR_ZPX,2,4);
this.setOp(this.INS_CMP,0xCD,this.ADDR_ABS,3,4);
this.setOp(this.INS_CMP,0xDD,this.ADDR_ABSX,3,4);
this.setOp(this.INS_CMP,0xD9,this.ADDR_ABSY,3,4);
this.setOp(this.INS_CMP,0xC1,this.ADDR_PREIDXIND,2,6);
this.setOp(this.INS_CMP,0xD1,this.ADDR_POSTIDXIND,2,5);
// CPX:
this.setOp(this.INS_CPX,0xE0,this.ADDR_IMM,2,2);
this.setOp(this.INS_CPX,0xE4,this.ADDR_ZP,2,3);
this.setOp(this.INS_CPX,0xEC,this.ADDR_ABS,3,4);
// CPY:
this.setOp(this.INS_CPY,0xC0,this.ADDR_IMM,2,2);
this.setOp(this.INS_CPY,0xC4,this.ADDR_ZP,2,3);
this.setOp(this.INS_CPY,0xCC,this.ADDR_ABS,3,4);
// DEC:
this.setOp(this.INS_DEC,0xC6,this.ADDR_ZP,2,5);
this.setOp(this.INS_DEC,0xD6,this.ADDR_ZPX,2,6);
this.setOp(this.INS_DEC,0xCE,this.ADDR_ABS,3,6);
this.setOp(this.INS_DEC,0xDE,this.ADDR_ABSX,3,7);
// DEX:
this.setOp(this.INS_DEX,0xCA,this.ADDR_IMP,1,2);
// DEY:
this.setOp(this.INS_DEY,0x88,this.ADDR_IMP,1,2);
// EOR:
this.setOp(this.INS_EOR,0x49,this.ADDR_IMM,2,2);
this.setOp(this.INS_EOR,0x45,this.ADDR_ZP,2,3);
this.setOp(this.INS_EOR,0x55,this.ADDR_ZPX,2,4);
this.setOp(this.INS_EOR,0x4D,this.ADDR_ABS,3,4);
this.setOp(this.INS_EOR,0x5D,this.ADDR_ABSX,3,4);
this.setOp(this.INS_EOR,0x59,this.ADDR_ABSY,3,4);
this.setOp(this.INS_EOR,0x41,this.ADDR_PREIDXIND,2,6);
this.setOp(this.INS_EOR,0x51,this.ADDR_POSTIDXIND,2,5);
// INC:
this.setOp(this.INS_INC,0xE6,this.ADDR_ZP,2,5);
this.setOp(this.INS_INC,0xF6,this.ADDR_ZPX,2,6);
this.setOp(this.INS_INC,0xEE,this.ADDR_ABS,3,6);
this.setOp(this.INS_INC,0xFE,this.ADDR_ABSX,3,7);
// INX:
this.setOp(this.INS_INX,0xE8,this.ADDR_IMP,1,2);
// INY:
this.setOp(this.INS_INY,0xC8,this.ADDR_IMP,1,2);
// JMP:
this.setOp(this.INS_JMP,0x4C,this.ADDR_ABS,3,3);
this.setOp(this.INS_JMP,0x6C,this.ADDR_INDABS,3,5);
// JSR:
this.setOp(this.INS_JSR,0x20,this.ADDR_ABS,3,6);
// LDA:
this.setOp(this.INS_LDA,0xA9,this.ADDR_IMM,2,2);
this.setOp(this.INS_LDA,0xA5,this.ADDR_ZP,2,3);
this.setOp(this.INS_LDA,0xB5,this.ADDR_ZPX,2,4);
this.setOp(this.INS_LDA,0xAD,this.ADDR_ABS,3,4);
this.setOp(this.INS_LDA,0xBD,this.ADDR_ABSX,3,4);
this.setOp(this.INS_LDA,0xB9,this.ADDR_ABSY,3,4);
this.setOp(this.INS_LDA,0xA1,this.ADDR_PREIDXIND,2,6);
this.setOp(this.INS_LDA,0xB1,this.ADDR_POSTIDXIND,2,5);
// LDX:
this.setOp(this.INS_LDX,0xA2,this.ADDR_IMM,2,2);
this.setOp(this.INS_LDX,0xA6,this.ADDR_ZP,2,3);
this.setOp(this.INS_LDX,0xB6,this.ADDR_ZPY,2,4);
this.setOp(this.INS_LDX,0xAE,this.ADDR_ABS,3,4);
this.setOp(this.INS_LDX,0xBE,this.ADDR_ABSY,3,4);
// LDY:
this.setOp(this.INS_LDY,0xA0,this.ADDR_IMM,2,2);
this.setOp(this.INS_LDY,0xA4,this.ADDR_ZP,2,3);
this.setOp(this.INS_LDY,0xB4,this.ADDR_ZPX,2,4);
this.setOp(this.INS_LDY,0xAC,this.ADDR_ABS,3,4);
this.setOp(this.INS_LDY,0xBC,this.ADDR_ABSX,3,4);
// LSR:
this.setOp(this.INS_LSR,0x4A,this.ADDR_ACC,1,2);
this.setOp(this.INS_LSR,0x46,this.ADDR_ZP,2,5);
this.setOp(this.INS_LSR,0x56,this.ADDR_ZPX,2,6);
this.setOp(this.INS_LSR,0x4E,this.ADDR_ABS,3,6);
this.setOp(this.INS_LSR,0x5E,this.ADDR_ABSX,3,7);
// NOP:
this.setOp(this.INS_NOP,0xEA,this.ADDR_IMP,1,2);
// ORA:
this.setOp(this.INS_ORA,0x09,this.ADDR_IMM,2,2);
this.setOp(this.INS_ORA,0x05,this.ADDR_ZP,2,3);
this.setOp(this.INS_ORA,0x15,this.ADDR_ZPX,2,4);
this.setOp(this.INS_ORA,0x0D,this.ADDR_ABS,3,4);
this.setOp(this.INS_ORA,0x1D,this.ADDR_ABSX,3,4);
this.setOp(this.INS_ORA,0x19,this.ADDR_ABSY,3,4);
this.setOp(this.INS_ORA,0x01,this.ADDR_PREIDXIND,2,6);
this.setOp(this.INS_ORA,0x11,this.ADDR_POSTIDXIND,2,5);
// PHA:
this.setOp(this.INS_PHA,0x48,this.ADDR_IMP,1,3);
// PHP:
this.setOp(this.INS_PHP,0x08,this.ADDR_IMP,1,3);
// PLA:
this.setOp(this.INS_PLA,0x68,this.ADDR_IMP,1,4);
// PLP:
this.setOp(this.INS_PLP,0x28,this.ADDR_IMP,1,4);
// ROL:
this.setOp(this.INS_ROL,0x2A,this.ADDR_ACC,1,2);
this.setOp(this.INS_ROL,0x26,this.ADDR_ZP,2,5);
this.setOp(this.INS_ROL,0x36,this.ADDR_ZPX,2,6);
this.setOp(this.INS_ROL,0x2E,this.ADDR_ABS,3,6);
this.setOp(this.INS_ROL,0x3E,this.ADDR_ABSX,3,7);
// ROR:
this.setOp(this.INS_ROR,0x6A,this.ADDR_ACC,1,2);
this.setOp(this.INS_ROR,0x66,this.ADDR_ZP,2,5);
this.setOp(this.INS_ROR,0x76,this.ADDR_ZPX,2,6);
this.setOp(this.INS_ROR,0x6E,this.ADDR_ABS,3,6);
this.setOp(this.INS_ROR,0x7E,this.ADDR_ABSX,3,7);
// RTI:
this.setOp(this.INS_RTI,0x40,this.ADDR_IMP,1,6);
// RTS:
this.setOp(this.INS_RTS,0x60,this.ADDR_IMP,1,6);
// SBC:
this.setOp(this.INS_SBC,0xE9,this.ADDR_IMM,2,2);
this.setOp(this.INS_SBC,0xE5,this.ADDR_ZP,2,3);
this.setOp(this.INS_SBC,0xF5,this.ADDR_ZPX,2,4);
this.setOp(this.INS_SBC,0xED,this.ADDR_ABS,3,4);
this.setOp(this.INS_SBC,0xFD,this.ADDR_ABSX,3,4);
this.setOp(this.INS_SBC,0xF9,this.ADDR_ABSY,3,4);
this.setOp(this.INS_SBC,0xE1,this.ADDR_PREIDXIND,2,6);
this.setOp(this.INS_SBC,0xF1,this.ADDR_POSTIDXIND,2,5);
// SEC:
this.setOp(this.INS_SEC,0x38,this.ADDR_IMP,1,2);
// SED:
this.setOp(this.INS_SED,0xF8,this.ADDR_IMP,1,2);
// SEI:
this.setOp(this.INS_SEI,0x78,this.ADDR_IMP,1,2);
// STA:
this.setOp(this.INS_STA,0x85,this.ADDR_ZP,2,3);
this.setOp(this.INS_STA,0x95,this.ADDR_ZPX,2,4);
this.setOp(this.INS_STA,0x8D,this.ADDR_ABS,3,4);
this.setOp(this.INS_STA,0x9D,this.ADDR_ABSX,3,5);
this.setOp(this.INS_STA,0x99,this.ADDR_ABSY,3,5);
this.setOp(this.INS_STA,0x81,this.ADDR_PREIDXIND,2,6);
this.setOp(this.INS_STA,0x91,this.ADDR_POSTIDXIND,2,6);
// STX:
this.setOp(this.INS_STX,0x86,this.ADDR_ZP,2,3);
this.setOp(this.INS_STX,0x96,this.ADDR_ZPY,2,4);
this.setOp(this.INS_STX,0x8E,this.ADDR_ABS,3,4);
// STY:
this.setOp(this.INS_STY,0x84,this.ADDR_ZP,2,3);
this.setOp(this.INS_STY,0x94,this.ADDR_ZPX,2,4);
this.setOp(this.INS_STY,0x8C,this.ADDR_ABS,3,4);
// TAX:
this.setOp(this.INS_TAX,0xAA,this.ADDR_IMP,1,2);
// TAY:
this.setOp(this.INS_TAY,0xA8,this.ADDR_IMP,1,2);
// TSX:
this.setOp(this.INS_TSX,0xBA,this.ADDR_IMP,1,2);
// TXA:
this.setOp(this.INS_TXA,0x8A,this.ADDR_IMP,1,2);
// TXS:
this.setOp(this.INS_TXS,0x9A,this.ADDR_IMP,1,2);
// TYA:
this.setOp(this.INS_TYA,0x98,this.ADDR_IMP,1,2);
this.cycTable = new Array(
/*0x00*/ 7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,
/*0x10*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
/*0x20*/ 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,
/*0x30*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
/*0x40*/ 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,
/*0x50*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
/*0x60*/ 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,
/*0x70*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
/*0x80*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
/*0x90*/ 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,
/*0xA0*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
/*0xB0*/ 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,
/*0xC0*/ 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
/*0xD0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
/*0xE0*/ 2,6,3,8,3,3,5,5,2,2,2,2,4,4,6,6,
/*0xF0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7
);
this.instname = new Array(56);
// Instruction Names:
this.instname[ 0] = "ADC";
this.instname[ 1] = "AND";
this.instname[ 2] = "ASL";
this.instname[ 3] = "BCC";
this.instname[ 4] = "BCS";
this.instname[ 5] = "BEQ";
this.instname[ 6] = "BIT";
this.instname[ 7] = "BMI";
this.instname[ 8] = "BNE";
this.instname[ 9] = "BPL";
this.instname[10] = "BRK";
this.instname[11] = "BVC";
this.instname[12] = "BVS";
this.instname[13] = "CLC";
this.instname[14] = "CLD";
this.instname[15] = "CLI";
this.instname[16] = "CLV";
this.instname[17] = "CMP";
this.instname[18] = "CPX";
this.instname[19] = "CPY";
this.instname[20] = "DEC";
this.instname[21] = "DEX";
this.instname[22] = "DEY";
this.instname[23] = "EOR";
this.instname[24] = "INC";
this.instname[25] = "INX";
this.instname[26] = "INY";
this.instname[27] = "JMP";
this.instname[28] = "JSR";
this.instname[29] = "LDA";
this.instname[30] = "LDX";
this.instname[31] = "LDY";
this.instname[32] = "LSR";
this.instname[33] = "NOP";
this.instname[34] = "ORA";
this.instname[35] = "PHA";
this.instname[36] = "PHP";
this.instname[37] = "PLA";
this.instname[38] = "PLP";
this.instname[39] = "ROL";
this.instname[40] = "ROR";
this.instname[41] = "RTI";
this.instname[42] = "RTS";
this.instname[43] = "SBC";
this.instname[44] = "SEC";
this.instname[45] = "SED";
this.instname[46] = "SEI";
this.instname[47] = "STA";
this.instname[48] = "STX";
this.instname[49] = "STY";
this.instname[50] = "TAX";
this.instname[51] = "TAY";
this.instname[52] = "TSX";
this.instname[53] = "TXA";
this.instname[54] = "TXS";
this.instname[55] = "TYA";
this.addrDesc = new Array(
"Zero Page ",
"Relative ",
"Implied ",
"Absolute ",
"Accumulator ",
"Immediate ",
"Zero Page,X ",
"Zero Page,Y ",
"Absolute,X ",
"Absolute,Y ",
"Preindexed Indirect ",
"Postindexed Indirect",
"Indirect Absolute "
);
}
JSNES.CPU.OpData.prototype = {
INS_ADC: 0,
INS_AND: 1,
INS_ASL: 2,
INS_BCC: 3,
INS_BCS: 4,
INS_BEQ: 5,
INS_BIT: 6,
INS_BMI: 7,
INS_BNE: 8,
INS_BPL: 9,
INS_BRK: 10,
INS_BVC: 11,
INS_BVS: 12,
INS_CLC: 13,
INS_CLD: 14,
INS_CLI: 15,
INS_CLV: 16,
INS_CMP: 17,
INS_CPX: 18,
INS_CPY: 19,
INS_DEC: 20,
INS_DEX: 21,
INS_DEY: 22,
INS_EOR: 23,
INS_INC: 24,
INS_INX: 25,
INS_INY: 26,
INS_JMP: 27,
INS_JSR: 28,
INS_LDA: 29,
INS_LDX: 30,
INS_LDY: 31,
INS_LSR: 32,
INS_NOP: 33,
INS_ORA: 34,
INS_PHA: 35,
INS_PHP: 36,
INS_PLA: 37,
INS_PLP: 38,
INS_ROL: 39,
INS_ROR: 40,
INS_RTI: 41,
INS_RTS: 42,
INS_SBC: 43,
INS_SEC: 44,
INS_SED: 45,
INS_SEI: 46,
INS_STA: 47,
INS_STX: 48,
INS_STY: 49,
INS_TAX: 50,
INS_TAY: 51,
INS_TSX: 52,
INS_TXA: 53,
INS_TXS: 54,
INS_TYA: 55,
INS_DUMMY: 56, // dummy instruction used for 'halting' the processor some cycles
// -------------------------------- //
// Addressing modes:
ADDR_ZP : 0,
ADDR_REL : 1,
ADDR_IMP : 2,
ADDR_ABS : 3,
ADDR_ACC : 4,
ADDR_IMM : 5,
ADDR_ZPX : 6,
ADDR_ZPY : 7,
ADDR_ABSX : 8,
ADDR_ABSY : 9,
ADDR_PREIDXIND : 10,
ADDR_POSTIDXIND: 11,
ADDR_INDABS : 12,
setOp: function(inst, op, addr, size, cycles){
this.opdata[op] =
((inst &0xFF) )|
((addr &0xFF)<< 8)|
((size &0xFF)<<16)|
((cycles&0xFF)<<24);
}
};
var swfobject=function(){var m="undefined",t="object",W="Shockwave Flash",bh="ShockwaveFlash.ShockwaveFlash",F="application/x-shockwave-flash",X="SWFObjectExprInst",Y="onreadystatechange",r=window,i=document,w=navigator,Z=false,G=[bi],x=[],H=[],B=[],D,I,O,ba,z=false,J=false,u,P,bb=true,f=function(){var a=typeof i.getElementById!=m&&typeof i.getElementsByTagName!=m&&typeof i.createElement!=m,c=w.userAgent.toLowerCase(),b=w.platform.toLowerCase(),d=b?/win/.test(b):/win/.test(c),g=b?/mac/.test(b):/mac/.test(c),j=/webkit/.test(c)?parseFloat(c.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,h=!+"\v1",o=[0,0,0],l=null;if(typeof w.plugins!=m&&typeof w.plugins[W]==t){l=w.plugins[W].description;if(l&&!(typeof w.mimeTypes!=m&&w.mimeTypes[F]&&!w.mimeTypes[F].enabledPlugin)){Z=true;h=false;l=l.replace(/^.*\s+(\S+\s+\S+$)/,"$1");o[0]=parseInt(l.replace(/^(.*)\..*$/,"$1"),10);o[1]=parseInt(l.replace(/^.*\.(.*)\s.*$/,"$1"),10);o[2]=/[a-zA-Z]/.test(l)?parseInt(l.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else if(typeof r.ActiveXObject!=m){try{var q=new ActiveXObject(bh);if(q){l=q.GetVariable("$version");if(l){h=true;l=l.split(" ")[1].split(",");o=[parseInt(l[0],10),parseInt(l[1],10),parseInt(l[2],10)]}}}catch(e){}}return{w3:a,pv:o,wk:j,ie:h,win:d,mac:g}}(),bo=function(){if(!f.w3){return}if((typeof i.readyState!=m&&i.readyState=="complete")||(typeof i.readyState==m&&(i.getElementsByTagName("body")[0]||i.body))){C()}if(!z){if(typeof i.addEventListener!=m){i.addEventListener("DOMContentLoaded",C,false)}if(f.ie&&f.win){i.attachEvent(Y,function(){if(i.readyState=="complete"){i.detachEvent(Y,arguments.callee);C()}});if(r==top){(function(){if(z){return}try{i.documentElement.doScroll("left")}catch(e){setTimeout(arguments.callee,0);return}C()})()}}if(f.wk){(function(){if(z){return}if(!/loaded|complete/.test(i.readyState)){setTimeout(arguments.callee,0);return}C()})()}bc(C)}}();function C(){if(z){return}try{var a=i.getElementsByTagName("body")[0].appendChild(y("span"));a.parentNode.removeChild(a)}catch(e){return}z=true;var c=G.length;for(var b=0;b<c;b++){G[b]()}}function bd(a){if(z){a()}else{G[G.length]=a}}function bc(a){if(typeof r.addEventListener!=m){r.addEventListener("load",a,false)}else if(typeof i.addEventListener!=m){i.addEventListener("load",a,false)}else if(typeof r.attachEvent!=m){bj(r,"onload",a)}else if(typeof r.onload=="function"){var c=r.onload;r.onload=function(){c();a()}}else{r.onload=a}}function bi(){if(Z){bk()}else{Q()}}function bk(){var c=i.getElementsByTagName("body")[0];var b=y(t);b.setAttribute("type",F);var d=c.appendChild(b);if(d){var g=0;(function(){if(typeof d.GetVariable!=m){var a=d.GetVariable("$version");if(a){a=a.split(" ")[1].split(",");f.pv=[parseInt(a[0],10),parseInt(a[1],10),parseInt(a[2],10)]}}else if(g<10){g++;setTimeout(arguments.callee,10);return}c.removeChild(b);d=null;Q()})()}else{Q()}}function Q(){var a=x.length;if(a>0){for(var c=0;c<a;c++){var b=x[c].id;var d=x[c].callbackFn;var g={success:false,id:b};if(f.pv[0]>0){var j=s(b);if(j){if(K(x[c].swfVersion)&&!(f.wk&&f.wk<312)){A(b,true);if(d){g.success=true;g.ref=R(b);d(g)}}else if(x[c].expressInstall&&S()){var h={};h.data=x[c].expressInstall;h.width=j.getAttribute("width")||"0";h.height=j.getAttribute("height")||"0";if(j.getAttribute("class")){h.styleclass=j.getAttribute("class")}if(j.getAttribute("align")){h.align=j.getAttribute("align")}var o={};var l=j.getElementsByTagName("param");var q=l.length;for(var p=0;p<q;p++){if(l[p].getAttribute("name").toLowerCase()!="movie"){o[l[p].getAttribute("name")]=l[p].getAttribute("value")}}T(h,o,b,d)}else{bl(j);if(d){d(g)}}}}else{A(b,true);if(d){var v=R(b);if(v&&typeof v.SetVariable!=m){g.success=true;g.ref=v}d(g)}}}}}function R(a){var c=null;var b=s(a);if(b&&b.nodeName=="OBJECT"){if(typeof b.SetVariable!=m){c=b}else{var d=b.getElementsByTagName(t)[0];if(d){c=d}}}return c}function S(){return!J&&K("6.0.65")&&(f.win||f.mac)&&!(f.wk&&f.wk<312)}function T(a,c,b,d){J=true;O=d||null;ba={success:false,id:b};var g=s(b);if(g){if(g.nodeName=="OBJECT"){D=U(g);I=null}else{D=g;I=b}a.id=X;if(typeof a.width==m||(!/%$/.test(a.width)&&parseInt(a.width,10)<310)){a.width="310"}if(typeof a.height==m||(!/%$/.test(a.height)&&parseInt(a.height,10)<137)){a.height="137"}i.title=i.title.slice(0,47)+" - Flash Player Installation";var j=f.ie&&f.win?"ActiveX":"PlugIn",h="MMredirectURL="+r.location.toString().replace(/&/g,"%26")+"&MMplayerType="+j+"&MMdoctitle="+i.title;if(typeof c.flashvars!=m){c.flashvars+="&"+h}else{c.flashvars=h}if(f.ie&&f.win&&g.readyState!=4){var o=y("div");b+="SWFObjectNew";o.setAttribute("id",b);g.parentNode.insertBefore(o,g);g.style.display="none";(function(){if(g.readyState==4){g.parentNode.removeChild(g)}else{setTimeout(arguments.callee,10)}})()}V(a,c,b)}}function bl(a){if(f.ie&&f.win&&a.readyState!=4){var c=y("div");a.parentNode.insertBefore(c,a);c.parentNode.replaceChild(U(a),c);a.style.display="none";(function(){if(a.readyState==4){a.parentNode.removeChild(a)}else{setTimeout(arguments.callee,10)}})()}else{a.parentNode.replaceChild(U(a),a)}}function U(a){var c=y("div");if(f.win&&f.ie){c.innerHTML=a.innerHTML}else{var b=a.getElementsByTagName(t)[0];if(b){var d=b.childNodes;if(d){var g=d.length;for(var j=0;j<g;j++){if(!(d[j].nodeType==1&&d[j].nodeName=="PARAM")&&!(d[j].nodeType==8)){c.appendChild(d[j].cloneNode(true))}}}}}return c}function V(a,c,b){var d,g=s(b);if(f.wk&&f.wk<312){return d}if(g){if(typeof a.id==m){a.id=b}if(f.ie&&f.win){var j="";for(var h in a){if(a[h]!=Object.prototype[h]){if(h.toLowerCase()=="data"){c.movie=a[h]}else if(h.toLowerCase()=="styleclass"){j+=' class="'+a[h]+'"'}else if(h.toLowerCase()!="classid"){j+=' '+h+'="'+a[h]+'"'}}}var o="";for(var l in c){if(c[l]!=Object.prototype[l]){o+='<param name="'+l+'" value="'+c[l]+'" />'}}g.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+j+'>'+o+'</object>';H[H.length]=a.id;d=s(a.id)}else{var q=y(t);q.setAttribute("type",F);for(var p in a){if(a[p]!=Object.prototype[p]){if(p.toLowerCase()=="styleclass"){q.setAttribute("class",a[p])}else if(p.toLowerCase()!="classid"){q.setAttribute(p,a[p])}}}for(var n in c){if(c[n]!=Object.prototype[n]&&n.toLowerCase()!="movie"){bm(q,n,c[n])}}g.parentNode.replaceChild(q,g);d=q}}return d}function bm(a,c,b){var d=y("param");d.setAttribute("name",c);d.setAttribute("value",b);a.appendChild(d)}function be(a){var c=s(a);if(c&&c.nodeName=="OBJECT"){if(f.ie&&f.win){c.style.display="none";(function(){if(c.readyState==4){bn(a)}else{setTimeout(arguments.callee,10)}})()}else{c.parentNode.removeChild(c)}}}function bn(a){var c=s(a);if(c){for(var b in c){if(typeof c[b]=="function"){c[b]=null}}c.parentNode.removeChild(c)}}function s(a){var c=null;try{c=i.getElementById(a)}catch(e){}return c}function y(a){return i.createElement(a)}function bj(a,c,b){a.attachEvent(c,b);B[B.length]=[a,c,b]}function K(a){var c=f.pv,b=a.split(".");b[0]=parseInt(b[0],10);b[1]=parseInt(b[1],10)||0;b[2]=parseInt(b[2],10)||0;return(c[0]>b[0]||(c[0]==b[0]&&c[1]>b[1])||(c[0]==b[0]&&c[1]==b[1]&&c[2]>=b[2]))?true:false}function bf(a,c,b,d){if(f.ie&&f.mac){return}var g=i.getElementsByTagName("head")[0];if(!g){return}var j=(b&&typeof b=="string")?b:"screen";if(d){u=null;P=null}if(!u||P!=j){var h=y("style");h.setAttribute("type","text/css");h.setAttribute("media",j);u=g.appendChild(h);if(f.ie&&f.win&&typeof i.styleSheets!=m&&i.styleSheets.length>0){u=i.styleSheets[i.styleSheets.length-1]}P=j}if(f.ie&&f.win){if(u&&typeof u.addRule==t){u.addRule(a,c)}}else{if(u&&typeof i.createTextNode!=m){u.appendChild(i.createTextNode(a+" {"+c+"}"))}}}function A(a,c){if(!bb){return}var b=c?"visible":"hidden";if(z&&s(a)){s(a).style.visibility=b}else{bf("#"+a,"visibility:"+b)}}function bg(a){var c=/[\\\"<>\.;]/;var b=c.exec(a)!=null;return b&&typeof encodeURIComponent!=m?encodeURIComponent(a):a}var bp=function(){if(f.ie&&f.win){window.attachEvent("onunload",function(){var a=B.length;for(var c=0;c<a;c++){B[c][0].detachEvent(B[c][1],B[c][2])}var b=H.length;for(var d=0;d<b;d++){be(H[d])}for(var g in f){f[g]=null}f=null;for(var j in swfobject){swfobject[j]=null}swfobject=null})}}();return{registerObject:function(a,c,b,d){if(f.w3&&a&&c){var g={};g.id=a;g.swfVersion=c;g.expressInstall=b;g.callbackFn=d;x[x.length]=g;A(a,false)}else if(d){d({success:false,id:a})}},getObjectById:function(a){if(f.w3){return R(a)}},embedSWF:function(j,h,o,l,q,p,v,L,M,E){var N={success:false,id:h};if(f.w3&&!(f.wk&&f.wk<312)&&j&&h&&o&&l&&q){A(h,false);bd(function(){o+="";l+="";var a={};if(M&&typeof M===t){for(var c in M){a[c]=M[c]}}a.data=j;a.width=o;a.height=l;var b={};if(L&&typeof L===t){for(var d in L){b[d]=L[d]}}if(v&&typeof v===t){for(var k in v){if(typeof b.flashvars!=m){b.flashvars+="&"+k+"="+v[k]}else{b.flashvars=k+"="+v[k]}}}if(K(q)){var g=V(a,b,h);if(a.id==h){A(h,true)}N.success=true;N.ref=g}else if(p&&S()){a.data=p;T(a,b,h,E);return}else{A(h,true)}if(E){E(N)}})}else if(E){E(N)}},switchOffAutoHideShow:function(){bb=false},ua:f,getFlashPlayerVersion:function(){return{major:f.pv[0],minor:f.pv[1],release:f.pv[2]}},hasFlashPlayerVersion:K,createSWF:function(a,c,b){if(f.w3){return V(a,c,b)}else{return undefined}},showExpressInstall:function(a,c,b,d){if(f.w3&&S()){T(a,c,b,d)}},removeSWF:function(a){if(f.w3){be(a)}},createCSS:function(a,c,b,d){if(f.w3){bf(a,c,b,d)}},addDomLoadEvent:bd,addLoadEvent:bc,getQueryParamValue:function(a){var c=i.location.search||i.location.hash;if(c){if(/\?/.test(c)){c=c.split("?")[1]}if(a==null){return bg(c)}var b=c.split("&");for(var d=0;d<b.length;d++){if(b[d].substring(0,b[d].indexOf("="))==a){return bg(b[d].substring((b[d].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(J){var a=s(X);if(a&&D){a.parentNode.replaceChild(D,a);if(I){A(I,true);if(f.ie&&f.win){D.style.display="block"}}if(O){O(ba)}}J=false}}}}();function DynamicAudio(a){if(this instanceof arguments.callee){if(typeof this.init=="function"){this.init.apply(this,(a&&a.callee)?a:arguments)}}else{return new arguments.callee(arguments)}}DynamicAudio.nextId=1;DynamicAudio.prototype={nextId:null,swf:'dynamicaudio.swf',audioElement:null,flashWrapper:null,flashElement:null,init:function(c){var b=this;b.id=DynamicAudio.nextId++;if(c&&typeof c['swf']!='undefined'){b.swf=c['swf']}if(typeof Audio!='undefined'){b.audioElement=new Audio();if(b.audioElement.mozSetup){b.audioElement.mozSetup(2,44100,1);return}}b.audioElement=null;b.flashWrapper=document.createElement('div');b.flashWrapper.id='dynamicaudio-flashwrapper-'+b.id;var d=b.flashWrapper.style;d['position']='fixed';d['width']=d['height']='8px';d['bottom']=d['left']='0px';d['overflow']='hidden';b.flashElement=document.createElement('div');b.flashElement.id='dynamicaudio-flashelement-'+b.id;b.flashWrapper.appendChild(b.flashElement);document.body.appendChild(b.flashWrapper);swfobject.embedSWF(b.swf,b.flashElement.id,"8","8","9.0.0",null,null,{'allowScriptAccess':'always'},null,function(a){b.flashElement=a.ref})},write:function(a){if(this.audioElement!=null){this.audioElement.mozWriteAudio(a.length,a)}else if(this.flashElement!=null){var c=new Array(a.length);for(var b=a.length-1;b!=0;b--){c[b]=Math.floor(a[b]*32768)}this.flashElement.write(c.join(' '))}},writeInt:function(a){if(this.audioElement!=null){var c=new Array(a.length);for(var b=a.length-1;b!=0;b--){c[b]=Math.floor(a[b]/32768)}this.audioElement.mozWriteAudio(c.length,c)}else if(this.flashElement!=null){this.flashElement.write(a.join(' '))}}};
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>JSNES for Google Glass: A JavaScript NES emulator running on Google Glass via Wearscript</title>
</head>
<body bgcolor="#000000">
<div style="background-color:black;height:380px;width:640px;">
<div align="center" id="emulator"></div>
</div>
<script src="jquery-1.4.2.min.js" type="text/javascript" charset="utf-8"></script>
<script src="dynamicaudio-min.js" type="text/javascript" charset="utf-8"></script>
<script src="nes.js" type="text/javascript" charset="utf-8"></script>
<script src="utils.js" type="text/javascript" charset="utf-8"></script>
<script src="cpu.js" type="text/javascript" charset="utf-8"></script>
<script src="keyboard.js" type="text/javascript" charset="utf-8"></script>
<script src="mappers.js" type="text/javascript" charset="utf-8"></script>
<script src="papu.js" type="text/javascript" charset="utf-8"></script>
<script src="ppu.js" type="text/javascript" charset="utf-8"></script>
<script src="rom.js" type="text/javascript" charset="utf-8"></script>
<script src="ui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var nes;
$(function() {
nes = new JSNES({
'ui': $('#emulator').JSNESUI({
"Homebrew": [
['Super Mario Bros', 'smb.nes'],
],
})
});
});
</script>
</body>
</html>
/*!
* jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Sat Feb 13 22:33:48 2010 -0500
*/
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
/*
JSNES, based on Jamie Sanders' vNES
Copyright (C) 2010 Ben Firshman
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Keyboard events are bound in the UI
JSNES.Keyboard = function() {
var i;
this.keys = {
KEY_A: 0,
KEY_B: 1,
KEY_SELECT: 2,
KEY_START: 3,
KEY_UP: 4,
KEY_DOWN: 5,
KEY_LEFT: 6,
KEY_RIGHT: 7
};
this.state1 = new Array(8);
for (i = 0; i < this.state1.length; i++) {
this.state1[i] = 0x40;
}
this.state2 = new Array(8);
for (i = 0; i < this.state2.length; i++) {
this.state2[i] = 0x40;
}
};
JSNES.Keyboard.prototype = {
setKey: function(key, value) {
console.log(key);
console.log(value);
switch (key) {
case 88: this.state1[this.keys.KEY_A] = value; break; // X
case 89: this.state1[this.keys.KEY_B] = value; break; // Y (Central European keyboard)
case 90: this.state1[this.keys.KEY_B] = value; break; // Z
case 38: this.state1[this.keys.KEY_A] = value; break; // MM Up
case 17: this.state1[this.keys.KEY_SELECT] = value; break; // Right Ctrl
case 13: this.state1[this.keys.KEY_START] = value; break; // Enter
case 38: this.state1[this.keys.KEY_UP] = value; break; // Up
case 40: this.state1[this.keys.KEY_DOWN] = value; break; // Down
case 188: this.state1[this.keys.KEY_LEFT] = value; break; // Left
case 190: this.state1[this.keys.KEY_RIGHT] = value; break; // Right
case 39: this.state1[this.keys.KEY_RIGHT] = value; break; // MM Right
case 103: this.state2[this.keys.KEY_A] = value; break; // Num-7
case 105: this.state2[this.keys.KEY_B] = value; break; // Num-9
case 99: this.state2[this.keys.KEY_SELECT] = value; break; // Num-3
case 97: this.state2[this.keys.KEY_START] = value; break; // Num-1
case 104: this.state2[this.keys.KEY_UP] = value; break; // Num-8
case 98: this.state2[this.keys.KEY_DOWN] = value; break; // Num-2
case 100: this.state2[this.keys.KEY_LEFT] = value; break; // Num-4
case 102: this.state2[this.keys.KEY_RIGHT] = value; break; // Num-6
default: return true;
}
return false; // preventDefault
},
keyDown: function(evt) {
if (!this.setKey(evt.keyCode, 0x41) && evt.preventDefault) {
evt.preventDefault();
}
},
keyUp: function(evt) {
if (!this.setKey(evt.keyCode, 0x40) && evt.preventDefault) {
evt.preventDefault();
}
},
keyPress: function(evt) {
evt.preventDefault();
}
};
/*
JSNES, based on Jamie Sanders' vNES
Copyright (C) 2010 Ben Firshman
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
JSNES.Mappers = {};
JSNES.Mappers[0] = function(nes) {
this.nes = nes;
};
JSNES.Mappers[0].prototype = {
reset: function() {
this.joy1StrobeState = 0;
this.joy2StrobeState = 0;
this.joypadLastWrite = 0;
this.mousePressed = false;
this.mouseX = null;
this.mouseY = null;
},
write: function(address, value) {
if (address < 0x2000) {
// Mirroring of RAM:
this.nes.cpu.mem[address & 0x7FF] = value;
}
else if (address > 0x4017) {
this.nes.cpu.mem[address] = value;
if (address >= 0x6000 && address < 0x8000) {
// Write to SaveRAM. Store in file:
// TODO: not yet
//if(this.nes.rom!=null)
// this.nes.rom.writeBatteryRam(address,value);
}
}
else if (address > 0x2007 && address < 0x4000) {
this.regWrite(0x2000 + (address & 0x7), value);
}
else {
this.regWrite(address, value);
}
},
writelow: function(address, value) {
if (address < 0x2000) {
// Mirroring of RAM:
this.nes.cpu.mem[address & 0x7FF] = value;
}
else if (address > 0x4017) {
this.nes.cpu.mem[address] = value;
}
else if (address > 0x2007 && address < 0x4000) {
this.regWrite(0x2000 + (address & 0x7), value);
}
else {
this.regWrite(address, value);
}
},
load: function(address) {
// Wrap around:
address &= 0xFFFF;
// Check address range:
if (address > 0x4017) {
// ROM:
return this.nes.cpu.mem[address];
}
else if (address >= 0x2000) {
// I/O Ports.
return this.regLoad(address);
}
else {
// RAM (mirrored)
return this.nes.cpu.mem[address & 0x7FF];
}
},
regLoad: function(address) {
switch (address >> 12) { // use fourth nibble (0xF000)
case 0:
break;
case 1:
break;
case 2:
// Fall through to case 3
case 3:
// PPU Registers
switch (address & 0x7) {
case 0x0:
// 0x2000:
// PPU Control Register 1.
// (the value is stored both
// in main memory and in the
// PPU as flags):
// (not in the real NES)
return this.nes.cpu.mem[0x2000];
case 0x1:
// 0x2001:
// PPU Control Register 2.
// (the value is stored both
// in main memory and in the
// PPU as flags):
// (not in the real NES)
return this.nes.cpu.mem[0x2001];
case 0x2:
// 0x2002:
// PPU Status Register.
// The value is stored in
// main memory in addition
// to as flags in the PPU.
// (not in the real NES)
return this.nes.ppu.readStatusRegister();
case 0x3:
return 0;
case 0x4:
// 0x2004:
// Sprite Memory read.
return this.nes.ppu.sramLoad();
case 0x5:
return 0;
case 0x6:
return 0;
case 0x7:
// 0x2007:
// VRAM read:
return this.nes.ppu.vramLoad();
}
break;
case 4:
// Sound+Joypad registers
switch (address - 0x4015) {
case 0:
// 0x4015:
// Sound channel enable, DMC Status
return this.nes.papu.readReg(address);
case 1:
// 0x4016:
// Joystick 1 + Strobe
return this.joy1Read();
case 2:
// 0x4017:
// Joystick 2 + Strobe
if (this.mousePressed) {
// Check for white pixel nearby:
var sx = Math.max(0, this.mouseX - 4);
var ex = Math.min(256, this.mouseX + 4);
var sy = Math.max(0, this.mouseY - 4);
var ey = Math.min(240, this.mouseY + 4);
var w = 0;
for (var y=sy; y<ey; y++) {
for (var x=sx; x<ex; x++) {
if (this.nes.ppu.buffer[(y<<8)+x] == 0xFFFFFF) {
w |= 0x1<<3;
console.debug("Clicked on white!");
break;
}
}
}
w |= (this.mousePressed?(0x1<<4):0);
return (this.joy2Read()|w) & 0xFFFF;
}
else {
return this.joy2Read();
}
}
break;
}
return 0;
},
regWrite: function(address, value) {
switch (address) {
case 0x2000:
// PPU Control register 1
this.nes.cpu.mem[address] = value;
this.nes.ppu.updateControlReg1(value);
break;
case 0x2001:
// PPU Control register 2
this.nes.cpu.mem[address] = value;
this.nes.ppu.updateControlReg2(value);
break;
case 0x2003:
// Set Sprite RAM address:
this.nes.ppu.writeSRAMAddress(value);
break;
case 0x2004:
// Write to Sprite RAM:
this.nes.ppu.sramWrite(value);
break;
case 0x2005:
// Screen Scroll offsets:
this.nes.ppu.scrollWrite(value);
break;
case 0x2006:
// Set VRAM address:
this.nes.ppu.writeVRAMAddress(value);
break;
case 0x2007:
// Write to VRAM:
this.nes.ppu.vramWrite(value);
break;
case 0x4014:
// Sprite Memory DMA Access
this.nes.ppu.sramDMA(value);
break;
case 0x4015:
// Sound Channel Switch, DMC Status
this.nes.papu.writeReg(address, value);
break;
case 0x4016:
// Joystick 1 + Strobe
if ((value&1) === 0 && (this.joypadLastWrite&1) === 1) {
this.joy1StrobeState = 0;
this.joy2StrobeState = 0;
}
this.joypadLastWrite = value;
break;
case 0x4017:
// Sound channel frame sequencer:
this.nes.papu.writeReg(address, value);
break;
default:
// Sound registers
////System.out.println("write to sound reg");
if (address >= 0x4000 && address <= 0x4017) {
this.nes.papu.writeReg(address,value);
}
}
},
joy1Read: function() {
var ret;
switch (this.joy1StrobeState) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
ret = this.nes.keyboard.state1[this.joy1StrobeState];
break;
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
ret = 0;
break;
case 19:
ret = 1;
break;
default:
ret = 0;
}
this.joy1StrobeState++;
if (this.joy1StrobeState == 24) {
this.joy1StrobeState = 0;
}
return ret;
},
joy2Read: function() {
var ret;
switch (this.joy2StrobeState) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
ret = this.nes.keyboard.state2[this.joy2StrobeState];
break;
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
ret = 0;
break;
case 19:
ret = 1;
break;
default:
ret = 0;
}
this.joy2StrobeState++;
if (this.joy2StrobeState == 24) {
this.joy2StrobeState = 0;
}
return ret;
},
loadROM: function() {
if (!this.nes.rom.valid || this.nes.rom.romCount < 1) {
alert("NoMapper: Invalid ROM! Unable to load.");
return;
}
// Load ROM into memory:
this.loadPRGROM();
// Load CHR-ROM:
this.loadCHRROM();
// Load Battery RAM (if present):
this.loadBatteryRam();
// Reset IRQ:
//nes.getCpu().doResetInterrupt();
this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);
},
loadPRGROM: function() {
if (this.nes.rom.romCount > 1) {
// Load the two first banks into memory.
this.loadRomBank(0, 0x8000);
this.loadRomBank(1, 0xC000);
}
else {
// Load the one bank into both memory locations:
this.loadRomBank(0, 0x8000);
this.loadRomBank(0, 0xC000);
}
},
loadCHRROM: function() {
////System.out.println("Loading CHR ROM..");
if (this.nes.rom.vromCount > 0) {
if (this.nes.rom.vromCount == 1) {
this.loadVromBank(0,0x0000);
this.loadVromBank(0,0x1000);
}
else {
this.loadVromBank(0,0x0000);
this.loadVromBank(1,0x1000);
}
}
else {
//System.out.println("There aren't any CHR-ROM banks..");
}
},
loadBatteryRam: function() {
if (this.nes.rom.batteryRam) {
var ram = this.nes.rom.batteryRam;
if (ram !== null && ram.length == 0x2000) {
// Load Battery RAM into memory:
JSNES.Utils.copyArrayElements(ram, 0, this.nes.cpu.mem, 0x6000, 0x2000);
}
}
},
loadRomBank: function(bank, address) {
// Loads a ROM bank into the specified address.
bank %= this.nes.rom.romCount;
//var data = this.nes.rom.rom[bank];
//cpuMem.write(address,data,data.length);
JSNES.Utils.copyArrayElements(this.nes.rom.rom[bank], 0, this.nes.cpu.mem, address, 16384);
},
loadVromBank: function(bank, address) {
if (this.nes.rom.vromCount === 0) {
return;
}
this.nes.ppu.triggerRendering();
JSNES.Utils.copyArrayElements(this.nes.rom.vrom[bank % this.nes.rom.vromCount],
0, this.nes.ppu.vramMem, address, 4096);
var vromTile = this.nes.rom.vromTile[bank % this.nes.rom.vromCount];
JSNES.Utils.copyArrayElements(vromTile, 0, this.nes.ppu.ptTile,address >> 4, 256);
},
load32kRomBank: function(bank, address) {
this.loadRomBank((bank*2) % this.nes.rom.romCount, address);
this.loadRomBank((bank*2+1) % this.nes.rom.romCount, address+16384);
},
load8kVromBank: function(bank4kStart, address) {
if (this.nes.rom.vromCount === 0) {
return;
}
this.nes.ppu.triggerRendering();
this.loadVromBank((bank4kStart) % this.nes.rom.vromCount, address);
this.loadVromBank((bank4kStart + 1) % this.nes.rom.vromCount,
address + 4096);
},
load1kVromBank: function(bank1k, address) {
if (this.nes.rom.vromCount === 0) {
return;
}
this.nes.ppu.triggerRendering();
var bank4k = Math.floor(bank1k / 4) % this.nes.rom.vromCount;
var bankoffset = (bank1k % 4) * 1024;
JSNES.Utils.copyArrayElements(this.nes.rom.vrom[bank4k], 0,
this.nes.ppu.vramMem, bankoffset, 1024);
// Update tiles:
var vromTile = this.nes.rom.vromTile[bank4k];
var baseIndex = address >> 4;
for (var i = 0; i < 64; i++) {
this.nes.ppu.ptTile[baseIndex+i] = vromTile[((bank1k%4) << 6) + i];
}
},
load2kVromBank: function(bank2k, address) {
if (this.nes.rom.vromCount === 0) {
return;
}
this.nes.ppu.triggerRendering();
var bank4k = Math.floor(bank2k / 2) % this.nes.rom.vromCount;
var bankoffset = (bank2k % 2) * 2048;
JSNES.Utils.copyArrayElements(this.nes.rom.vrom[bank4k], bankoffset,
this.nes.ppu.vramMem, address, 2048);
// Update tiles:
var vromTile = this.nes.rom.vromTile[bank4k];
var baseIndex = address >> 4;
for (var i = 0; i < 128; i++) {
this.nes.ppu.ptTile[baseIndex+i] = vromTile[((bank2k%2) << 7) + i];
}
},
load8kRomBank: function(bank8k, address) {
var bank16k = Math.floor(bank8k / 2) % this.nes.rom.romCount;
var offset = (bank8k % 2) * 8192;
//this.nes.cpu.mem.write(address,this.nes.rom.rom[bank16k],offset,8192);
JSNES.Utils.copyArrayElements(this.nes.rom.rom[bank16k], offset,
this.nes.cpu.mem, address, 8192);
},
clockIrqCounter: function() {
// Does nothing. This is used by the MMC3 mapper.
},
latchAccess: function(address) {
// Does nothing. This is used by MMC2.
},
toJSON: function() {
return {
'joy1StrobeState': this.joy1StrobeState,
'joy2StrobeState': this.joy2StrobeState,
'joypadLastWrite': this.joypadLastWrite
};
},
fromJSON: function(s) {
this.joy1StrobeState = s.joy1StrobeState;
this.joy2StrobeState = s.joy2StrobeState;
this.joypadLastWrite = s.joypadLastWrite;
}
};
JSNES.Mappers[1] = function(nes) {
this.nes = nes;
};
JSNES.Mappers[1].prototype = new JSNES.Mappers[0]();
JSNES.Mappers[1].prototype.reset = function() {
JSNES.Mappers[0].prototype.reset.apply(this);
// 5-bit buffer:
this.regBuffer = 0;
this.regBufferCounter = 0;
// Register 0:
this.mirroring = 0;
this.oneScreenMirroring = 0;
this.prgSwitchingArea = 1;
this.prgSwitchingSize = 1;
this.vromSwitchingSize = 0;
// Register 1:
this.romSelectionReg0 = 0;
// Register 2:
this.romSelectionReg1 = 0;
// Register 3:
this.romBankSelect = 0;
};
JSNES.Mappers[1].prototype.write = function(address, value) {
// Writes to addresses other than MMC registers are handled by NoMapper.
if (address < 0x8000) {
JSNES.Mappers[0].prototype.write.apply(this, arguments);
return;
}
// See what should be done with the written value:
if ((value & 128) !== 0) {
// Reset buffering:
this.regBufferCounter = 0;
this.regBuffer = 0;
// Reset register:
if (this.getRegNumber(address) === 0) {
this.prgSwitchingArea = 1;
this.prgSwitchingSize = 1;
}
}
else {
// Continue buffering:
//regBuffer = (regBuffer & (0xFF-(1<<regBufferCounter))) | ((value & (1<<regBufferCounter))<<regBufferCounter);
this.regBuffer = (this.regBuffer & (0xFF - (1 << this.regBufferCounter))) | ((value & 1) << this.regBufferCounter);
this.regBufferCounter++;
if (this.regBufferCounter == 5) {
// Use the buffered value:
this.setReg(this.getRegNumber(address), this.regBuffer);
// Reset buffer:
this.regBuffer = 0;
this.regBufferCounter = 0;
}
}
};
JSNES.Mappers[1].prototype.setReg = function(reg, value) {
var tmp;
switch (reg) {
case 0:
// Mirroring:
tmp = value & 3;
if (tmp !== this.mirroring) {
// Set mirroring:
this.mirroring = tmp;
if ((this.mirroring & 2) === 0) {
// SingleScreen mirroring overrides the other setting:
this.nes.ppu.setMirroring(
this.nes.rom.SINGLESCREEN_MIRRORING);
}
// Not overridden by SingleScreen mirroring.
else if ((this.mirroring & 1) !== 0) {
this.nes.ppu.setMirroring(
this.nes.rom.HORIZONTAL_MIRRORING
);
}
else {
this.nes.ppu.setMirroring(this.nes.rom.VERTICAL_MIRRORING);
}
}
// PRG Switching Area;
this.prgSwitchingArea = (value >> 2) & 1;
// PRG Switching Size:
this.prgSwitchingSize = (value >> 3) & 1;
// VROM Switching Size:
this.vromSwitchingSize = (value >> 4) & 1;
break;
case 1:
// ROM selection:
this.romSelectionReg0 = (value >> 4) & 1;
// Check whether the cart has VROM:
if (this.nes.rom.vromCount > 0) {
// Select VROM bank at 0x0000:
if (this.vromSwitchingSize === 0) {
// Swap 8kB VROM:
if (this.romSelectionReg0 === 0) {
this.load8kVromBank((value & 0xF), 0x0000);
}
else {
this.load8kVromBank(
Math.floor(this.nes.rom.vromCount / 2) +
(value & 0xF),
0x0000
);
}
}
else {
// Swap 4kB VROM:
if (this.romSelectionReg0 === 0) {
this.loadVromBank((value & 0xF), 0x0000);
}
else {
this.loadVromBank(
Math.floor(this.nes.rom.vromCount / 2) +
(value & 0xF),
0x0000
);
}
}
}
break;
case 2:
// ROM selection:
this.romSelectionReg1 = (value >> 4) & 1;
// Check whether the cart has VROM:
if (this.nes.rom.vromCount > 0) {
// Select VROM bank at 0x1000:
if (this.vromSwitchingSize === 1) {
// Swap 4kB of VROM:
if (this.romSelectionReg1 === 0) {
this.loadVromBank((value & 0xF), 0x1000);
}
else {
this.loadVromBank(
Math.floor(this.nes.rom.vromCount / 2) +
(value & 0xF),
0x1000
);
}
}
}
break;
default:
// Select ROM bank:
// -------------------------
tmp = value & 0xF;
var bank;
var baseBank = 0;
if (this.nes.rom.romCount >= 32) {
// 1024 kB cart
if (this.vromSwitchingSize === 0) {
if (this.romSelectionReg0 === 1) {
baseBank = 16;
}
}
else {
baseBank = (this.romSelectionReg0
| (this.romSelectionReg1 << 1)) << 3;
}
}
else if (this.nes.rom.romCount >= 16) {
// 512 kB cart
if (this.romSelectionReg0 === 1) {
baseBank = 8;
}
}
if (this.prgSwitchingSize === 0) {
// 32kB
bank = baseBank + (value & 0xF);
this.load32kRomBank(bank, 0x8000);
}
else {
// 16kB
bank = baseBank * 2 + (value & 0xF);
if (this.prgSwitchingArea === 0) {
this.loadRomBank(bank, 0xC000);
}
else {
this.loadRomBank(bank, 0x8000);
}
}
}
};
// Returns the register number from the address written to:
JSNES.Mappers[1].prototype.getRegNumber = function(address) {
if (address >= 0x8000 && address <= 0x9FFF) {
return 0;
}
else if (address >= 0xA000 && address <= 0xBFFF) {
return 1;
}
else if (address >= 0xC000 && address <= 0xDFFF) {
return 2;
}
else {
return 3;
}
};
JSNES.Mappers[1].prototype.loadROM = function(rom) {
if (!this.nes.rom.valid) {
alert("MMC1: Invalid ROM! Unable to load.");
return;
}
// Load PRG-ROM:
this.loadRomBank(0, 0x8000); // First ROM bank..
this.loadRomBank(this.nes.rom.romCount - 1, 0xC000); // ..and last ROM bank.
// Load CHR-ROM:
this.loadCHRROM();
// Load Battery RAM (if present):
this.loadBatteryRam();
// Do Reset-Interrupt:
this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);
};
JSNES.Mappers[1].prototype.switchLowHighPrgRom = function(oldSetting) {
// not yet.
};
JSNES.Mappers[1].prototype.switch16to32 = function() {
// not yet.
};
JSNES.Mappers[1].prototype.switch32to16 = function() {
// not yet.
};
JSNES.Mappers[1].prototype.toJSON = function() {
var s = JSNES.Mappers[0].prototype.toJSON.apply(this);
s.mirroring = this.mirroring;
s.oneScreenMirroring = this.oneScreenMirroring;
s.prgSwitchingArea = this.prgSwitchingArea;
s.prgSwitchingSize = this.prgSwitchingSize;
s.vromSwitchingSize = this.vromSwitchingSize;
s.romSelectionReg0 = this.romSelectionReg0;
s.romSelectionReg1 = this.romSelectionReg1;
s.romBankSelect = this.romBankSelect;
s.regBuffer = this.regBuffer;
s.regBufferCounter = this.regBufferCounter;
return s;
};
JSNES.Mappers[1].prototype.fromJSON = function(s) {
JSNES.Mappers[0].prototype.fromJSON.apply(this, s);
this.mirroring = s.mirroring;
this.oneScreenMirroring = s.oneScreenMirroring;
this.prgSwitchingArea = s.prgSwitchingArea;
this.prgSwitchingSize = s.prgSwitchingSize;
this.vromSwitchingSize = s.vromSwitchingSize;
this.romSelectionReg0 = s.romSelectionReg0;
this.romSelectionReg1 = s.romSelectionReg1;
this.romBankSelect = s.romBankSelect;
this.regBuffer = s.regBuffer;
this.regBufferCounter = s.regBufferCounter;
};
JSNES.Mappers[2] = function(nes) {
this.nes = nes;
};
JSNES.Mappers[2].prototype = new JSNES.Mappers[0]();
JSNES.Mappers[2].prototype.write = function(address, value) {
// Writes to addresses other than MMC registers are handled by NoMapper.
if (address < 0x8000) {
JSNES.Mappers[0].prototype.write.apply(this, arguments);
return;
}
else {
// This is a ROM bank select command.
// Swap in the given ROM bank at 0x8000:
this.loadRomBank(value, 0x8000);
}
};
JSNES.Mappers[2].prototype.loadROM = function(rom) {
if (!this.nes.rom.valid) {
alert("UNROM: Invalid ROM! Unable to load.");
return;
}
// Load PRG-ROM:
this.loadRomBank(0, 0x8000);
this.loadRomBank(this.nes.rom.romCount - 1, 0xC000);
// Load CHR-ROM:
this.loadCHRROM();
// Do Reset-Interrupt:
this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);
};
JSNES.Mappers[4] = function(nes) {
this.nes = nes;
this.CMD_SEL_2_1K_VROM_0000 = 0;
this.CMD_SEL_2_1K_VROM_0800 = 1;
this.CMD_SEL_1K_VROM_1000 = 2;
this.CMD_SEL_1K_VROM_1400 = 3;
this.CMD_SEL_1K_VROM_1800 = 4;
this.CMD_SEL_1K_VROM_1C00 = 5;
this.CMD_SEL_ROM_PAGE1 = 6;
this.CMD_SEL_ROM_PAGE2 = 7;
this.command = null;
this.prgAddressSelect = null;
this.chrAddressSelect = null;
this.pageNumber = null;
this.irqCounter = null;
this.irqLatchValue = null;
this.irqEnable = null;
this.prgAddressChanged = false;
};
JSNES.Mappers[4].prototype = new JSNES.Mappers[0]();
JSNES.Mappers[4].prototype.write = function(address, value) {
// Writes to addresses other than MMC registers are handled by NoMapper.
if (address < 0x8000) {
JSNES.Mappers[0].prototype.write.apply(this, arguments);
return;
}
switch (address) {
case 0x8000:
// Command/Address Select register
this.command = value & 7;
var tmp = (value >> 6) & 1;
if (tmp != this.prgAddressSelect) {
this.prgAddressChanged = true;
}
this.prgAddressSelect = tmp;
this.chrAddressSelect = (value >> 7) & 1;
break;
case 0x8001:
// Page number for command
this.executeCommand(this.command, value);
break;
case 0xA000:
// Mirroring select
if ((value & 1) !== 0) {
this.nes.ppu.setMirroring(
this.nes.rom.HORIZONTAL_MIRRORING
);
}
else {
this.nes.ppu.setMirroring(this.nes.rom.VERTICAL_MIRRORING);
}
break;
case 0xA001:
// SaveRAM Toggle
// TODO
//nes.getRom().setSaveState((value&1)!=0);
break;
case 0xC000:
// IRQ Counter register
this.irqCounter = value;
//nes.ppu.mapperIrqCounter = 0;
break;
case 0xC001:
// IRQ Latch register
this.irqLatchValue = value;
break;
case 0xE000:
// IRQ Control Reg 0 (disable)
//irqCounter = irqLatchValue;
this.irqEnable = 0;
break;
case 0xE001:
// IRQ Control Reg 1 (enable)
this.irqEnable = 1;
break;
default:
// Not a MMC3 register.
// The game has probably crashed,
// since it tries to write to ROM..
// IGNORE.
}
};
JSNES.Mappers[4].prototype.executeCommand = function(cmd, arg) {
switch (cmd) {
case this.CMD_SEL_2_1K_VROM_0000:
// Select 2 1KB VROM pages at 0x0000:
if (this.chrAddressSelect === 0) {
this.load1kVromBank(arg, 0x0000);
this.load1kVromBank(arg + 1, 0x0400);
}
else {
this.load1kVromBank(arg, 0x1000);
this.load1kVromBank(arg + 1, 0x1400);
}
break;
case this.CMD_SEL_2_1K_VROM_0800:
// Select 2 1KB VROM pages at 0x0800:
if (this.chrAddressSelect === 0) {
this.load1kVromBank(arg, 0x0800);
this.load1kVromBank(arg + 1, 0x0C00);
}
else {
this.load1kVromBank(arg, 0x1800);
this.load1kVromBank(arg + 1, 0x1C00);
}
break;
case this.CMD_SEL_1K_VROM_1000:
// Select 1K VROM Page at 0x1000:
if (this.chrAddressSelect === 0) {
this.load1kVromBank(arg, 0x1000);
}
else {
this.load1kVromBank(arg, 0x0000);
}
break;
case this.CMD_SEL_1K_VROM_1400:
// Select 1K VROM Page at 0x1400:
if (this.chrAddressSelect === 0) {
this.load1kVromBank(arg, 0x1400);
}
else {
this.load1kVromBank(arg, 0x0400);
}
break;
case this.CMD_SEL_1K_VROM_1800:
// Select 1K VROM Page at 0x1800:
if (this.chrAddressSelect === 0) {
this.load1kVromBank(arg, 0x1800);
}
else {
this.load1kVromBank(arg, 0x0800);
}
break;
case this.CMD_SEL_1K_VROM_1C00:
// Select 1K VROM Page at 0x1C00:
if (this.chrAddressSelect === 0) {
this.load1kVromBank(arg, 0x1C00);
}else {
this.load1kVromBank(arg, 0x0C00);
}
break;