tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gbemu-part2.js (464771B)


      1 // Portions copyright 2013 Google, Inc
      2 
      3 // Copyright (C) 2010 - 2012 Grant Galitz
      4 // This program is free software; you can redistribute it and/or modify
      5 // it under the terms of the GNU General Public License version 2 as
      6 // published by the Free Software Foundation.
      7 // The full license is available at http://www.gnu.org/licenses/gpl.html
      8 // This program is distributed in the hope that it will be useful, but
      9 // WITHOUT ANY WARRANTY; without even the implied warranty of
     10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     11 // See the GNU General Public License for more details.
     12 
     13 // The code has been adapted for use as a benchmark by Google.
     14 
     15 // Previous files are in gbemu-part1.js, since they need to run in sloppy mode.
     16 
     17 // Start of js/GameBoyCore.js file.
     18 
     19 "use strict";
     20 /*
     21 * JavaScript GameBoy Color Emulator
     22 * Copyright (C) 2010 - 2012 Grant Galitz
     23 *
     24 * This program is free software; you can redistribute it and/or
     25 * modify it under the terms of the GNU General Public License
     26 * version 2 as published by the Free Software Foundation.
     27 * The full license is available at http://www.gnu.org/licenses/gpl.html
     28 *
     29 * This program is distributed in the hope that it will be useful,
     30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     32 * GNU General Public License for more details.
     33 *
     34 */
     35 function GameBoyCore(canvas, ROMImage) {
     36  //Params, etc...
     37  this.canvas = canvas;            //Canvas DOM object for drawing out the graphics to.
     38  this.drawContext = null;          // LCD Context
     39  this.ROMImage = ROMImage;          //The game's ROM.
     40  //CPU Registers and Flags:
     41  this.registerA = 0x01;             //Register A (Accumulator)
     42  this.FZero = true;               //Register F  - Result was zero
     43  this.FSubtract = false;            //Register F  - Subtraction was executed
     44  this.FHalfCarry = true;            //Register F  - Half carry or half borrow
     45  this.FCarry = true;              //Register F  - Carry or borrow
     46  this.registerB = 0x00;            //Register B
     47  this.registerC = 0x13;            //Register C
     48  this.registerD = 0x00;            //Register D
     49  this.registerE = 0xD8;            //Register E
     50  this.registersHL = 0x014D;          //Registers H and L combined
     51  this.stackPointer = 0xFFFE;          //Stack Pointer
     52  this.programCounter = 0x0100;        //Program Counter
     53  //Some CPU Emulation State Variables:
     54  this.CPUCyclesTotal = 0;          //Relative CPU clocking to speed set, rounded appropriately.
     55  this.CPUCyclesTotalBase = 0;        //Relative CPU clocking to speed set base.
     56  this.CPUCyclesTotalCurrent = 0;        //Relative CPU clocking to speed set, the directly used value.
     57  this.CPUCyclesTotalRoundoff = 0;      //Clocking per iteration rounding catch.
     58  this.baseCPUCyclesPerIteration = 0;    //CPU clocks per iteration at 1x speed.
     59  this.remainingClocks = 0;          //HALT clocking overrun carry over.
     60  this.inBootstrap = true;          //Whether we're in the GBC boot ROM.
     61  this.usedBootROM = false;          //Updated upon ROM loading...
     62  this.usedGBCBootROM = false;        //Did we boot to the GBC boot ROM?
     63  this.halt = false;              //Has the CPU been suspended until the next interrupt?
     64  this.skipPCIncrement = false;        //Did we trip the DMG Halt bug?
     65  this.stopEmulator = 3;            //Has the emulation been paused or a frame has ended?
     66  this.IME = true;              //Are interrupts enabled?
     67  this.IRQLineMatched = 0;          //CPU IRQ assertion.
     68  this.interruptsRequested = 0;        //IF Register
     69  this.interruptsEnabled = 0;          //IE Register
     70  this.hdmaRunning = false;          //HDMA Transfer Flag - GBC only
     71  this.CPUTicks = 0;              //The number of clock cycles emulated.
     72  this.doubleSpeedShifter = 0;        //GBC double speed clocking shifter.
     73  this.JoyPad = 0xFF;              //Joypad State (two four-bit states actually)
     74  this.CPUStopped = false;          //CPU STOP status.
     75  //Main RAM, MBC RAM, GBC Main RAM, VRAM, etc.
     76  this.memoryReader = [];            //Array of functions mapped to read back memory
     77  this.memoryWriter = [];            //Array of functions mapped to write to memory
     78  this.memoryHighReader = [];          //Array of functions mapped to read back 0xFFXX memory
     79  this.memoryHighWriter = [];          //Array of functions mapped to write to 0xFFXX memory
     80  this.ROM = [];                //The full ROM file dumped to an array.
     81  this.memory = [];              //Main Core Memory
     82  this.MBCRam = [];              //Switchable RAM (Used by games for more RAM) for the main memory range 0xA000 - 0xC000.
     83  this.VRAM = [];                //Extra VRAM bank for GBC.
     84  this.GBCMemory = [];            //GBC main RAM Banks
     85  this.MBC1Mode = false;            //MBC1 Type (4/32, 16/8)
     86  this.MBCRAMBanksEnabled = false;      //MBC RAM Access Control.
     87  this.currMBCRAMBank = 0;          //MBC Currently Indexed RAM Bank
     88  this.currMBCRAMBankPosition = -0xA000;    //MBC Position Adder;
     89  this.cGBC = false;              //GameBoy Color detection.
     90  this.gbcRamBank = 1;            //Currently Switched GameBoy Color ram bank
     91  this.gbcRamBankPosition = -0xD000;      //GBC RAM offset from address start.
     92  this.gbcRamBankPositionECHO = -0xF000;    //GBC RAM (ECHO mirroring) offset from address start.
     93  this.RAMBanks = [0, 1, 2, 4, 16];      //Used to map the RAM banks to maximum size the MBC used can do.
     94  this.ROMBank1offs = 0;            //Offset of the ROM bank switching.
     95  this.currentROMBank = 0;          //The parsed current ROM bank selection.
     96  this.cartridgeType = 0;            //Cartridge Type
     97  this.name = "";                //Name of the game
     98  this.gameCode = "";              //Game code (Suffix for older games)
     99  this.fromSaveState = false;          //A boolean to see if this was loaded in as a save state.
    100  this.savedStateFileName = "";        //When loaded in as a save state, this will not be empty.
    101  this.STATTracker = 0;            //Tracker for STAT triggering.
    102  this.modeSTAT = 0;              //The scan line mode (for lines 1-144 it's 2-3-0, for 145-154 it's 1)
    103  this.spriteCount = 252;            //Mode 3 extra clocking counter (Depends on how many sprites are on the current line.).
    104  this.LYCMatchTriggerSTAT = false;      //Should we trigger an interrupt if LY==LYC?
    105  this.mode2TriggerSTAT = false;        //Should we trigger an interrupt if in mode 2?
    106  this.mode1TriggerSTAT = false;        //Should we trigger an interrupt if in mode 1?
    107  this.mode0TriggerSTAT = false;        //Should we trigger an interrupt if in mode 0?
    108  this.LCDisOn = false;            //Is the emulated LCD controller on?
    109  this.LINECONTROL = [];            //Array of functions to handle each scan line we do (onscreen + offscreen)
    110  this.DISPLAYOFFCONTROL = [function (parentObj) {
    111    //Array of line 0 function to handle the LCD controller when it's off (Do nothing!).
    112  }];
    113  this.LCDCONTROL = null;            //Pointer to either LINECONTROL or DISPLAYOFFCONTROL.
    114  this.initializeLCDController();        //Compile the LCD controller functions.
    115  //RTC (Real Time Clock for MBC3):
    116  this.RTCisLatched = false;
    117  this.latchedSeconds = 0;          //RTC latched seconds.
    118  this.latchedMinutes = 0;          //RTC latched minutes.
    119  this.latchedHours = 0;            //RTC latched hours.
    120  this.latchedLDays = 0;            //RTC latched lower 8-bits of the day counter.
    121  this.latchedHDays = 0;            //RTC latched high-bit of the day counter.
    122  this.RTCSeconds = 0;            //RTC seconds counter.
    123  this.RTCMinutes = 0;            //RTC minutes counter.
    124  this.RTCHours = 0;              //RTC hours counter.
    125  this.RTCDays = 0;              //RTC days counter.
    126  this.RTCDayOverFlow = false;        //Did the RTC overflow and wrap the day counter?
    127  this.RTCHALT = false;            //Is the RTC allowed to clock up?
    128  //Gyro:
    129  this.highX = 127;
    130  this.lowX = 127;
    131  this.highY = 127;
    132  this.lowY = 127;
    133  //Sound variables:
    134  this.audioHandle = null;            //XAudioJS handle
    135  this.numSamplesTotal = 0;            //Length of the sound buffers.
    136  this.sampleSize = 0;              //Length of the sound buffer for one channel.
    137  this.dutyLookup = [                //Map the duty values given to ones we can work with.
    138    [false, false, false, false, false, false, false, true],
    139    [true, false, false, false, false, false, false, true],
    140    [true, false, false, false, false, true, true, true],
    141    [false, true, true, true, true, true, true, false]
    142  ];
    143  this.currentBuffer = [];            //The audio buffer we're working on.
    144  this.bufferContainAmount = 0;          //Buffer maintenance metric.
    145  this.LSFR15Table = null;
    146  this.LSFR7Table = null;
    147  this.noiseSampleTable = null;
    148  this.initializeAudioStartState();
    149  this.soundMasterEnabled = false;      //As its name implies
    150  this.channel3PCM = null;          //Channel 3 adjusted sample buffer.
    151  //Vin Shit:
    152  this.VinLeftChannelMasterVolume = 8;    //Computed post-mixing volume.
    153  this.VinRightChannelMasterVolume = 8;    //Computed post-mixing volume.
    154  //Channel paths enabled:
    155  this.leftChannel1 = false;
    156  this.leftChannel2 = false;
    157  this.leftChannel3 = false;
    158  this.leftChannel4 = false;
    159  this.rightChannel1 = false;
    160  this.rightChannel2 = false;
    161  this.rightChannel3 = false;
    162  this.rightChannel4 = false;
    163  //Channel output level caches:
    164  this.channel1currentSampleLeft = 0;
    165  this.channel1currentSampleRight = 0;
    166  this.channel2currentSampleLeft = 0;
    167  this.channel2currentSampleRight = 0;
    168  this.channel3currentSampleLeft = 0;
    169  this.channel3currentSampleRight = 0;
    170  this.channel4currentSampleLeft = 0;
    171  this.channel4currentSampleRight = 0;
    172  this.channel1currentSampleLeftSecondary = 0;
    173  this.channel1currentSampleRightSecondary = 0;
    174  this.channel2currentSampleLeftSecondary = 0;
    175  this.channel2currentSampleRightSecondary = 0;
    176  this.channel3currentSampleLeftSecondary = 0;
    177  this.channel3currentSampleRightSecondary = 0;
    178  this.channel4currentSampleLeftSecondary = 0;
    179  this.channel4currentSampleRightSecondary = 0;
    180  this.channel1currentSampleLeftTrimary = 0;
    181  this.channel1currentSampleRightTrimary = 0;
    182  this.channel2currentSampleLeftTrimary = 0;
    183  this.channel2currentSampleRightTrimary = 0;
    184  this.mixerOutputCache = 0;
    185  //Pre-multipliers to cache some calculations:
    186  this.initializeTiming();
    187  this.machineOut = 0;        //Premultiplier for audio samples per instruction.
    188  //Audio generation counters:
    189  this.audioTicks = 0;        //Used to sample the audio system every x CPU instructions.
    190  this.audioIndex = 0;        //Used to keep alignment on audio generation.
    191  this.rollover = 0;          //Used to keep alignment on the number of samples to output (Realign from counter alias).
    192  //Timing Variables
    193  this.emulatorTicks = 0;        //Times for how many instructions to execute before ending the loop.
    194  this.DIVTicks = 56;          //DIV Ticks Counter (Invisible lower 8-bit)
    195  this.LCDTicks = 60;          //Counter for how many instructions have been executed on a scanline so far.
    196  this.timerTicks = 0;        //Counter for the TIMA timer.
    197  this.TIMAEnabled = false;      //Is TIMA enabled?
    198  this.TACClocker = 1024;        //Timer Max Ticks
    199  this.serialTimer = 0;        //Serial IRQ Timer
    200  this.serialShiftTimer = 0;      //Serial Transfer Shift Timer
    201  this.serialShiftTimerAllocated = 0;  //Serial Transfer Shift Timer Refill
    202  this.IRQEnableDelay = 0;      //Are the interrupts on queue to be enabled?
    203  var dateVar = new_Date();     // The line is changed for benchmarking.
    204  this.lastIteration = dateVar.getTime();//The last time we iterated the main loop.
    205  dateVar = new_Date();         // The line is changed for benchmarking.
    206  this.firstIteration = dateVar.getTime();
    207  this.iterations = 0;
    208  this.actualScanLine = 0;      //Actual scan line...
    209  this.lastUnrenderedLine = 0;    //Last rendered scan line...
    210  this.queuedScanLines = 0;
    211  this.totalLinesPassed = 0;
    212  this.haltPostClocks = 0;      //Post-Halt clocking.
    213  //ROM Cartridge Components:
    214  this.cMBC1 = false;          //Does the cartridge use MBC1?
    215  this.cMBC2 = false;          //Does the cartridge use MBC2?
    216  this.cMBC3 = false;          //Does the cartridge use MBC3?
    217  this.cMBC5 = false;          //Does the cartridge use MBC5?
    218  this.cMBC7 = false;          //Does the cartridge use MBC7?
    219  this.cSRAM = false;          //Does the cartridge use save RAM?
    220  this.cMMMO1 = false;        //...
    221  this.cRUMBLE = false;        //Does the cartridge use the RUMBLE addressing (modified MBC5)?
    222  this.cCamera = false;        //Is the cartridge actually a GameBoy Camera?
    223  this.cTAMA5 = false;        //Does the cartridge use TAMA5? (Tamagotchi Cartridge)
    224  this.cHuC3 = false;          //Does the cartridge use HuC3 (Hudson Soft / modified MBC3)?
    225  this.cHuC1 = false;          //Does the cartridge use HuC1 (Hudson Soft / modified MBC1)?
    226  this.cTIMER = false;        //Does the cartridge have an RTC?
    227  this.ROMBanks = [          // 1 Bank = 16 KBytes = 256 Kbits
    228    2, 4, 8, 16, 32, 64, 128, 256, 512
    229  ];
    230  this.ROMBanks[0x52] = 72;
    231  this.ROMBanks[0x53] = 80;
    232  this.ROMBanks[0x54] = 96;
    233  this.numRAMBanks = 0;          //How many RAM banks were actually allocated?
    234  ////Graphics Variables
    235  this.currVRAMBank = 0;          //Current VRAM bank for GBC.
    236  this.backgroundX = 0;          //Register SCX (X-Scroll)
    237  this.backgroundY = 0;          //Register SCY (Y-Scroll)
    238  this.gfxWindowDisplay = false;      //Is the windows enabled?
    239  this.gfxSpriteShow = false;        //Are sprites enabled?
    240  this.gfxSpriteNormalHeight = true;    //Are we doing 8x8 or 8x16 sprites?
    241  this.bgEnabled = true;          //Is the BG enabled?
    242  this.BGPriorityEnabled = true;      //Can we flag the BG for priority over sprites?
    243  this.gfxWindowCHRBankPosition = 0;    //The current bank of the character map the window uses.
    244  this.gfxBackgroundCHRBankPosition = 0;  //The current bank of the character map the BG uses.
    245  this.gfxBackgroundBankOffset = 0x80;  //Fast mapping of the tile numbering/
    246  this.windowY = 0;            //Current Y offset of the window.
    247  this.windowX = 0;            //Current X offset of the window.
    248  this.drewBlank = 0;            //To prevent the repeating of drawing a blank screen.
    249  this.drewFrame = false;          //Throttle how many draws we can do to once per iteration.
    250  this.midScanlineOffset = -1;      //mid-scanline rendering offset.
    251  this.pixelEnd = 0;            //track the x-coord limit for line rendering (mid-scanline usage).
    252  this.currentX = 0;            //The x-coord we left off at for mid-scanline rendering.
    253  //BG Tile Pointer Caches:
    254  this.BGCHRBank1 = null;
    255  this.BGCHRBank2 = null;
    256  this.BGCHRCurrentBank = null;
    257  //Tile Data Cache:
    258  this.tileCache = null;
    259  //Palettes:
    260  this.colors = [0xEFFFDE, 0xADD794, 0x529273, 0x183442];      //"Classic" GameBoy palette colors.
    261  this.OBJPalette = null;
    262  this.BGPalette = null;
    263  this.gbcOBJRawPalette = null;
    264  this.gbcBGRawPalette = null;
    265  this.gbOBJPalette = null;
    266  this.gbBGPalette = null;
    267  this.gbcOBJPalette = null;
    268  this.gbcBGPalette = null;
    269  this.gbBGColorizedPalette = null;
    270  this.gbOBJColorizedPalette = null;
    271  this.cachedBGPaletteConversion = null;
    272  this.cachedOBJPaletteConversion = null;
    273  this.updateGBBGPalette = this.updateGBRegularBGPalette;
    274  this.updateGBOBJPalette = this.updateGBRegularOBJPalette;
    275  this.colorizedGBPalettes = false;
    276  this.BGLayerRender = null;      //Reference to the BG rendering function.
    277  this.WindowLayerRender = null;    //Reference to the window rendering function.
    278  this.SpriteLayerRender = null;    //Reference to the OAM rendering function.
    279  this.frameBuffer = [];        //The internal frame-buffer.
    280  this.swizzledFrame = null;      //The secondary gfx buffer that holds the converted RGBA values.
    281  this.canvasBuffer = null;      //imageData handle
    282  this.pixelStart = 0;        //Temp variable for holding the current working framebuffer offset.
    283  //Variables used for scaling in JS:
    284  this.onscreenWidth = this.offscreenWidth = 160;
    285  this.onscreenHeight = this.offScreenheight = 144;
    286  this.offscreenRGBCount = this.onscreenWidth * this.onscreenHeight * 4;
    287  //Initialize the white noise cache tables ahead of time:
    288  this.intializeWhiteNoise();
    289 }
    290 
    291 // Start of code changed for benchmarking (removed ROM):
    292 GameBoyCore.prototype.GBBOOTROM = [];
    293 GameBoyCore.prototype.GBCBOOTROM = [];
    294 // End of code changed for benchmarking.
    295 
    296 GameBoyCore.prototype.ffxxDump = [  //Dump of the post-BOOT I/O register state (From gambatte):
    297  0x0F, 0x00, 0x7C, 0xFF, 0x00, 0x00, 0x00, 0xF8,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
    298  0x80, 0xBF, 0xF3, 0xFF, 0xBF, 0xFF, 0x3F, 0x00,   0xFF, 0xBF, 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, 0xFF,
    299  0xFF, 0x00, 0x00, 0xBF, 0x77, 0xF3, 0xF1, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    300  0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,   0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
    301  0x91, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC,   0x00, 0x00, 0x00, 0x00, 0xFF, 0x7E, 0xFF, 0xFE,
    302  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    303  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xC0, 0xFF, 0xC1, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
    304  0xF8, 0xFF, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    305  0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B,   0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D,
    306  0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E,   0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99,
    307  0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC,   0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E,
    308  0x45, 0xEC, 0x52, 0xFA, 0x08, 0xB7, 0x07, 0x5D,   0x01, 0xFD, 0xC0, 0xFF, 0x08, 0xFC, 0x00, 0xE5,
    309  0x0B, 0xF8, 0xC2, 0xCE, 0xF4, 0xF9, 0x0F, 0x7F,   0x45, 0x6D, 0x3D, 0xFE, 0x46, 0x97, 0x33, 0x5E,
    310  0x08, 0xEF, 0xF1, 0xFF, 0x86, 0x83, 0x24, 0x74,   0x12, 0xFC, 0x00, 0x9F, 0xB4, 0xB7, 0x06, 0xD5,
    311  0xD0, 0x7A, 0x00, 0x9E, 0x04, 0x5F, 0x41, 0x2F,   0x1D, 0x77, 0x36, 0x75, 0x81, 0xAA, 0x70, 0x3A,
    312  0x98, 0xD1, 0x71, 0x02, 0x4D, 0x01, 0xC1, 0xFF,   0x0D, 0x00, 0xD3, 0x05, 0xF9, 0x00, 0x0B, 0x00
    313 ];
    314 GameBoyCore.prototype.OPCODE = [
    315  //NOP
    316  //#0x00:
    317  function (parentObj) {
    318    //Do Nothing...
    319  },
    320  //LD BC, nn
    321  //#0x01:
    322  function (parentObj) {
    323    parentObj.registerC = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    324    parentObj.registerB = parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF);
    325    parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
    326  },
    327  //LD (BC), A
    328  //#0x02:
    329  function (parentObj) {
    330    parentObj.memoryWrite((parentObj.registerB << 8) | parentObj.registerC, parentObj.registerA);
    331  },
    332  //INC BC
    333  //#0x03:
    334  function (parentObj) {
    335    var temp_var = ((parentObj.registerB << 8) | parentObj.registerC) + 1;
    336    parentObj.registerB = (temp_var >> 8) & 0xFF;
    337    parentObj.registerC = temp_var & 0xFF;
    338  },
    339  //INC B
    340  //#0x04:
    341  function (parentObj) {
    342    parentObj.registerB = (parentObj.registerB + 1) & 0xFF;
    343    parentObj.FZero = (parentObj.registerB == 0);
    344    parentObj.FHalfCarry = ((parentObj.registerB & 0xF) == 0);
    345    parentObj.FSubtract = false;
    346  },
    347  //DEC B
    348  //#0x05:
    349  function (parentObj) {
    350    parentObj.registerB = (parentObj.registerB - 1) & 0xFF;
    351    parentObj.FZero = (parentObj.registerB == 0);
    352    parentObj.FHalfCarry = ((parentObj.registerB & 0xF) == 0xF);
    353    parentObj.FSubtract = true;
    354  },
    355  //LD B, n
    356  //#0x06:
    357  function (parentObj) {
    358    parentObj.registerB = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    359    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    360  },
    361  //RLCA
    362  //#0x07:
    363  function (parentObj) {
    364    parentObj.FCarry = (parentObj.registerA > 0x7F);
    365    parentObj.registerA = ((parentObj.registerA << 1) & 0xFF) | (parentObj.registerA >> 7);
    366    parentObj.FZero = parentObj.FSubtract = parentObj.FHalfCarry = false;
    367  },
    368  //LD (nn), SP
    369  //#0x08:
    370  function (parentObj) {
    371    var temp_var = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    372    parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
    373    parentObj.memoryWrite(temp_var, parentObj.stackPointer & 0xFF);
    374    parentObj.memoryWrite((temp_var + 1) & 0xFFFF, parentObj.stackPointer >> 8);
    375  },
    376  //ADD HL, BC
    377  //#0x09:
    378  function (parentObj) {
    379    var dirtySum = parentObj.registersHL + ((parentObj.registerB << 8) | parentObj.registerC);
    380    parentObj.FHalfCarry = ((parentObj.registersHL & 0xFFF) > (dirtySum & 0xFFF));
    381    parentObj.FCarry = (dirtySum > 0xFFFF);
    382    parentObj.registersHL = dirtySum & 0xFFFF;
    383    parentObj.FSubtract = false;
    384  },
    385  //LD A, (BC)
    386  //#0x0A:
    387  function (parentObj) {
    388    parentObj.registerA = parentObj.memoryRead((parentObj.registerB << 8) | parentObj.registerC);
    389  },
    390  //DEC BC
    391  //#0x0B:
    392  function (parentObj) {
    393    var temp_var = (((parentObj.registerB << 8) | parentObj.registerC) - 1) & 0xFFFF;
    394    parentObj.registerB = temp_var >> 8;
    395    parentObj.registerC = temp_var & 0xFF;
    396  },
    397  //INC C
    398  //#0x0C:
    399  function (parentObj) {
    400    parentObj.registerC = (parentObj.registerC + 1) & 0xFF;
    401    parentObj.FZero = (parentObj.registerC == 0);
    402    parentObj.FHalfCarry = ((parentObj.registerC & 0xF) == 0);
    403    parentObj.FSubtract = false;
    404  },
    405  //DEC C
    406  //#0x0D:
    407  function (parentObj) {
    408    parentObj.registerC = (parentObj.registerC - 1) & 0xFF;
    409    parentObj.FZero = (parentObj.registerC == 0);
    410    parentObj.FHalfCarry = ((parentObj.registerC & 0xF) == 0xF);
    411    parentObj.FSubtract = true;
    412  },
    413  //LD C, n
    414  //#0x0E:
    415  function (parentObj) {
    416    parentObj.registerC = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    417    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    418  },
    419  //RRCA
    420  //#0x0F:
    421  function (parentObj) {
    422    parentObj.registerA = (parentObj.registerA >> 1) | ((parentObj.registerA & 1) << 7);
    423    parentObj.FCarry = (parentObj.registerA > 0x7F);
    424    parentObj.FZero = parentObj.FSubtract = parentObj.FHalfCarry = false;
    425  },
    426  //STOP
    427  //#0x10:
    428  function (parentObj) {
    429    if (parentObj.cGBC) {
    430      if ((parentObj.memory[0xFF4D] & 0x01) == 0x01) {    //Speed change requested.
    431        if (parentObj.memory[0xFF4D] > 0x7F) {        //Go back to single speed mode.
    432          cout("Going into single clock speed mode.", 0);
    433          parentObj.doubleSpeedShifter = 0;
    434          parentObj.memory[0xFF4D] &= 0x7F;        //Clear the double speed mode flag.
    435        }
    436        else {                        //Go to double speed mode.
    437          cout("Going into double clock speed mode.", 0);
    438          parentObj.doubleSpeedShifter = 1;
    439          parentObj.memory[0xFF4D] |= 0x80;        //Set the double speed mode flag.
    440        }
    441        parentObj.memory[0xFF4D] &= 0xFE;          //Reset the request bit.
    442      }
    443      else {
    444        parentObj.handleSTOP();
    445      }
    446    }
    447    else {
    448      parentObj.handleSTOP();
    449    }
    450  },
    451  //LD DE, nn
    452  //#0x11:
    453  function (parentObj) {
    454    parentObj.registerE = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    455    parentObj.registerD = parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF);
    456    parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
    457  },
    458  //LD (DE), A
    459  //#0x12:
    460  function (parentObj) {
    461    parentObj.memoryWrite((parentObj.registerD << 8) | parentObj.registerE, parentObj.registerA);
    462  },
    463  //INC DE
    464  //#0x13:
    465  function (parentObj) {
    466    var temp_var = ((parentObj.registerD << 8) | parentObj.registerE) + 1;
    467    parentObj.registerD = (temp_var >> 8) & 0xFF;
    468    parentObj.registerE = temp_var & 0xFF;
    469  },
    470  //INC D
    471  //#0x14:
    472  function (parentObj) {
    473    parentObj.registerD = (parentObj.registerD + 1) & 0xFF;
    474    parentObj.FZero = (parentObj.registerD == 0);
    475    parentObj.FHalfCarry = ((parentObj.registerD & 0xF) == 0);
    476    parentObj.FSubtract = false;
    477  },
    478  //DEC D
    479  //#0x15:
    480  function (parentObj) {
    481    parentObj.registerD = (parentObj.registerD - 1) & 0xFF;
    482    parentObj.FZero = (parentObj.registerD == 0);
    483    parentObj.FHalfCarry = ((parentObj.registerD & 0xF) == 0xF);
    484    parentObj.FSubtract = true;
    485  },
    486  //LD D, n
    487  //#0x16:
    488  function (parentObj) {
    489    parentObj.registerD = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    490    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    491  },
    492  //RLA
    493  //#0x17:
    494  function (parentObj) {
    495    var carry_flag = (parentObj.FCarry) ? 1 : 0;
    496    parentObj.FCarry = (parentObj.registerA > 0x7F);
    497    parentObj.registerA = ((parentObj.registerA << 1) & 0xFF) | carry_flag;
    498    parentObj.FZero = parentObj.FSubtract = parentObj.FHalfCarry = false;
    499  },
    500  //JR n
    501  //#0x18:
    502  function (parentObj) {
    503    parentObj.programCounter = (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << 24) >> 24) + 1) & 0xFFFF;
    504  },
    505  //ADD HL, DE
    506  //#0x19:
    507  function (parentObj) {
    508    var dirtySum = parentObj.registersHL + ((parentObj.registerD << 8) | parentObj.registerE);
    509    parentObj.FHalfCarry = ((parentObj.registersHL & 0xFFF) > (dirtySum & 0xFFF));
    510    parentObj.FCarry = (dirtySum > 0xFFFF);
    511    parentObj.registersHL = dirtySum & 0xFFFF;
    512    parentObj.FSubtract = false;
    513  },
    514  //LD A, (DE)
    515  //#0x1A:
    516  function (parentObj) {
    517    parentObj.registerA = parentObj.memoryRead((parentObj.registerD << 8) | parentObj.registerE);
    518  },
    519  //DEC DE
    520  //#0x1B:
    521  function (parentObj) {
    522    var temp_var = (((parentObj.registerD << 8) | parentObj.registerE) - 1) & 0xFFFF;
    523    parentObj.registerD = temp_var >> 8;
    524    parentObj.registerE = temp_var & 0xFF;
    525  },
    526  //INC E
    527  //#0x1C:
    528  function (parentObj) {
    529    parentObj.registerE = (parentObj.registerE + 1) & 0xFF;
    530    parentObj.FZero = (parentObj.registerE == 0);
    531    parentObj.FHalfCarry = ((parentObj.registerE & 0xF) == 0);
    532    parentObj.FSubtract = false;
    533  },
    534  //DEC E
    535  //#0x1D:
    536  function (parentObj) {
    537    parentObj.registerE = (parentObj.registerE - 1) & 0xFF;
    538    parentObj.FZero = (parentObj.registerE == 0);
    539    parentObj.FHalfCarry = ((parentObj.registerE & 0xF) == 0xF);
    540    parentObj.FSubtract = true;
    541  },
    542  //LD E, n
    543  //#0x1E:
    544  function (parentObj) {
    545    parentObj.registerE = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    546    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    547  },
    548  //RRA
    549  //#0x1F:
    550  function (parentObj) {
    551    var carry_flag = (parentObj.FCarry) ? 0x80 : 0;
    552    parentObj.FCarry = ((parentObj.registerA & 1) == 1);
    553    parentObj.registerA = (parentObj.registerA >> 1) | carry_flag;
    554    parentObj.FZero = parentObj.FSubtract = parentObj.FHalfCarry = false;
    555  },
    556  //JR NZ, n
    557  //#0x20:
    558  function (parentObj) {
    559    if (!parentObj.FZero) {
    560      parentObj.programCounter = (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << 24) >> 24) + 1) & 0xFFFF;
    561      parentObj.CPUTicks += 4;
    562    }
    563    else {
    564      parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    565    }
    566  },
    567  //LD HL, nn
    568  //#0x21:
    569  function (parentObj) {
    570    parentObj.registersHL = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    571    parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
    572  },
    573  //LDI (HL), A
    574  //#0x22:
    575  function (parentObj) {
    576    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerA);
    577    parentObj.registersHL = (parentObj.registersHL + 1) & 0xFFFF;
    578  },
    579  //INC HL
    580  //#0x23:
    581  function (parentObj) {
    582    parentObj.registersHL = (parentObj.registersHL + 1) & 0xFFFF;
    583  },
    584  //INC H
    585  //#0x24:
    586  function (parentObj) {
    587    var H = ((parentObj.registersHL >> 8) + 1) & 0xFF;
    588    parentObj.FZero = (H == 0);
    589    parentObj.FHalfCarry = ((H & 0xF) == 0);
    590    parentObj.FSubtract = false;
    591    parentObj.registersHL = (H << 8) | (parentObj.registersHL & 0xFF);
    592  },
    593  //DEC H
    594  //#0x25:
    595  function (parentObj) {
    596    var H = ((parentObj.registersHL >> 8) - 1) & 0xFF;
    597    parentObj.FZero = (H == 0);
    598    parentObj.FHalfCarry = ((H & 0xF) == 0xF);
    599    parentObj.FSubtract = true;
    600    parentObj.registersHL = (H << 8) | (parentObj.registersHL & 0xFF);
    601  },
    602  //LD H, n
    603  //#0x26:
    604  function (parentObj) {
    605    parentObj.registersHL = (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << 8) | (parentObj.registersHL & 0xFF);
    606    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    607  },
    608  //DAA
    609  //#0x27:
    610  function (parentObj) {
    611    if (!parentObj.FSubtract) {
    612      if (parentObj.FCarry || parentObj.registerA > 0x99) {
    613        parentObj.registerA = (parentObj.registerA + 0x60) & 0xFF;
    614        parentObj.FCarry = true;
    615      }
    616      if (parentObj.FHalfCarry || (parentObj.registerA & 0xF) > 0x9) {
    617        parentObj.registerA = (parentObj.registerA + 0x06) & 0xFF;
    618        parentObj.FHalfCarry = false;
    619      }
    620    }
    621    else if (parentObj.FCarry && parentObj.FHalfCarry) {
    622      parentObj.registerA = (parentObj.registerA + 0x9A) & 0xFF;
    623      parentObj.FHalfCarry = false;
    624    }
    625    else if (parentObj.FCarry) {
    626      parentObj.registerA = (parentObj.registerA + 0xA0) & 0xFF;
    627    }
    628    else if (parentObj.FHalfCarry) {
    629      parentObj.registerA = (parentObj.registerA + 0xFA) & 0xFF;
    630      parentObj.FHalfCarry = false;
    631    }
    632    parentObj.FZero = (parentObj.registerA == 0);
    633  },
    634  //JR Z, n
    635  //#0x28:
    636  function (parentObj) {
    637    if (parentObj.FZero) {
    638      parentObj.programCounter = (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << 24) >> 24) + 1) & 0xFFFF;
    639      parentObj.CPUTicks += 4;
    640    }
    641    else {
    642      parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    643    }
    644  },
    645  //ADD HL, HL
    646  //#0x29:
    647  function (parentObj) {
    648    parentObj.FHalfCarry = ((parentObj.registersHL & 0xFFF) > 0x7FF);
    649    parentObj.FCarry = (parentObj.registersHL > 0x7FFF);
    650    parentObj.registersHL = (parentObj.registersHL << 1) & 0xFFFF;
    651    parentObj.FSubtract = false;
    652  },
    653  //LDI A, (HL)
    654  //#0x2A:
    655  function (parentObj) {
    656    parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    657    parentObj.registersHL = (parentObj.registersHL + 1) & 0xFFFF;
    658  },
    659  //DEC HL
    660  //#0x2B:
    661  function (parentObj) {
    662    parentObj.registersHL = (parentObj.registersHL - 1) & 0xFFFF;
    663  },
    664  //INC L
    665  //#0x2C:
    666  function (parentObj) {
    667    var L = (parentObj.registersHL + 1) & 0xFF;
    668    parentObj.FZero = (L == 0);
    669    parentObj.FHalfCarry = ((L & 0xF) == 0);
    670    parentObj.FSubtract = false;
    671    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | L;
    672  },
    673  //DEC L
    674  //#0x2D:
    675  function (parentObj) {
    676    var L = (parentObj.registersHL - 1) & 0xFF;
    677    parentObj.FZero = (L == 0);
    678    parentObj.FHalfCarry = ((L & 0xF) == 0xF);
    679    parentObj.FSubtract = true;
    680    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | L;
    681  },
    682  //LD L, n
    683  //#0x2E:
    684  function (parentObj) {
    685    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    686    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    687  },
    688  //CPL
    689  //#0x2F:
    690  function (parentObj) {
    691    parentObj.registerA ^= 0xFF;
    692    parentObj.FSubtract = parentObj.FHalfCarry = true;
    693  },
    694  //JR NC, n
    695  //#0x30:
    696  function (parentObj) {
    697    if (!parentObj.FCarry) {
    698      parentObj.programCounter = (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << 24) >> 24) + 1) & 0xFFFF;
    699      parentObj.CPUTicks += 4;
    700    }
    701    else {
    702      parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    703    }
    704  },
    705  //LD SP, nn
    706  //#0x31:
    707  function (parentObj) {
    708    parentObj.stackPointer = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    709    parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
    710  },
    711  //LDD (HL), A
    712  //#0x32:
    713  function (parentObj) {
    714    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerA);
    715    parentObj.registersHL = (parentObj.registersHL - 1) & 0xFFFF;
    716  },
    717  //INC SP
    718  //#0x33:
    719  function (parentObj) {
    720    parentObj.stackPointer = (parentObj.stackPointer + 1) & 0xFFFF;
    721  },
    722  //INC (HL)
    723  //#0x34:
    724  function (parentObj) {
    725    var temp_var = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) + 1) & 0xFF;
    726    parentObj.FZero = (temp_var == 0);
    727    parentObj.FHalfCarry = ((temp_var & 0xF) == 0);
    728    parentObj.FSubtract = false;
    729    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var);
    730  },
    731  //DEC (HL)
    732  //#0x35:
    733  function (parentObj) {
    734    var temp_var = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) - 1) & 0xFF;
    735    parentObj.FZero = (temp_var == 0);
    736    parentObj.FHalfCarry = ((temp_var & 0xF) == 0xF);
    737    parentObj.FSubtract = true;
    738    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var);
    739  },
    740  //LD (HL), n
    741  //#0x36:
    742  function (parentObj) {
    743    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
    744    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    745  },
    746  //SCF
    747  //#0x37:
    748  function (parentObj) {
    749    parentObj.FCarry = true;
    750    parentObj.FSubtract = parentObj.FHalfCarry = false;
    751  },
    752  //JR C, n
    753  //#0x38:
    754  function (parentObj) {
    755    if (parentObj.FCarry) {
    756      parentObj.programCounter = (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << 24) >> 24) + 1) & 0xFFFF;
    757      parentObj.CPUTicks += 4;
    758    }
    759    else {
    760      parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    761    }
    762  },
    763  //ADD HL, SP
    764  //#0x39:
    765  function (parentObj) {
    766    var dirtySum = parentObj.registersHL + parentObj.stackPointer;
    767    parentObj.FHalfCarry = ((parentObj.registersHL & 0xFFF) > (dirtySum & 0xFFF));
    768    parentObj.FCarry = (dirtySum > 0xFFFF);
    769    parentObj.registersHL = dirtySum & 0xFFFF;
    770    parentObj.FSubtract = false;
    771  },
    772  //LDD A, (HL)
    773  //#0x3A:
    774  function (parentObj) {
    775    parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    776    parentObj.registersHL = (parentObj.registersHL - 1) & 0xFFFF;
    777  },
    778  //DEC SP
    779  //#0x3B:
    780  function (parentObj) {
    781    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
    782  },
    783  //INC A
    784  //#0x3C:
    785  function (parentObj) {
    786    parentObj.registerA = (parentObj.registerA + 1) & 0xFF;
    787    parentObj.FZero = (parentObj.registerA == 0);
    788    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) == 0);
    789    parentObj.FSubtract = false;
    790  },
    791  //DEC A
    792  //#0x3D:
    793  function (parentObj) {
    794    parentObj.registerA = (parentObj.registerA - 1) & 0xFF;
    795    parentObj.FZero = (parentObj.registerA == 0);
    796    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) == 0xF);
    797    parentObj.FSubtract = true;
    798  },
    799  //LD A, n
    800  //#0x3E:
    801  function (parentObj) {
    802    parentObj.registerA = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    803    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
    804  },
    805  //CCF
    806  //#0x3F:
    807  function (parentObj) {
    808    parentObj.FCarry = !parentObj.FCarry;
    809    parentObj.FSubtract = parentObj.FHalfCarry = false;
    810  },
    811  //LD B, B
    812  //#0x40:
    813  function (parentObj) {
    814    //Do nothing...
    815  },
    816  //LD B, C
    817  //#0x41:
    818  function (parentObj) {
    819    parentObj.registerB = parentObj.registerC;
    820  },
    821  //LD B, D
    822  //#0x42:
    823  function (parentObj) {
    824    parentObj.registerB = parentObj.registerD;
    825  },
    826  //LD B, E
    827  //#0x43:
    828  function (parentObj) {
    829    parentObj.registerB = parentObj.registerE;
    830  },
    831  //LD B, H
    832  //#0x44:
    833  function (parentObj) {
    834    parentObj.registerB = parentObj.registersHL >> 8;
    835  },
    836  //LD B, L
    837  //#0x45:
    838  function (parentObj) {
    839    parentObj.registerB = parentObj.registersHL & 0xFF;
    840  },
    841  //LD B, (HL)
    842  //#0x46:
    843  function (parentObj) {
    844    parentObj.registerB = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    845  },
    846  //LD B, A
    847  //#0x47:
    848  function (parentObj) {
    849    parentObj.registerB = parentObj.registerA;
    850  },
    851  //LD C, B
    852  //#0x48:
    853  function (parentObj) {
    854    parentObj.registerC = parentObj.registerB;
    855  },
    856  //LD C, C
    857  //#0x49:
    858  function (parentObj) {
    859    //Do nothing...
    860  },
    861  //LD C, D
    862  //#0x4A:
    863  function (parentObj) {
    864    parentObj.registerC = parentObj.registerD;
    865  },
    866  //LD C, E
    867  //#0x4B:
    868  function (parentObj) {
    869    parentObj.registerC = parentObj.registerE;
    870  },
    871  //LD C, H
    872  //#0x4C:
    873  function (parentObj) {
    874    parentObj.registerC = parentObj.registersHL >> 8;
    875  },
    876  //LD C, L
    877  //#0x4D:
    878  function (parentObj) {
    879    parentObj.registerC = parentObj.registersHL & 0xFF;
    880  },
    881  //LD C, (HL)
    882  //#0x4E:
    883  function (parentObj) {
    884    parentObj.registerC = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    885  },
    886  //LD C, A
    887  //#0x4F:
    888  function (parentObj) {
    889    parentObj.registerC = parentObj.registerA;
    890  },
    891  //LD D, B
    892  //#0x50:
    893  function (parentObj) {
    894    parentObj.registerD = parentObj.registerB;
    895  },
    896  //LD D, C
    897  //#0x51:
    898  function (parentObj) {
    899    parentObj.registerD = parentObj.registerC;
    900  },
    901  //LD D, D
    902  //#0x52:
    903  function (parentObj) {
    904    //Do nothing...
    905  },
    906  //LD D, E
    907  //#0x53:
    908  function (parentObj) {
    909    parentObj.registerD = parentObj.registerE;
    910  },
    911  //LD D, H
    912  //#0x54:
    913  function (parentObj) {
    914    parentObj.registerD = parentObj.registersHL >> 8;
    915  },
    916  //LD D, L
    917  //#0x55:
    918  function (parentObj) {
    919    parentObj.registerD = parentObj.registersHL & 0xFF;
    920  },
    921  //LD D, (HL)
    922  //#0x56:
    923  function (parentObj) {
    924    parentObj.registerD = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    925  },
    926  //LD D, A
    927  //#0x57:
    928  function (parentObj) {
    929    parentObj.registerD = parentObj.registerA;
    930  },
    931  //LD E, B
    932  //#0x58:
    933  function (parentObj) {
    934    parentObj.registerE = parentObj.registerB;
    935  },
    936  //LD E, C
    937  //#0x59:
    938  function (parentObj) {
    939    parentObj.registerE = parentObj.registerC;
    940  },
    941  //LD E, D
    942  //#0x5A:
    943  function (parentObj) {
    944    parentObj.registerE = parentObj.registerD;
    945  },
    946  //LD E, E
    947  //#0x5B:
    948  function (parentObj) {
    949    //Do nothing...
    950  },
    951  //LD E, H
    952  //#0x5C:
    953  function (parentObj) {
    954    parentObj.registerE = parentObj.registersHL >> 8;
    955  },
    956  //LD E, L
    957  //#0x5D:
    958  function (parentObj) {
    959    parentObj.registerE = parentObj.registersHL & 0xFF;
    960  },
    961  //LD E, (HL)
    962  //#0x5E:
    963  function (parentObj) {
    964    parentObj.registerE = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    965  },
    966  //LD E, A
    967  //#0x5F:
    968  function (parentObj) {
    969    parentObj.registerE = parentObj.registerA;
    970  },
    971  //LD H, B
    972  //#0x60:
    973  function (parentObj) {
    974    parentObj.registersHL = (parentObj.registerB << 8) | (parentObj.registersHL & 0xFF);
    975  },
    976  //LD H, C
    977  //#0x61:
    978  function (parentObj) {
    979    parentObj.registersHL = (parentObj.registerC << 8) | (parentObj.registersHL & 0xFF);
    980  },
    981  //LD H, D
    982  //#0x62:
    983  function (parentObj) {
    984    parentObj.registersHL = (parentObj.registerD << 8) | (parentObj.registersHL & 0xFF);
    985  },
    986  //LD H, E
    987  //#0x63:
    988  function (parentObj) {
    989    parentObj.registersHL = (parentObj.registerE << 8) | (parentObj.registersHL & 0xFF);
    990  },
    991  //LD H, H
    992  //#0x64:
    993  function (parentObj) {
    994    //Do nothing...
    995  },
    996  //LD H, L
    997  //#0x65:
    998  function (parentObj) {
    999    parentObj.registersHL = (parentObj.registersHL & 0xFF) * 0x101;
   1000  },
   1001  //LD H, (HL)
   1002  //#0x66:
   1003  function (parentObj) {
   1004    parentObj.registersHL = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) << 8) | (parentObj.registersHL & 0xFF);
   1005  },
   1006  //LD H, A
   1007  //#0x67:
   1008  function (parentObj) {
   1009    parentObj.registersHL = (parentObj.registerA << 8) | (parentObj.registersHL & 0xFF);
   1010  },
   1011  //LD L, B
   1012  //#0x68:
   1013  function (parentObj) {
   1014    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerB;
   1015  },
   1016  //LD L, C
   1017  //#0x69:
   1018  function (parentObj) {
   1019    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerC;
   1020  },
   1021  //LD L, D
   1022  //#0x6A:
   1023  function (parentObj) {
   1024    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerD;
   1025  },
   1026  //LD L, E
   1027  //#0x6B:
   1028  function (parentObj) {
   1029    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerE;
   1030  },
   1031  //LD L, H
   1032  //#0x6C:
   1033  function (parentObj) {
   1034    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | (parentObj.registersHL >> 8);
   1035  },
   1036  //LD L, L
   1037  //#0x6D:
   1038  function (parentObj) {
   1039    //Do nothing...
   1040  },
   1041  //LD L, (HL)
   1042  //#0x6E:
   1043  function (parentObj) {
   1044    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1045  },
   1046  //LD L, A
   1047  //#0x6F:
   1048  function (parentObj) {
   1049    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerA;
   1050  },
   1051  //LD (HL), B
   1052  //#0x70:
   1053  function (parentObj) {
   1054    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerB);
   1055  },
   1056  //LD (HL), C
   1057  //#0x71:
   1058  function (parentObj) {
   1059    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerC);
   1060  },
   1061  //LD (HL), D
   1062  //#0x72:
   1063  function (parentObj) {
   1064    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerD);
   1065  },
   1066  //LD (HL), E
   1067  //#0x73:
   1068  function (parentObj) {
   1069    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerE);
   1070  },
   1071  //LD (HL), H
   1072  //#0x74:
   1073  function (parentObj) {
   1074    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registersHL >> 8);
   1075  },
   1076  //LD (HL), L
   1077  //#0x75:
   1078  function (parentObj) {
   1079    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registersHL & 0xFF);
   1080  },
   1081  //HALT
   1082  //#0x76:
   1083  function (parentObj) {
   1084    //See if there's already an IRQ match:
   1085    if ((parentObj.interruptsEnabled & parentObj.interruptsRequested & 0x1F) > 0) {
   1086      if (!parentObj.cGBC && !parentObj.usedBootROM) {
   1087        //HALT bug in the DMG CPU model (Program Counter fails to increment for one instruction after HALT):
   1088        parentObj.skipPCIncrement = true;
   1089      }
   1090      else {
   1091        //CGB gets around the HALT PC bug by doubling the hidden NOP.
   1092        parentObj.CPUTicks += 4;
   1093      }
   1094    }
   1095    else {
   1096      //CPU is stalled until the next IRQ match:
   1097      parentObj.calculateHALTPeriod();
   1098    }
   1099  },
   1100  //LD (HL), A
   1101  //#0x77:
   1102  function (parentObj) {
   1103    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerA);
   1104  },
   1105  //LD A, B
   1106  //#0x78:
   1107  function (parentObj) {
   1108    parentObj.registerA = parentObj.registerB;
   1109  },
   1110  //LD A, C
   1111  //#0x79:
   1112  function (parentObj) {
   1113    parentObj.registerA = parentObj.registerC;
   1114  },
   1115  //LD A, D
   1116  //#0x7A:
   1117  function (parentObj) {
   1118    parentObj.registerA = parentObj.registerD;
   1119  },
   1120  //LD A, E
   1121  //#0x7B:
   1122  function (parentObj) {
   1123    parentObj.registerA = parentObj.registerE;
   1124  },
   1125  //LD A, H
   1126  //#0x7C:
   1127  function (parentObj) {
   1128    parentObj.registerA = parentObj.registersHL >> 8;
   1129  },
   1130  //LD A, L
   1131  //#0x7D:
   1132  function (parentObj) {
   1133    parentObj.registerA = parentObj.registersHL & 0xFF;
   1134  },
   1135  //LD, A, (HL)
   1136  //#0x7E:
   1137  function (parentObj) {
   1138    parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1139  },
   1140  //LD A, A
   1141  //#0x7F:
   1142  function (parentObj) {
   1143    //Do Nothing...
   1144  },
   1145  //ADD A, B
   1146  //#0x80:
   1147  function (parentObj) {
   1148    var dirtySum = parentObj.registerA + parentObj.registerB;
   1149    parentObj.FHalfCarry = ((dirtySum & 0xF) < (parentObj.registerA & 0xF));
   1150    parentObj.FCarry = (dirtySum > 0xFF);
   1151    parentObj.registerA = dirtySum & 0xFF;
   1152    parentObj.FZero = (parentObj.registerA == 0);
   1153    parentObj.FSubtract = false;
   1154  },
   1155  //ADD A, C
   1156  //#0x81:
   1157  function (parentObj) {
   1158    var dirtySum = parentObj.registerA + parentObj.registerC;
   1159    parentObj.FHalfCarry = ((dirtySum & 0xF) < (parentObj.registerA & 0xF));
   1160    parentObj.FCarry = (dirtySum > 0xFF);
   1161    parentObj.registerA = dirtySum & 0xFF;
   1162    parentObj.FZero = (parentObj.registerA == 0);
   1163    parentObj.FSubtract = false;
   1164  },
   1165  //ADD A, D
   1166  //#0x82:
   1167  function (parentObj) {
   1168    var dirtySum = parentObj.registerA + parentObj.registerD;
   1169    parentObj.FHalfCarry = ((dirtySum & 0xF) < (parentObj.registerA & 0xF));
   1170    parentObj.FCarry = (dirtySum > 0xFF);
   1171    parentObj.registerA = dirtySum & 0xFF;
   1172    parentObj.FZero = (parentObj.registerA == 0);
   1173    parentObj.FSubtract = false;
   1174  },
   1175  //ADD A, E
   1176  //#0x83:
   1177  function (parentObj) {
   1178    var dirtySum = parentObj.registerA + parentObj.registerE;
   1179    parentObj.FHalfCarry = ((dirtySum & 0xF) < (parentObj.registerA & 0xF));
   1180    parentObj.FCarry = (dirtySum > 0xFF);
   1181    parentObj.registerA = dirtySum & 0xFF;
   1182    parentObj.FZero = (parentObj.registerA == 0);
   1183    parentObj.FSubtract = false;
   1184  },
   1185  //ADD A, H
   1186  //#0x84:
   1187  function (parentObj) {
   1188    var dirtySum = parentObj.registerA + (parentObj.registersHL >> 8);
   1189    parentObj.FHalfCarry = ((dirtySum & 0xF) < (parentObj.registerA & 0xF));
   1190    parentObj.FCarry = (dirtySum > 0xFF);
   1191    parentObj.registerA = dirtySum & 0xFF;
   1192    parentObj.FZero = (parentObj.registerA == 0);
   1193    parentObj.FSubtract = false;
   1194  },
   1195  //ADD A, L
   1196  //#0x85:
   1197  function (parentObj) {
   1198    var dirtySum = parentObj.registerA + (parentObj.registersHL & 0xFF);
   1199    parentObj.FHalfCarry = ((dirtySum & 0xF) < (parentObj.registerA & 0xF));
   1200    parentObj.FCarry = (dirtySum > 0xFF);
   1201    parentObj.registerA = dirtySum & 0xFF;
   1202    parentObj.FZero = (parentObj.registerA == 0);
   1203    parentObj.FSubtract = false;
   1204  },
   1205  //ADD A, (HL)
   1206  //#0x86:
   1207  function (parentObj) {
   1208    var dirtySum = parentObj.registerA + parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1209    parentObj.FHalfCarry = ((dirtySum & 0xF) < (parentObj.registerA & 0xF));
   1210    parentObj.FCarry = (dirtySum > 0xFF);
   1211    parentObj.registerA = dirtySum & 0xFF;
   1212    parentObj.FZero = (parentObj.registerA == 0);
   1213    parentObj.FSubtract = false;
   1214  },
   1215  //ADD A, A
   1216  //#0x87:
   1217  function (parentObj) {
   1218    parentObj.FHalfCarry = ((parentObj.registerA & 0x8) == 0x8);
   1219    parentObj.FCarry = (parentObj.registerA > 0x7F);
   1220    parentObj.registerA = (parentObj.registerA << 1) & 0xFF;
   1221    parentObj.FZero = (parentObj.registerA == 0);
   1222    parentObj.FSubtract = false;
   1223  },
   1224  //ADC A, B
   1225  //#0x88:
   1226  function (parentObj) {
   1227    var dirtySum = parentObj.registerA + parentObj.registerB + ((parentObj.FCarry) ? 1 : 0);
   1228    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (parentObj.registerB & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
   1229    parentObj.FCarry = (dirtySum > 0xFF);
   1230    parentObj.registerA = dirtySum & 0xFF;
   1231    parentObj.FZero = (parentObj.registerA == 0);
   1232    parentObj.FSubtract = false;
   1233  },
   1234  //ADC A, C
   1235  //#0x89:
   1236  function (parentObj) {
   1237    var dirtySum = parentObj.registerA + parentObj.registerC + ((parentObj.FCarry) ? 1 : 0);
   1238    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (parentObj.registerC & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
   1239    parentObj.FCarry = (dirtySum > 0xFF);
   1240    parentObj.registerA = dirtySum & 0xFF;
   1241    parentObj.FZero = (parentObj.registerA == 0);
   1242    parentObj.FSubtract = false;
   1243  },
   1244  //ADC A, D
   1245  //#0x8A:
   1246  function (parentObj) {
   1247    var dirtySum = parentObj.registerA + parentObj.registerD + ((parentObj.FCarry) ? 1 : 0);
   1248    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (parentObj.registerD & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
   1249    parentObj.FCarry = (dirtySum > 0xFF);
   1250    parentObj.registerA = dirtySum & 0xFF;
   1251    parentObj.FZero = (parentObj.registerA == 0);
   1252    parentObj.FSubtract = false;
   1253  },
   1254  //ADC A, E
   1255  //#0x8B:
   1256  function (parentObj) {
   1257    var dirtySum = parentObj.registerA + parentObj.registerE + ((parentObj.FCarry) ? 1 : 0);
   1258    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (parentObj.registerE & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
   1259    parentObj.FCarry = (dirtySum > 0xFF);
   1260    parentObj.registerA = dirtySum & 0xFF;
   1261    parentObj.FZero = (parentObj.registerA == 0);
   1262    parentObj.FSubtract = false;
   1263  },
   1264  //ADC A, H
   1265  //#0x8C:
   1266  function (parentObj) {
   1267    var tempValue = (parentObj.registersHL >> 8);
   1268    var dirtySum = parentObj.registerA + tempValue + ((parentObj.FCarry) ? 1 : 0);
   1269    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (tempValue & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
   1270    parentObj.FCarry = (dirtySum > 0xFF);
   1271    parentObj.registerA = dirtySum & 0xFF;
   1272    parentObj.FZero = (parentObj.registerA == 0);
   1273    parentObj.FSubtract = false;
   1274  },
   1275  //ADC A, L
   1276  //#0x8D:
   1277  function (parentObj) {
   1278    var tempValue = (parentObj.registersHL & 0xFF);
   1279    var dirtySum = parentObj.registerA + tempValue + ((parentObj.FCarry) ? 1 : 0);
   1280    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (tempValue & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
   1281    parentObj.FCarry = (dirtySum > 0xFF);
   1282    parentObj.registerA = dirtySum & 0xFF;
   1283    parentObj.FZero = (parentObj.registerA == 0);
   1284    parentObj.FSubtract = false;
   1285  },
   1286  //ADC A, (HL)
   1287  //#0x8E:
   1288  function (parentObj) {
   1289    var tempValue = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1290    var dirtySum = parentObj.registerA + tempValue + ((parentObj.FCarry) ? 1 : 0);
   1291    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (tempValue & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
   1292    parentObj.FCarry = (dirtySum > 0xFF);
   1293    parentObj.registerA = dirtySum & 0xFF;
   1294    parentObj.FZero = (parentObj.registerA == 0);
   1295    parentObj.FSubtract = false;
   1296  },
   1297  //ADC A, A
   1298  //#0x8F:
   1299  function (parentObj) {
   1300    //shift left register A one bit for some ops here as an optimization:
   1301    var dirtySum = (parentObj.registerA << 1) | ((parentObj.FCarry) ? 1 : 0);
   1302    parentObj.FHalfCarry = ((((parentObj.registerA << 1) & 0x1E) | ((parentObj.FCarry) ? 1 : 0)) > 0xF);
   1303    parentObj.FCarry = (dirtySum > 0xFF);
   1304    parentObj.registerA = dirtySum & 0xFF;
   1305    parentObj.FZero = (parentObj.registerA == 0);
   1306    parentObj.FSubtract = false;
   1307  },
   1308  //SUB A, B
   1309  //#0x90:
   1310  function (parentObj) {
   1311    var dirtySum = parentObj.registerA - parentObj.registerB;
   1312    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) < (dirtySum & 0xF));
   1313    parentObj.FCarry = (dirtySum < 0);
   1314    parentObj.registerA = dirtySum & 0xFF;
   1315    parentObj.FZero = (dirtySum == 0);
   1316    parentObj.FSubtract = true;
   1317  },
   1318  //SUB A, C
   1319  //#0x91:
   1320  function (parentObj) {
   1321    var dirtySum = parentObj.registerA - parentObj.registerC;
   1322    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) < (dirtySum & 0xF));
   1323    parentObj.FCarry = (dirtySum < 0);
   1324    parentObj.registerA = dirtySum & 0xFF;
   1325    parentObj.FZero = (dirtySum == 0);
   1326    parentObj.FSubtract = true;
   1327  },
   1328  //SUB A, D
   1329  //#0x92:
   1330  function (parentObj) {
   1331    var dirtySum = parentObj.registerA - parentObj.registerD;
   1332    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) < (dirtySum & 0xF));
   1333    parentObj.FCarry = (dirtySum < 0);
   1334    parentObj.registerA = dirtySum & 0xFF;
   1335    parentObj.FZero = (dirtySum == 0);
   1336    parentObj.FSubtract = true;
   1337  },
   1338  //SUB A, E
   1339  //#0x93:
   1340  function (parentObj) {
   1341    var dirtySum = parentObj.registerA - parentObj.registerE;
   1342    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) < (dirtySum & 0xF));
   1343    parentObj.FCarry = (dirtySum < 0);
   1344    parentObj.registerA = dirtySum & 0xFF;
   1345    parentObj.FZero = (dirtySum == 0);
   1346    parentObj.FSubtract = true;
   1347  },
   1348  //SUB A, H
   1349  //#0x94:
   1350  function (parentObj) {
   1351    var dirtySum = parentObj.registerA - (parentObj.registersHL >> 8);
   1352    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) < (dirtySum & 0xF));
   1353    parentObj.FCarry = (dirtySum < 0);
   1354    parentObj.registerA = dirtySum & 0xFF;
   1355    parentObj.FZero = (dirtySum == 0);
   1356    parentObj.FSubtract = true;
   1357  },
   1358  //SUB A, L
   1359  //#0x95:
   1360  function (parentObj) {
   1361    var dirtySum = parentObj.registerA - (parentObj.registersHL & 0xFF);
   1362    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) < (dirtySum & 0xF));
   1363    parentObj.FCarry = (dirtySum < 0);
   1364    parentObj.registerA = dirtySum & 0xFF;
   1365    parentObj.FZero = (dirtySum == 0);
   1366    parentObj.FSubtract = true;
   1367  },
   1368  //SUB A, (HL)
   1369  //#0x96:
   1370  function (parentObj) {
   1371    var dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1372    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) < (dirtySum & 0xF));
   1373    parentObj.FCarry = (dirtySum < 0);
   1374    parentObj.registerA = dirtySum & 0xFF;
   1375    parentObj.FZero = (dirtySum == 0);
   1376    parentObj.FSubtract = true;
   1377  },
   1378  //SUB A, A
   1379  //#0x97:
   1380  function (parentObj) {
   1381    //number - same number == 0
   1382    parentObj.registerA = 0;
   1383    parentObj.FHalfCarry = parentObj.FCarry = false;
   1384    parentObj.FZero = parentObj.FSubtract = true;
   1385  },
   1386  //SBC A, B
   1387  //#0x98:
   1388  function (parentObj) {
   1389    var dirtySum = parentObj.registerA - parentObj.registerB - ((parentObj.FCarry) ? 1 : 0);
   1390    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registerB & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
   1391    parentObj.FCarry = (dirtySum < 0);
   1392    parentObj.registerA = dirtySum & 0xFF;
   1393    parentObj.FZero = (parentObj.registerA == 0);
   1394    parentObj.FSubtract = true;
   1395  },
   1396  //SBC A, C
   1397  //#0x99:
   1398  function (parentObj) {
   1399    var dirtySum = parentObj.registerA - parentObj.registerC - ((parentObj.FCarry) ? 1 : 0);
   1400    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registerC & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
   1401    parentObj.FCarry = (dirtySum < 0);
   1402    parentObj.registerA = dirtySum & 0xFF;
   1403    parentObj.FZero = (parentObj.registerA == 0);
   1404    parentObj.FSubtract = true;
   1405  },
   1406  //SBC A, D
   1407  //#0x9A:
   1408  function (parentObj) {
   1409    var dirtySum = parentObj.registerA - parentObj.registerD - ((parentObj.FCarry) ? 1 : 0);
   1410    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registerD & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
   1411    parentObj.FCarry = (dirtySum < 0);
   1412    parentObj.registerA = dirtySum & 0xFF;
   1413    parentObj.FZero = (parentObj.registerA == 0);
   1414    parentObj.FSubtract = true;
   1415  },
   1416  //SBC A, E
   1417  //#0x9B:
   1418  function (parentObj) {
   1419    var dirtySum = parentObj.registerA - parentObj.registerE - ((parentObj.FCarry) ? 1 : 0);
   1420    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registerE & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
   1421    parentObj.FCarry = (dirtySum < 0);
   1422    parentObj.registerA = dirtySum & 0xFF;
   1423    parentObj.FZero = (parentObj.registerA == 0);
   1424    parentObj.FSubtract = true;
   1425  },
   1426  //SBC A, H
   1427  //#0x9C:
   1428  function (parentObj) {
   1429    var temp_var = parentObj.registersHL >> 8;
   1430    var dirtySum = parentObj.registerA - temp_var - ((parentObj.FCarry) ? 1 : 0);
   1431    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (temp_var & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
   1432    parentObj.FCarry = (dirtySum < 0);
   1433    parentObj.registerA = dirtySum & 0xFF;
   1434    parentObj.FZero = (parentObj.registerA == 0);
   1435    parentObj.FSubtract = true;
   1436  },
   1437  //SBC A, L
   1438  //#0x9D:
   1439  function (parentObj) {
   1440    var dirtySum = parentObj.registerA - (parentObj.registersHL & 0xFF) - ((parentObj.FCarry) ? 1 : 0);
   1441    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registersHL & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
   1442    parentObj.FCarry = (dirtySum < 0);
   1443    parentObj.registerA = dirtySum & 0xFF;
   1444    parentObj.FZero = (parentObj.registerA == 0);
   1445    parentObj.FSubtract = true;
   1446  },
   1447  //SBC A, (HL)
   1448  //#0x9E:
   1449  function (parentObj) {
   1450    var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1451    var dirtySum = parentObj.registerA - temp_var - ((parentObj.FCarry) ? 1 : 0);
   1452    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (temp_var & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
   1453    parentObj.FCarry = (dirtySum < 0);
   1454    parentObj.registerA = dirtySum & 0xFF;
   1455    parentObj.FZero = (parentObj.registerA == 0);
   1456    parentObj.FSubtract = true;
   1457  },
   1458  //SBC A, A
   1459  //#0x9F:
   1460  function (parentObj) {
   1461    //Optimized SBC A:
   1462    if (parentObj.FCarry) {
   1463      parentObj.FZero = false;
   1464      parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = true;
   1465      parentObj.registerA = 0xFF;
   1466    }
   1467    else {
   1468      parentObj.FHalfCarry = parentObj.FCarry = false;
   1469      parentObj.FSubtract = parentObj.FZero = true;
   1470      parentObj.registerA = 0;
   1471    }
   1472  },
   1473  //AND B
   1474  //#0xA0:
   1475  function (parentObj) {
   1476    parentObj.registerA &= parentObj.registerB;
   1477    parentObj.FZero = (parentObj.registerA == 0);
   1478    parentObj.FHalfCarry = true;
   1479    parentObj.FSubtract = parentObj.FCarry = false;
   1480  },
   1481  //AND C
   1482  //#0xA1:
   1483  function (parentObj) {
   1484    parentObj.registerA &= parentObj.registerC;
   1485    parentObj.FZero = (parentObj.registerA == 0);
   1486    parentObj.FHalfCarry = true;
   1487    parentObj.FSubtract = parentObj.FCarry = false;
   1488  },
   1489  //AND D
   1490  //#0xA2:
   1491  function (parentObj) {
   1492    parentObj.registerA &= parentObj.registerD;
   1493    parentObj.FZero = (parentObj.registerA == 0);
   1494    parentObj.FHalfCarry = true;
   1495    parentObj.FSubtract = parentObj.FCarry = false;
   1496  },
   1497  //AND E
   1498  //#0xA3:
   1499  function (parentObj) {
   1500    parentObj.registerA &= parentObj.registerE;
   1501    parentObj.FZero = (parentObj.registerA == 0);
   1502    parentObj.FHalfCarry = true;
   1503    parentObj.FSubtract = parentObj.FCarry = false;
   1504  },
   1505  //AND H
   1506  //#0xA4:
   1507  function (parentObj) {
   1508    parentObj.registerA &= (parentObj.registersHL >> 8);
   1509    parentObj.FZero = (parentObj.registerA == 0);
   1510    parentObj.FHalfCarry = true;
   1511    parentObj.FSubtract = parentObj.FCarry = false;
   1512  },
   1513  //AND L
   1514  //#0xA5:
   1515  function (parentObj) {
   1516    parentObj.registerA &= parentObj.registersHL;
   1517    parentObj.FZero = (parentObj.registerA == 0);
   1518    parentObj.FHalfCarry = true;
   1519    parentObj.FSubtract = parentObj.FCarry = false;
   1520  },
   1521  //AND (HL)
   1522  //#0xA6:
   1523  function (parentObj) {
   1524    parentObj.registerA &= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1525    parentObj.FZero = (parentObj.registerA == 0);
   1526    parentObj.FHalfCarry = true;
   1527    parentObj.FSubtract = parentObj.FCarry = false;
   1528  },
   1529  //AND A
   1530  //#0xA7:
   1531  function (parentObj) {
   1532    //number & same number = same number
   1533    parentObj.FZero = (parentObj.registerA == 0);
   1534    parentObj.FHalfCarry = true;
   1535    parentObj.FSubtract = parentObj.FCarry = false;
   1536  },
   1537  //XOR B
   1538  //#0xA8:
   1539  function (parentObj) {
   1540    parentObj.registerA ^= parentObj.registerB;
   1541    parentObj.FZero = (parentObj.registerA == 0);
   1542    parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
   1543  },
   1544  //XOR C
   1545  //#0xA9:
   1546  function (parentObj) {
   1547    parentObj.registerA ^= parentObj.registerC;
   1548    parentObj.FZero = (parentObj.registerA == 0);
   1549    parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
   1550  },
   1551  //XOR D
   1552  //#0xAA:
   1553  function (parentObj) {
   1554    parentObj.registerA ^= parentObj.registerD;
   1555    parentObj.FZero = (parentObj.registerA == 0);
   1556    parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
   1557  },
   1558  //XOR E
   1559  //#0xAB:
   1560  function (parentObj) {
   1561    parentObj.registerA ^= parentObj.registerE;
   1562    parentObj.FZero = (parentObj.registerA == 0);
   1563    parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
   1564  },
   1565  //XOR H
   1566  //#0xAC:
   1567  function (parentObj) {
   1568    parentObj.registerA ^= (parentObj.registersHL >> 8);
   1569    parentObj.FZero = (parentObj.registerA == 0);
   1570    parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
   1571  },
   1572  //XOR L
   1573  //#0xAD:
   1574  function (parentObj) {
   1575    parentObj.registerA ^= (parentObj.registersHL & 0xFF);
   1576    parentObj.FZero = (parentObj.registerA == 0);
   1577    parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
   1578  },
   1579  //XOR (HL)
   1580  //#0xAE:
   1581  function (parentObj) {
   1582    parentObj.registerA ^= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1583    parentObj.FZero = (parentObj.registerA == 0);
   1584    parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
   1585  },
   1586  //XOR A
   1587  //#0xAF:
   1588  function (parentObj) {
   1589    //number ^ same number == 0
   1590    parentObj.registerA = 0;
   1591    parentObj.FZero = true;
   1592    parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
   1593  },
   1594  //OR B
   1595  //#0xB0:
   1596  function (parentObj) {
   1597    parentObj.registerA |= parentObj.registerB;
   1598    parentObj.FZero = (parentObj.registerA == 0);
   1599    parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
   1600  },
   1601  //OR C
   1602  //#0xB1:
   1603  function (parentObj) {
   1604    parentObj.registerA |= parentObj.registerC;
   1605    parentObj.FZero = (parentObj.registerA == 0);
   1606    parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
   1607  },
   1608  //OR D
   1609  //#0xB2:
   1610  function (parentObj) {
   1611    parentObj.registerA |= parentObj.registerD;
   1612    parentObj.FZero = (parentObj.registerA == 0);
   1613    parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
   1614  },
   1615  //OR E
   1616  //#0xB3:
   1617  function (parentObj) {
   1618    parentObj.registerA |= parentObj.registerE;
   1619    parentObj.FZero = (parentObj.registerA == 0);
   1620    parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
   1621  },
   1622  //OR H
   1623  //#0xB4:
   1624  function (parentObj) {
   1625    parentObj.registerA |= (parentObj.registersHL >> 8);
   1626    parentObj.FZero = (parentObj.registerA == 0);
   1627    parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
   1628  },
   1629  //OR L
   1630  //#0xB5:
   1631  function (parentObj) {
   1632    parentObj.registerA |= (parentObj.registersHL & 0xFF);
   1633    parentObj.FZero = (parentObj.registerA == 0);
   1634    parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
   1635  },
   1636  //OR (HL)
   1637  //#0xB6:
   1638  function (parentObj) {
   1639    parentObj.registerA |= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1640    parentObj.FZero = (parentObj.registerA == 0);
   1641    parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
   1642  },
   1643  //OR A
   1644  //#0xB7:
   1645  function (parentObj) {
   1646    //number | same number == same number
   1647    parentObj.FZero = (parentObj.registerA == 0);
   1648    parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
   1649  },
   1650  //CP B
   1651  //#0xB8:
   1652  function (parentObj) {
   1653    var dirtySum = parentObj.registerA - parentObj.registerB;
   1654    parentObj.FHalfCarry = ((dirtySum & 0xF) > (parentObj.registerA & 0xF));
   1655    parentObj.FCarry = (dirtySum < 0);
   1656    parentObj.FZero = (dirtySum == 0);
   1657    parentObj.FSubtract = true;
   1658  },
   1659  //CP C
   1660  //#0xB9:
   1661  function (parentObj) {
   1662    var dirtySum = parentObj.registerA - parentObj.registerC;
   1663    parentObj.FHalfCarry = ((dirtySum & 0xF) > (parentObj.registerA & 0xF));
   1664    parentObj.FCarry = (dirtySum < 0);
   1665    parentObj.FZero = (dirtySum == 0);
   1666    parentObj.FSubtract = true;
   1667  },
   1668  //CP D
   1669  //#0xBA:
   1670  function (parentObj) {
   1671    var dirtySum = parentObj.registerA - parentObj.registerD;
   1672    parentObj.FHalfCarry = ((dirtySum & 0xF) > (parentObj.registerA & 0xF));
   1673    parentObj.FCarry = (dirtySum < 0);
   1674    parentObj.FZero = (dirtySum == 0);
   1675    parentObj.FSubtract = true;
   1676  },
   1677  //CP E
   1678  //#0xBB:
   1679  function (parentObj) {
   1680    var dirtySum = parentObj.registerA - parentObj.registerE;
   1681    parentObj.FHalfCarry = ((dirtySum & 0xF) > (parentObj.registerA & 0xF));
   1682    parentObj.FCarry = (dirtySum < 0);
   1683    parentObj.FZero = (dirtySum == 0);
   1684    parentObj.FSubtract = true;
   1685  },
   1686  //CP H
   1687  //#0xBC:
   1688  function (parentObj) {
   1689    var dirtySum = parentObj.registerA - (parentObj.registersHL >> 8);
   1690    parentObj.FHalfCarry = ((dirtySum & 0xF) > (parentObj.registerA & 0xF));
   1691    parentObj.FCarry = (dirtySum < 0);
   1692    parentObj.FZero = (dirtySum == 0);
   1693    parentObj.FSubtract = true;
   1694  },
   1695  //CP L
   1696  //#0xBD:
   1697  function (parentObj) {
   1698    var dirtySum = parentObj.registerA - (parentObj.registersHL & 0xFF);
   1699    parentObj.FHalfCarry = ((dirtySum & 0xF) > (parentObj.registerA & 0xF));
   1700    parentObj.FCarry = (dirtySum < 0);
   1701    parentObj.FZero = (dirtySum == 0);
   1702    parentObj.FSubtract = true;
   1703  },
   1704  //CP (HL)
   1705  //#0xBE:
   1706  function (parentObj) {
   1707    var dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   1708    parentObj.FHalfCarry = ((dirtySum & 0xF) > (parentObj.registerA & 0xF));
   1709    parentObj.FCarry = (dirtySum < 0);
   1710    parentObj.FZero = (dirtySum == 0);
   1711    parentObj.FSubtract = true;
   1712  },
   1713  //CP A
   1714  //#0xBF:
   1715  function (parentObj) {
   1716    parentObj.FHalfCarry = parentObj.FCarry = false;
   1717    parentObj.FZero = parentObj.FSubtract = true;
   1718  },
   1719  //RET !FZ
   1720  //#0xC0:
   1721  function (parentObj) {
   1722    if (!parentObj.FZero) {
   1723      parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   1724      parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   1725      parentObj.CPUTicks += 12;
   1726    }
   1727  },
   1728  //POP BC
   1729  //#0xC1:
   1730  function (parentObj) {
   1731    parentObj.registerC = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   1732    parentObj.registerB = parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF);
   1733    parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   1734  },
   1735  //JP !FZ, nn
   1736  //#0xC2:
   1737  function (parentObj) {
   1738    if (!parentObj.FZero) {
   1739      parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1740      parentObj.CPUTicks += 4;
   1741    }
   1742    else {
   1743      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1744    }
   1745  },
   1746  //JP nn
   1747  //#0xC3:
   1748  function (parentObj) {
   1749    parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1750  },
   1751  //CALL !FZ, nn
   1752  //#0xC4:
   1753  function (parentObj) {
   1754    if (!parentObj.FZero) {
   1755      var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1756      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1757      parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1758      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   1759      parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1760      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   1761      parentObj.programCounter = temp_pc;
   1762      parentObj.CPUTicks += 12;
   1763    }
   1764    else {
   1765      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1766    }
   1767  },
   1768  //PUSH BC
   1769  //#0xC5:
   1770  function (parentObj) {
   1771    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1772    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerB);
   1773    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1774    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerC);
   1775  },
   1776  //ADD, n
   1777  //#0xC6:
   1778  function (parentObj) {
   1779    var dirtySum = parentObj.registerA + parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1780    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   1781    parentObj.FHalfCarry = ((dirtySum & 0xF) < (parentObj.registerA & 0xF));
   1782    parentObj.FCarry = (dirtySum > 0xFF);
   1783    parentObj.registerA = dirtySum & 0xFF;
   1784    parentObj.FZero = (parentObj.registerA == 0);
   1785    parentObj.FSubtract = false;
   1786  },
   1787  //RST 0
   1788  //#0xC7:
   1789  function (parentObj) {
   1790    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1791    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   1792    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1793    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   1794    parentObj.programCounter = 0;
   1795  },
   1796  //RET FZ
   1797  //#0xC8:
   1798  function (parentObj) {
   1799    if (parentObj.FZero) {
   1800      parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   1801      parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   1802      parentObj.CPUTicks += 12;
   1803    }
   1804  },
   1805  //RET
   1806  //#0xC9:
   1807  function (parentObj) {
   1808    parentObj.programCounter =  (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   1809    parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   1810  },
   1811  //JP FZ, nn
   1812  //#0xCA:
   1813  function (parentObj) {
   1814    if (parentObj.FZero) {
   1815      parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1816      parentObj.CPUTicks += 4;
   1817    }
   1818    else {
   1819      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1820    }
   1821  },
   1822  //Secondary OP Code Set:
   1823  //#0xCB:
   1824  function (parentObj) {
   1825    var opcode = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1826    //Increment the program counter to the next instruction:
   1827    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   1828    //Get how many CPU cycles the current 0xCBXX op code counts for:
   1829    parentObj.CPUTicks += parentObj.SecondaryTICKTable[opcode];
   1830    //Execute secondary OP codes for the 0xCB OP code call.
   1831    parentObj.CBOPCODE[opcode](parentObj);
   1832  },
   1833  //CALL FZ, nn
   1834  //#0xCC:
   1835  function (parentObj) {
   1836    if (parentObj.FZero) {
   1837      var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1838      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1839      parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1840      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   1841      parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1842      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   1843      parentObj.programCounter = temp_pc;
   1844      parentObj.CPUTicks += 12;
   1845    }
   1846    else {
   1847      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1848    }
   1849  },
   1850  //CALL nn
   1851  //#0xCD:
   1852  function (parentObj) {
   1853    var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1854    parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1855    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1856    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   1857    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1858    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   1859    parentObj.programCounter = temp_pc;
   1860  },
   1861  //ADC A, n
   1862  //#0xCE:
   1863  function (parentObj) {
   1864    var tempValue = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1865    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   1866    var dirtySum = parentObj.registerA + tempValue + ((parentObj.FCarry) ? 1 : 0);
   1867    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (tempValue & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
   1868    parentObj.FCarry = (dirtySum > 0xFF);
   1869    parentObj.registerA = dirtySum & 0xFF;
   1870    parentObj.FZero = (parentObj.registerA == 0);
   1871    parentObj.FSubtract = false;
   1872  },
   1873  //RST 0x8
   1874  //#0xCF:
   1875  function (parentObj) {
   1876    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1877    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   1878    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1879    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   1880    parentObj.programCounter = 0x8;
   1881  },
   1882  //RET !FC
   1883  //#0xD0:
   1884  function (parentObj) {
   1885    if (!parentObj.FCarry) {
   1886      parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   1887      parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   1888      parentObj.CPUTicks += 12;
   1889    }
   1890  },
   1891  //POP DE
   1892  //#0xD1:
   1893  function (parentObj) {
   1894    parentObj.registerE = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   1895    parentObj.registerD = parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF);
   1896    parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   1897  },
   1898  //JP !FC, nn
   1899  //#0xD2:
   1900  function (parentObj) {
   1901    if (!parentObj.FCarry) {
   1902      parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1903      parentObj.CPUTicks += 4;
   1904    }
   1905    else {
   1906      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1907    }
   1908  },
   1909  //0xD3 - Illegal
   1910  //#0xD3:
   1911  function (parentObj) {
   1912    cout("Illegal op code 0xD3 called, pausing emulation.", 2);
   1913    pause();
   1914  },
   1915  //CALL !FC, nn
   1916  //#0xD4:
   1917  function (parentObj) {
   1918    if (!parentObj.FCarry) {
   1919      var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1920      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1921      parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1922      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   1923      parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1924      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   1925      parentObj.programCounter = temp_pc;
   1926      parentObj.CPUTicks += 12;
   1927    }
   1928    else {
   1929      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1930    }
   1931  },
   1932  //PUSH DE
   1933  //#0xD5:
   1934  function (parentObj) {
   1935    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1936    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerD);
   1937    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1938    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerE);
   1939  },
   1940  //SUB A, n
   1941  //#0xD6:
   1942  function (parentObj) {
   1943    var dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1944    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   1945    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) < (dirtySum & 0xF));
   1946    parentObj.FCarry = (dirtySum < 0);
   1947    parentObj.registerA = dirtySum & 0xFF;
   1948    parentObj.FZero = (dirtySum == 0);
   1949    parentObj.FSubtract = true;
   1950  },
   1951  //RST 0x10
   1952  //#0xD7:
   1953  function (parentObj) {
   1954    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1955    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   1956    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   1957    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   1958    parentObj.programCounter = 0x10;
   1959  },
   1960  //RET FC
   1961  //#0xD8:
   1962  function (parentObj) {
   1963    if (parentObj.FCarry) {
   1964      parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   1965      parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   1966      parentObj.CPUTicks += 12;
   1967    }
   1968  },
   1969  //RETI
   1970  //#0xD9:
   1971  function (parentObj) {
   1972    parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   1973    parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   1974    //Immediate for HALT:
   1975    parentObj.IRQEnableDelay = (parentObj.IRQEnableDelay == 2 || parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) == 0x76) ? 1 : 2;
   1976  },
   1977  //JP FC, nn
   1978  //#0xDA:
   1979  function (parentObj) {
   1980    if (parentObj.FCarry) {
   1981      parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1982      parentObj.CPUTicks += 4;
   1983    }
   1984    else {
   1985      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   1986    }
   1987  },
   1988  //0xDB - Illegal
   1989  //#0xDB:
   1990  function (parentObj) {
   1991    cout("Illegal op code 0xDB called, pausing emulation.", 2);
   1992    pause();
   1993  },
   1994  //CALL FC, nn
   1995  //#0xDC:
   1996  function (parentObj) {
   1997    if (parentObj.FCarry) {
   1998      var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   1999      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   2000      parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2001      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   2002      parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2003      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   2004      parentObj.programCounter = temp_pc;
   2005      parentObj.CPUTicks += 12;
   2006    }
   2007    else {
   2008      parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   2009    }
   2010  },
   2011  //0xDD - Illegal
   2012  //#0xDD:
   2013  function (parentObj) {
   2014    cout("Illegal op code 0xDD called, pausing emulation.", 2);
   2015    pause();
   2016  },
   2017  //SBC A, n
   2018  //#0xDE:
   2019  function (parentObj) {
   2020    var temp_var = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   2021    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   2022    var dirtySum = parentObj.registerA - temp_var - ((parentObj.FCarry) ? 1 : 0);
   2023    parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (temp_var & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
   2024    parentObj.FCarry = (dirtySum < 0);
   2025    parentObj.registerA = dirtySum & 0xFF;
   2026    parentObj.FZero = (parentObj.registerA == 0);
   2027    parentObj.FSubtract = true;
   2028  },
   2029  //RST 0x18
   2030  //#0xDF:
   2031  function (parentObj) {
   2032    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2033    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   2034    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2035    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   2036    parentObj.programCounter = 0x18;
   2037  },
   2038  //LDH (n), A
   2039  //#0xE0:
   2040  function (parentObj) {
   2041    parentObj.memoryHighWrite(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter), parentObj.registerA);
   2042    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   2043  },
   2044  //POP HL
   2045  //#0xE1:
   2046  function (parentObj) {
   2047    parentObj.registersHL = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   2048    parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   2049  },
   2050  //LD (0xFF00 + C), A
   2051  //#0xE2:
   2052  function (parentObj) {
   2053    parentObj.memoryHighWriter[parentObj.registerC](parentObj, parentObj.registerC, parentObj.registerA);
   2054  },
   2055  //0xE3 - Illegal
   2056  //#0xE3:
   2057  function (parentObj) {
   2058    cout("Illegal op code 0xE3 called, pausing emulation.", 2);
   2059    pause();
   2060  },
   2061  //0xE4 - Illegal
   2062  //#0xE4:
   2063  function (parentObj) {
   2064    cout("Illegal op code 0xE4 called, pausing emulation.", 2);
   2065    pause();
   2066  },
   2067  //PUSH HL
   2068  //#0xE5:
   2069  function (parentObj) {
   2070    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2071    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registersHL >> 8);
   2072    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2073    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registersHL & 0xFF);
   2074  },
   2075  //AND n
   2076  //#0xE6:
   2077  function (parentObj) {
   2078    parentObj.registerA &= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   2079    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   2080    parentObj.FZero = (parentObj.registerA == 0);
   2081    parentObj.FHalfCarry = true;
   2082    parentObj.FSubtract = parentObj.FCarry = false;
   2083  },
   2084  //RST 0x20
   2085  //#0xE7:
   2086  function (parentObj) {
   2087    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2088    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   2089    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2090    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   2091    parentObj.programCounter = 0x20;
   2092  },
   2093  //ADD SP, n
   2094  //#0xE8:
   2095  function (parentObj) {
   2096    var temp_value2 = (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << 24) >> 24;
   2097    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   2098    var temp_value = (parentObj.stackPointer + temp_value2) & 0xFFFF;
   2099    temp_value2 = parentObj.stackPointer ^ temp_value2 ^ temp_value;
   2100    parentObj.stackPointer = temp_value;
   2101    parentObj.FCarry = ((temp_value2 & 0x100) == 0x100);
   2102    parentObj.FHalfCarry = ((temp_value2 & 0x10) == 0x10);
   2103    parentObj.FZero = parentObj.FSubtract = false;
   2104  },
   2105  //JP, (HL)
   2106  //#0xE9:
   2107  function (parentObj) {
   2108    parentObj.programCounter = parentObj.registersHL;
   2109  },
   2110  //LD n, A
   2111  //#0xEA:
   2112  function (parentObj) {
   2113    parentObj.memoryWrite((parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter), parentObj.registerA);
   2114    parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   2115  },
   2116  //0xEB - Illegal
   2117  //#0xEB:
   2118  function (parentObj) {
   2119    cout("Illegal op code 0xEB called, pausing emulation.", 2);
   2120    pause();
   2121  },
   2122  //0xEC - Illegal
   2123  //#0xEC:
   2124  function (parentObj) {
   2125    cout("Illegal op code 0xEC called, pausing emulation.", 2);
   2126    pause();
   2127  },
   2128  //0xED - Illegal
   2129  //#0xED:
   2130  function (parentObj) {
   2131    cout("Illegal op code 0xED called, pausing emulation.", 2);
   2132    pause();
   2133  },
   2134  //XOR n
   2135  //#0xEE:
   2136  function (parentObj) {
   2137    parentObj.registerA ^= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   2138    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   2139    parentObj.FZero = (parentObj.registerA == 0);
   2140    parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
   2141  },
   2142  //RST 0x28
   2143  //#0xEF:
   2144  function (parentObj) {
   2145    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2146    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   2147    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2148    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   2149    parentObj.programCounter = 0x28;
   2150  },
   2151  //LDH A, (n)
   2152  //#0xF0:
   2153  function (parentObj) {
   2154    parentObj.registerA = parentObj.memoryHighRead(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
   2155    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   2156  },
   2157  //POP AF
   2158  //#0xF1:
   2159  function (parentObj) {
   2160    var temp_var = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
   2161    parentObj.FZero = (temp_var > 0x7F);
   2162    parentObj.FSubtract = ((temp_var & 0x40) == 0x40);
   2163    parentObj.FHalfCarry = ((temp_var & 0x20) == 0x20);
   2164    parentObj.FCarry = ((temp_var & 0x10) == 0x10);
   2165    parentObj.registerA = parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF);
   2166    parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
   2167  },
   2168  //LD A, (0xFF00 + C)
   2169  //#0xF2:
   2170  function (parentObj) {
   2171    parentObj.registerA = parentObj.memoryHighReader[parentObj.registerC](parentObj, parentObj.registerC);
   2172  },
   2173  //DI
   2174  //#0xF3:
   2175  function (parentObj) {
   2176    parentObj.IME = false;
   2177    parentObj.IRQEnableDelay = 0;
   2178  },
   2179  //0xF4 - Illegal
   2180  //#0xF4:
   2181  function (parentObj) {
   2182    cout("Illegal op code 0xF4 called, pausing emulation.", 2);
   2183    pause();
   2184  },
   2185  //PUSH AF
   2186  //#0xF5:
   2187  function (parentObj) {
   2188    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2189    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerA);
   2190    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2191    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, ((parentObj.FZero) ? 0x80 : 0) | ((parentObj.FSubtract) ? 0x40 : 0) | ((parentObj.FHalfCarry) ? 0x20 : 0) | ((parentObj.FCarry) ? 0x10 : 0));
   2192  },
   2193  //OR n
   2194  //#0xF6:
   2195  function (parentObj) {
   2196    parentObj.registerA |= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   2197    parentObj.FZero = (parentObj.registerA == 0);
   2198    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   2199    parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
   2200  },
   2201  //RST 0x30
   2202  //#0xF7:
   2203  function (parentObj) {
   2204    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2205    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   2206    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2207    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   2208    parentObj.programCounter = 0x30;
   2209  },
   2210  //LDHL SP, n
   2211  //#0xF8:
   2212  function (parentObj) {
   2213    var temp_var = (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << 24) >> 24;
   2214    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   2215    parentObj.registersHL = (parentObj.stackPointer + temp_var) & 0xFFFF;
   2216    temp_var = parentObj.stackPointer ^ temp_var ^ parentObj.registersHL;
   2217    parentObj.FCarry = ((temp_var & 0x100) == 0x100);
   2218    parentObj.FHalfCarry = ((temp_var & 0x10) == 0x10);
   2219    parentObj.FZero = parentObj.FSubtract = false;
   2220  },
   2221  //LD SP, HL
   2222  //#0xF9:
   2223  function (parentObj) {
   2224    parentObj.stackPointer = parentObj.registersHL;
   2225  },
   2226  //LD A, (nn)
   2227  //#0xFA:
   2228  function (parentObj) {
   2229    parentObj.registerA = parentObj.memoryRead((parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
   2230    parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
   2231  },
   2232  //EI
   2233  //#0xFB:
   2234  function (parentObj) {
   2235    //Immediate for HALT:
   2236    parentObj.IRQEnableDelay = (parentObj.IRQEnableDelay == 2 || parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) == 0x76) ? 1 : 2;
   2237  },
   2238  //0xFC - Illegal
   2239  //#0xFC:
   2240  function (parentObj) {
   2241    cout("Illegal op code 0xFC called, pausing emulation.", 2);
   2242    pause();
   2243  },
   2244  //0xFD - Illegal
   2245  //#0xFD:
   2246  function (parentObj) {
   2247    cout("Illegal op code 0xFD called, pausing emulation.", 2);
   2248    pause();
   2249  },
   2250  //CP n
   2251  //#0xFE:
   2252  function (parentObj) {
   2253    var dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
   2254    parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
   2255    parentObj.FHalfCarry = ((dirtySum & 0xF) > (parentObj.registerA & 0xF));
   2256    parentObj.FCarry = (dirtySum < 0);
   2257    parentObj.FZero = (dirtySum == 0);
   2258    parentObj.FSubtract = true;
   2259  },
   2260  //RST 0x38
   2261  //#0xFF:
   2262  function (parentObj) {
   2263    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2264    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
   2265    parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
   2266    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
   2267    parentObj.programCounter = 0x38;
   2268  }
   2269 ];
   2270 GameBoyCore.prototype.CBOPCODE = [
   2271  //RLC B
   2272  //#0x00:
   2273  function (parentObj) {
   2274    parentObj.FCarry = (parentObj.registerB > 0x7F);
   2275    parentObj.registerB = ((parentObj.registerB << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2276    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2277    parentObj.FZero = (parentObj.registerB == 0);
   2278  }
   2279  //RLC C
   2280  //#0x01:
   2281  ,function (parentObj) {
   2282    parentObj.FCarry = (parentObj.registerC > 0x7F);
   2283    parentObj.registerC = ((parentObj.registerC << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2284    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2285    parentObj.FZero = (parentObj.registerC == 0);
   2286  }
   2287  //RLC D
   2288  //#0x02:
   2289  ,function (parentObj) {
   2290    parentObj.FCarry = (parentObj.registerD > 0x7F);
   2291    parentObj.registerD = ((parentObj.registerD << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2292    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2293    parentObj.FZero = (parentObj.registerD == 0);
   2294  }
   2295  //RLC E
   2296  //#0x03:
   2297  ,function (parentObj) {
   2298    parentObj.FCarry = (parentObj.registerE > 0x7F);
   2299    parentObj.registerE = ((parentObj.registerE << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2300    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2301    parentObj.FZero = (parentObj.registerE == 0);
   2302  }
   2303  //RLC H
   2304  //#0x04:
   2305  ,function (parentObj) {
   2306    parentObj.FCarry = (parentObj.registersHL > 0x7FFF);
   2307    parentObj.registersHL = ((parentObj.registersHL << 1) & 0xFE00) | ((parentObj.FCarry) ? 0x100 : 0) | (parentObj.registersHL & 0xFF);
   2308    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2309    parentObj.FZero = (parentObj.registersHL < 0x100);
   2310  }
   2311  //RLC L
   2312  //#0x05:
   2313  ,function (parentObj) {
   2314    parentObj.FCarry = ((parentObj.registersHL & 0x80) == 0x80);
   2315    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2316    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2317    parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0);
   2318  }
   2319  //RLC (HL)
   2320  //#0x06:
   2321  ,function (parentObj) {
   2322    var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   2323    parentObj.FCarry = (temp_var > 0x7F);
   2324    temp_var = ((temp_var << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2325    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var);
   2326    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2327    parentObj.FZero = (temp_var == 0);
   2328  }
   2329  //RLC A
   2330  //#0x07:
   2331  ,function (parentObj) {
   2332    parentObj.FCarry = (parentObj.registerA > 0x7F);
   2333    parentObj.registerA = ((parentObj.registerA << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2334    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2335    parentObj.FZero = (parentObj.registerA == 0);
   2336  }
   2337  //RRC B
   2338  //#0x08:
   2339  ,function (parentObj) {
   2340    parentObj.FCarry = ((parentObj.registerB & 0x01) == 0x01);
   2341    parentObj.registerB = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerB >> 1);
   2342    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2343    parentObj.FZero = (parentObj.registerB == 0);
   2344  }
   2345  //RRC C
   2346  //#0x09:
   2347  ,function (parentObj) {
   2348    parentObj.FCarry = ((parentObj.registerC & 0x01) == 0x01);
   2349    parentObj.registerC = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerC >> 1);
   2350    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2351    parentObj.FZero = (parentObj.registerC == 0);
   2352  }
   2353  //RRC D
   2354  //#0x0A:
   2355  ,function (parentObj) {
   2356    parentObj.FCarry = ((parentObj.registerD & 0x01) == 0x01);
   2357    parentObj.registerD = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerD >> 1);
   2358    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2359    parentObj.FZero = (parentObj.registerD == 0);
   2360  }
   2361  //RRC E
   2362  //#0x0B:
   2363  ,function (parentObj) {
   2364    parentObj.FCarry = ((parentObj.registerE & 0x01) == 0x01);
   2365    parentObj.registerE = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerE >> 1);
   2366    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2367    parentObj.FZero = (parentObj.registerE == 0);
   2368  }
   2369  //RRC H
   2370  //#0x0C:
   2371  ,function (parentObj) {
   2372    parentObj.FCarry = ((parentObj.registersHL & 0x0100) == 0x0100);
   2373    parentObj.registersHL = ((parentObj.FCarry) ? 0x8000 : 0) | ((parentObj.registersHL >> 1) & 0xFF00) | (parentObj.registersHL & 0xFF);
   2374    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2375    parentObj.FZero = (parentObj.registersHL < 0x100);
   2376  }
   2377  //RRC L
   2378  //#0x0D:
   2379  ,function (parentObj) {
   2380    parentObj.FCarry = ((parentObj.registersHL & 0x01) == 0x01);
   2381    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.FCarry) ? 0x80 : 0) | ((parentObj.registersHL & 0xFF) >> 1);
   2382    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2383    parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0);
   2384  }
   2385  //RRC (HL)
   2386  //#0x0E:
   2387  ,function (parentObj) {
   2388    var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   2389    parentObj.FCarry = ((temp_var & 0x01) == 0x01);
   2390    temp_var = ((parentObj.FCarry) ? 0x80 : 0) | (temp_var >> 1);
   2391    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var);
   2392    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2393    parentObj.FZero = (temp_var == 0);
   2394  }
   2395  //RRC A
   2396  //#0x0F:
   2397  ,function (parentObj) {
   2398    parentObj.FCarry = ((parentObj.registerA & 0x01) == 0x01);
   2399    parentObj.registerA = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerA >> 1);
   2400    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2401    parentObj.FZero = (parentObj.registerA == 0);
   2402  }
   2403  //RL B
   2404  //#0x10:
   2405  ,function (parentObj) {
   2406    var newFCarry = (parentObj.registerB > 0x7F);
   2407    parentObj.registerB = ((parentObj.registerB << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2408    parentObj.FCarry = newFCarry;
   2409    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2410    parentObj.FZero = (parentObj.registerB == 0);
   2411  }
   2412  //RL C
   2413  //#0x11:
   2414  ,function (parentObj) {
   2415    var newFCarry = (parentObj.registerC > 0x7F);
   2416    parentObj.registerC = ((parentObj.registerC << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2417    parentObj.FCarry = newFCarry;
   2418    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2419    parentObj.FZero = (parentObj.registerC == 0);
   2420  }
   2421  //RL D
   2422  //#0x12:
   2423  ,function (parentObj) {
   2424    var newFCarry = (parentObj.registerD > 0x7F);
   2425    parentObj.registerD = ((parentObj.registerD << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2426    parentObj.FCarry = newFCarry;
   2427    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2428    parentObj.FZero = (parentObj.registerD == 0);
   2429  }
   2430  //RL E
   2431  //#0x13:
   2432  ,function (parentObj) {
   2433    var newFCarry = (parentObj.registerE > 0x7F);
   2434    parentObj.registerE = ((parentObj.registerE << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2435    parentObj.FCarry = newFCarry;
   2436    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2437    parentObj.FZero = (parentObj.registerE == 0);
   2438  }
   2439  //RL H
   2440  //#0x14:
   2441  ,function (parentObj) {
   2442    var newFCarry = (parentObj.registersHL > 0x7FFF);
   2443    parentObj.registersHL = ((parentObj.registersHL << 1) & 0xFE00) | ((parentObj.FCarry) ? 0x100 : 0) | (parentObj.registersHL & 0xFF);
   2444    parentObj.FCarry = newFCarry;
   2445    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2446    parentObj.FZero = (parentObj.registersHL < 0x100);
   2447  }
   2448  //RL L
   2449  //#0x15:
   2450  ,function (parentObj) {
   2451    var newFCarry = ((parentObj.registersHL & 0x80) == 0x80);
   2452    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2453    parentObj.FCarry = newFCarry;
   2454    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2455    parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0);
   2456  }
   2457  //RL (HL)
   2458  //#0x16:
   2459  ,function (parentObj) {
   2460    var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   2461    var newFCarry = (temp_var > 0x7F);
   2462    temp_var = ((temp_var << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2463    parentObj.FCarry = newFCarry;
   2464    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var);
   2465    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2466    parentObj.FZero = (temp_var == 0);
   2467  }
   2468  //RL A
   2469  //#0x17:
   2470  ,function (parentObj) {
   2471    var newFCarry = (parentObj.registerA > 0x7F);
   2472    parentObj.registerA = ((parentObj.registerA << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
   2473    parentObj.FCarry = newFCarry;
   2474    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2475    parentObj.FZero = (parentObj.registerA == 0);
   2476  }
   2477  //RR B
   2478  //#0x18:
   2479  ,function (parentObj) {
   2480    var newFCarry = ((parentObj.registerB & 0x01) == 0x01);
   2481    parentObj.registerB = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerB >> 1);
   2482    parentObj.FCarry = newFCarry;
   2483    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2484    parentObj.FZero = (parentObj.registerB == 0);
   2485  }
   2486  //RR C
   2487  //#0x19:
   2488  ,function (parentObj) {
   2489    var newFCarry = ((parentObj.registerC & 0x01) == 0x01);
   2490    parentObj.registerC = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerC >> 1);
   2491    parentObj.FCarry = newFCarry;
   2492    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2493    parentObj.FZero = (parentObj.registerC == 0);
   2494  }
   2495  //RR D
   2496  //#0x1A:
   2497  ,function (parentObj) {
   2498    var newFCarry = ((parentObj.registerD & 0x01) == 0x01);
   2499    parentObj.registerD = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerD >> 1);
   2500    parentObj.FCarry = newFCarry;
   2501    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2502    parentObj.FZero = (parentObj.registerD == 0);
   2503  }
   2504  //RR E
   2505  //#0x1B:
   2506  ,function (parentObj) {
   2507    var newFCarry = ((parentObj.registerE & 0x01) == 0x01);
   2508    parentObj.registerE = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerE >> 1);
   2509    parentObj.FCarry = newFCarry;
   2510    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2511    parentObj.FZero = (parentObj.registerE == 0);
   2512  }
   2513  //RR H
   2514  //#0x1C:
   2515  ,function (parentObj) {
   2516    var newFCarry = ((parentObj.registersHL & 0x0100) == 0x0100);
   2517    parentObj.registersHL = ((parentObj.FCarry) ? 0x8000 : 0) | ((parentObj.registersHL >> 1) & 0xFF00) | (parentObj.registersHL & 0xFF);
   2518    parentObj.FCarry = newFCarry;
   2519    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2520    parentObj.FZero = (parentObj.registersHL < 0x100);
   2521  }
   2522  //RR L
   2523  //#0x1D:
   2524  ,function (parentObj) {
   2525    var newFCarry = ((parentObj.registersHL & 0x01) == 0x01);
   2526    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.FCarry) ? 0x80 : 0) | ((parentObj.registersHL & 0xFF) >> 1);
   2527    parentObj.FCarry = newFCarry;
   2528    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2529    parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0);
   2530  }
   2531  //RR (HL)
   2532  //#0x1E:
   2533  ,function (parentObj) {
   2534    var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   2535    var newFCarry = ((temp_var & 0x01) == 0x01);
   2536    temp_var = ((parentObj.FCarry) ? 0x80 : 0) | (temp_var >> 1);
   2537    parentObj.FCarry = newFCarry;
   2538    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var);
   2539    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2540    parentObj.FZero = (temp_var == 0);
   2541  }
   2542  //RR A
   2543  //#0x1F:
   2544  ,function (parentObj) {
   2545    var newFCarry = ((parentObj.registerA & 0x01) == 0x01);
   2546    parentObj.registerA = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerA >> 1);
   2547    parentObj.FCarry = newFCarry;
   2548    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2549    parentObj.FZero = (parentObj.registerA == 0);
   2550  }
   2551  //SLA B
   2552  //#0x20:
   2553  ,function (parentObj) {
   2554    parentObj.FCarry = (parentObj.registerB > 0x7F);
   2555    parentObj.registerB = (parentObj.registerB << 1) & 0xFF;
   2556    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2557    parentObj.FZero = (parentObj.registerB == 0);
   2558  }
   2559  //SLA C
   2560  //#0x21:
   2561  ,function (parentObj) {
   2562    parentObj.FCarry = (parentObj.registerC > 0x7F);
   2563    parentObj.registerC = (parentObj.registerC << 1) & 0xFF;
   2564    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2565    parentObj.FZero = (parentObj.registerC == 0);
   2566  }
   2567  //SLA D
   2568  //#0x22:
   2569  ,function (parentObj) {
   2570    parentObj.FCarry = (parentObj.registerD > 0x7F);
   2571    parentObj.registerD = (parentObj.registerD << 1) & 0xFF;
   2572    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2573    parentObj.FZero = (parentObj.registerD == 0);
   2574  }
   2575  //SLA E
   2576  //#0x23:
   2577  ,function (parentObj) {
   2578    parentObj.FCarry = (parentObj.registerE > 0x7F);
   2579    parentObj.registerE = (parentObj.registerE << 1) & 0xFF;
   2580    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2581    parentObj.FZero = (parentObj.registerE == 0);
   2582  }
   2583  //SLA H
   2584  //#0x24:
   2585  ,function (parentObj) {
   2586    parentObj.FCarry = (parentObj.registersHL > 0x7FFF);
   2587    parentObj.registersHL = ((parentObj.registersHL << 1) & 0xFE00) | (parentObj.registersHL & 0xFF);
   2588    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2589    parentObj.FZero = (parentObj.registersHL < 0x100);
   2590  }
   2591  //SLA L
   2592  //#0x25:
   2593  ,function (parentObj) {
   2594    parentObj.FCarry = ((parentObj.registersHL & 0x0080) == 0x0080);
   2595    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL << 1) & 0xFF);
   2596    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2597    parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0);
   2598  }
   2599  //SLA (HL)
   2600  //#0x26:
   2601  ,function (parentObj) {
   2602    var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   2603    parentObj.FCarry = (temp_var > 0x7F);
   2604    temp_var = (temp_var << 1) & 0xFF;
   2605    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var);
   2606    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2607    parentObj.FZero = (temp_var == 0);
   2608  }
   2609  //SLA A
   2610  //#0x27:
   2611  ,function (parentObj) {
   2612    parentObj.FCarry = (parentObj.registerA > 0x7F);
   2613    parentObj.registerA = (parentObj.registerA << 1) & 0xFF;
   2614    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2615    parentObj.FZero = (parentObj.registerA == 0);
   2616  }
   2617  //SRA B
   2618  //#0x28:
   2619  ,function (parentObj) {
   2620    parentObj.FCarry = ((parentObj.registerB & 0x01) == 0x01);
   2621    parentObj.registerB = (parentObj.registerB & 0x80) | (parentObj.registerB >> 1);
   2622    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2623    parentObj.FZero = (parentObj.registerB == 0);
   2624  }
   2625  //SRA C
   2626  //#0x29:
   2627  ,function (parentObj) {
   2628    parentObj.FCarry = ((parentObj.registerC & 0x01) == 0x01);
   2629    parentObj.registerC = (parentObj.registerC & 0x80) | (parentObj.registerC >> 1);
   2630    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2631    parentObj.FZero = (parentObj.registerC == 0);
   2632  }
   2633  //SRA D
   2634  //#0x2A:
   2635  ,function (parentObj) {
   2636    parentObj.FCarry = ((parentObj.registerD & 0x01) == 0x01);
   2637    parentObj.registerD = (parentObj.registerD & 0x80) | (parentObj.registerD >> 1);
   2638    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2639    parentObj.FZero = (parentObj.registerD == 0);
   2640  }
   2641  //SRA E
   2642  //#0x2B:
   2643  ,function (parentObj) {
   2644    parentObj.FCarry = ((parentObj.registerE & 0x01) == 0x01);
   2645    parentObj.registerE = (parentObj.registerE & 0x80) | (parentObj.registerE >> 1);
   2646    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2647    parentObj.FZero = (parentObj.registerE == 0);
   2648  }
   2649  //SRA H
   2650  //#0x2C:
   2651  ,function (parentObj) {
   2652    parentObj.FCarry = ((parentObj.registersHL & 0x0100) == 0x0100);
   2653    parentObj.registersHL = ((parentObj.registersHL >> 1) & 0xFF00) | (parentObj.registersHL & 0x80FF);
   2654    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2655    parentObj.FZero = (parentObj.registersHL < 0x100);
   2656  }
   2657  //SRA L
   2658  //#0x2D:
   2659  ,function (parentObj) {
   2660    parentObj.FCarry = ((parentObj.registersHL & 0x0001) == 0x0001);
   2661    parentObj.registersHL = (parentObj.registersHL & 0xFF80) | ((parentObj.registersHL & 0xFF) >> 1);
   2662    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2663    parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0);
   2664  }
   2665  //SRA (HL)
   2666  //#0x2E:
   2667  ,function (parentObj) {
   2668    var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   2669    parentObj.FCarry = ((temp_var & 0x01) == 0x01);
   2670    temp_var = (temp_var & 0x80) | (temp_var >> 1);
   2671    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var);
   2672    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2673    parentObj.FZero = (temp_var == 0);
   2674  }
   2675  //SRA A
   2676  //#0x2F:
   2677  ,function (parentObj) {
   2678    parentObj.FCarry = ((parentObj.registerA & 0x01) == 0x01);
   2679    parentObj.registerA = (parentObj.registerA & 0x80) | (parentObj.registerA >> 1);
   2680    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2681    parentObj.FZero = (parentObj.registerA == 0);
   2682  }
   2683  //SWAP B
   2684  //#0x30:
   2685  ,function (parentObj) {
   2686    parentObj.registerB = ((parentObj.registerB & 0xF) << 4) | (parentObj.registerB >> 4);
   2687    parentObj.FZero = (parentObj.registerB == 0);
   2688    parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
   2689  }
   2690  //SWAP C
   2691  //#0x31:
   2692  ,function (parentObj) {
   2693    parentObj.registerC = ((parentObj.registerC & 0xF) << 4) | (parentObj.registerC >> 4);
   2694    parentObj.FZero = (parentObj.registerC == 0);
   2695    parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
   2696  }
   2697  //SWAP D
   2698  //#0x32:
   2699  ,function (parentObj) {
   2700    parentObj.registerD = ((parentObj.registerD & 0xF) << 4) | (parentObj.registerD >> 4);
   2701    parentObj.FZero = (parentObj.registerD == 0);
   2702    parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
   2703  }
   2704  //SWAP E
   2705  //#0x33:
   2706  ,function (parentObj) {
   2707    parentObj.registerE = ((parentObj.registerE & 0xF) << 4) | (parentObj.registerE >> 4);
   2708    parentObj.FZero = (parentObj.registerE == 0);
   2709    parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
   2710  }
   2711  //SWAP H
   2712  //#0x34:
   2713  ,function (parentObj) {
   2714    parentObj.registersHL = ((parentObj.registersHL & 0xF00) << 4) | ((parentObj.registersHL & 0xF000) >> 4) | (parentObj.registersHL & 0xFF);
   2715    parentObj.FZero = (parentObj.registersHL < 0x100);
   2716    parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
   2717  }
   2718  //SWAP L
   2719  //#0x35:
   2720  ,function (parentObj) {
   2721    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL & 0xF) << 4) | ((parentObj.registersHL & 0xF0) >> 4);
   2722    parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0);
   2723    parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
   2724  }
   2725  //SWAP (HL)
   2726  //#0x36:
   2727  ,function (parentObj) {
   2728    var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   2729    temp_var = ((temp_var & 0xF) << 4) | (temp_var >> 4);
   2730    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var);
   2731    parentObj.FZero = (temp_var == 0);
   2732    parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
   2733  }
   2734  //SWAP A
   2735  //#0x37:
   2736  ,function (parentObj) {
   2737    parentObj.registerA = ((parentObj.registerA & 0xF) << 4) | (parentObj.registerA >> 4);
   2738    parentObj.FZero = (parentObj.registerA == 0);
   2739    parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
   2740  }
   2741  //SRL B
   2742  //#0x38:
   2743  ,function (parentObj) {
   2744    parentObj.FCarry = ((parentObj.registerB & 0x01) == 0x01);
   2745    parentObj.registerB >>= 1;
   2746    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2747    parentObj.FZero = (parentObj.registerB == 0);
   2748  }
   2749  //SRL C
   2750  //#0x39:
   2751  ,function (parentObj) {
   2752    parentObj.FCarry = ((parentObj.registerC & 0x01) == 0x01);
   2753    parentObj.registerC >>= 1;
   2754    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2755    parentObj.FZero = (parentObj.registerC == 0);
   2756  }
   2757  //SRL D
   2758  //#0x3A:
   2759  ,function (parentObj) {
   2760    parentObj.FCarry = ((parentObj.registerD & 0x01) == 0x01);
   2761    parentObj.registerD >>= 1;
   2762    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2763    parentObj.FZero = (parentObj.registerD == 0);
   2764  }
   2765  //SRL E
   2766  //#0x3B:
   2767  ,function (parentObj) {
   2768    parentObj.FCarry = ((parentObj.registerE & 0x01) == 0x01);
   2769    parentObj.registerE >>= 1;
   2770    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2771    parentObj.FZero = (parentObj.registerE == 0);
   2772  }
   2773  //SRL H
   2774  //#0x3C:
   2775  ,function (parentObj) {
   2776    parentObj.FCarry = ((parentObj.registersHL & 0x0100) == 0x0100);
   2777    parentObj.registersHL = ((parentObj.registersHL >> 1) & 0xFF00) | (parentObj.registersHL & 0xFF);
   2778    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2779    parentObj.FZero = (parentObj.registersHL < 0x100);
   2780  }
   2781  //SRL L
   2782  //#0x3D:
   2783  ,function (parentObj) {
   2784    parentObj.FCarry = ((parentObj.registersHL & 0x0001) == 0x0001);
   2785    parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL & 0xFF) >> 1);
   2786    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2787    parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0);
   2788  }
   2789  //SRL (HL)
   2790  //#0x3E:
   2791  ,function (parentObj) {
   2792    var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
   2793    parentObj.FCarry = ((temp_var & 0x01) == 0x01);
   2794    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, temp_var >> 1);
   2795    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2796    parentObj.FZero = (temp_var < 2);
   2797  }
   2798  //SRL A
   2799  //#0x3F:
   2800  ,function (parentObj) {
   2801    parentObj.FCarry = ((parentObj.registerA & 0x01) == 0x01);
   2802    parentObj.registerA >>= 1;
   2803    parentObj.FHalfCarry = parentObj.FSubtract = false;
   2804    parentObj.FZero = (parentObj.registerA == 0);
   2805  }
   2806  //BIT 0, B
   2807  //#0x40:
   2808  ,function (parentObj) {
   2809    parentObj.FHalfCarry = true;
   2810    parentObj.FSubtract = false;
   2811    parentObj.FZero = ((parentObj.registerB & 0x01) == 0);
   2812  }
   2813  //BIT 0, C
   2814  //#0x41:
   2815  ,function (parentObj) {
   2816    parentObj.FHalfCarry = true;
   2817    parentObj.FSubtract = false;
   2818    parentObj.FZero = ((parentObj.registerC & 0x01) == 0);
   2819  }
   2820  //BIT 0, D
   2821  //#0x42:
   2822  ,function (parentObj) {
   2823    parentObj.FHalfCarry = true;
   2824    parentObj.FSubtract = false;
   2825    parentObj.FZero = ((parentObj.registerD & 0x01) == 0);
   2826  }
   2827  //BIT 0, E
   2828  //#0x43:
   2829  ,function (parentObj) {
   2830    parentObj.FHalfCarry = true;
   2831    parentObj.FSubtract = false;
   2832    parentObj.FZero = ((parentObj.registerE & 0x01) == 0);
   2833  }
   2834  //BIT 0, H
   2835  //#0x44:
   2836  ,function (parentObj) {
   2837    parentObj.FHalfCarry = true;
   2838    parentObj.FSubtract = false;
   2839    parentObj.FZero = ((parentObj.registersHL & 0x0100) == 0);
   2840  }
   2841  //BIT 0, L
   2842  //#0x45:
   2843  ,function (parentObj) {
   2844    parentObj.FHalfCarry = true;
   2845    parentObj.FSubtract = false;
   2846    parentObj.FZero = ((parentObj.registersHL & 0x0001) == 0);
   2847  }
   2848  //BIT 0, (HL)
   2849  //#0x46:
   2850  ,function (parentObj) {
   2851    parentObj.FHalfCarry = true;
   2852    parentObj.FSubtract = false;
   2853    parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x01) == 0);
   2854  }
   2855  //BIT 0, A
   2856  //#0x47:
   2857  ,function (parentObj) {
   2858    parentObj.FHalfCarry = true;
   2859    parentObj.FSubtract = false;
   2860    parentObj.FZero = ((parentObj.registerA & 0x01) == 0);
   2861  }
   2862  //BIT 1, B
   2863  //#0x48:
   2864  ,function (parentObj) {
   2865    parentObj.FHalfCarry = true;
   2866    parentObj.FSubtract = false;
   2867    parentObj.FZero = ((parentObj.registerB & 0x02) == 0);
   2868  }
   2869  //BIT 1, C
   2870  //#0x49:
   2871  ,function (parentObj) {
   2872    parentObj.FHalfCarry = true;
   2873    parentObj.FSubtract = false;
   2874    parentObj.FZero = ((parentObj.registerC & 0x02) == 0);
   2875  }
   2876  //BIT 1, D
   2877  //#0x4A:
   2878  ,function (parentObj) {
   2879    parentObj.FHalfCarry = true;
   2880    parentObj.FSubtract = false;
   2881    parentObj.FZero = ((parentObj.registerD & 0x02) == 0);
   2882  }
   2883  //BIT 1, E
   2884  //#0x4B:
   2885  ,function (parentObj) {
   2886    parentObj.FHalfCarry = true;
   2887    parentObj.FSubtract = false;
   2888    parentObj.FZero = ((parentObj.registerE & 0x02) == 0);
   2889  }
   2890  //BIT 1, H
   2891  //#0x4C:
   2892  ,function (parentObj) {
   2893    parentObj.FHalfCarry = true;
   2894    parentObj.FSubtract = false;
   2895    parentObj.FZero = ((parentObj.registersHL & 0x0200) == 0);
   2896  }
   2897  //BIT 1, L
   2898  //#0x4D:
   2899  ,function (parentObj) {
   2900    parentObj.FHalfCarry = true;
   2901    parentObj.FSubtract = false;
   2902    parentObj.FZero = ((parentObj.registersHL & 0x0002) == 0);
   2903  }
   2904  //BIT 1, (HL)
   2905  //#0x4E:
   2906  ,function (parentObj) {
   2907    parentObj.FHalfCarry = true;
   2908    parentObj.FSubtract = false;
   2909    parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x02) == 0);
   2910  }
   2911  //BIT 1, A
   2912  //#0x4F:
   2913  ,function (parentObj) {
   2914    parentObj.FHalfCarry = true;
   2915    parentObj.FSubtract = false;
   2916    parentObj.FZero = ((parentObj.registerA & 0x02) == 0);
   2917  }
   2918  //BIT 2, B
   2919  //#0x50:
   2920  ,function (parentObj) {
   2921    parentObj.FHalfCarry = true;
   2922    parentObj.FSubtract = false;
   2923    parentObj.FZero = ((parentObj.registerB & 0x04) == 0);
   2924  }
   2925  //BIT 2, C
   2926  //#0x51:
   2927  ,function (parentObj) {
   2928    parentObj.FHalfCarry = true;
   2929    parentObj.FSubtract = false;
   2930    parentObj.FZero = ((parentObj.registerC & 0x04) == 0);
   2931  }
   2932  //BIT 2, D
   2933  //#0x52:
   2934  ,function (parentObj) {
   2935    parentObj.FHalfCarry = true;
   2936    parentObj.FSubtract = false;
   2937    parentObj.FZero = ((parentObj.registerD & 0x04) == 0);
   2938  }
   2939  //BIT 2, E
   2940  //#0x53:
   2941  ,function (parentObj) {
   2942    parentObj.FHalfCarry = true;
   2943    parentObj.FSubtract = false;
   2944    parentObj.FZero = ((parentObj.registerE & 0x04) == 0);
   2945  }
   2946  //BIT 2, H
   2947  //#0x54:
   2948  ,function (parentObj) {
   2949    parentObj.FHalfCarry = true;
   2950    parentObj.FSubtract = false;
   2951    parentObj.FZero = ((parentObj.registersHL & 0x0400) == 0);
   2952  }
   2953  //BIT 2, L
   2954  //#0x55:
   2955  ,function (parentObj) {
   2956    parentObj.FHalfCarry = true;
   2957    parentObj.FSubtract = false;
   2958    parentObj.FZero = ((parentObj.registersHL & 0x0004) == 0);
   2959  }
   2960  //BIT 2, (HL)
   2961  //#0x56:
   2962  ,function (parentObj) {
   2963    parentObj.FHalfCarry = true;
   2964    parentObj.FSubtract = false;
   2965    parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x04) == 0);
   2966  }
   2967  //BIT 2, A
   2968  //#0x57:
   2969  ,function (parentObj) {
   2970    parentObj.FHalfCarry = true;
   2971    parentObj.FSubtract = false;
   2972    parentObj.FZero = ((parentObj.registerA & 0x04) == 0);
   2973  }
   2974  //BIT 3, B
   2975  //#0x58:
   2976  ,function (parentObj) {
   2977    parentObj.FHalfCarry = true;
   2978    parentObj.FSubtract = false;
   2979    parentObj.FZero = ((parentObj.registerB & 0x08) == 0);
   2980  }
   2981  //BIT 3, C
   2982  //#0x59:
   2983  ,function (parentObj) {
   2984    parentObj.FHalfCarry = true;
   2985    parentObj.FSubtract = false;
   2986    parentObj.FZero = ((parentObj.registerC & 0x08) == 0);
   2987  }
   2988  //BIT 3, D
   2989  //#0x5A:
   2990  ,function (parentObj) {
   2991    parentObj.FHalfCarry = true;
   2992    parentObj.FSubtract = false;
   2993    parentObj.FZero = ((parentObj.registerD & 0x08) == 0);
   2994  }
   2995  //BIT 3, E
   2996  //#0x5B:
   2997  ,function (parentObj) {
   2998    parentObj.FHalfCarry = true;
   2999    parentObj.FSubtract = false;
   3000    parentObj.FZero = ((parentObj.registerE & 0x08) == 0);
   3001  }
   3002  //BIT 3, H
   3003  //#0x5C:
   3004  ,function (parentObj) {
   3005    parentObj.FHalfCarry = true;
   3006    parentObj.FSubtract = false;
   3007    parentObj.FZero = ((parentObj.registersHL & 0x0800) == 0);
   3008  }
   3009  //BIT 3, L
   3010  //#0x5D:
   3011  ,function (parentObj) {
   3012    parentObj.FHalfCarry = true;
   3013    parentObj.FSubtract = false;
   3014    parentObj.FZero = ((parentObj.registersHL & 0x0008) == 0);
   3015  }
   3016  //BIT 3, (HL)
   3017  //#0x5E:
   3018  ,function (parentObj) {
   3019    parentObj.FHalfCarry = true;
   3020    parentObj.FSubtract = false;
   3021    parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x08) == 0);
   3022  }
   3023  //BIT 3, A
   3024  //#0x5F:
   3025  ,function (parentObj) {
   3026    parentObj.FHalfCarry = true;
   3027    parentObj.FSubtract = false;
   3028    parentObj.FZero = ((parentObj.registerA & 0x08) == 0);
   3029  }
   3030  //BIT 4, B
   3031  //#0x60:
   3032  ,function (parentObj) {
   3033    parentObj.FHalfCarry = true;
   3034    parentObj.FSubtract = false;
   3035    parentObj.FZero = ((parentObj.registerB & 0x10) == 0);
   3036  }
   3037  //BIT 4, C
   3038  //#0x61:
   3039  ,function (parentObj) {
   3040    parentObj.FHalfCarry = true;
   3041    parentObj.FSubtract = false;
   3042    parentObj.FZero = ((parentObj.registerC & 0x10) == 0);
   3043  }
   3044  //BIT 4, D
   3045  //#0x62:
   3046  ,function (parentObj) {
   3047    parentObj.FHalfCarry = true;
   3048    parentObj.FSubtract = false;
   3049    parentObj.FZero = ((parentObj.registerD & 0x10) == 0);
   3050  }
   3051  //BIT 4, E
   3052  //#0x63:
   3053  ,function (parentObj) {
   3054    parentObj.FHalfCarry = true;
   3055    parentObj.FSubtract = false;
   3056    parentObj.FZero = ((parentObj.registerE & 0x10) == 0);
   3057  }
   3058  //BIT 4, H
   3059  //#0x64:
   3060  ,function (parentObj) {
   3061    parentObj.FHalfCarry = true;
   3062    parentObj.FSubtract = false;
   3063    parentObj.FZero = ((parentObj.registersHL & 0x1000) == 0);
   3064  }
   3065  //BIT 4, L
   3066  //#0x65:
   3067  ,function (parentObj) {
   3068    parentObj.FHalfCarry = true;
   3069    parentObj.FSubtract = false;
   3070    parentObj.FZero = ((parentObj.registersHL & 0x0010) == 0);
   3071  }
   3072  //BIT 4, (HL)
   3073  //#0x66:
   3074  ,function (parentObj) {
   3075    parentObj.FHalfCarry = true;
   3076    parentObj.FSubtract = false;
   3077    parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x10) == 0);
   3078  }
   3079  //BIT 4, A
   3080  //#0x67:
   3081  ,function (parentObj) {
   3082    parentObj.FHalfCarry = true;
   3083    parentObj.FSubtract = false;
   3084    parentObj.FZero = ((parentObj.registerA & 0x10) == 0);
   3085  }
   3086  //BIT 5, B
   3087  //#0x68:
   3088  ,function (parentObj) {
   3089    parentObj.FHalfCarry = true;
   3090    parentObj.FSubtract = false;
   3091    parentObj.FZero = ((parentObj.registerB & 0x20) == 0);
   3092  }
   3093  //BIT 5, C
   3094  //#0x69:
   3095  ,function (parentObj) {
   3096    parentObj.FHalfCarry = true;
   3097    parentObj.FSubtract = false;
   3098    parentObj.FZero = ((parentObj.registerC & 0x20) == 0);
   3099  }
   3100  //BIT 5, D
   3101  //#0x6A:
   3102  ,function (parentObj) {
   3103    parentObj.FHalfCarry = true;
   3104    parentObj.FSubtract = false;
   3105    parentObj.FZero = ((parentObj.registerD & 0x20) == 0);
   3106  }
   3107  //BIT 5, E
   3108  //#0x6B:
   3109  ,function (parentObj) {
   3110    parentObj.FHalfCarry = true;
   3111    parentObj.FSubtract = false;
   3112    parentObj.FZero = ((parentObj.registerE & 0x20) == 0);
   3113  }
   3114  //BIT 5, H
   3115  //#0x6C:
   3116  ,function (parentObj) {
   3117    parentObj.FHalfCarry = true;
   3118    parentObj.FSubtract = false;
   3119    parentObj.FZero = ((parentObj.registersHL & 0x2000) == 0);
   3120  }
   3121  //BIT 5, L
   3122  //#0x6D:
   3123  ,function (parentObj) {
   3124    parentObj.FHalfCarry = true;
   3125    parentObj.FSubtract = false;
   3126    parentObj.FZero = ((parentObj.registersHL & 0x0020) == 0);
   3127  }
   3128  //BIT 5, (HL)
   3129  //#0x6E:
   3130  ,function (parentObj) {
   3131    parentObj.FHalfCarry = true;
   3132    parentObj.FSubtract = false;
   3133    parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x20) == 0);
   3134  }
   3135  //BIT 5, A
   3136  //#0x6F:
   3137  ,function (parentObj) {
   3138    parentObj.FHalfCarry = true;
   3139    parentObj.FSubtract = false;
   3140    parentObj.FZero = ((parentObj.registerA & 0x20) == 0);
   3141  }
   3142  //BIT 6, B
   3143  //#0x70:
   3144  ,function (parentObj) {
   3145    parentObj.FHalfCarry = true;
   3146    parentObj.FSubtract = false;
   3147    parentObj.FZero = ((parentObj.registerB & 0x40) == 0);
   3148  }
   3149  //BIT 6, C
   3150  //#0x71:
   3151  ,function (parentObj) {
   3152    parentObj.FHalfCarry = true;
   3153    parentObj.FSubtract = false;
   3154    parentObj.FZero = ((parentObj.registerC & 0x40) == 0);
   3155  }
   3156  //BIT 6, D
   3157  //#0x72:
   3158  ,function (parentObj) {
   3159    parentObj.FHalfCarry = true;
   3160    parentObj.FSubtract = false;
   3161    parentObj.FZero = ((parentObj.registerD & 0x40) == 0);
   3162  }
   3163  //BIT 6, E
   3164  //#0x73:
   3165  ,function (parentObj) {
   3166    parentObj.FHalfCarry = true;
   3167    parentObj.FSubtract = false;
   3168    parentObj.FZero = ((parentObj.registerE & 0x40) == 0);
   3169  }
   3170  //BIT 6, H
   3171  //#0x74:
   3172  ,function (parentObj) {
   3173    parentObj.FHalfCarry = true;
   3174    parentObj.FSubtract = false;
   3175    parentObj.FZero = ((parentObj.registersHL & 0x4000) == 0);
   3176  }
   3177  //BIT 6, L
   3178  //#0x75:
   3179  ,function (parentObj) {
   3180    parentObj.FHalfCarry = true;
   3181    parentObj.FSubtract = false;
   3182    parentObj.FZero = ((parentObj.registersHL & 0x0040) == 0);
   3183  }
   3184  //BIT 6, (HL)
   3185  //#0x76:
   3186  ,function (parentObj) {
   3187    parentObj.FHalfCarry = true;
   3188    parentObj.FSubtract = false;
   3189    parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x40) == 0);
   3190  }
   3191  //BIT 6, A
   3192  //#0x77:
   3193  ,function (parentObj) {
   3194    parentObj.FHalfCarry = true;
   3195    parentObj.FSubtract = false;
   3196    parentObj.FZero = ((parentObj.registerA & 0x40) == 0);
   3197  }
   3198  //BIT 7, B
   3199  //#0x78:
   3200  ,function (parentObj) {
   3201    parentObj.FHalfCarry = true;
   3202    parentObj.FSubtract = false;
   3203    parentObj.FZero = ((parentObj.registerB & 0x80) == 0);
   3204  }
   3205  //BIT 7, C
   3206  //#0x79:
   3207  ,function (parentObj) {
   3208    parentObj.FHalfCarry = true;
   3209    parentObj.FSubtract = false;
   3210    parentObj.FZero = ((parentObj.registerC & 0x80) == 0);
   3211  }
   3212  //BIT 7, D
   3213  //#0x7A:
   3214  ,function (parentObj) {
   3215    parentObj.FHalfCarry = true;
   3216    parentObj.FSubtract = false;
   3217    parentObj.FZero = ((parentObj.registerD & 0x80) == 0);
   3218  }
   3219  //BIT 7, E
   3220  //#0x7B:
   3221  ,function (parentObj) {
   3222    parentObj.FHalfCarry = true;
   3223    parentObj.FSubtract = false;
   3224    parentObj.FZero = ((parentObj.registerE & 0x80) == 0);
   3225  }
   3226  //BIT 7, H
   3227  //#0x7C:
   3228  ,function (parentObj) {
   3229    parentObj.FHalfCarry = true;
   3230    parentObj.FSubtract = false;
   3231    parentObj.FZero = ((parentObj.registersHL & 0x8000) == 0);
   3232  }
   3233  //BIT 7, L
   3234  //#0x7D:
   3235  ,function (parentObj) {
   3236    parentObj.FHalfCarry = true;
   3237    parentObj.FSubtract = false;
   3238    parentObj.FZero = ((parentObj.registersHL & 0x0080) == 0);
   3239  }
   3240  //BIT 7, (HL)
   3241  //#0x7E:
   3242  ,function (parentObj) {
   3243    parentObj.FHalfCarry = true;
   3244    parentObj.FSubtract = false;
   3245    parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x80) == 0);
   3246  }
   3247  //BIT 7, A
   3248  //#0x7F:
   3249  ,function (parentObj) {
   3250    parentObj.FHalfCarry = true;
   3251    parentObj.FSubtract = false;
   3252    parentObj.FZero = ((parentObj.registerA & 0x80) == 0);
   3253  }
   3254  //RES 0, B
   3255  //#0x80:
   3256  ,function (parentObj) {
   3257    parentObj.registerB &= 0xFE;
   3258  }
   3259  //RES 0, C
   3260  //#0x81:
   3261  ,function (parentObj) {
   3262    parentObj.registerC &= 0xFE;
   3263  }
   3264  //RES 0, D
   3265  //#0x82:
   3266  ,function (parentObj) {
   3267    parentObj.registerD &= 0xFE;
   3268  }
   3269  //RES 0, E
   3270  //#0x83:
   3271  ,function (parentObj) {
   3272    parentObj.registerE &= 0xFE;
   3273  }
   3274  //RES 0, H
   3275  //#0x84:
   3276  ,function (parentObj) {
   3277    parentObj.registersHL &= 0xFEFF;
   3278  }
   3279  //RES 0, L
   3280  //#0x85:
   3281  ,function (parentObj) {
   3282    parentObj.registersHL &= 0xFFFE;
   3283  }
   3284  //RES 0, (HL)
   3285  //#0x86:
   3286  ,function (parentObj) {
   3287    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xFE);
   3288  }
   3289  //RES 0, A
   3290  //#0x87:
   3291  ,function (parentObj) {
   3292    parentObj.registerA &= 0xFE;
   3293  }
   3294  //RES 1, B
   3295  //#0x88:
   3296  ,function (parentObj) {
   3297    parentObj.registerB &= 0xFD;
   3298  }
   3299  //RES 1, C
   3300  //#0x89:
   3301  ,function (parentObj) {
   3302    parentObj.registerC &= 0xFD;
   3303  }
   3304  //RES 1, D
   3305  //#0x8A:
   3306  ,function (parentObj) {
   3307    parentObj.registerD &= 0xFD;
   3308  }
   3309  //RES 1, E
   3310  //#0x8B:
   3311  ,function (parentObj) {
   3312    parentObj.registerE &= 0xFD;
   3313  }
   3314  //RES 1, H
   3315  //#0x8C:
   3316  ,function (parentObj) {
   3317    parentObj.registersHL &= 0xFDFF;
   3318  }
   3319  //RES 1, L
   3320  //#0x8D:
   3321  ,function (parentObj) {
   3322    parentObj.registersHL &= 0xFFFD;
   3323  }
   3324  //RES 1, (HL)
   3325  //#0x8E:
   3326  ,function (parentObj) {
   3327    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xFD);
   3328  }
   3329  //RES 1, A
   3330  //#0x8F:
   3331  ,function (parentObj) {
   3332    parentObj.registerA &= 0xFD;
   3333  }
   3334  //RES 2, B
   3335  //#0x90:
   3336  ,function (parentObj) {
   3337    parentObj.registerB &= 0xFB;
   3338  }
   3339  //RES 2, C
   3340  //#0x91:
   3341  ,function (parentObj) {
   3342    parentObj.registerC &= 0xFB;
   3343  }
   3344  //RES 2, D
   3345  //#0x92:
   3346  ,function (parentObj) {
   3347    parentObj.registerD &= 0xFB;
   3348  }
   3349  //RES 2, E
   3350  //#0x93:
   3351  ,function (parentObj) {
   3352    parentObj.registerE &= 0xFB;
   3353  }
   3354  //RES 2, H
   3355  //#0x94:
   3356  ,function (parentObj) {
   3357    parentObj.registersHL &= 0xFBFF;
   3358  }
   3359  //RES 2, L
   3360  //#0x95:
   3361  ,function (parentObj) {
   3362    parentObj.registersHL &= 0xFFFB;
   3363  }
   3364  //RES 2, (HL)
   3365  //#0x96:
   3366  ,function (parentObj) {
   3367    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xFB);
   3368  }
   3369  //RES 2, A
   3370  //#0x97:
   3371  ,function (parentObj) {
   3372    parentObj.registerA &= 0xFB;
   3373  }
   3374  //RES 3, B
   3375  //#0x98:
   3376  ,function (parentObj) {
   3377    parentObj.registerB &= 0xF7;
   3378  }
   3379  //RES 3, C
   3380  //#0x99:
   3381  ,function (parentObj) {
   3382    parentObj.registerC &= 0xF7;
   3383  }
   3384  //RES 3, D
   3385  //#0x9A:
   3386  ,function (parentObj) {
   3387    parentObj.registerD &= 0xF7;
   3388  }
   3389  //RES 3, E
   3390  //#0x9B:
   3391  ,function (parentObj) {
   3392    parentObj.registerE &= 0xF7;
   3393  }
   3394  //RES 3, H
   3395  //#0x9C:
   3396  ,function (parentObj) {
   3397    parentObj.registersHL &= 0xF7FF;
   3398  }
   3399  //RES 3, L
   3400  //#0x9D:
   3401  ,function (parentObj) {
   3402    parentObj.registersHL &= 0xFFF7;
   3403  }
   3404  //RES 3, (HL)
   3405  //#0x9E:
   3406  ,function (parentObj) {
   3407    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xF7);
   3408  }
   3409  //RES 3, A
   3410  //#0x9F:
   3411  ,function (parentObj) {
   3412    parentObj.registerA &= 0xF7;
   3413  }
   3414  //RES 3, B
   3415  //#0xA0:
   3416  ,function (parentObj) {
   3417    parentObj.registerB &= 0xEF;
   3418  }
   3419  //RES 4, C
   3420  //#0xA1:
   3421  ,function (parentObj) {
   3422    parentObj.registerC &= 0xEF;
   3423  }
   3424  //RES 4, D
   3425  //#0xA2:
   3426  ,function (parentObj) {
   3427    parentObj.registerD &= 0xEF;
   3428  }
   3429  //RES 4, E
   3430  //#0xA3:
   3431  ,function (parentObj) {
   3432    parentObj.registerE &= 0xEF;
   3433  }
   3434  //RES 4, H
   3435  //#0xA4:
   3436  ,function (parentObj) {
   3437    parentObj.registersHL &= 0xEFFF;
   3438  }
   3439  //RES 4, L
   3440  //#0xA5:
   3441  ,function (parentObj) {
   3442    parentObj.registersHL &= 0xFFEF;
   3443  }
   3444  //RES 4, (HL)
   3445  //#0xA6:
   3446  ,function (parentObj) {
   3447    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xEF);
   3448  }
   3449  //RES 4, A
   3450  //#0xA7:
   3451  ,function (parentObj) {
   3452    parentObj.registerA &= 0xEF;
   3453  }
   3454  //RES 5, B
   3455  //#0xA8:
   3456  ,function (parentObj) {
   3457    parentObj.registerB &= 0xDF;
   3458  }
   3459  //RES 5, C
   3460  //#0xA9:
   3461  ,function (parentObj) {
   3462    parentObj.registerC &= 0xDF;
   3463  }
   3464  //RES 5, D
   3465  //#0xAA:
   3466  ,function (parentObj) {
   3467    parentObj.registerD &= 0xDF;
   3468  }
   3469  //RES 5, E
   3470  //#0xAB:
   3471  ,function (parentObj) {
   3472    parentObj.registerE &= 0xDF;
   3473  }
   3474  //RES 5, H
   3475  //#0xAC:
   3476  ,function (parentObj) {
   3477    parentObj.registersHL &= 0xDFFF;
   3478  }
   3479  //RES 5, L
   3480  //#0xAD:
   3481  ,function (parentObj) {
   3482    parentObj.registersHL &= 0xFFDF;
   3483  }
   3484  //RES 5, (HL)
   3485  //#0xAE:
   3486  ,function (parentObj) {
   3487    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xDF);
   3488  }
   3489  //RES 5, A
   3490  //#0xAF:
   3491  ,function (parentObj) {
   3492    parentObj.registerA &= 0xDF;
   3493  }
   3494  //RES 6, B
   3495  //#0xB0:
   3496  ,function (parentObj) {
   3497    parentObj.registerB &= 0xBF;
   3498  }
   3499  //RES 6, C
   3500  //#0xB1:
   3501  ,function (parentObj) {
   3502    parentObj.registerC &= 0xBF;
   3503  }
   3504  //RES 6, D
   3505  //#0xB2:
   3506  ,function (parentObj) {
   3507    parentObj.registerD &= 0xBF;
   3508  }
   3509  //RES 6, E
   3510  //#0xB3:
   3511  ,function (parentObj) {
   3512    parentObj.registerE &= 0xBF;
   3513  }
   3514  //RES 6, H
   3515  //#0xB4:
   3516  ,function (parentObj) {
   3517    parentObj.registersHL &= 0xBFFF;
   3518  }
   3519  //RES 6, L
   3520  //#0xB5:
   3521  ,function (parentObj) {
   3522    parentObj.registersHL &= 0xFFBF;
   3523  }
   3524  //RES 6, (HL)
   3525  //#0xB6:
   3526  ,function (parentObj) {
   3527    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xBF);
   3528  }
   3529  //RES 6, A
   3530  //#0xB7:
   3531  ,function (parentObj) {
   3532    parentObj.registerA &= 0xBF;
   3533  }
   3534  //RES 7, B
   3535  //#0xB8:
   3536  ,function (parentObj) {
   3537    parentObj.registerB &= 0x7F;
   3538  }
   3539  //RES 7, C
   3540  //#0xB9:
   3541  ,function (parentObj) {
   3542    parentObj.registerC &= 0x7F;
   3543  }
   3544  //RES 7, D
   3545  //#0xBA:
   3546  ,function (parentObj) {
   3547    parentObj.registerD &= 0x7F;
   3548  }
   3549  //RES 7, E
   3550  //#0xBB:
   3551  ,function (parentObj) {
   3552    parentObj.registerE &= 0x7F;
   3553  }
   3554  //RES 7, H
   3555  //#0xBC:
   3556  ,function (parentObj) {
   3557    parentObj.registersHL &= 0x7FFF;
   3558  }
   3559  //RES 7, L
   3560  //#0xBD:
   3561  ,function (parentObj) {
   3562    parentObj.registersHL &= 0xFF7F;
   3563  }
   3564  //RES 7, (HL)
   3565  //#0xBE:
   3566  ,function (parentObj) {
   3567    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x7F);
   3568  }
   3569  //RES 7, A
   3570  //#0xBF:
   3571  ,function (parentObj) {
   3572    parentObj.registerA &= 0x7F;
   3573  }
   3574  //SET 0, B
   3575  //#0xC0:
   3576  ,function (parentObj) {
   3577    parentObj.registerB |= 0x01;
   3578  }
   3579  //SET 0, C
   3580  //#0xC1:
   3581  ,function (parentObj) {
   3582    parentObj.registerC |= 0x01;
   3583  }
   3584  //SET 0, D
   3585  //#0xC2:
   3586  ,function (parentObj) {
   3587    parentObj.registerD |= 0x01;
   3588  }
   3589  //SET 0, E
   3590  //#0xC3:
   3591  ,function (parentObj) {
   3592    parentObj.registerE |= 0x01;
   3593  }
   3594  //SET 0, H
   3595  //#0xC4:
   3596  ,function (parentObj) {
   3597    parentObj.registersHL |= 0x0100;
   3598  }
   3599  //SET 0, L
   3600  //#0xC5:
   3601  ,function (parentObj) {
   3602    parentObj.registersHL |= 0x01;
   3603  }
   3604  //SET 0, (HL)
   3605  //#0xC6:
   3606  ,function (parentObj) {
   3607    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x01);
   3608  }
   3609  //SET 0, A
   3610  //#0xC7:
   3611  ,function (parentObj) {
   3612    parentObj.registerA |= 0x01;
   3613  }
   3614  //SET 1, B
   3615  //#0xC8:
   3616  ,function (parentObj) {
   3617    parentObj.registerB |= 0x02;
   3618  }
   3619  //SET 1, C
   3620  //#0xC9:
   3621  ,function (parentObj) {
   3622    parentObj.registerC |= 0x02;
   3623  }
   3624  //SET 1, D
   3625  //#0xCA:
   3626  ,function (parentObj) {
   3627    parentObj.registerD |= 0x02;
   3628  }
   3629  //SET 1, E
   3630  //#0xCB:
   3631  ,function (parentObj) {
   3632    parentObj.registerE |= 0x02;
   3633  }
   3634  //SET 1, H
   3635  //#0xCC:
   3636  ,function (parentObj) {
   3637    parentObj.registersHL |= 0x0200;
   3638  }
   3639  //SET 1, L
   3640  //#0xCD:
   3641  ,function (parentObj) {
   3642    parentObj.registersHL |= 0x02;
   3643  }
   3644  //SET 1, (HL)
   3645  //#0xCE:
   3646  ,function (parentObj) {
   3647    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x02);
   3648  }
   3649  //SET 1, A
   3650  //#0xCF:
   3651  ,function (parentObj) {
   3652    parentObj.registerA |= 0x02;
   3653  }
   3654  //SET 2, B
   3655  //#0xD0:
   3656  ,function (parentObj) {
   3657    parentObj.registerB |= 0x04;
   3658  }
   3659  //SET 2, C
   3660  //#0xD1:
   3661  ,function (parentObj) {
   3662    parentObj.registerC |= 0x04;
   3663  }
   3664  //SET 2, D
   3665  //#0xD2:
   3666  ,function (parentObj) {
   3667    parentObj.registerD |= 0x04;
   3668  }
   3669  //SET 2, E
   3670  //#0xD3:
   3671  ,function (parentObj) {
   3672    parentObj.registerE |= 0x04;
   3673  }
   3674  //SET 2, H
   3675  //#0xD4:
   3676  ,function (parentObj) {
   3677    parentObj.registersHL |= 0x0400;
   3678  }
   3679  //SET 2, L
   3680  //#0xD5:
   3681  ,function (parentObj) {
   3682    parentObj.registersHL |= 0x04;
   3683  }
   3684  //SET 2, (HL)
   3685  //#0xD6:
   3686  ,function (parentObj) {
   3687    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x04);
   3688  }
   3689  //SET 2, A
   3690  //#0xD7:
   3691  ,function (parentObj) {
   3692    parentObj.registerA |= 0x04;
   3693  }
   3694  //SET 3, B
   3695  //#0xD8:
   3696  ,function (parentObj) {
   3697    parentObj.registerB |= 0x08;
   3698  }
   3699  //SET 3, C
   3700  //#0xD9:
   3701  ,function (parentObj) {
   3702    parentObj.registerC |= 0x08;
   3703  }
   3704  //SET 3, D
   3705  //#0xDA:
   3706  ,function (parentObj) {
   3707    parentObj.registerD |= 0x08;
   3708  }
   3709  //SET 3, E
   3710  //#0xDB:
   3711  ,function (parentObj) {
   3712    parentObj.registerE |= 0x08;
   3713  }
   3714  //SET 3, H
   3715  //#0xDC:
   3716  ,function (parentObj) {
   3717    parentObj.registersHL |= 0x0800;
   3718  }
   3719  //SET 3, L
   3720  //#0xDD:
   3721  ,function (parentObj) {
   3722    parentObj.registersHL |= 0x08;
   3723  }
   3724  //SET 3, (HL)
   3725  //#0xDE:
   3726  ,function (parentObj) {
   3727    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x08);
   3728  }
   3729  //SET 3, A
   3730  //#0xDF:
   3731  ,function (parentObj) {
   3732    parentObj.registerA |= 0x08;
   3733  }
   3734  //SET 4, B
   3735  //#0xE0:
   3736  ,function (parentObj) {
   3737    parentObj.registerB |= 0x10;
   3738  }
   3739  //SET 4, C
   3740  //#0xE1:
   3741  ,function (parentObj) {
   3742    parentObj.registerC |= 0x10;
   3743  }
   3744  //SET 4, D
   3745  //#0xE2:
   3746  ,function (parentObj) {
   3747    parentObj.registerD |= 0x10;
   3748  }
   3749  //SET 4, E
   3750  //#0xE3:
   3751  ,function (parentObj) {
   3752    parentObj.registerE |= 0x10;
   3753  }
   3754  //SET 4, H
   3755  //#0xE4:
   3756  ,function (parentObj) {
   3757    parentObj.registersHL |= 0x1000;
   3758  }
   3759  //SET 4, L
   3760  //#0xE5:
   3761  ,function (parentObj) {
   3762    parentObj.registersHL |= 0x10;
   3763  }
   3764  //SET 4, (HL)
   3765  //#0xE6:
   3766  ,function (parentObj) {
   3767    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x10);
   3768  }
   3769  //SET 4, A
   3770  //#0xE7:
   3771  ,function (parentObj) {
   3772    parentObj.registerA |= 0x10;
   3773  }
   3774  //SET 5, B
   3775  //#0xE8:
   3776  ,function (parentObj) {
   3777    parentObj.registerB |= 0x20;
   3778  }
   3779  //SET 5, C
   3780  //#0xE9:
   3781  ,function (parentObj) {
   3782    parentObj.registerC |= 0x20;
   3783  }
   3784  //SET 5, D
   3785  //#0xEA:
   3786  ,function (parentObj) {
   3787    parentObj.registerD |= 0x20;
   3788  }
   3789  //SET 5, E
   3790  //#0xEB:
   3791  ,function (parentObj) {
   3792    parentObj.registerE |= 0x20;
   3793  }
   3794  //SET 5, H
   3795  //#0xEC:
   3796  ,function (parentObj) {
   3797    parentObj.registersHL |= 0x2000;
   3798  }
   3799  //SET 5, L
   3800  //#0xED:
   3801  ,function (parentObj) {
   3802    parentObj.registersHL |= 0x20;
   3803  }
   3804  //SET 5, (HL)
   3805  //#0xEE:
   3806  ,function (parentObj) {
   3807    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x20);
   3808  }
   3809  //SET 5, A
   3810  //#0xEF:
   3811  ,function (parentObj) {
   3812    parentObj.registerA |= 0x20;
   3813  }
   3814  //SET 6, B
   3815  //#0xF0:
   3816  ,function (parentObj) {
   3817    parentObj.registerB |= 0x40;
   3818  }
   3819  //SET 6, C
   3820  //#0xF1:
   3821  ,function (parentObj) {
   3822    parentObj.registerC |= 0x40;
   3823  }
   3824  //SET 6, D
   3825  //#0xF2:
   3826  ,function (parentObj) {
   3827    parentObj.registerD |= 0x40;
   3828  }
   3829  //SET 6, E
   3830  //#0xF3:
   3831  ,function (parentObj) {
   3832    parentObj.registerE |= 0x40;
   3833  }
   3834  //SET 6, H
   3835  //#0xF4:
   3836  ,function (parentObj) {
   3837    parentObj.registersHL |= 0x4000;
   3838  }
   3839  //SET 6, L
   3840  //#0xF5:
   3841  ,function (parentObj) {
   3842    parentObj.registersHL |= 0x40;
   3843  }
   3844  //SET 6, (HL)
   3845  //#0xF6:
   3846  ,function (parentObj) {
   3847    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x40);
   3848  }
   3849  //SET 6, A
   3850  //#0xF7:
   3851  ,function (parentObj) {
   3852    parentObj.registerA |= 0x40;
   3853  }
   3854  //SET 7, B
   3855  //#0xF8:
   3856  ,function (parentObj) {
   3857    parentObj.registerB |= 0x80;
   3858  }
   3859  //SET 7, C
   3860  //#0xF9:
   3861  ,function (parentObj) {
   3862    parentObj.registerC |= 0x80;
   3863  }
   3864  //SET 7, D
   3865  //#0xFA:
   3866  ,function (parentObj) {
   3867    parentObj.registerD |= 0x80;
   3868  }
   3869  //SET 7, E
   3870  //#0xFB:
   3871  ,function (parentObj) {
   3872    parentObj.registerE |= 0x80;
   3873  }
   3874  //SET 7, H
   3875  //#0xFC:
   3876  ,function (parentObj) {
   3877    parentObj.registersHL |= 0x8000;
   3878  }
   3879  //SET 7, L
   3880  //#0xFD:
   3881  ,function (parentObj) {
   3882    parentObj.registersHL |= 0x80;
   3883  }
   3884  //SET 7, (HL)
   3885  //#0xFE:
   3886  ,function (parentObj) {
   3887    parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x80);
   3888  }
   3889  //SET 7, A
   3890  //#0xFF:
   3891  ,function (parentObj) {
   3892    parentObj.registerA |= 0x80;
   3893  }
   3894 ];
   3895 GameBoyCore.prototype.TICKTable = [    //Number of machine cycles for each instruction:
   3896 /*   0,  1,  2,  3,  4,  5,  6,  7,      8,  9,  A, B,  C,  D, E,  F*/
   3897     4, 12,  8,  8,  4,  4,  8,  4,     20,  8,  8, 8,  4,  4, 8,  4,  //0
   3898     4, 12,  8,  8,  4,  4,  8,  4,     12,  8,  8, 8,  4,  4, 8,  4,  //1
   3899     8, 12,  8,  8,  4,  4,  8,  4,      8,  8,  8, 8,  4,  4, 8,  4,  //2
   3900     8, 12,  8,  8, 12, 12, 12,  4,      8,  8,  8, 8,  4,  4, 8,  4,  //3
   3901 
   3902     4,  4,  4,  4,  4,  4,  8,  4,      4,  4,  4, 4,  4,  4, 8,  4,  //4
   3903     4,  4,  4,  4,  4,  4,  8,  4,      4,  4,  4, 4,  4,  4, 8,  4,  //5
   3904     4,  4,  4,  4,  4,  4,  8,  4,      4,  4,  4, 4,  4,  4, 8,  4,  //6
   3905     8,  8,  8,  8,  8,  8,  4,  8,      4,  4,  4, 4,  4,  4, 8,  4,  //7
   3906 
   3907     4,  4,  4,  4,  4,  4,  8,  4,      4,  4,  4, 4,  4,  4, 8,  4,  //8
   3908     4,  4,  4,  4,  4,  4,  8,  4,      4,  4,  4, 4,  4,  4, 8,  4,  //9
   3909     4,  4,  4,  4,  4,  4,  8,  4,      4,  4,  4, 4,  4,  4, 8,  4,  //A
   3910     4,  4,  4,  4,  4,  4,  8,  4,      4,  4,  4, 4,  4,  4, 8,  4,  //B
   3911 
   3912     8, 12, 12, 16, 12, 16,  8, 16,      8, 16, 12, 0, 12, 24, 8, 16,  //C
   3913     8, 12, 12,  4, 12, 16,  8, 16,      8, 16, 12, 4, 12,  4, 8, 16,  //D
   3914    12, 12,  8,  4,  4, 16,  8, 16,     16,  4, 16, 4,  4,  4, 8, 16,  //E
   3915    12, 12,  8,  4,  4, 16,  8, 16,     12,  8, 16, 4,  0,  4, 8, 16   //F
   3916 ];
   3917 GameBoyCore.prototype.SecondaryTICKTable = [  //Number of machine cycles for each 0xCBXX instruction:
   3918 /*  0, 1, 2, 3, 4, 5,  6, 7,        8, 9, A, B, C, D,  E, F*/
   3919    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //0
   3920    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //1
   3921    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //2
   3922    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //3
   3923 
   3924    8, 8, 8, 8, 8, 8, 12, 8,        8, 8, 8, 8, 8, 8, 12, 8,  //4
   3925    8, 8, 8, 8, 8, 8, 12, 8,        8, 8, 8, 8, 8, 8, 12, 8,  //5
   3926    8, 8, 8, 8, 8, 8, 12, 8,        8, 8, 8, 8, 8, 8, 12, 8,  //6
   3927    8, 8, 8, 8, 8, 8, 12, 8,        8, 8, 8, 8, 8, 8, 12, 8,  //7
   3928 
   3929    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //8
   3930    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //9
   3931    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //A
   3932    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //B
   3933 
   3934    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //C
   3935    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //D
   3936    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8,  //E
   3937    8, 8, 8, 8, 8, 8, 16, 8,        8, 8, 8, 8, 8, 8, 16, 8   //F
   3938 ];
   3939 GameBoyCore.prototype.saveSRAMState = function () {
   3940  if (!this.cBATT || this.MBCRam.length == 0) {
   3941    //No battery backup...
   3942    return [];
   3943  }
   3944  else {
   3945    //Return the MBC RAM for backup...
   3946    return this.fromTypedArray(this.MBCRam);
   3947  }
   3948 }
   3949 GameBoyCore.prototype.saveRTCState = function () {
   3950  if (!this.cTIMER) {
   3951    //No battery backup...
   3952    return [];
   3953  }
   3954  else {
   3955    //Return the MBC RAM for backup...
   3956    return [
   3957      this.lastIteration,
   3958      this.RTCisLatched,
   3959      this.latchedSeconds,
   3960      this.latchedMinutes,
   3961      this.latchedHours,
   3962      this.latchedLDays,
   3963      this.latchedHDays,
   3964      this.RTCSeconds,
   3965      this.RTCMinutes,
   3966      this.RTCHours,
   3967      this.RTCDays,
   3968      this.RTCDayOverFlow,
   3969      this.RTCHALT
   3970    ];
   3971  }
   3972 }
   3973 GameBoyCore.prototype.saveState = function () {
   3974  return [
   3975    this.fromTypedArray(this.ROM),
   3976    this.inBootstrap,
   3977    this.registerA,
   3978    this.FZero,
   3979    this.FSubtract,
   3980    this.FHalfCarry,
   3981    this.FCarry,
   3982    this.registerB,
   3983    this.registerC,
   3984    this.registerD,
   3985    this.registerE,
   3986    this.registersHL,
   3987    this.stackPointer,
   3988    this.programCounter,
   3989    this.halt,
   3990    this.IME,
   3991    this.hdmaRunning,
   3992    this.CPUTicks,
   3993    this.doubleSpeedShifter,
   3994    this.fromTypedArray(this.memory),
   3995    this.fromTypedArray(this.MBCRam),
   3996    this.fromTypedArray(this.VRAM),
   3997    this.currVRAMBank,
   3998    this.fromTypedArray(this.GBCMemory),
   3999    this.MBC1Mode,
   4000    this.MBCRAMBanksEnabled,
   4001    this.currMBCRAMBank,
   4002    this.currMBCRAMBankPosition,
   4003    this.cGBC,
   4004    this.gbcRamBank,
   4005    this.gbcRamBankPosition,
   4006    this.ROMBank1offs,
   4007    this.currentROMBank,
   4008    this.cartridgeType,
   4009    this.name,
   4010    this.gameCode,
   4011    this.modeSTAT,
   4012    this.LYCMatchTriggerSTAT,
   4013    this.mode2TriggerSTAT,
   4014    this.mode1TriggerSTAT,
   4015    this.mode0TriggerSTAT,
   4016    this.LCDisOn,
   4017    this.gfxWindowCHRBankPosition,
   4018    this.gfxWindowDisplay,
   4019    this.gfxSpriteShow,
   4020    this.gfxSpriteNormalHeight,
   4021    this.gfxBackgroundCHRBankPosition,
   4022    this.gfxBackgroundBankOffset,
   4023    this.TIMAEnabled,
   4024    this.DIVTicks,
   4025    this.LCDTicks,
   4026    this.timerTicks,
   4027    this.TACClocker,
   4028    this.serialTimer,
   4029    this.serialShiftTimer,
   4030    this.serialShiftTimerAllocated,
   4031    this.IRQEnableDelay,
   4032    this.lastIteration,
   4033    this.cMBC1,
   4034    this.cMBC2,
   4035    this.cMBC3,
   4036    this.cMBC5,
   4037    this.cMBC7,
   4038    this.cSRAM,
   4039    this.cMMMO1,
   4040    this.cRUMBLE,
   4041    this.cCamera,
   4042    this.cTAMA5,
   4043    this.cHuC3,
   4044    this.cHuC1,
   4045    this.drewBlank,
   4046    this.fromTypedArray(this.frameBuffer),
   4047    this.bgEnabled,
   4048    this.BGPriorityEnabled,
   4049    this.channel1FrequencyTracker,
   4050    this.channel1FrequencyCounter,
   4051    this.channel1totalLength,
   4052    this.channel1envelopeVolume,
   4053    this.channel1envelopeType,
   4054    this.channel1envelopeSweeps,
   4055    this.channel1envelopeSweepsLast,
   4056    this.channel1consecutive,
   4057    this.channel1frequency,
   4058    this.channel1SweepFault,
   4059    this.channel1ShadowFrequency,
   4060    this.channel1timeSweep,
   4061    this.channel1lastTimeSweep,
   4062    this.channel1numSweep,
   4063    this.channel1frequencySweepDivider,
   4064    this.channel1decreaseSweep,
   4065    this.channel2FrequencyTracker,
   4066    this.channel2FrequencyCounter,
   4067    this.channel2totalLength,
   4068    this.channel2envelopeVolume,
   4069    this.channel2envelopeType,
   4070    this.channel2envelopeSweeps,
   4071    this.channel2envelopeSweepsLast,
   4072    this.channel2consecutive,
   4073    this.channel2frequency,
   4074    this.channel3canPlay,
   4075    this.channel3totalLength,
   4076    this.channel3patternType,
   4077    this.channel3frequency,
   4078    this.channel3consecutive,
   4079    this.fromTypedArray(this.channel3PCM),
   4080    this.channel4FrequencyPeriod,
   4081    this.channel4lastSampleLookup,
   4082    this.channel4totalLength,
   4083    this.channel4envelopeVolume,
   4084    this.channel4currentVolume,
   4085    this.channel4envelopeType,
   4086    this.channel4envelopeSweeps,
   4087    this.channel4envelopeSweepsLast,
   4088    this.channel4consecutive,
   4089    this.channel4BitRange,
   4090    this.soundMasterEnabled,
   4091    this.VinLeftChannelMasterVolume,
   4092    this.VinRightChannelMasterVolume,
   4093    this.leftChannel1,
   4094    this.leftChannel2,
   4095    this.leftChannel3,
   4096    this.leftChannel4,
   4097    this.rightChannel1,
   4098    this.rightChannel2,
   4099    this.rightChannel3,
   4100    this.rightChannel4,
   4101    this.channel1currentSampleLeft,
   4102    this.channel1currentSampleRight,
   4103    this.channel2currentSampleLeft,
   4104    this.channel2currentSampleRight,
   4105    this.channel3currentSampleLeft,
   4106    this.channel3currentSampleRight,
   4107    this.channel4currentSampleLeft,
   4108    this.channel4currentSampleRight,
   4109    this.channel1currentSampleLeftSecondary,
   4110    this.channel1currentSampleRightSecondary,
   4111    this.channel2currentSampleLeftSecondary,
   4112    this.channel2currentSampleRightSecondary,
   4113    this.channel3currentSampleLeftSecondary,
   4114    this.channel3currentSampleRightSecondary,
   4115    this.channel4currentSampleLeftSecondary,
   4116    this.channel4currentSampleRightSecondary,
   4117    this.channel1currentSampleLeftTrimary,
   4118    this.channel1currentSampleRightTrimary,
   4119    this.channel2currentSampleLeftTrimary,
   4120    this.channel2currentSampleRightTrimary,
   4121    this.mixerOutputCache,
   4122    this.channel1DutyTracker,
   4123    this.channel1CachedDuty,
   4124    this.channel2DutyTracker,
   4125    this.channel2CachedDuty,
   4126    this.channel1Enabled,
   4127    this.channel2Enabled,
   4128    this.channel3Enabled,
   4129    this.channel4Enabled,
   4130    this.sequencerClocks,
   4131    this.sequencePosition,
   4132    this.channel3Counter,
   4133    this.channel4Counter,
   4134    this.cachedChannel3Sample,
   4135    this.cachedChannel4Sample,
   4136    this.channel3FrequencyPeriod,
   4137    this.channel3lastSampleLookup,
   4138    this.actualScanLine,
   4139    this.lastUnrenderedLine,
   4140    this.queuedScanLines,
   4141    this.RTCisLatched,
   4142    this.latchedSeconds,
   4143    this.latchedMinutes,
   4144    this.latchedHours,
   4145    this.latchedLDays,
   4146    this.latchedHDays,
   4147    this.RTCSeconds,
   4148    this.RTCMinutes,
   4149    this.RTCHours,
   4150    this.RTCDays,
   4151    this.RTCDayOverFlow,
   4152    this.RTCHALT,
   4153    this.usedBootROM,
   4154    this.skipPCIncrement,
   4155    this.STATTracker,
   4156    this.gbcRamBankPositionECHO,
   4157    this.numRAMBanks,
   4158    this.windowY,
   4159    this.windowX,
   4160    this.fromTypedArray(this.gbcOBJRawPalette),
   4161    this.fromTypedArray(this.gbcBGRawPalette),
   4162    this.fromTypedArray(this.gbOBJPalette),
   4163    this.fromTypedArray(this.gbBGPalette),
   4164    this.fromTypedArray(this.gbcOBJPalette),
   4165    this.fromTypedArray(this.gbcBGPalette),
   4166    this.fromTypedArray(this.gbBGColorizedPalette),
   4167    this.fromTypedArray(this.gbOBJColorizedPalette),
   4168    this.fromTypedArray(this.cachedBGPaletteConversion),
   4169    this.fromTypedArray(this.cachedOBJPaletteConversion),
   4170    this.fromTypedArray(this.BGCHRBank1),
   4171    this.fromTypedArray(this.BGCHRBank2),
   4172    this.haltPostClocks,
   4173    this.interruptsRequested,
   4174    this.interruptsEnabled,
   4175    this.remainingClocks,
   4176    this.colorizedGBPalettes,
   4177    this.backgroundY,
   4178    this.backgroundX,
   4179    this.CPUStopped
   4180  ];
   4181 }
   4182 GameBoyCore.prototype.returnFromState = function (returnedFrom) {
   4183  var index = 0;
   4184  var state = returnedFrom.slice(0);
   4185  this.ROM = this.toTypedArray(state[index++], "uint8");
   4186  this.ROMBankEdge = Math.floor(this.ROM.length / 0x4000);
   4187  this.inBootstrap = state[index++];
   4188  this.registerA = state[index++];
   4189  this.FZero = state[index++];
   4190  this.FSubtract = state[index++];
   4191  this.FHalfCarry = state[index++];
   4192  this.FCarry = state[index++];
   4193  this.registerB = state[index++];
   4194  this.registerC = state[index++];
   4195  this.registerD = state[index++];
   4196  this.registerE = state[index++];
   4197  this.registersHL = state[index++];
   4198  this.stackPointer = state[index++];
   4199  this.programCounter = state[index++];
   4200  this.halt = state[index++];
   4201  this.IME = state[index++];
   4202  this.hdmaRunning = state[index++];
   4203  this.CPUTicks = state[index++];
   4204  this.doubleSpeedShifter = state[index++];
   4205  this.memory = this.toTypedArray(state[index++], "uint8");
   4206  this.MBCRam = this.toTypedArray(state[index++], "uint8");
   4207  this.VRAM = this.toTypedArray(state[index++], "uint8");
   4208  this.currVRAMBank = state[index++];
   4209  this.GBCMemory = this.toTypedArray(state[index++], "uint8");
   4210  this.MBC1Mode = state[index++];
   4211  this.MBCRAMBanksEnabled = state[index++];
   4212  this.currMBCRAMBank = state[index++];
   4213  this.currMBCRAMBankPosition = state[index++];
   4214  this.cGBC = state[index++];
   4215  this.gbcRamBank = state[index++];
   4216  this.gbcRamBankPosition = state[index++];
   4217  this.ROMBank1offs = state[index++];
   4218  this.currentROMBank = state[index++];
   4219  this.cartridgeType = state[index++];
   4220  this.name = state[index++];
   4221  this.gameCode = state[index++];
   4222  this.modeSTAT = state[index++];
   4223  this.LYCMatchTriggerSTAT = state[index++];
   4224  this.mode2TriggerSTAT = state[index++];
   4225  this.mode1TriggerSTAT = state[index++];
   4226  this.mode0TriggerSTAT = state[index++];
   4227  this.LCDisOn = state[index++];
   4228  this.gfxWindowCHRBankPosition = state[index++];
   4229  this.gfxWindowDisplay = state[index++];
   4230  this.gfxSpriteShow = state[index++];
   4231  this.gfxSpriteNormalHeight = state[index++];
   4232  this.gfxBackgroundCHRBankPosition = state[index++];
   4233  this.gfxBackgroundBankOffset = state[index++];
   4234  this.TIMAEnabled = state[index++];
   4235  this.DIVTicks = state[index++];
   4236  this.LCDTicks = state[index++];
   4237  this.timerTicks = state[index++];
   4238  this.TACClocker = state[index++];
   4239  this.serialTimer = state[index++];
   4240  this.serialShiftTimer = state[index++];
   4241  this.serialShiftTimerAllocated = state[index++];
   4242  this.IRQEnableDelay = state[index++];
   4243  this.lastIteration = state[index++];
   4244  this.cMBC1 = state[index++];
   4245  this.cMBC2 = state[index++];
   4246  this.cMBC3 = state[index++];
   4247  this.cMBC5 = state[index++];
   4248  this.cMBC7 = state[index++];
   4249  this.cSRAM = state[index++];
   4250  this.cMMMO1 = state[index++];
   4251  this.cRUMBLE = state[index++];
   4252  this.cCamera = state[index++];
   4253  this.cTAMA5 = state[index++];
   4254  this.cHuC3 = state[index++];
   4255  this.cHuC1 = state[index++];
   4256  this.drewBlank = state[index++];
   4257  this.frameBuffer = this.toTypedArray(state[index++], "int32");
   4258  this.bgEnabled = state[index++];
   4259  this.BGPriorityEnabled = state[index++];
   4260  this.channel1FrequencyTracker = state[index++];
   4261  this.channel1FrequencyCounter = state[index++];
   4262  this.channel1totalLength = state[index++];
   4263  this.channel1envelopeVolume = state[index++];
   4264  this.channel1envelopeType = state[index++];
   4265  this.channel1envelopeSweeps = state[index++];
   4266  this.channel1envelopeSweepsLast = state[index++];
   4267  this.channel1consecutive = state[index++];
   4268  this.channel1frequency = state[index++];
   4269  this.channel1SweepFault = state[index++];
   4270  this.channel1ShadowFrequency = state[index++];
   4271  this.channel1timeSweep = state[index++];
   4272  this.channel1lastTimeSweep = state[index++];
   4273  this.channel1numSweep = state[index++];
   4274  this.channel1frequencySweepDivider = state[index++];
   4275  this.channel1decreaseSweep = state[index++];
   4276  this.channel2FrequencyTracker = state[index++];
   4277  this.channel2FrequencyCounter = state[index++];
   4278  this.channel2totalLength = state[index++];
   4279  this.channel2envelopeVolume = state[index++];
   4280  this.channel2envelopeType = state[index++];
   4281  this.channel2envelopeSweeps = state[index++];
   4282  this.channel2envelopeSweepsLast = state[index++];
   4283  this.channel2consecutive = state[index++];
   4284  this.channel2frequency = state[index++];
   4285  this.channel3canPlay = state[index++];
   4286  this.channel3totalLength = state[index++];
   4287  this.channel3patternType = state[index++];
   4288  this.channel3frequency = state[index++];
   4289  this.channel3consecutive = state[index++];
   4290  this.channel3PCM = this.toTypedArray(state[index++], "int8");
   4291  this.channel4FrequencyPeriod = state[index++];
   4292  this.channel4lastSampleLookup = state[index++];
   4293  this.channel4totalLength = state[index++];
   4294  this.channel4envelopeVolume = state[index++];
   4295  this.channel4currentVolume = state[index++];
   4296  this.channel4envelopeType = state[index++];
   4297  this.channel4envelopeSweeps = state[index++];
   4298  this.channel4envelopeSweepsLast = state[index++];
   4299  this.channel4consecutive = state[index++];
   4300  this.channel4BitRange = state[index++];
   4301  this.soundMasterEnabled = state[index++];
   4302  this.VinLeftChannelMasterVolume = state[index++];
   4303  this.VinRightChannelMasterVolume = state[index++];
   4304  this.leftChannel1 = state[index++];
   4305  this.leftChannel2 = state[index++];
   4306  this.leftChannel3 = state[index++];
   4307  this.leftChannel4 = state[index++];
   4308  this.rightChannel1 = state[index++];
   4309  this.rightChannel2 = state[index++];
   4310  this.rightChannel3 = state[index++];
   4311  this.rightChannel4 = state[index++];
   4312  this.channel1currentSampleLeft = state[index++];
   4313  this.channel1currentSampleRight = state[index++];
   4314  this.channel2currentSampleLeft = state[index++];
   4315  this.channel2currentSampleRight = state[index++];
   4316  this.channel3currentSampleLeft = state[index++];
   4317  this.channel3currentSampleRight = state[index++];
   4318  this.channel4currentSampleLeft = state[index++];
   4319  this.channel4currentSampleRight = state[index++];
   4320  this.channel1currentSampleLeftSecondary = state[index++];
   4321  this.channel1currentSampleRightSecondary = state[index++];
   4322  this.channel2currentSampleLeftSecondary = state[index++];
   4323  this.channel2currentSampleRightSecondary = state[index++];
   4324  this.channel3currentSampleLeftSecondary = state[index++];
   4325  this.channel3currentSampleRightSecondary = state[index++];
   4326  this.channel4currentSampleLeftSecondary = state[index++];
   4327  this.channel4currentSampleRightSecondary = state[index++];
   4328  this.channel1currentSampleLeftTrimary = state[index++];
   4329  this.channel1currentSampleRightTrimary = state[index++];
   4330  this.channel2currentSampleLeftTrimary = state[index++];
   4331  this.channel2currentSampleRightTrimary = state[index++];
   4332  this.mixerOutputCache = state[index++];
   4333  this.channel1DutyTracker = state[index++];
   4334  this.channel1CachedDuty = state[index++];
   4335  this.channel2DutyTracker = state[index++];
   4336  this.channel2CachedDuty = state[index++];
   4337  this.channel1Enabled = state[index++];
   4338  this.channel2Enabled = state[index++];
   4339  this.channel3Enabled = state[index++];
   4340  this.channel4Enabled = state[index++];
   4341  this.sequencerClocks = state[index++];
   4342  this.sequencePosition = state[index++];
   4343  this.channel3Counter = state[index++];
   4344  this.channel4Counter = state[index++];
   4345  this.cachedChannel3Sample = state[index++];
   4346  this.cachedChannel4Sample = state[index++];
   4347  this.channel3FrequencyPeriod = state[index++];
   4348  this.channel3lastSampleLookup = state[index++];
   4349  this.actualScanLine = state[index++];
   4350  this.lastUnrenderedLine = state[index++];
   4351  this.queuedScanLines = state[index++];
   4352  this.RTCisLatched = state[index++];
   4353  this.latchedSeconds = state[index++];
   4354  this.latchedMinutes = state[index++];
   4355  this.latchedHours = state[index++];
   4356  this.latchedLDays = state[index++];
   4357  this.latchedHDays = state[index++];
   4358  this.RTCSeconds = state[index++];
   4359  this.RTCMinutes = state[index++];
   4360  this.RTCHours = state[index++];
   4361  this.RTCDays = state[index++];
   4362  this.RTCDayOverFlow = state[index++];
   4363  this.RTCHALT = state[index++];
   4364  this.usedBootROM = state[index++];
   4365  this.skipPCIncrement = state[index++];
   4366  this.STATTracker = state[index++];
   4367  this.gbcRamBankPositionECHO = state[index++];
   4368  this.numRAMBanks = state[index++];
   4369  this.windowY = state[index++];
   4370  this.windowX = state[index++];
   4371  this.gbcOBJRawPalette = this.toTypedArray(state[index++], "uint8");
   4372  this.gbcBGRawPalette = this.toTypedArray(state[index++], "uint8");
   4373  this.gbOBJPalette = this.toTypedArray(state[index++], "int32");
   4374  this.gbBGPalette = this.toTypedArray(state[index++], "int32");
   4375  this.gbcOBJPalette = this.toTypedArray(state[index++], "int32");
   4376  this.gbcBGPalette = this.toTypedArray(state[index++], "int32");
   4377  this.gbBGColorizedPalette = this.toTypedArray(state[index++], "int32");
   4378  this.gbOBJColorizedPalette = this.toTypedArray(state[index++], "int32");
   4379  this.cachedBGPaletteConversion = this.toTypedArray(state[index++], "int32");
   4380  this.cachedOBJPaletteConversion = this.toTypedArray(state[index++], "int32");
   4381  this.BGCHRBank1 = this.toTypedArray(state[index++], "uint8");
   4382  this.BGCHRBank2 = this.toTypedArray(state[index++], "uint8");
   4383  this.haltPostClocks = state[index++];
   4384  this.interruptsRequested = state[index++];
   4385  this.interruptsEnabled = state[index++];
   4386  this.checkIRQMatching();
   4387  this.remainingClocks = state[index++];
   4388  this.colorizedGBPalettes = state[index++];
   4389  this.backgroundY = state[index++];
   4390  this.backgroundX = state[index++];
   4391  this.CPUStopped = state[index];
   4392  this.fromSaveState = true;
   4393  this.TICKTable = this.toTypedArray(this.TICKTable, "uint8");
   4394  this.SecondaryTICKTable = this.toTypedArray(this.SecondaryTICKTable, "uint8");
   4395  this.initializeReferencesFromSaveState();
   4396  this.memoryReadJumpCompile();
   4397  this.memoryWriteJumpCompile();
   4398  this.initLCD();
   4399  this.initSound();
   4400  this.noiseSampleTable = (this.channel4BitRange == 0x7FFF) ? this.LSFR15Table : this.LSFR7Table;
   4401  this.channel4VolumeShifter = (this.channel4BitRange == 0x7FFF) ? 15 : 7;
   4402 }
   4403 GameBoyCore.prototype.returnFromRTCState = function () {
   4404  if (typeof this.openRTC == "function" && this.cTIMER) {
   4405    var rtcData = this.openRTC(this.name);
   4406    var index = 0;
   4407    this.lastIteration = rtcData[index++];
   4408    this.RTCisLatched = rtcData[index++];
   4409    this.latchedSeconds = rtcData[index++];
   4410    this.latchedMinutes = rtcData[index++];
   4411    this.latchedHours = rtcData[index++];
   4412    this.latchedLDays = rtcData[index++];
   4413    this.latchedHDays = rtcData[index++];
   4414    this.RTCSeconds = rtcData[index++];
   4415    this.RTCMinutes = rtcData[index++];
   4416    this.RTCHours = rtcData[index++];
   4417    this.RTCDays = rtcData[index++];
   4418    this.RTCDayOverFlow = rtcData[index++];
   4419    this.RTCHALT = rtcData[index];
   4420  }
   4421 }
   4422 
   4423 GameBoyCore.prototype.start = function () {
   4424  this.initMemory();  //Write the startup memory.
   4425  this.ROMLoad();    //Load the ROM into memory and get cartridge information from it.
   4426  this.initLCD();    //Initialize the graphics.
   4427  this.initSound();  //Sound object initialization.
   4428  this.run();      //Start the emulation.
   4429 }
   4430 GameBoyCore.prototype.initMemory = function () {
   4431  //Initialize the RAM:
   4432  this.memory = this.getTypedArray(0x10000, 0, "uint8");
   4433  this.frameBuffer = this.getTypedArray(23040, 0xF8F8F8, "int32");
   4434  this.BGCHRBank1 = this.getTypedArray(0x800, 0, "uint8");
   4435  this.TICKTable = this.toTypedArray(this.TICKTable, "uint8");
   4436  this.SecondaryTICKTable = this.toTypedArray(this.SecondaryTICKTable, "uint8");
   4437  this.channel3PCM = this.getTypedArray(0x20, 0, "int8");
   4438 }
   4439 GameBoyCore.prototype.generateCacheArray = function (tileAmount) {
   4440  var tileArray = [];
   4441  var tileNumber = 0;
   4442  while (tileNumber < tileAmount) {
   4443    tileArray[tileNumber++] = this.getTypedArray(64, 0, "uint8");
   4444  }
   4445  return tileArray;
   4446 }
   4447 GameBoyCore.prototype.initSkipBootstrap = function () {
   4448  //Fill in the boot ROM set register values
   4449  //Default values to the GB boot ROM values, then fill in the GBC boot ROM values after ROM loading
   4450  var index = 0xFF;
   4451  while (index >= 0) {
   4452    if (index >= 0x30 && index < 0x40) {
   4453      this.memoryWrite(0xFF00 | index, this.ffxxDump[index]);
   4454    }
   4455    else {
   4456      switch (index) {
   4457        case 0x00:
   4458        case 0x01:
   4459        case 0x02:
   4460        case 0x05:
   4461        case 0x07:
   4462        case 0x0F:
   4463        case 0xFF:
   4464          this.memoryWrite(0xFF00 | index, this.ffxxDump[index]);
   4465          break;
   4466        default:
   4467          this.memory[0xFF00 | index] = this.ffxxDump[index];
   4468      }
   4469    }
   4470    --index;
   4471  }
   4472  if (this.cGBC) {
   4473    this.memory[0xFF6C] = 0xFE;
   4474    this.memory[0xFF74] = 0xFE;
   4475  }
   4476  else {
   4477    this.memory[0xFF48] = 0xFF;
   4478    this.memory[0xFF49] = 0xFF;
   4479    this.memory[0xFF6C] = 0xFF;
   4480    this.memory[0xFF74] = 0xFF;
   4481  }
   4482  //Start as an unset device:
   4483  cout("Starting without the GBC boot ROM.", 0);
   4484  this.registerA = (this.cGBC) ? 0x11 : 0x1;
   4485  this.registerB = 0;
   4486  this.registerC = 0x13;
   4487  this.registerD = 0;
   4488  this.registerE = 0xD8;
   4489  this.FZero = true;
   4490  this.FSubtract = false;
   4491  this.FHalfCarry = true;
   4492  this.FCarry = true;
   4493  this.registersHL = 0x014D;
   4494  this.LCDCONTROL = this.LINECONTROL;
   4495  this.IME = false;
   4496  this.IRQLineMatched = 0;
   4497  this.interruptsRequested = 225;
   4498  this.interruptsEnabled = 0;
   4499  this.hdmaRunning = false;
   4500  this.CPUTicks = 12;
   4501  this.STATTracker = 0;
   4502  this.modeSTAT = 1;
   4503  this.spriteCount = 252;
   4504  this.LYCMatchTriggerSTAT = false;
   4505  this.mode2TriggerSTAT = false;
   4506  this.mode1TriggerSTAT = false;
   4507  this.mode0TriggerSTAT = false;
   4508  this.LCDisOn = true;
   4509  this.channel1FrequencyTracker = 0x2000;
   4510  this.channel1DutyTracker = 0;
   4511  this.channel1CachedDuty = this.dutyLookup[2];
   4512  this.channel1totalLength = 0;
   4513  this.channel1envelopeVolume = 0;
   4514  this.channel1envelopeType = false;
   4515  this.channel1envelopeSweeps = 0;
   4516  this.channel1envelopeSweepsLast = 0;
   4517  this.channel1consecutive = true;
   4518  this.channel1frequency = 1985;
   4519  this.channel1SweepFault = true;
   4520  this.channel1ShadowFrequency = 1985;
   4521  this.channel1timeSweep = 1;
   4522  this.channel1lastTimeSweep = 0;
   4523  this.channel1numSweep = 0;
   4524  this.channel1frequencySweepDivider = 0;
   4525  this.channel1decreaseSweep = false;
   4526  this.channel2FrequencyTracker = 0x2000;
   4527  this.channel2DutyTracker = 0;
   4528  this.channel2CachedDuty = this.dutyLookup[2];
   4529  this.channel2totalLength = 0;
   4530  this.channel2envelopeVolume = 0;
   4531  this.channel2envelopeType = false;
   4532  this.channel2envelopeSweeps = 0;
   4533  this.channel2envelopeSweepsLast = 0;
   4534  this.channel2consecutive = true;
   4535  this.channel2frequency = 0;
   4536  this.channel3canPlay = false;
   4537  this.channel3totalLength = 0;
   4538  this.channel3patternType = 4;
   4539  this.channel3frequency = 0;
   4540  this.channel3consecutive = true;
   4541  this.channel3Counter = 0x418;
   4542  this.channel4FrequencyPeriod = 8;
   4543  this.channel4totalLength = 0;
   4544  this.channel4envelopeVolume = 0;
   4545  this.channel4currentVolume = 0;
   4546  this.channel4envelopeType = false;
   4547  this.channel4envelopeSweeps = 0;
   4548  this.channel4envelopeSweepsLast = 0;
   4549  this.channel4consecutive = true;
   4550  this.channel4BitRange = 0x7FFF;
   4551  this.channel4VolumeShifter = 15;
   4552  this.channel1FrequencyCounter = 0x200;
   4553  this.channel2FrequencyCounter = 0x200;
   4554  this.channel3Counter = 0x800;
   4555  this.channel3FrequencyPeriod = 0x800;
   4556  this.channel3lastSampleLookup = 0;
   4557  this.channel4lastSampleLookup = 0;
   4558  this.VinLeftChannelMasterVolume = 1;
   4559  this.VinRightChannelMasterVolume = 1;
   4560  this.soundMasterEnabled = true;
   4561  this.leftChannel1 = true;
   4562  this.leftChannel2 = true;
   4563  this.leftChannel3 = true;
   4564  this.leftChannel4 = true;
   4565  this.rightChannel1 = true;
   4566  this.rightChannel2 = true;
   4567  this.rightChannel3 = false;
   4568  this.rightChannel4 = false;
   4569  this.DIVTicks = 27044;
   4570  this.LCDTicks = 160;
   4571  this.timerTicks = 0;
   4572  this.TIMAEnabled = false;
   4573  this.TACClocker = 1024;
   4574  this.serialTimer = 0;
   4575  this.serialShiftTimer = 0;
   4576  this.serialShiftTimerAllocated = 0;
   4577  this.IRQEnableDelay = 0;
   4578  this.actualScanLine = 144;
   4579  this.lastUnrenderedLine = 0;
   4580  this.gfxWindowDisplay = false;
   4581  this.gfxSpriteShow = false;
   4582  this.gfxSpriteNormalHeight = true;
   4583  this.bgEnabled = true;
   4584  this.BGPriorityEnabled = true;
   4585  this.gfxWindowCHRBankPosition = 0;
   4586  this.gfxBackgroundCHRBankPosition = 0;
   4587  this.gfxBackgroundBankOffset = 0;
   4588  this.windowY = 0;
   4589  this.windowX = 0;
   4590  this.drewBlank = 0;
   4591  this.midScanlineOffset = -1;
   4592  this.currentX = 0;
   4593 }
   4594 GameBoyCore.prototype.initBootstrap = function () {
   4595  //Start as an unset device:
   4596  cout("Starting the selected boot ROM.", 0);
   4597  this.programCounter = 0;
   4598  this.stackPointer = 0;
   4599  this.IME = false;
   4600  this.LCDTicks = 0;
   4601  this.DIVTicks = 0;
   4602  this.registerA = 0;
   4603  this.registerB = 0;
   4604  this.registerC = 0;
   4605  this.registerD = 0;
   4606  this.registerE = 0;
   4607  this.FZero = this.FSubtract = this.FHalfCarry = this.FCarry = false;
   4608  this.registersHL = 0;
   4609  this.leftChannel1 = false;
   4610  this.leftChannel2 = false;
   4611  this.leftChannel3 = false;
   4612  this.leftChannel4 = false;
   4613  this.rightChannel1 = false;
   4614  this.rightChannel2 = false;
   4615  this.rightChannel3 = false;
   4616  this.rightChannel4 = false;
   4617  this.channel2frequency = this.channel1frequency = 0;
   4618  this.channel4consecutive = this.channel2consecutive = this.channel1consecutive = false;
   4619  this.VinLeftChannelMasterVolume = 8;
   4620  this.VinRightChannelMasterVolume = 8;
   4621  this.memory[0xFF00] = 0xF;  //Set the joypad state.
   4622 }
   4623 GameBoyCore.prototype.ROMLoad = function () {
   4624  //Load the first two ROM banks (0x0000 - 0x7FFF) into regular gameboy memory:
   4625  this.ROM = [];
   4626  this.usedBootROM = settings[1];
   4627  var maxLength = this.ROMImage.length;
   4628  if (maxLength < 0x4000) {
   4629    throw(new Error("ROM image size too small."));
   4630  }
   4631  this.ROM = this.getTypedArray(maxLength, 0, "uint8");
   4632  var romIndex = 0;
   4633  if (this.usedBootROM) {
   4634    if (!settings[11]) {
   4635      //Patch in the GBC boot ROM into the memory map:
   4636      for (; romIndex < 0x100; ++romIndex) {
   4637        this.memory[romIndex] = this.GBCBOOTROM[romIndex];                      //Load in the GameBoy Color BOOT ROM.
   4638        this.ROM[romIndex] = (this.ROMImage.charCodeAt(romIndex) & 0xFF);              //Decode the ROM binary for the switch out.
   4639      }
   4640      for (; romIndex < 0x200; ++romIndex) {
   4641        this.memory[romIndex] = this.ROM[romIndex] = (this.ROMImage.charCodeAt(romIndex) & 0xFF);  //Load in the game ROM.
   4642      }
   4643      for (; romIndex < 0x900; ++romIndex) {
   4644        this.memory[romIndex] = this.GBCBOOTROM[romIndex - 0x100];                  //Load in the GameBoy Color BOOT ROM.
   4645        this.ROM[romIndex] = (this.ROMImage.charCodeAt(romIndex) & 0xFF);              //Decode the ROM binary for the switch out.
   4646      }
   4647      this.usedGBCBootROM = true;
   4648    }
   4649    else {
   4650      //Patch in the GBC boot ROM into the memory map:
   4651      for (; romIndex < 0x100; ++romIndex) {
   4652        this.memory[romIndex] = this.GBBOOTROM[romIndex];                      //Load in the GameBoy Color BOOT ROM.
   4653        this.ROM[romIndex] = (this.ROMImage.charCodeAt(romIndex) & 0xFF);              //Decode the ROM binary for the switch out.
   4654      }
   4655    }
   4656    for (; romIndex < 0x4000; ++romIndex) {
   4657      this.memory[romIndex] = this.ROM[romIndex] = (this.ROMImage.charCodeAt(romIndex) & 0xFF);  //Load in the game ROM.
   4658    }
   4659  }
   4660  else {
   4661    //Don't load in the boot ROM:
   4662    for (; romIndex < 0x4000; ++romIndex) {
   4663      this.memory[romIndex] = this.ROM[romIndex] = (this.ROMImage.charCodeAt(romIndex) & 0xFF);  //Load in the game ROM.
   4664    }
   4665  }
   4666  //Finish the decoding of the ROM binary:
   4667  for (; romIndex < maxLength; ++romIndex) {
   4668    this.ROM[romIndex] = (this.ROMImage.charCodeAt(romIndex) & 0xFF);
   4669  }
   4670  this.ROMBankEdge = Math.floor(this.ROM.length / 0x4000);
   4671  //Set up the emulator for the cartidge specifics:
   4672  this.interpretCartridge();
   4673  //Check for IRQ matching upon initialization:
   4674  this.checkIRQMatching();
   4675 }
   4676 GameBoyCore.prototype.getROMImage = function () {
   4677  //Return the binary version of the ROM image currently running:
   4678  if (this.ROMImage.length > 0) {
   4679    return this.ROMImage.length;
   4680  }
   4681  var length = this.ROM.length;
   4682  for (var index = 0; index < length; index++) {
   4683    this.ROMImage += String.fromCharCode(this.ROM[index]);
   4684  }
   4685  return this.ROMImage;
   4686 }
   4687 GameBoyCore.prototype.interpretCartridge = function () {
   4688  // ROM name
   4689  for (var index = 0x134; index < 0x13F; index++) {
   4690    if (this.ROMImage.charCodeAt(index) > 0) {
   4691      this.name += this.ROMImage[index];
   4692    }
   4693  }
   4694  // ROM game code (for newer games)
   4695  for (var index = 0x13F; index < 0x143; index++) {
   4696    if (this.ROMImage.charCodeAt(index) > 0) {
   4697      this.gameCode += this.ROMImage[index];
   4698    }
   4699  }
   4700  cout("Game Title: " + this.name + "[" + this.gameCode + "][" + this.ROMImage[0x143] + "]", 0);
   4701  cout("Game Code: " + this.gameCode, 0);
   4702  // Cartridge type
   4703  this.cartridgeType = this.ROM[0x147];
   4704  cout("Cartridge type #" + this.cartridgeType, 0);
   4705  //Map out ROM cartridge sub-types.
   4706  var MBCType = "";
   4707  switch (this.cartridgeType) {
   4708    case 0x00:
   4709      //ROM w/o bank switching
   4710      if (!settings[9]) {
   4711        MBCType = "ROM";
   4712        break;
   4713      }
   4714    case 0x01:
   4715      this.cMBC1 = true;
   4716      MBCType = "MBC1";
   4717      break;
   4718    case 0x02:
   4719      this.cMBC1 = true;
   4720      this.cSRAM = true;
   4721      MBCType = "MBC1 + SRAM";
   4722      break;
   4723    case 0x03:
   4724      this.cMBC1 = true;
   4725      this.cSRAM = true;
   4726      this.cBATT = true;
   4727      MBCType = "MBC1 + SRAM + BATT";
   4728      break;
   4729    case 0x05:
   4730      this.cMBC2 = true;
   4731      MBCType = "MBC2";
   4732      break;
   4733    case 0x06:
   4734      this.cMBC2 = true;
   4735      this.cBATT = true;
   4736      MBCType = "MBC2 + BATT";
   4737      break;
   4738    case 0x08:
   4739      this.cSRAM = true;
   4740      MBCType = "ROM + SRAM";
   4741      break;
   4742    case 0x09:
   4743      this.cSRAM = true;
   4744      this.cBATT = true;
   4745      MBCType = "ROM + SRAM + BATT";
   4746      break;
   4747    case 0x0B:
   4748      this.cMMMO1 = true;
   4749      MBCType = "MMMO1";
   4750      break;
   4751    case 0x0C:
   4752      this.cMMMO1 = true;
   4753      this.cSRAM = true;
   4754      MBCType = "MMMO1 + SRAM";
   4755      break;
   4756    case 0x0D:
   4757      this.cMMMO1 = true;
   4758      this.cSRAM = true;
   4759      this.cBATT = true;
   4760      MBCType = "MMMO1 + SRAM + BATT";
   4761      break;
   4762    case 0x0F:
   4763      this.cMBC3 = true;
   4764      this.cTIMER = true;
   4765      this.cBATT = true;
   4766      MBCType = "MBC3 + TIMER + BATT";
   4767      break;
   4768    case 0x10:
   4769      this.cMBC3 = true;
   4770      this.cTIMER = true;
   4771      this.cBATT = true;
   4772      this.cSRAM = true;
   4773      MBCType = "MBC3 + TIMER + BATT + SRAM";
   4774      break;
   4775    case 0x11:
   4776      this.cMBC3 = true;
   4777      MBCType = "MBC3";
   4778      break;
   4779    case 0x12:
   4780      this.cMBC3 = true;
   4781      this.cSRAM = true;
   4782      MBCType = "MBC3 + SRAM";
   4783      break;
   4784    case 0x13:
   4785      this.cMBC3 = true;
   4786      this.cSRAM = true;
   4787      this.cBATT = true;
   4788      MBCType = "MBC3 + SRAM + BATT";
   4789      break;
   4790    case 0x19:
   4791      this.cMBC5 = true;
   4792      MBCType = "MBC5";
   4793      break;
   4794    case 0x1A:
   4795      this.cMBC5 = true;
   4796      this.cSRAM = true;
   4797      MBCType = "MBC5 + SRAM";
   4798      break;
   4799    case 0x1B:
   4800      this.cMBC5 = true;
   4801      this.cSRAM = true;
   4802      this.cBATT = true;
   4803      MBCType = "MBC5 + SRAM + BATT";
   4804      break;
   4805    case 0x1C:
   4806      this.cRUMBLE = true;
   4807      MBCType = "RUMBLE";
   4808      break;
   4809    case 0x1D:
   4810      this.cRUMBLE = true;
   4811      this.cSRAM = true;
   4812      MBCType = "RUMBLE + SRAM";
   4813      break;
   4814    case 0x1E:
   4815      this.cRUMBLE = true;
   4816      this.cSRAM = true;
   4817      this.cBATT = true;
   4818      MBCType = "RUMBLE + SRAM + BATT";
   4819      break;
   4820    case 0x1F:
   4821      this.cCamera = true;
   4822      MBCType = "GameBoy Camera";
   4823      break;
   4824    case 0x22:
   4825      this.cMBC7 = true;
   4826      this.cSRAM = true;
   4827      this.cBATT = true;
   4828      MBCType = "MBC7 + SRAM + BATT";
   4829      break;
   4830    case 0xFD:
   4831      this.cTAMA5 = true;
   4832      MBCType = "TAMA5";
   4833      break;
   4834    case 0xFE:
   4835      this.cHuC3 = true;
   4836      MBCType = "HuC3";
   4837      break;
   4838    case 0xFF:
   4839      this.cHuC1 = true;
   4840      MBCType = "HuC1";
   4841      break;
   4842    default:
   4843      MBCType = "Unknown";
   4844      cout("Cartridge type is unknown.", 2);
   4845      pause();
   4846  }
   4847  cout("Cartridge Type: " + MBCType + ".", 0);
   4848  // ROM and RAM banks
   4849  this.numROMBanks = this.ROMBanks[this.ROM[0x148]];
   4850  cout(this.numROMBanks + " ROM banks.", 0);
   4851  switch (this.RAMBanks[this.ROM[0x149]]) {
   4852    case 0:
   4853      cout("No RAM banking requested for allocation or MBC is of type 2.", 0);
   4854      break;
   4855    case 2:
   4856      cout("1 RAM bank requested for allocation.", 0);
   4857      break;
   4858    case 3:
   4859      cout("4 RAM banks requested for allocation.", 0);
   4860      break;
   4861    case 4:
   4862      cout("16 RAM banks requested for allocation.", 0);
   4863      break;
   4864    default:
   4865      cout("RAM bank amount requested is unknown, will use maximum allowed by specified MBC type.", 0);
   4866  }
   4867  //Check the GB/GBC mode byte:
   4868  if (!this.usedBootROM) {
   4869    switch (this.ROM[0x143]) {
   4870      case 0x00:  //Only GB mode
   4871        this.cGBC = false;
   4872        cout("Only GB mode detected.", 0);
   4873        break;
   4874      case 0x32:  //Exception to the GBC identifying code:
   4875        if (!settings[2] && this.name + this.gameCode + this.ROM[0x143] == "Game and Watch 50") {
   4876          this.cGBC = true;
   4877          cout("Created a boot exception for Game and Watch Gallery 2 (GBC ID byte is wrong on the cartridge).", 1);
   4878        }
   4879        else {
   4880          this.cGBC = false;
   4881        }
   4882        break;
   4883      case 0x80:  //Both GB + GBC modes
   4884        this.cGBC = !settings[2];
   4885        cout("GB and GBC mode detected.", 0);
   4886        break;
   4887      case 0xC0:  //Only GBC mode
   4888        this.cGBC = true;
   4889        cout("Only GBC mode detected.", 0);
   4890        break;
   4891      default:
   4892        this.cGBC = false;
   4893        cout("Unknown GameBoy game type code #" + this.ROM[0x143] + ", defaulting to GB mode (Old games don't have a type code).", 1);
   4894    }
   4895    this.inBootstrap = false;
   4896    this.setupRAM();  //CPU/(V)RAM initialization.
   4897    this.initSkipBootstrap();
   4898    this.initializeAudioStartState(); // Line added for benchmarking.
   4899  }
   4900  else {
   4901    this.cGBC = this.usedGBCBootROM;  //Allow the GBC boot ROM to run in GBC mode...
   4902    this.setupRAM();  //CPU/(V)RAM initialization.
   4903    this.initBootstrap();
   4904  }
   4905  this.initializeModeSpecificArrays();
   4906  //License Code Lookup:
   4907  var cOldLicense = this.ROM[0x14B];
   4908  var cNewLicense = (this.ROM[0x144] & 0xFF00) | (this.ROM[0x145] & 0xFF);
   4909  if (cOldLicense != 0x33) {
   4910    //Old Style License Header
   4911    cout("Old style license code: " + cOldLicense, 0);
   4912  }
   4913  else {
   4914    //New Style License Header
   4915    cout("New style license code: " + cNewLicense, 0);
   4916  }
   4917  this.ROMImage = "";  //Memory consumption reduction.
   4918 }
   4919 GameBoyCore.prototype.disableBootROM = function () {
   4920  //Remove any traces of the boot ROM from ROM memory.
   4921  for (var index = 0; index < 0x100; ++index) {
   4922    this.memory[index] = this.ROM[index];  //Replace the GameBoy or GameBoy Color boot ROM with the game ROM.
   4923  }
   4924  if (this.usedGBCBootROM) {
   4925    //Remove any traces of the boot ROM from ROM memory.
   4926    for (index = 0x200; index < 0x900; ++index) {
   4927      this.memory[index] = this.ROM[index];  //Replace the GameBoy Color boot ROM with the game ROM.
   4928    }
   4929    if (!this.cGBC) {
   4930      //Clean up the post-boot (GB mode only) state:
   4931      this.GBCtoGBModeAdjust();
   4932    }
   4933    else {
   4934      this.recompileBootIOWriteHandling();
   4935    }
   4936  }
   4937  else {
   4938    this.recompileBootIOWriteHandling();
   4939  }
   4940 }
   4941 GameBoyCore.prototype.initializeTiming = function () {
   4942  //Emulator Timing:
   4943  this.baseCPUCyclesPerIteration = 0x80000 / 0x7D * settings[6];
   4944  this.CPUCyclesTotalRoundoff = this.baseCPUCyclesPerIteration % 4;
   4945  this.CPUCyclesTotalBase = this.CPUCyclesTotal = (this.baseCPUCyclesPerIteration - this.CPUCyclesTotalRoundoff) | 0;
   4946  this.CPUCyclesTotalCurrent = 0;
   4947 }
   4948 GameBoyCore.prototype.setupRAM = function () {
   4949  //Setup the auxilliary/switchable RAM:
   4950  if (this.cMBC2) {
   4951    this.numRAMBanks = 1 / 16;
   4952  }
   4953  else if (this.cMBC1 || this.cRUMBLE || this.cMBC3 || this.cHuC3) {
   4954    this.numRAMBanks = 4;
   4955  }
   4956  else if (this.cMBC5) {
   4957    this.numRAMBanks = 16;
   4958  }
   4959  else if (this.cSRAM) {
   4960    this.numRAMBanks = 1;
   4961  }
   4962  if (this.numRAMBanks > 0) {
   4963    if (!this.MBCRAMUtilized()) {
   4964      //For ROM and unknown MBC cartridges using the external RAM:
   4965      this.MBCRAMBanksEnabled = true;
   4966    }
   4967    //Switched RAM Used
   4968    var MBCRam = (typeof this.openMBC == "function") ? this.openMBC(this.name) : [];
   4969    if (MBCRam.length > 0) {
   4970      //Flash the SRAM into memory:
   4971      this.MBCRam = this.toTypedArray(MBCRam, "uint8");
   4972    }
   4973    else {
   4974      this.MBCRam = this.getTypedArray(this.numRAMBanks * 0x2000, 0, "uint8");
   4975    }
   4976  }
   4977  cout("Actual bytes of MBC RAM allocated: " + (this.numRAMBanks * 0x2000), 0);
   4978  this.returnFromRTCState();
   4979  //Setup the RAM for GBC mode.
   4980  if (this.cGBC) {
   4981    this.VRAM = this.getTypedArray(0x2000, 0, "uint8");
   4982    this.GBCMemory = this.getTypedArray(0x7000, 0, "uint8");
   4983  }
   4984  this.memoryReadJumpCompile();
   4985  this.memoryWriteJumpCompile();
   4986 }
   4987 GameBoyCore.prototype.MBCRAMUtilized = function () {
   4988  return this.cMBC1 || this.cMBC2 || this.cMBC3 || this.cMBC5 || this.cMBC7 || this.cRUMBLE;
   4989 }
   4990 GameBoyCore.prototype.recomputeDimension = function () {
   4991  initNewCanvas();
   4992  //Cache some dimension info:
   4993  this.onscreenWidth = this.canvas.width;
   4994  this.onscreenHeight = this.canvas.height;
   4995  // The following line was modified for benchmarking:
   4996  if (GameBoyWindow && GameBoyWindow.mozRequestAnimationFrame) {
   4997    //Firefox slowness hack:
   4998    this.canvas.width = this.onscreenWidth = (!settings[12]) ? 160 : this.canvas.width;
   4999    this.canvas.height = this.onscreenHeight = (!settings[12]) ? 144 : this.canvas.height;
   5000  }
   5001  else {
   5002    this.onscreenWidth = this.canvas.width;
   5003    this.onscreenHeight = this.canvas.height;
   5004  }
   5005  this.offscreenWidth = (!settings[12]) ? 160 : this.canvas.width;
   5006  this.offscreenHeight = (!settings[12]) ? 144 : this.canvas.height;
   5007  this.offscreenRGBCount = this.offscreenWidth * this.offscreenHeight * 4;
   5008 }
   5009 GameBoyCore.prototype.initLCD = function () {
   5010  this.recomputeDimension();
   5011  if (this.offscreenRGBCount != 92160) {
   5012    //Only create the resizer handle if we need it:
   5013    this.compileResizeFrameBufferFunction();
   5014  }
   5015  else {
   5016    //Resizer not needed:
   5017    this.resizer = null;
   5018  }
   5019  try {
   5020    this.canvasOffscreen = new GameBoyCanvas();  // Line modified for benchmarking.
   5021    this.canvasOffscreen.width = this.offscreenWidth;
   5022    this.canvasOffscreen.height = this.offscreenHeight;
   5023    this.drawContextOffscreen = this.canvasOffscreen.getContext("2d");
   5024    this.drawContextOnscreen = this.canvas.getContext("2d");
   5025    //Get a CanvasPixelArray buffer:
   5026    try {
   5027      this.canvasBuffer = this.drawContextOffscreen.createImageData(this.offscreenWidth, this.offscreenHeight);
   5028    }
   5029    catch (error) {
   5030      cout("Falling back to the getImageData initialization (Error \"" + error.message + "\").", 1);
   5031      this.canvasBuffer = this.drawContextOffscreen.getImageData(0, 0, this.offscreenWidth, this.offscreenHeight);
   5032    }
   5033    var index = this.offscreenRGBCount;
   5034    while (index > 0) {
   5035      this.canvasBuffer.data[index -= 4] = 0xF8;
   5036      this.canvasBuffer.data[index + 1] = 0xF8;
   5037      this.canvasBuffer.data[index + 2] = 0xF8;
   5038      this.canvasBuffer.data[index + 3] = 0xFF;
   5039    }
   5040    this.graphicsBlit();
   5041    this.canvas.style.visibility = "visible";
   5042    if (this.swizzledFrame == null) {
   5043      this.swizzledFrame = this.getTypedArray(69120, 0xFF, "uint8");
   5044    }
   5045    //Test the draw system and browser vblank latching:
   5046    this.drewFrame = true;                    //Copy the latest graphics to buffer.
   5047    this.requestDraw();
   5048  }
   5049  catch (error) {
   5050    throw(new Error("HTML5 Canvas support required: " + error.message + "file: " + error.fileName + ", line: " + error.lineNumber));
   5051  }
   5052 }
   5053 GameBoyCore.prototype.graphicsBlit = function () {
   5054  if (this.offscreenWidth == this.onscreenWidth && this.offscreenHeight == this.onscreenHeight) {
   5055    this.drawContextOnscreen.putImageData(this.canvasBuffer, 0, 0);
   5056  }
   5057  else {
   5058    this.drawContextOffscreen.putImageData(this.canvasBuffer, 0, 0);
   5059    this.drawContextOnscreen.drawImage(this.canvasOffscreen, 0, 0, this.onscreenWidth, this.onscreenHeight);
   5060  }
   5061 }
   5062 GameBoyCore.prototype.JoyPadEvent = function (key, down) {
   5063  if (down) {
   5064    this.JoyPad &= 0xFF ^ (1 << key);
   5065    if (!this.cGBC && (!this.usedBootROM || !this.usedGBCBootROM)) {
   5066      this.interruptsRequested |= 0x10;  //A real GBC doesn't set this!
   5067      this.remainingClocks = 0;
   5068      this.checkIRQMatching();
   5069    }
   5070  }
   5071  else {
   5072    this.JoyPad |= (1 << key);
   5073  }
   5074  this.memory[0xFF00] = (this.memory[0xFF00] & 0x30) + ((((this.memory[0xFF00] & 0x20) == 0) ? (this.JoyPad >> 4) : 0xF) & (((this.memory[0xFF00] & 0x10) == 0) ? (this.JoyPad & 0xF) : 0xF));
   5075  this.CPUStopped = false;
   5076 }
   5077 GameBoyCore.prototype.GyroEvent = function (x, y) {
   5078  x *= -100;
   5079  x += 2047;
   5080  this.highX = x >> 8;
   5081  this.lowX = x & 0xFF;
   5082  y *= -100;
   5083  y += 2047;
   5084  this.highY = y >> 8;
   5085  this.lowY = y & 0xFF;
   5086 }
   5087 GameBoyCore.prototype.initSound = function () {
   5088  this.sampleSize = 0x400000 / 1000 * settings[6];
   5089  this.machineOut = settings[13];
   5090  if (settings[0]) {
   5091    try {
   5092      var parentObj = this;
   5093      this.audioHandle = new XAudioServer(2, 0x400000 / settings[13], 0, Math.max(this.sampleSize * settings[8] / settings[13], 8192) << 1, null, settings[14]);
   5094      this.initAudioBuffer();
   5095    }
   5096    catch (error) {
   5097      cout("Audio system cannot run: " + error.message, 2);
   5098      settings[0] = false;
   5099    }
   5100  }
   5101  else if (this.audioHandle) {
   5102    //Mute the audio output, as it has an immediate silencing effect:
   5103    try {
   5104      this.audioHandle.changeVolume(0);
   5105    }
   5106    catch (error) { }
   5107  }
   5108 }
   5109 GameBoyCore.prototype.changeVolume = function () {
   5110  if (settings[0] && this.audioHandle) {
   5111    try {
   5112      this.audioHandle.changeVolume(settings[14]);
   5113    }
   5114    catch (error) { }
   5115  }
   5116 }
   5117 GameBoyCore.prototype.initAudioBuffer = function () {
   5118  this.audioIndex = 0;
   5119  this.bufferContainAmount = Math.max(this.sampleSize * settings[7] / settings[13], 4096) << 1;
   5120  this.numSamplesTotal = (this.sampleSize - (this.sampleSize % settings[13])) | 0;
   5121  this.currentBuffer = this.getTypedArray(this.numSamplesTotal, 0xF0F0, "int32");
   5122  this.secondaryBuffer = this.getTypedArray((this.numSamplesTotal << 1) / settings[13], 0, "float32");
   5123 }
   5124 GameBoyCore.prototype.intializeWhiteNoise = function () {
   5125  //Noise Sample Tables:
   5126  var randomFactor = 1;
   5127  //15-bit LSFR Cache Generation:
   5128  this.LSFR15Table = this.getTypedArray(0x80000, 0, "int8");
   5129  var LSFR = 0x7FFF;  //Seed value has all its bits set.
   5130  var LSFRShifted = 0x3FFF;
   5131  for (var index = 0; index < 0x8000; ++index) {
   5132    //Normalize the last LSFR value for usage:
   5133    randomFactor = 1 - (LSFR & 1);  //Docs say it's the inverse.
   5134    //Cache the different volume level results:
   5135    this.LSFR15Table[0x08000 | index] = randomFactor;
   5136    this.LSFR15Table[0x10000 | index] = randomFactor * 0x2;
   5137    this.LSFR15Table[0x18000 | index] = randomFactor * 0x3;
   5138    this.LSFR15Table[0x20000 | index] = randomFactor * 0x4;
   5139    this.LSFR15Table[0x28000 | index] = randomFactor * 0x5;
   5140    this.LSFR15Table[0x30000 | index] = randomFactor * 0x6;
   5141    this.LSFR15Table[0x38000 | index] = randomFactor * 0x7;
   5142    this.LSFR15Table[0x40000 | index] = randomFactor * 0x8;
   5143    this.LSFR15Table[0x48000 | index] = randomFactor * 0x9;
   5144    this.LSFR15Table[0x50000 | index] = randomFactor * 0xA;
   5145    this.LSFR15Table[0x58000 | index] = randomFactor * 0xB;
   5146    this.LSFR15Table[0x60000 | index] = randomFactor * 0xC;
   5147    this.LSFR15Table[0x68000 | index] = randomFactor * 0xD;
   5148    this.LSFR15Table[0x70000 | index] = randomFactor * 0xE;
   5149    this.LSFR15Table[0x78000 | index] = randomFactor * 0xF;
   5150    //Recompute the LSFR algorithm:
   5151    LSFRShifted = LSFR >> 1;
   5152    LSFR = LSFRShifted | (((LSFRShifted ^ LSFR) & 0x1) << 14);
   5153  }
   5154  //7-bit LSFR Cache Generation:
   5155  this.LSFR7Table = this.getTypedArray(0x800, 0, "int8");
   5156  LSFR = 0x7F;  //Seed value has all its bits set.
   5157  for (index = 0; index < 0x80; ++index) {
   5158    //Normalize the last LSFR value for usage:
   5159    randomFactor = 1 - (LSFR & 1);  //Docs say it's the inverse.
   5160    //Cache the different volume level results:
   5161    this.LSFR7Table[0x080 | index] = randomFactor;
   5162    this.LSFR7Table[0x100 | index] = randomFactor * 0x2;
   5163    this.LSFR7Table[0x180 | index] = randomFactor * 0x3;
   5164    this.LSFR7Table[0x200 | index] = randomFactor * 0x4;
   5165    this.LSFR7Table[0x280 | index] = randomFactor * 0x5;
   5166    this.LSFR7Table[0x300 | index] = randomFactor * 0x6;
   5167    this.LSFR7Table[0x380 | index] = randomFactor * 0x7;
   5168    this.LSFR7Table[0x400 | index] = randomFactor * 0x8;
   5169    this.LSFR7Table[0x480 | index] = randomFactor * 0x9;
   5170    this.LSFR7Table[0x500 | index] = randomFactor * 0xA;
   5171    this.LSFR7Table[0x580 | index] = randomFactor * 0xB;
   5172    this.LSFR7Table[0x600 | index] = randomFactor * 0xC;
   5173    this.LSFR7Table[0x680 | index] = randomFactor * 0xD;
   5174    this.LSFR7Table[0x700 | index] = randomFactor * 0xE;
   5175    this.LSFR7Table[0x780 | index] = randomFactor * 0xF;
   5176    //Recompute the LSFR algorithm:
   5177    LSFRShifted = LSFR >> 1;
   5178    LSFR = LSFRShifted | (((LSFRShifted ^ LSFR) & 0x1) << 6);
   5179  }
   5180  if (!this.noiseSampleTable && this.memory.length == 0x10000) {
   5181    //If enabling audio for the first time after a game is already running, set up the internal table reference:
   5182    this.noiseSampleTable = ((this.memory[0xFF22] & 0x8) == 0x8) ? this.LSFR7Table : this.LSFR15Table;
   5183  }
   5184 }
   5185 GameBoyCore.prototype.audioUnderrunAdjustment = function () {
   5186  if (settings[0]) {
   5187    var underrunAmount = this.bufferContainAmount - this.audioHandle.remainingBuffer();
   5188    if (underrunAmount > 0) {
   5189      this.CPUCyclesTotalCurrent += (underrunAmount >> 1) * this.machineOut;
   5190      this.recalculateIterationClockLimit();
   5191    }
   5192  }
   5193 }
   5194 GameBoyCore.prototype.initializeAudioStartState = function () {
   5195  this.channel1FrequencyTracker = 0x2000;
   5196  this.channel1DutyTracker = 0;
   5197  this.channel1CachedDuty = this.dutyLookup[2];
   5198  this.channel1totalLength = 0;
   5199  this.channel1envelopeVolume = 0;
   5200  this.channel1envelopeType = false;
   5201  this.channel1envelopeSweeps = 0;
   5202  this.channel1envelopeSweepsLast = 0;
   5203  this.channel1consecutive = true;
   5204  this.channel1frequency = 0;
   5205  this.channel1SweepFault = false;
   5206  this.channel1ShadowFrequency = 0;
   5207  this.channel1timeSweep = 1;
   5208  this.channel1lastTimeSweep = 0;
   5209  this.channel1numSweep = 0;
   5210  this.channel1frequencySweepDivider = 0;
   5211  this.channel1decreaseSweep = false;
   5212  this.channel2FrequencyTracker = 0x2000;
   5213  this.channel2DutyTracker = 0;
   5214  this.channel2CachedDuty = this.dutyLookup[2];
   5215  this.channel2totalLength = 0;
   5216  this.channel2envelopeVolume = 0;
   5217  this.channel2envelopeType = false;
   5218  this.channel2envelopeSweeps = 0;
   5219  this.channel2envelopeSweepsLast = 0;
   5220  this.channel2consecutive = true;
   5221  this.channel2frequency = 0;
   5222  this.channel3canPlay = false;
   5223  this.channel3totalLength = 0;
   5224  this.channel3patternType = 4;
   5225  this.channel3frequency = 0;
   5226  this.channel3consecutive = true;
   5227  this.channel3Counter = 0x800;
   5228  this.channel4FrequencyPeriod = 8;
   5229  this.channel4totalLength = 0;
   5230  this.channel4envelopeVolume = 0;
   5231  this.channel4currentVolume = 0;
   5232  this.channel4envelopeType = false;
   5233  this.channel4envelopeSweeps = 0;
   5234  this.channel4envelopeSweepsLast = 0;
   5235  this.channel4consecutive = true;
   5236  this.channel4BitRange = 0x7FFF;
   5237  this.noiseSampleTable = this.LSFR15Table;
   5238  this.channel4VolumeShifter = 15;
   5239  this.channel1FrequencyCounter = 0x2000;
   5240  this.channel2FrequencyCounter = 0x2000;
   5241  this.channel3Counter = 0x800;
   5242  this.channel3FrequencyPeriod = 0x800;
   5243  this.channel3lastSampleLookup = 0;
   5244  this.channel4lastSampleLookup = 0;
   5245  this.VinLeftChannelMasterVolume = 8;
   5246  this.VinRightChannelMasterVolume = 8;
   5247  this.mixerOutputCache = 0;
   5248  this.sequencerClocks = 0x2000;
   5249  this.sequencePosition = 0;
   5250  this.channel4FrequencyPeriod = 8;
   5251  this.channel4Counter = 8;
   5252  this.cachedChannel3Sample = 0;
   5253  this.cachedChannel4Sample = 0;
   5254  this.channel1Enabled = false;
   5255  this.channel2Enabled = false;
   5256  this.channel3Enabled = false;
   5257  this.channel4Enabled = false;
   5258  this.channel1canPlay = false;
   5259  this.channel2canPlay = false;
   5260  this.channel4canPlay = false;
   5261  this.channel1OutputLevelCache();
   5262  this.channel2OutputLevelCache();
   5263  this.channel3OutputLevelCache();
   5264  this.channel4OutputLevelCache();
   5265 }
   5266 GameBoyCore.prototype.outputAudio = function () {
   5267  var sampleFactor = 0;
   5268  var dirtySample = 0;
   5269  var averageL = 0;
   5270  var averageR = 0;
   5271  var destinationPosition = 0;
   5272  var divisor1 = settings[13];
   5273  var divisor2 = divisor1 * 0xF0;
   5274  for (var sourcePosition = 0; sourcePosition < this.numSamplesTotal;) {
   5275    for (sampleFactor = averageL = averageR = 0; sampleFactor < divisor1; ++sampleFactor) {
   5276      dirtySample = this.currentBuffer[sourcePosition++];
   5277      averageL += dirtySample >> 9;
   5278      averageR += dirtySample & 0x1FF;
   5279    }
   5280    this.secondaryBuffer[destinationPosition++] = averageL / divisor2 - 1;
   5281    this.secondaryBuffer[destinationPosition++] = averageR / divisor2 - 1;
   5282  }
   5283  this.audioHandle.writeAudioNoCallback(this.secondaryBuffer);
   5284 }
   5285 //Below are the audio generation functions timed against the CPU:
   5286 GameBoyCore.prototype.generateAudio = function (numSamples) {
   5287  if (this.soundMasterEnabled && !this.CPUStopped) {
   5288    for (var samplesToGenerate = 0; numSamples > 0;) {
   5289      samplesToGenerate = (numSamples < this.sequencerClocks) ? numSamples : this.sequencerClocks;
   5290      this.sequencerClocks -= samplesToGenerate;
   5291      numSamples -= samplesToGenerate;
   5292      while (--samplesToGenerate > -1) {
   5293        this.computeAudioChannels();
   5294        this.currentBuffer[this.audioIndex++] = this.mixerOutputCache;
   5295        if (this.audioIndex == this.numSamplesTotal) {
   5296          this.audioIndex = 0;
   5297          this.outputAudio();
   5298        }
   5299      }
   5300      if (this.sequencerClocks == 0) {
   5301        this.audioComputeSequencer();
   5302        this.sequencerClocks = 0x2000;
   5303      }
   5304    }
   5305  }
   5306  else {
   5307    //SILENT OUTPUT:
   5308    while (--numSamples > -1) {
   5309      this.currentBuffer[this.audioIndex++] = 0xF0F0;
   5310      if (this.audioIndex == this.numSamplesTotal) {
   5311        this.audioIndex = 0;
   5312        this.outputAudio();
   5313      }
   5314    }
   5315  }
   5316 }
   5317 //Generate audio, but don't actually output it (Used for when sound is disabled by user/browser):
   5318 GameBoyCore.prototype.generateAudioFake = function (numSamples) {
   5319  if (this.soundMasterEnabled && !this.CPUStopped) {
   5320    while (--numSamples > -1) {
   5321      this.computeAudioChannels();
   5322      if (--this.sequencerClocks == 0) {
   5323        this.audioComputeSequencer();
   5324        this.sequencerClocks = 0x2000;
   5325      }
   5326    }
   5327  }
   5328 }
   5329 GameBoyCore.prototype.audioJIT = function () {
   5330  //Audio Sample Generation Timing:
   5331  if (settings[0]) {
   5332    this.generateAudio(this.audioTicks);
   5333  }
   5334  else {
   5335    this.generateAudioFake(this.audioTicks);
   5336  }
   5337  this.audioTicks = 0;
   5338 }
   5339 GameBoyCore.prototype.audioComputeSequencer = function () {
   5340  switch (this.sequencePosition++) {
   5341    case 0:
   5342      this.clockAudioLength();
   5343      break;
   5344    case 2:
   5345      this.clockAudioLength();
   5346      this.clockAudioSweep();
   5347      break;
   5348    case 4:
   5349      this.clockAudioLength();
   5350      break;
   5351    case 6:
   5352      this.clockAudioLength();
   5353      this.clockAudioSweep();
   5354      break;
   5355    case 7:
   5356      this.clockAudioEnvelope();
   5357      this.sequencePosition = 0;
   5358  }
   5359 }
   5360 GameBoyCore.prototype.clockAudioLength = function () {
   5361  //Channel 1:
   5362  if (this.channel1totalLength > 1) {
   5363    --this.channel1totalLength;
   5364  }
   5365  else if (this.channel1totalLength == 1) {
   5366    this.channel1totalLength = 0;
   5367    this.channel1EnableCheck();
   5368    this.memory[0xFF26] &= 0xFE;  //Channel #1 On Flag Off
   5369  }
   5370  //Channel 2:
   5371  if (this.channel2totalLength > 1) {
   5372    --this.channel2totalLength;
   5373  }
   5374  else if (this.channel2totalLength == 1) {
   5375    this.channel2totalLength = 0;
   5376    this.channel2EnableCheck();
   5377    this.memory[0xFF26] &= 0xFD;  //Channel #2 On Flag Off
   5378  }
   5379  //Channel 3:
   5380  if (this.channel3totalLength > 1) {
   5381    --this.channel3totalLength;
   5382  }
   5383  else if (this.channel3totalLength == 1) {
   5384    this.channel3totalLength = 0;
   5385    this.channel3EnableCheck();
   5386    this.memory[0xFF26] &= 0xFB;  //Channel #3 On Flag Off
   5387  }
   5388  //Channel 4:
   5389  if (this.channel4totalLength > 1) {
   5390    --this.channel4totalLength;
   5391  }
   5392  else if (this.channel4totalLength == 1) {
   5393    this.channel4totalLength = 0;
   5394    this.channel4EnableCheck();
   5395    this.memory[0xFF26] &= 0xF7;  //Channel #4 On Flag Off
   5396  }
   5397 }
   5398 GameBoyCore.prototype.clockAudioSweep = function () {
   5399  //Channel 1:
   5400  if (!this.channel1SweepFault && this.channel1timeSweep > 0) {
   5401    if (--this.channel1timeSweep == 0) {
   5402      this.runAudioSweep();
   5403    }
   5404  }
   5405 }
   5406 GameBoyCore.prototype.runAudioSweep = function () {
   5407  //Channel 1:
   5408  if (this.channel1lastTimeSweep > 0) {
   5409    if (this.channel1frequencySweepDivider > 0) {
   5410      if (this.channel1numSweep > 0) {
   5411        --this.channel1numSweep;
   5412        if (this.channel1decreaseSweep) {
   5413          this.channel1ShadowFrequency -= this.channel1ShadowFrequency >> this.channel1frequencySweepDivider;
   5414          this.channel1frequency = this.channel1ShadowFrequency & 0x7FF;
   5415          this.channel1FrequencyTracker = (0x800 - this.channel1frequency) << 2;
   5416        }
   5417        else {
   5418          this.channel1ShadowFrequency += this.channel1ShadowFrequency >> this.channel1frequencySweepDivider;
   5419          this.channel1frequency = this.channel1ShadowFrequency;
   5420          if (this.channel1ShadowFrequency <= 0x7FF) {
   5421            this.channel1FrequencyTracker = (0x800 - this.channel1frequency) << 2;
   5422            //Run overflow check twice:
   5423            if ((this.channel1ShadowFrequency + (this.channel1ShadowFrequency >> this.channel1frequencySweepDivider)) > 0x7FF) {
   5424              this.channel1SweepFault = true;
   5425              this.channel1EnableCheck();
   5426              this.memory[0xFF26] &= 0xFE;  //Channel #1 On Flag Off
   5427            }
   5428          }
   5429          else {
   5430            this.channel1frequency &= 0x7FF;
   5431            this.channel1SweepFault = true;
   5432            this.channel1EnableCheck();
   5433            this.memory[0xFF26] &= 0xFE;  //Channel #1 On Flag Off
   5434          }
   5435        }
   5436      }
   5437      this.channel1timeSweep = this.channel1lastTimeSweep;
   5438    }
   5439    else {
   5440      //Channel has sweep disabled and timer becomes a length counter:
   5441      this.channel1SweepFault = true;
   5442      this.channel1EnableCheck();
   5443    }
   5444  }
   5445 }
   5446 GameBoyCore.prototype.clockAudioEnvelope = function () {
   5447  //Channel 1:
   5448  if (this.channel1envelopeSweepsLast > -1) {
   5449    if (this.channel1envelopeSweeps > 0) {
   5450      --this.channel1envelopeSweeps;
   5451    }
   5452    else {
   5453      if (!this.channel1envelopeType) {
   5454        if (this.channel1envelopeVolume > 0) {
   5455          --this.channel1envelopeVolume;
   5456          this.channel1envelopeSweeps = this.channel1envelopeSweepsLast;
   5457          this.channel1OutputLevelCache();
   5458        }
   5459        else {
   5460          this.channel1envelopeSweepsLast = -1;
   5461        }
   5462      }
   5463      else if (this.channel1envelopeVolume < 0xF) {
   5464        ++this.channel1envelopeVolume;
   5465        this.channel1envelopeSweeps = this.channel1envelopeSweepsLast;
   5466        this.channel1OutputLevelCache();
   5467      }
   5468      else {
   5469        this.channel1envelopeSweepsLast = -1;
   5470      }
   5471    }
   5472  }
   5473  //Channel 2:
   5474  if (this.channel2envelopeSweepsLast > -1) {
   5475    if (this.channel2envelopeSweeps > 0) {
   5476      --this.channel2envelopeSweeps;
   5477    }
   5478    else {
   5479      if (!this.channel2envelopeType) {
   5480        if (this.channel2envelopeVolume > 0) {
   5481          --this.channel2envelopeVolume;
   5482          this.channel2envelopeSweeps = this.channel2envelopeSweepsLast;
   5483          this.channel2OutputLevelCache();
   5484        }
   5485        else {
   5486          this.channel2envelopeSweepsLast = -1;
   5487        }
   5488      }
   5489      else if (this.channel2envelopeVolume < 0xF) {
   5490        ++this.channel2envelopeVolume;
   5491        this.channel2envelopeSweeps = this.channel2envelopeSweepsLast;
   5492        this.channel2OutputLevelCache();
   5493      }
   5494      else {
   5495        this.channel2envelopeSweepsLast = -1;
   5496      }
   5497    }
   5498  }
   5499  //Channel 4:
   5500  if (this.channel4envelopeSweepsLast > -1) {
   5501    if (this.channel4envelopeSweeps > 0) {
   5502      --this.channel4envelopeSweeps;
   5503    }
   5504    else {
   5505      if (!this.channel4envelopeType) {
   5506        if (this.channel4envelopeVolume > 0) {
   5507          this.channel4currentVolume = --this.channel4envelopeVolume << this.channel4VolumeShifter;
   5508          this.channel4envelopeSweeps = this.channel4envelopeSweepsLast;
   5509          this.channel4UpdateCache();
   5510        }
   5511        else {
   5512          this.channel4envelopeSweepsLast = -1;
   5513        }
   5514      }
   5515      else if (this.channel4envelopeVolume < 0xF) {
   5516        this.channel4currentVolume = ++this.channel4envelopeVolume << this.channel4VolumeShifter;
   5517        this.channel4envelopeSweeps = this.channel4envelopeSweepsLast;
   5518        this.channel4UpdateCache();
   5519      }
   5520      else {
   5521        this.channel4envelopeSweepsLast = -1;
   5522      }
   5523    }
   5524  }
   5525 }
   5526 GameBoyCore.prototype.computeAudioChannels = function () {
   5527  //Channel 1 counter:
   5528  if (--this.channel1FrequencyCounter == 0) {
   5529    this.channel1FrequencyCounter = this.channel1FrequencyTracker;
   5530    this.channel1DutyTracker = (this.channel1DutyTracker + 1) & 0x7;
   5531    this.channel1OutputLevelTrimaryCache();
   5532  }
   5533  //Channel 2 counter:
   5534  if (--this.channel2FrequencyCounter == 0) {
   5535    this.channel2FrequencyCounter = this.channel2FrequencyTracker;
   5536    this.channel2DutyTracker = (this.channel2DutyTracker + 1) & 0x7;
   5537    this.channel2OutputLevelTrimaryCache();
   5538  }
   5539  //Channel 3 counter:
   5540  if (--this.channel3Counter == 0) {
   5541    if (this.channel3canPlay) {
   5542      this.channel3lastSampleLookup = (this.channel3lastSampleLookup + 1) & 0x1F;
   5543    }
   5544    this.channel3Counter = this.channel3FrequencyPeriod;
   5545    this.channel3UpdateCache();
   5546  }
   5547  //Channel 4 counter:
   5548  if (--this.channel4Counter == 0) {
   5549    this.channel4lastSampleLookup = (this.channel4lastSampleLookup + 1) & this.channel4BitRange;
   5550    this.channel4Counter = this.channel4FrequencyPeriod;
   5551    this.channel4UpdateCache();
   5552  }
   5553 }
   5554 GameBoyCore.prototype.channel1EnableCheck = function () {
   5555  this.channel1Enabled = ((this.channel1consecutive || this.channel1totalLength > 0) && !this.channel1SweepFault && this.channel1canPlay);
   5556  this.channel1OutputLevelSecondaryCache();
   5557 }
   5558 GameBoyCore.prototype.channel1VolumeEnableCheck = function () {
   5559  this.channel1canPlay = (this.memory[0xFF12] > 7);
   5560  this.channel1EnableCheck();
   5561  this.channel1OutputLevelSecondaryCache();
   5562 }
   5563 GameBoyCore.prototype.channel1OutputLevelCache = function () {
   5564  this.channel1currentSampleLeft = (this.leftChannel1) ? this.channel1envelopeVolume : 0;
   5565  this.channel1currentSampleRight = (this.rightChannel1) ? this.channel1envelopeVolume : 0;
   5566  this.channel1OutputLevelSecondaryCache();
   5567 }
   5568 GameBoyCore.prototype.channel1OutputLevelSecondaryCache = function () {
   5569  if (this.channel1Enabled) {
   5570    this.channel1currentSampleLeftSecondary = this.channel1currentSampleLeft;
   5571    this.channel1currentSampleRightSecondary = this.channel1currentSampleRight;
   5572  }
   5573  else {
   5574    this.channel1currentSampleLeftSecondary = 0;
   5575    this.channel1currentSampleRightSecondary = 0;
   5576  }
   5577  this.channel1OutputLevelTrimaryCache();
   5578 }
   5579 GameBoyCore.prototype.channel1OutputLevelTrimaryCache = function () {
   5580  if (this.channel1CachedDuty[this.channel1DutyTracker]) {
   5581    this.channel1currentSampleLeftTrimary = this.channel1currentSampleLeftSecondary;
   5582    this.channel1currentSampleRightTrimary = this.channel1currentSampleRightSecondary;
   5583  }
   5584  else {
   5585    this.channel1currentSampleLeftTrimary = 0;
   5586    this.channel1currentSampleRightTrimary = 0;
   5587  }
   5588  this.mixerOutputLevelCache();
   5589 }
   5590 GameBoyCore.prototype.channel2EnableCheck = function () {
   5591  this.channel2Enabled = ((this.channel2consecutive || this.channel2totalLength > 0) && this.channel2canPlay);
   5592  this.channel2OutputLevelSecondaryCache();
   5593 }
   5594 GameBoyCore.prototype.channel2VolumeEnableCheck = function () {
   5595  this.channel2canPlay = (this.memory[0xFF17] > 7);
   5596  this.channel2EnableCheck();
   5597  this.channel2OutputLevelSecondaryCache();
   5598 }
   5599 GameBoyCore.prototype.channel2OutputLevelCache = function () {
   5600  this.channel2currentSampleLeft = (this.leftChannel2) ? this.channel2envelopeVolume : 0;
   5601  this.channel2currentSampleRight = (this.rightChannel2) ? this.channel2envelopeVolume : 0;
   5602  this.channel2OutputLevelSecondaryCache();
   5603 }
   5604 GameBoyCore.prototype.channel2OutputLevelSecondaryCache = function () {
   5605  if (this.channel2Enabled) {
   5606    this.channel2currentSampleLeftSecondary = this.channel2currentSampleLeft;
   5607    this.channel2currentSampleRightSecondary = this.channel2currentSampleRight;
   5608  }
   5609  else {
   5610    this.channel2currentSampleLeftSecondary = 0;
   5611    this.channel2currentSampleRightSecondary = 0;
   5612  }
   5613  this.channel2OutputLevelTrimaryCache();
   5614 }
   5615 GameBoyCore.prototype.channel2OutputLevelTrimaryCache = function () {
   5616  if (this.channel2CachedDuty[this.channel2DutyTracker]) {
   5617    this.channel2currentSampleLeftTrimary = this.channel2currentSampleLeftSecondary;
   5618    this.channel2currentSampleRightTrimary = this.channel2currentSampleRightSecondary;
   5619  }
   5620  else {
   5621    this.channel2currentSampleLeftTrimary = 0;
   5622    this.channel2currentSampleRightTrimary = 0;
   5623  }
   5624  this.mixerOutputLevelCache();
   5625 }
   5626 GameBoyCore.prototype.channel3EnableCheck = function () {
   5627  this.channel3Enabled = (/*this.channel3canPlay && */(this.channel3consecutive || this.channel3totalLength > 0));
   5628  this.channel3OutputLevelSecondaryCache();
   5629 }
   5630 GameBoyCore.prototype.channel3OutputLevelCache = function () {
   5631  this.channel3currentSampleLeft = (this.leftChannel3) ? this.cachedChannel3Sample : 0;
   5632  this.channel3currentSampleRight = (this.rightChannel3) ? this.cachedChannel3Sample : 0;
   5633  this.channel3OutputLevelSecondaryCache();
   5634 }
   5635 GameBoyCore.prototype.channel3OutputLevelSecondaryCache = function () {
   5636  if (this.channel3Enabled) {
   5637    this.channel3currentSampleLeftSecondary = this.channel3currentSampleLeft;
   5638    this.channel3currentSampleRightSecondary = this.channel3currentSampleRight;
   5639  }
   5640  else {
   5641    this.channel3currentSampleLeftSecondary = 0;
   5642    this.channel3currentSampleRightSecondary = 0;
   5643  }
   5644  this.mixerOutputLevelCache();
   5645 }
   5646 GameBoyCore.prototype.channel4EnableCheck = function () {
   5647  this.channel4Enabled = ((this.channel4consecutive || this.channel4totalLength > 0) && this.channel4canPlay);
   5648  this.channel4OutputLevelSecondaryCache();
   5649 }
   5650 GameBoyCore.prototype.channel4VolumeEnableCheck = function () {
   5651  this.channel4canPlay = (this.memory[0xFF21] > 7);
   5652  this.channel4EnableCheck();
   5653  this.channel4OutputLevelSecondaryCache();
   5654 }
   5655 GameBoyCore.prototype.channel4OutputLevelCache = function () {
   5656  this.channel4currentSampleLeft = (this.leftChannel4) ? this.cachedChannel4Sample : 0;
   5657  this.channel4currentSampleRight = (this.rightChannel4) ? this.cachedChannel4Sample : 0;
   5658  this.channel4OutputLevelSecondaryCache();
   5659 }
   5660 GameBoyCore.prototype.channel4OutputLevelSecondaryCache = function () {
   5661  if (this.channel4Enabled) {
   5662    this.channel4currentSampleLeftSecondary = this.channel4currentSampleLeft;
   5663    this.channel4currentSampleRightSecondary = this.channel4currentSampleRight;
   5664  }
   5665  else {
   5666    this.channel4currentSampleLeftSecondary = 0;
   5667    this.channel4currentSampleRightSecondary = 0;
   5668  }
   5669  this.mixerOutputLevelCache();
   5670 }
   5671 GameBoyCore.prototype.mixerOutputLevelCache = function () {
   5672  this.mixerOutputCache = ((((this.channel1currentSampleLeftTrimary + this.channel2currentSampleLeftTrimary + this.channel3currentSampleLeftSecondary + this.channel4currentSampleLeftSecondary) * this.VinLeftChannelMasterVolume) << 9) +
   5673  ((this.channel1currentSampleRightTrimary + this.channel2currentSampleRightTrimary + this.channel3currentSampleRightSecondary + this.channel4currentSampleRightSecondary) * this.VinRightChannelMasterVolume));
   5674 }
   5675 GameBoyCore.prototype.channel3UpdateCache = function () {
   5676  this.cachedChannel3Sample = this.channel3PCM[this.channel3lastSampleLookup] >> this.channel3patternType;
   5677  this.channel3OutputLevelCache();
   5678 }
   5679 GameBoyCore.prototype.channel3WriteRAM = function (address, data) {
   5680  if (this.channel3canPlay) {
   5681    this.audioJIT();
   5682    //address = this.channel3lastSampleLookup >> 1;
   5683  }
   5684  this.memory[0xFF30 | address] = data;
   5685  address <<= 1;
   5686  this.channel3PCM[address] = data >> 4;
   5687  this.channel3PCM[address | 1] = data & 0xF;
   5688 }
   5689 GameBoyCore.prototype.channel4UpdateCache = function () {
   5690  this.cachedChannel4Sample = this.noiseSampleTable[this.channel4currentVolume | this.channel4lastSampleLookup];
   5691  this.channel4OutputLevelCache();
   5692 }
   5693 GameBoyCore.prototype.run = function () {
   5694  //The preprocessing before the actual iteration loop:
   5695  if ((this.stopEmulator & 2) == 0) {
   5696    if ((this.stopEmulator & 1) == 1) {
   5697      if (!this.CPUStopped) {
   5698        this.stopEmulator = 0;
   5699        this.drewFrame = false;
   5700        this.audioUnderrunAdjustment();
   5701        this.clockUpdate();      //RTC clocking.
   5702        if (!this.halt) {
   5703          this.executeIteration();
   5704        }
   5705        else {            //Finish the HALT rundown execution.
   5706          this.CPUTicks = 0;
   5707          this.calculateHALTPeriod();
   5708          if (this.halt) {
   5709            this.updateCoreFull();
   5710          }
   5711          else {
   5712            this.executeIteration();
   5713          }
   5714        }
   5715        //Request the graphics target to be updated:
   5716        this.requestDraw();
   5717      }
   5718      else {
   5719        this.audioUnderrunAdjustment();
   5720        this.audioTicks += this.CPUCyclesTotal;
   5721        this.audioJIT();
   5722        this.stopEmulator |= 1;      //End current loop.
   5723      }
   5724    }
   5725    else {    //We can only get here if there was an internal error, but the loop was restarted.
   5726      cout("Iterator restarted a faulted core.", 2);
   5727      pause();
   5728    }
   5729  }
   5730 }
   5731 
   5732 GameBoyCore.prototype.executeIteration = function () {
   5733  //Iterate the interpreter loop:
   5734  var opcodeToExecute = 0;
   5735  var timedTicks = 0;
   5736  while (this.stopEmulator == 0) {
   5737    //Interrupt Arming:
   5738    switch (this.IRQEnableDelay) {
   5739      case 1:
   5740        this.IME = true;
   5741        this.checkIRQMatching();
   5742      case 2:
   5743        --this.IRQEnableDelay;
   5744    }
   5745    //Is an IRQ set to fire?:
   5746    if (this.IRQLineMatched > 0) {
   5747      //IME is true and and interrupt was matched:
   5748      this.launchIRQ();
   5749    }
   5750    //Fetch the current opcode:
   5751    opcodeToExecute = this.memoryReader[this.programCounter](this, this.programCounter);
   5752    //Increment the program counter to the next instruction:
   5753    this.programCounter = (this.programCounter + 1) & 0xFFFF;
   5754    //Check for the program counter quirk:
   5755    if (this.skipPCIncrement) {
   5756      this.programCounter = (this.programCounter - 1) & 0xFFFF;
   5757      this.skipPCIncrement = false;
   5758    }
   5759    //Get how many CPU cycles the current instruction counts for:
   5760    this.CPUTicks = this.TICKTable[opcodeToExecute];
   5761    //Execute the current instruction:
   5762    this.OPCODE[opcodeToExecute](this);
   5763    //Update the state (Inlined updateCoreFull manually here):
   5764    //Update the clocking for the LCD emulation:
   5765    this.LCDTicks += this.CPUTicks >> this.doubleSpeedShifter;  //LCD Timing
   5766    this.LCDCONTROL[this.actualScanLine](this);          //Scan Line and STAT Mode Control
   5767    //Single-speed relative timing for A/V emulation:
   5768    timedTicks = this.CPUTicks >> this.doubleSpeedShifter;    //CPU clocking can be updated from the LCD handling.
   5769    this.audioTicks += timedTicks;                //Audio Timing
   5770    this.emulatorTicks += timedTicks;              //Emulator Timing
   5771    //CPU Timers:
   5772    this.DIVTicks += this.CPUTicks;                //DIV Timing
   5773    if (this.TIMAEnabled) {                    //TIMA Timing
   5774      this.timerTicks += this.CPUTicks;
   5775      while (this.timerTicks >= this.TACClocker) {
   5776        this.timerTicks -= this.TACClocker;
   5777        if (++this.memory[0xFF05] == 0x100) {
   5778          this.memory[0xFF05] = this.memory[0xFF06];
   5779          this.interruptsRequested |= 0x4;
   5780          this.checkIRQMatching();
   5781        }
   5782      }
   5783    }
   5784    if (this.serialTimer > 0) {                    //Serial Timing
   5785      //IRQ Counter:
   5786      this.serialTimer -= this.CPUTicks;
   5787      if (this.serialTimer <= 0) {
   5788        this.interruptsRequested |= 0x8;
   5789        this.checkIRQMatching();
   5790      }
   5791      //Bit Shit Counter:
   5792      this.serialShiftTimer -= this.CPUTicks;
   5793      if (this.serialShiftTimer <= 0) {
   5794        this.serialShiftTimer = this.serialShiftTimerAllocated;
   5795        this.memory[0xFF01] = ((this.memory[0xFF01] << 1) & 0xFE) | 0x01;  //We could shift in actual link data here if we were to implement such!!!
   5796      }
   5797    }
   5798    //End of iteration routine:
   5799    if (this.emulatorTicks >= this.CPUCyclesTotal) {
   5800      this.iterationEndRoutine();
   5801    }
   5802    // Start of code added for benchmarking:
   5803    this.instructions += 1;
   5804    if (this.instructions > this.totalInstructions) {
   5805      this.iterationEndRoutine();
   5806      this.stopEmulator |= 2;
   5807      checkFinalState();
   5808    }
   5809    // End of code added for benchmarking.
   5810  }
   5811 }
   5812 GameBoyCore.prototype.iterationEndRoutine = function () {
   5813  if ((this.stopEmulator & 0x1) == 0) {
   5814    this.audioJIT();  //Make sure we at least output once per iteration.
   5815    //Update DIV Alignment (Integer overflow safety):
   5816    this.memory[0xFF04] = (this.memory[0xFF04] + (this.DIVTicks >> 8)) & 0xFF;
   5817    this.DIVTicks &= 0xFF;
   5818    //Update emulator flags:
   5819    this.stopEmulator |= 1;      //End current loop.
   5820    this.emulatorTicks -= this.CPUCyclesTotal;
   5821    this.CPUCyclesTotalCurrent += this.CPUCyclesTotalRoundoff;
   5822    this.recalculateIterationClockLimit();
   5823  }
   5824 }
   5825 GameBoyCore.prototype.handleSTOP = function () {
   5826  this.CPUStopped = true;            //Stop CPU until joypad input changes.
   5827  this.iterationEndRoutine();
   5828  if (this.emulatorTicks < 0) {
   5829    this.audioTicks -= this.emulatorTicks;
   5830    this.audioJIT();
   5831  }
   5832 }
   5833 GameBoyCore.prototype.recalculateIterationClockLimit = function () {
   5834  var endModulus = this.CPUCyclesTotalCurrent % 4;
   5835  this.CPUCyclesTotal = this.CPUCyclesTotalBase + this.CPUCyclesTotalCurrent - endModulus;
   5836  this.CPUCyclesTotalCurrent = endModulus;
   5837 }
   5838 GameBoyCore.prototype.scanLineMode2 = function () {  //OAM Search Period
   5839  if (this.STATTracker != 1) {
   5840    if (this.mode2TriggerSTAT) {
   5841      this.interruptsRequested |= 0x2;
   5842      this.checkIRQMatching();
   5843    }
   5844    this.STATTracker = 1;
   5845    this.modeSTAT = 2;
   5846  }
   5847 }
   5848 GameBoyCore.prototype.scanLineMode3 = function () {  //Scan Line Drawing Period
   5849  if (this.modeSTAT != 3) {
   5850    if (this.STATTracker == 0 && this.mode2TriggerSTAT) {
   5851      this.interruptsRequested |= 0x2;
   5852      this.checkIRQMatching();
   5853    }
   5854    this.STATTracker = 1;
   5855    this.modeSTAT = 3;
   5856  }
   5857 }
   5858 GameBoyCore.prototype.scanLineMode0 = function () {  //Horizontal Blanking Period
   5859  if (this.modeSTAT != 0) {
   5860    if (this.STATTracker != 2) {
   5861      if (this.STATTracker == 0) {
   5862        if (this.mode2TriggerSTAT) {
   5863          this.interruptsRequested |= 0x2;
   5864          this.checkIRQMatching();
   5865        }
   5866        this.modeSTAT = 3;
   5867      }
   5868      this.incrementScanLineQueue();
   5869      this.updateSpriteCount(this.actualScanLine);
   5870      this.STATTracker = 2;
   5871    }
   5872    if (this.LCDTicks >= this.spriteCount) {
   5873      if (this.hdmaRunning) {
   5874        this.executeHDMA();
   5875      }
   5876      if (this.mode0TriggerSTAT) {
   5877        this.interruptsRequested |= 0x2;
   5878        this.checkIRQMatching();
   5879      }
   5880      this.STATTracker = 3;
   5881      this.modeSTAT = 0;
   5882    }
   5883  }
   5884 }
   5885 GameBoyCore.prototype.clocksUntilLYCMatch = function () {
   5886  if (this.memory[0xFF45] != 0) {
   5887    if (this.memory[0xFF45] > this.actualScanLine) {
   5888      return 456 * (this.memory[0xFF45] - this.actualScanLine);
   5889    }
   5890    return 456 * (154 - this.actualScanLine + this.memory[0xFF45]);
   5891  }
   5892  return (456 * ((this.actualScanLine == 153 && this.memory[0xFF44] == 0) ? 154 : (153 - this.actualScanLine))) + 8;
   5893 }
   5894 GameBoyCore.prototype.clocksUntilMode0 = function () {
   5895  switch (this.modeSTAT) {
   5896    case 0:
   5897      if (this.actualScanLine == 143) {
   5898        this.updateSpriteCount(0);
   5899        return this.spriteCount + 5016;
   5900      }
   5901      this.updateSpriteCount(this.actualScanLine + 1);
   5902      return this.spriteCount + 456;
   5903    case 2:
   5904    case 3:
   5905      this.updateSpriteCount(this.actualScanLine);
   5906      return this.spriteCount;
   5907    case 1:
   5908      this.updateSpriteCount(0);
   5909      return this.spriteCount + (456 * (154 - this.actualScanLine));
   5910  }
   5911 }
   5912 GameBoyCore.prototype.updateSpriteCount = function (line) {
   5913  this.spriteCount = 252;
   5914  if (this.cGBC && this.gfxSpriteShow) {                    //Is the window enabled and are we in CGB mode?
   5915    var lineAdjusted = line + 0x10;
   5916    var yoffset = 0;
   5917    var yCap = (this.gfxSpriteNormalHeight) ? 0x8 : 0x10;
   5918    for (var OAMAddress = 0xFE00; OAMAddress < 0xFEA0 && this.spriteCount < 312; OAMAddress += 4) {
   5919      yoffset = lineAdjusted - this.memory[OAMAddress];
   5920      if (yoffset > -1 && yoffset < yCap) {
   5921        this.spriteCount += 6;
   5922      }
   5923    }
   5924  }
   5925 }
   5926 GameBoyCore.prototype.matchLYC = function () {  //LYC Register Compare
   5927  if (this.memory[0xFF44] == this.memory[0xFF45]) {
   5928    this.memory[0xFF41] |= 0x04;
   5929    if (this.LYCMatchTriggerSTAT) {
   5930      this.interruptsRequested |= 0x2;
   5931      this.checkIRQMatching();
   5932    }
   5933  }
   5934  else {
   5935    this.memory[0xFF41] &= 0x7B;
   5936  }
   5937 }
   5938 GameBoyCore.prototype.updateCore = function () {
   5939  //Update the clocking for the LCD emulation:
   5940  this.LCDTicks += this.CPUTicks >> this.doubleSpeedShifter;  //LCD Timing
   5941  this.LCDCONTROL[this.actualScanLine](this);          //Scan Line and STAT Mode Control
   5942  //Single-speed relative timing for A/V emulation:
   5943  var timedTicks = this.CPUTicks >> this.doubleSpeedShifter;  //CPU clocking can be updated from the LCD handling.
   5944  this.audioTicks += timedTicks;                //Audio Timing
   5945  this.emulatorTicks += timedTicks;              //Emulator Timing
   5946  //CPU Timers:
   5947  this.DIVTicks += this.CPUTicks;                //DIV Timing
   5948  if (this.TIMAEnabled) {                    //TIMA Timing
   5949    this.timerTicks += this.CPUTicks;
   5950    while (this.timerTicks >= this.TACClocker) {
   5951      this.timerTicks -= this.TACClocker;
   5952      if (++this.memory[0xFF05] == 0x100) {
   5953        this.memory[0xFF05] = this.memory[0xFF06];
   5954        this.interruptsRequested |= 0x4;
   5955        this.checkIRQMatching();
   5956      }
   5957    }
   5958  }
   5959  if (this.serialTimer > 0) {                    //Serial Timing
   5960    //IRQ Counter:
   5961    this.serialTimer -= this.CPUTicks;
   5962    if (this.serialTimer <= 0) {
   5963      this.interruptsRequested |= 0x8;
   5964      this.checkIRQMatching();
   5965    }
   5966    //Bit Shit Counter:
   5967    this.serialShiftTimer -= this.CPUTicks;
   5968    if (this.serialShiftTimer <= 0) {
   5969      this.serialShiftTimer = this.serialShiftTimerAllocated;
   5970      this.memory[0xFF01] = ((this.memory[0xFF01] << 1) & 0xFE) | 0x01;  //We could shift in actual link data here if we were to implement such!!!
   5971    }
   5972  }
   5973 }
   5974 GameBoyCore.prototype.updateCoreFull = function () {
   5975  //Update the state machine:
   5976  this.updateCore();
   5977  //End of iteration routine:
   5978  if (this.emulatorTicks >= this.CPUCyclesTotal) {
   5979    this.iterationEndRoutine();
   5980  }
   5981 }
   5982 GameBoyCore.prototype.initializeLCDController = function () {
   5983  //Display on hanlding:
   5984  var line = 0;
   5985  while (line < 154) {
   5986    if (line < 143) {
   5987      //We're on a normal scan line:
   5988      this.LINECONTROL[line] = function (parentObj) {
   5989        if (parentObj.LCDTicks < 80) {
   5990          parentObj.scanLineMode2();
   5991        }
   5992        else if (parentObj.LCDTicks < 252) {
   5993          parentObj.scanLineMode3();
   5994        }
   5995        else if (parentObj.LCDTicks < 456) {
   5996          parentObj.scanLineMode0();
   5997        }
   5998        else {
   5999          //We're on a new scan line:
   6000          parentObj.LCDTicks -= 456;
   6001          if (parentObj.STATTracker != 3) {
   6002            //Make sure the mode 0 handler was run at least once per scan line:
   6003            if (parentObj.STATTracker != 2) {
   6004              if (parentObj.STATTracker == 0 && parentObj.mode2TriggerSTAT) {
   6005                parentObj.interruptsRequested |= 0x2;
   6006              }
   6007              parentObj.incrementScanLineQueue();
   6008            }
   6009            if (parentObj.hdmaRunning) {
   6010              parentObj.executeHDMA();
   6011            }
   6012            if (parentObj.mode0TriggerSTAT) {
   6013              parentObj.interruptsRequested |= 0x2;
   6014            }
   6015          }
   6016          //Update the scanline registers and assert the LYC counter:
   6017          parentObj.actualScanLine = ++parentObj.memory[0xFF44];
   6018          //Perform a LYC counter assert:
   6019          if (parentObj.actualScanLine == parentObj.memory[0xFF45]) {
   6020            parentObj.memory[0xFF41] |= 0x04;
   6021            if (parentObj.LYCMatchTriggerSTAT) {
   6022              parentObj.interruptsRequested |= 0x2;
   6023            }
   6024          }
   6025          else {
   6026            parentObj.memory[0xFF41] &= 0x7B;
   6027          }
   6028          parentObj.checkIRQMatching();
   6029          //Reset our mode contingency variables:
   6030          parentObj.STATTracker = 0;
   6031          parentObj.modeSTAT = 2;
   6032          parentObj.LINECONTROL[parentObj.actualScanLine](parentObj);  //Scan Line and STAT Mode Control.
   6033        }
   6034      }
   6035    }
   6036    else if (line == 143) {
   6037      //We're on the last visible scan line of the LCD screen:
   6038      this.LINECONTROL[143] = function (parentObj) {
   6039        if (parentObj.LCDTicks < 80) {
   6040          parentObj.scanLineMode2();
   6041        }
   6042        else if (parentObj.LCDTicks < 252) {
   6043          parentObj.scanLineMode3();
   6044        }
   6045        else if (parentObj.LCDTicks < 456) {
   6046          parentObj.scanLineMode0();
   6047        }
   6048        else {
   6049          //Starting V-Blank:
   6050          //Just finished the last visible scan line:
   6051          parentObj.LCDTicks -= 456;
   6052          if (parentObj.STATTracker != 3) {
   6053            //Make sure the mode 0 handler was run at least once per scan line:
   6054            if (parentObj.STATTracker != 2) {
   6055              if (parentObj.STATTracker == 0 && parentObj.mode2TriggerSTAT) {
   6056                parentObj.interruptsRequested |= 0x2;
   6057              }
   6058              parentObj.incrementScanLineQueue();
   6059            }
   6060            if (parentObj.hdmaRunning) {
   6061              parentObj.executeHDMA();
   6062            }
   6063            if (parentObj.mode0TriggerSTAT) {
   6064              parentObj.interruptsRequested |= 0x2;
   6065            }
   6066          }
   6067          //Update the scanline registers and assert the LYC counter:
   6068          parentObj.actualScanLine = parentObj.memory[0xFF44] = 144;
   6069          //Perform a LYC counter assert:
   6070          if (parentObj.memory[0xFF45] == 144) {
   6071            parentObj.memory[0xFF41] |= 0x04;
   6072            if (parentObj.LYCMatchTriggerSTAT) {
   6073              parentObj.interruptsRequested |= 0x2;
   6074            }
   6075          }
   6076          else {
   6077            parentObj.memory[0xFF41] &= 0x7B;
   6078          }
   6079          //Reset our mode contingency variables:
   6080          parentObj.STATTracker = 0;
   6081          //Update our state for v-blank:
   6082          parentObj.modeSTAT = 1;
   6083          parentObj.interruptsRequested |= (parentObj.mode1TriggerSTAT) ? 0x3 : 0x1;
   6084          parentObj.checkIRQMatching();
   6085          //Attempt to blit out to our canvas:
   6086          if (parentObj.drewBlank == 0) {
   6087            //Ensure JIT framing alignment:
   6088            if (parentObj.totalLinesPassed < 144 || (parentObj.totalLinesPassed == 144 && parentObj.midScanlineOffset > -1)) {
   6089              //Make sure our gfx are up-to-date:
   6090              parentObj.graphicsJITVBlank();
   6091              //Draw the frame:
   6092              parentObj.prepareFrame();
   6093            }
   6094          }
   6095          else {
   6096            //LCD off takes at least 2 frames:
   6097            --parentObj.drewBlank;
   6098          }
   6099          parentObj.LINECONTROL[144](parentObj);  //Scan Line and STAT Mode Control.
   6100        }
   6101      }
   6102    }
   6103    else if (line < 153) {
   6104      //In VBlank
   6105      this.LINECONTROL[line] = function (parentObj) {
   6106        if (parentObj.LCDTicks >= 456) {
   6107          //We're on a new scan line:
   6108          parentObj.LCDTicks -= 456;
   6109          parentObj.actualScanLine = ++parentObj.memory[0xFF44];
   6110          //Perform a LYC counter assert:
   6111          if (parentObj.actualScanLine == parentObj.memory[0xFF45]) {
   6112            parentObj.memory[0xFF41] |= 0x04;
   6113            if (parentObj.LYCMatchTriggerSTAT) {
   6114              parentObj.interruptsRequested |= 0x2;
   6115              parentObj.checkIRQMatching();
   6116            }
   6117          }
   6118          else {
   6119            parentObj.memory[0xFF41] &= 0x7B;
   6120          }
   6121          parentObj.LINECONTROL[parentObj.actualScanLine](parentObj);  //Scan Line and STAT Mode Control.
   6122        }
   6123      }
   6124    }
   6125    else {
   6126      //VBlank Ending (We're on the last actual scan line)
   6127      this.LINECONTROL[153] = function (parentObj) {
   6128        if (parentObj.LCDTicks >= 8) {
   6129          if (parentObj.STATTracker != 4 && parentObj.memory[0xFF44] == 153) {
   6130            parentObj.memory[0xFF44] = 0;  //LY register resets to 0 early.
   6131            //Perform a LYC counter assert:
   6132            if (parentObj.memory[0xFF45] == 0) {
   6133              parentObj.memory[0xFF41] |= 0x04;
   6134              if (parentObj.LYCMatchTriggerSTAT) {
   6135                parentObj.interruptsRequested |= 0x2;
   6136                parentObj.checkIRQMatching();
   6137              }
   6138            }
   6139            else {
   6140              parentObj.memory[0xFF41] &= 0x7B;
   6141            }
   6142            parentObj.STATTracker = 4;
   6143          }
   6144          if (parentObj.LCDTicks >= 456) {
   6145            //We reset back to the beginning:
   6146            parentObj.LCDTicks -= 456;
   6147            parentObj.STATTracker = parentObj.actualScanLine = 0;
   6148            parentObj.LINECONTROL[0](parentObj);  //Scan Line and STAT Mode Control.
   6149          }
   6150        }
   6151      }
   6152    }
   6153    ++line;
   6154  }
   6155 }
   6156 GameBoyCore.prototype.DisplayShowOff = function () {
   6157  if (this.drewBlank == 0) {
   6158    //Output a blank screen to the output framebuffer:
   6159    this.clearFrameBuffer();
   6160    this.drewFrame = true;
   6161  }
   6162  this.drewBlank = 2;
   6163 }
   6164 GameBoyCore.prototype.executeHDMA = function () {
   6165  this.DMAWrite(1);
   6166  if (this.halt) {
   6167    if ((this.LCDTicks - this.spriteCount) < ((4 >> this.doubleSpeedShifter) | 0x20)) {
   6168      //HALT clocking correction:
   6169      this.CPUTicks = 4 + ((0x20 + this.spriteCount) << this.doubleSpeedShifter);
   6170      this.LCDTicks = this.spriteCount + ((4 >> this.doubleSpeedShifter) | 0x20);
   6171    }
   6172  }
   6173  else {
   6174    this.LCDTicks += (4 >> this.doubleSpeedShifter) | 0x20;      //LCD Timing Update For HDMA.
   6175  }
   6176  if (this.memory[0xFF55] == 0) {
   6177    this.hdmaRunning = false;
   6178    this.memory[0xFF55] = 0xFF;  //Transfer completed ("Hidden last step," since some ROMs don't imply this, but most do).
   6179  }
   6180  else {
   6181    --this.memory[0xFF55];
   6182  }
   6183 }
   6184 GameBoyCore.prototype.clockUpdate = function () {
   6185  if (this.cTIMER) {
   6186    var dateObj = new_Date(); // The line is changed for benchmarking.
   6187    var newTime = dateObj.getTime();
   6188    var timeElapsed = newTime - this.lastIteration;  //Get the numnber of milliseconds since this last executed.
   6189    this.lastIteration = newTime;
   6190    if (this.cTIMER && !this.RTCHALT) {
   6191      //Update the MBC3 RTC:
   6192      this.RTCSeconds += timeElapsed / 1000;
   6193      while (this.RTCSeconds >= 60) {  //System can stutter, so the seconds difference can get large, thus the "while".
   6194        this.RTCSeconds -= 60;
   6195        ++this.RTCMinutes;
   6196        if (this.RTCMinutes >= 60) {
   6197          this.RTCMinutes -= 60;
   6198          ++this.RTCHours;
   6199          if (this.RTCHours >= 24) {
   6200            this.RTCHours -= 24
   6201            ++this.RTCDays;
   6202            if (this.RTCDays >= 512) {
   6203              this.RTCDays -= 512;
   6204              this.RTCDayOverFlow = true;
   6205            }
   6206          }
   6207        }
   6208      }
   6209    }
   6210  }
   6211 }
   6212 GameBoyCore.prototype.prepareFrame = function () {
   6213  //Copy the internal frame buffer to the output buffer:
   6214  this.swizzleFrameBuffer();
   6215  this.drewFrame = true;
   6216 }
   6217 GameBoyCore.prototype.requestDraw = function () {
   6218  if (this.drewFrame) {
   6219    this.dispatchDraw();
   6220  }
   6221 }
   6222 GameBoyCore.prototype.dispatchDraw = function () {
   6223  var canvasRGBALength = this.offscreenRGBCount;
   6224  if (canvasRGBALength > 0) {
   6225    //We actually updated the graphics internally, so copy out:
   6226    var frameBuffer = (canvasRGBALength == 92160) ? this.swizzledFrame : this.resizeFrameBuffer();
   6227    var canvasData = this.canvasBuffer.data;
   6228    var bufferIndex = 0;
   6229    for (var canvasIndex = 0; canvasIndex < canvasRGBALength; ++canvasIndex) {
   6230      canvasData[canvasIndex++] = frameBuffer[bufferIndex++];
   6231      canvasData[canvasIndex++] = frameBuffer[bufferIndex++];
   6232      canvasData[canvasIndex++] = frameBuffer[bufferIndex++];
   6233    }
   6234    this.graphicsBlit();
   6235  }
   6236 }
   6237 GameBoyCore.prototype.swizzleFrameBuffer = function () {
   6238  //Convert our dirty 24-bit (24-bit, with internal render flags above it) framebuffer to an 8-bit buffer with separate indices for the RGB channels:
   6239  var frameBuffer = this.frameBuffer;
   6240  var swizzledFrame = this.swizzledFrame;
   6241  var bufferIndex = 0;
   6242  for (var canvasIndex = 0; canvasIndex < 69120;) {
   6243    swizzledFrame[canvasIndex++] = (frameBuffer[bufferIndex] >> 16) & 0xFF;    //Red
   6244    swizzledFrame[canvasIndex++] = (frameBuffer[bufferIndex] >> 8) & 0xFF;    //Green
   6245    swizzledFrame[canvasIndex++] = frameBuffer[bufferIndex++] & 0xFF;      //Blue
   6246  }
   6247 }
   6248 GameBoyCore.prototype.clearFrameBuffer = function () {
   6249  var bufferIndex = 0;
   6250  var frameBuffer = this.swizzledFrame;
   6251  if (this.cGBC || this.colorizedGBPalettes) {
   6252    while (bufferIndex < 69120) {
   6253      frameBuffer[bufferIndex++] = 248;
   6254    }
   6255  }
   6256  else {
   6257    while (bufferIndex < 69120) {
   6258      frameBuffer[bufferIndex++] = 239;
   6259      frameBuffer[bufferIndex++] = 255;
   6260      frameBuffer[bufferIndex++] = 222;
   6261    }
   6262  }
   6263 }
   6264 GameBoyCore.prototype.resizeFrameBuffer = function () {
   6265  //Return a reference to the generated resized framebuffer:
   6266  return this.resizer.resize(this.swizzledFrame);
   6267 }
   6268 GameBoyCore.prototype.compileResizeFrameBufferFunction = function () {
   6269  if (this.offscreenRGBCount > 0) {
   6270    this.resizer = new Resize(160, 144, this.offscreenWidth, this.offscreenHeight, false, true);
   6271  }
   6272 }
   6273 GameBoyCore.prototype.renderScanLine = function (scanlineToRender) {
   6274  this.pixelStart = scanlineToRender * 160;
   6275  if (this.bgEnabled) {
   6276    this.pixelEnd = 160;
   6277    this.BGLayerRender(scanlineToRender);
   6278    this.WindowLayerRender(scanlineToRender);
   6279  }
   6280  else {
   6281    var pixelLine = (scanlineToRender + 1) * 160;
   6282    var defaultColor = (this.cGBC || this.colorizedGBPalettes) ? 0xF8F8F8 : 0xEFFFDE;
   6283    for (var pixelPosition = (scanlineToRender * 160) + this.currentX; pixelPosition < pixelLine; pixelPosition++) {
   6284      this.frameBuffer[pixelPosition] = defaultColor;
   6285    }
   6286  }
   6287  this.SpriteLayerRender(scanlineToRender);
   6288  this.currentX = 0;
   6289  this.midScanlineOffset = -1;
   6290 }
   6291 GameBoyCore.prototype.renderMidScanLine = function () {
   6292  if (this.actualScanLine < 144 && this.modeSTAT == 3) {
   6293    //TODO: Get this accurate:
   6294    if (this.midScanlineOffset == -1) {
   6295      this.midScanlineOffset = this.backgroundX & 0x7;
   6296    }
   6297    if (this.LCDTicks >= 82) {
   6298      this.pixelEnd = this.LCDTicks - 74;
   6299      this.pixelEnd = Math.min(this.pixelEnd - this.midScanlineOffset - (this.pixelEnd % 0x8), 160);
   6300      if (this.bgEnabled) {
   6301        this.pixelStart = this.lastUnrenderedLine * 160;
   6302        this.BGLayerRender(this.lastUnrenderedLine);
   6303        this.WindowLayerRender(this.lastUnrenderedLine);
   6304        //TODO: Do midscanline JIT for sprites...
   6305      }
   6306      else {
   6307        var pixelLine = (this.lastUnrenderedLine * 160) + this.pixelEnd;
   6308        var defaultColor = (this.cGBC || this.colorizedGBPalettes) ? 0xF8F8F8 : 0xEFFFDE;
   6309        for (var pixelPosition = (this.lastUnrenderedLine * 160) + this.currentX; pixelPosition < pixelLine; pixelPosition++) {
   6310          this.frameBuffer[pixelPosition] = defaultColor;
   6311        }
   6312      }
   6313      this.currentX = this.pixelEnd;
   6314    }
   6315  }
   6316 }
   6317 GameBoyCore.prototype.initializeModeSpecificArrays = function () {
   6318  this.LCDCONTROL = (this.LCDisOn) ? this.LINECONTROL : this.DISPLAYOFFCONTROL;
   6319  if (this.cGBC) {
   6320    this.gbcOBJRawPalette = this.getTypedArray(0x40, 0, "uint8");
   6321    this.gbcBGRawPalette = this.getTypedArray(0x40, 0, "uint8");
   6322    this.gbcOBJPalette = this.getTypedArray(0x20, 0x1000000, "int32");
   6323    this.gbcBGPalette = this.getTypedArray(0x40, 0, "int32");
   6324    this.BGCHRBank2 = this.getTypedArray(0x800, 0, "uint8");
   6325    this.BGCHRCurrentBank = (this.currVRAMBank > 0) ? this.BGCHRBank2 : this.BGCHRBank1;
   6326    this.tileCache = this.generateCacheArray(0xF80);
   6327  }
   6328  else {
   6329    this.gbOBJPalette = this.getTypedArray(8, 0, "int32");
   6330    this.gbBGPalette = this.getTypedArray(4, 0, "int32");
   6331    this.BGPalette = this.gbBGPalette;
   6332    this.OBJPalette = this.gbOBJPalette;
   6333    this.tileCache = this.generateCacheArray(0x700);
   6334    this.sortBuffer = this.getTypedArray(0x100, 0, "uint8");
   6335    this.OAMAddressCache = this.getTypedArray(10, 0, "int32");
   6336  }
   6337  this.renderPathBuild();
   6338 }
   6339 GameBoyCore.prototype.GBCtoGBModeAdjust = function () {
   6340  cout("Stepping down from GBC mode.", 0);
   6341  this.VRAM = this.GBCMemory = this.BGCHRCurrentBank = this.BGCHRBank2 = null;
   6342  this.tileCache.length = 0x700;
   6343  if (settings[4]) {
   6344    this.gbBGColorizedPalette = this.getTypedArray(4, 0, "int32");
   6345    this.gbOBJColorizedPalette = this.getTypedArray(8, 0, "int32");
   6346    this.cachedBGPaletteConversion = this.getTypedArray(4, 0, "int32");
   6347    this.cachedOBJPaletteConversion = this.getTypedArray(8, 0, "int32");
   6348    this.BGPalette = this.gbBGColorizedPalette;
   6349    this.OBJPalette = this.gbOBJColorizedPalette;
   6350    this.gbOBJPalette = this.gbBGPalette = null;
   6351    this.getGBCColor();
   6352  }
   6353  else {
   6354    this.gbOBJPalette = this.getTypedArray(8, 0, "int32");
   6355    this.gbBGPalette = this.getTypedArray(4, 0, "int32");
   6356    this.BGPalette = this.gbBGPalette;
   6357    this.OBJPalette = this.gbOBJPalette;
   6358  }
   6359  this.sortBuffer = this.getTypedArray(0x100, 0, "uint8");
   6360  this.OAMAddressCache = this.getTypedArray(10, 0, "int32");
   6361  this.renderPathBuild();
   6362  this.memoryReadJumpCompile();
   6363  this.memoryWriteJumpCompile();
   6364 }
   6365 GameBoyCore.prototype.renderPathBuild = function () {
   6366  if (!this.cGBC) {
   6367    this.BGLayerRender = this.BGGBLayerRender;
   6368    this.WindowLayerRender = this.WindowGBLayerRender;
   6369    this.SpriteLayerRender = this.SpriteGBLayerRender;
   6370  }
   6371  else {
   6372    this.priorityFlaggingPathRebuild();
   6373    this.SpriteLayerRender = this.SpriteGBCLayerRender;
   6374  }
   6375 }
   6376 GameBoyCore.prototype.priorityFlaggingPathRebuild = function () {
   6377  if (this.BGPriorityEnabled) {
   6378    this.BGLayerRender = this.BGGBCLayerRender;
   6379    this.WindowLayerRender = this.WindowGBCLayerRender;
   6380  }
   6381  else {
   6382    this.BGLayerRender = this.BGGBCLayerRenderNoPriorityFlagging;
   6383    this.WindowLayerRender = this.WindowGBCLayerRenderNoPriorityFlagging;
   6384  }
   6385 }
   6386 GameBoyCore.prototype.initializeReferencesFromSaveState = function () {
   6387  this.LCDCONTROL = (this.LCDisOn) ? this.LINECONTROL : this.DISPLAYOFFCONTROL;
   6388  var tileIndex = 0;
   6389  if (!this.cGBC) {
   6390    if (this.colorizedGBPalettes) {
   6391      this.BGPalette = this.gbBGColorizedPalette;
   6392      this.OBJPalette = this.gbOBJColorizedPalette;
   6393      this.updateGBBGPalette = this.updateGBColorizedBGPalette;
   6394      this.updateGBOBJPalette = this.updateGBColorizedOBJPalette;
   6395 
   6396    }
   6397    else {
   6398      this.BGPalette = this.gbBGPalette;
   6399      this.OBJPalette = this.gbOBJPalette;
   6400    }
   6401    this.tileCache = this.generateCacheArray(0x700);
   6402    for (tileIndex = 0x8000; tileIndex < 0x9000; tileIndex += 2) {
   6403      this.generateGBOAMTileLine(tileIndex);
   6404    }
   6405    for (tileIndex = 0x9000; tileIndex < 0x9800; tileIndex += 2) {
   6406      this.generateGBTileLine(tileIndex);
   6407    }
   6408    this.sortBuffer = this.getTypedArray(0x100, 0, "uint8");
   6409    this.OAMAddressCache = this.getTypedArray(10, 0, "int32");
   6410  }
   6411  else {
   6412    this.BGCHRCurrentBank = (this.currVRAMBank > 0) ? this.BGCHRBank2 : this.BGCHRBank1;
   6413    this.tileCache = this.generateCacheArray(0xF80);
   6414    for (; tileIndex < 0x1800; tileIndex += 0x10) {
   6415      this.generateGBCTileBank1(tileIndex);
   6416      this.generateGBCTileBank2(tileIndex);
   6417    }
   6418  }
   6419  this.renderPathBuild();
   6420 }
   6421 GameBoyCore.prototype.RGBTint = function (value) {
   6422  //Adjustment for the GBC's tinting (According to Gambatte):
   6423  var r = value & 0x1F;
   6424  var g = (value >> 5) & 0x1F;
   6425  var b = (value >> 10) & 0x1F;
   6426  return ((r * 13 + g * 2 + b) >> 1) << 16 | (g * 3 + b) << 9 | (r * 3 + g * 2 + b * 11) >> 1;
   6427 }
   6428 GameBoyCore.prototype.getGBCColor = function () {
   6429  //GBC Colorization of DMG ROMs:
   6430  //BG
   6431  for (var counter = 0; counter < 4; counter++) {
   6432    var adjustedIndex = counter << 1;
   6433    //BG
   6434    this.cachedBGPaletteConversion[counter] = this.RGBTint((this.gbcBGRawPalette[adjustedIndex | 1] << 8) | this.gbcBGRawPalette[adjustedIndex]);
   6435    //OBJ 1
   6436    this.cachedOBJPaletteConversion[counter] = this.RGBTint((this.gbcOBJRawPalette[adjustedIndex | 1] << 8) | this.gbcOBJRawPalette[adjustedIndex]);
   6437  }
   6438  //OBJ 2
   6439  for (counter = 4; counter < 8; counter++) {
   6440    adjustedIndex = counter << 1;
   6441    this.cachedOBJPaletteConversion[counter] = this.RGBTint((this.gbcOBJRawPalette[adjustedIndex | 1] << 8) | this.gbcOBJRawPalette[adjustedIndex]);
   6442  }
   6443  //Update the palette entries:
   6444  this.updateGBBGPalette = this.updateGBColorizedBGPalette;
   6445  this.updateGBOBJPalette = this.updateGBColorizedOBJPalette;
   6446  this.updateGBBGPalette(this.memory[0xFF47]);
   6447  this.updateGBOBJPalette(0, this.memory[0xFF48]);
   6448  this.updateGBOBJPalette(1, this.memory[0xFF49]);
   6449  this.colorizedGBPalettes = true;
   6450 }
   6451 GameBoyCore.prototype.updateGBRegularBGPalette = function (data) {
   6452  this.gbBGPalette[0] = this.colors[data & 0x03] | 0x2000000;
   6453  this.gbBGPalette[1] = this.colors[(data >> 2) & 0x03];
   6454  this.gbBGPalette[2] = this.colors[(data >> 4) & 0x03];
   6455  this.gbBGPalette[3] = this.colors[data >> 6];
   6456 }
   6457 GameBoyCore.prototype.updateGBColorizedBGPalette = function (data) {
   6458  //GB colorization:
   6459  this.gbBGColorizedPalette[0] = this.cachedBGPaletteConversion[data & 0x03] | 0x2000000;
   6460  this.gbBGColorizedPalette[1] = this.cachedBGPaletteConversion[(data >> 2) & 0x03];
   6461  this.gbBGColorizedPalette[2] = this.cachedBGPaletteConversion[(data >> 4) & 0x03];
   6462  this.gbBGColorizedPalette[3] = this.cachedBGPaletteConversion[data >> 6];
   6463 }
   6464 GameBoyCore.prototype.updateGBRegularOBJPalette = function (index, data) {
   6465  this.gbOBJPalette[index | 1] = this.colors[(data >> 2) & 0x03];
   6466  this.gbOBJPalette[index | 2] = this.colors[(data >> 4) & 0x03];
   6467  this.gbOBJPalette[index | 3] = this.colors[data >> 6];
   6468 }
   6469 GameBoyCore.prototype.updateGBColorizedOBJPalette = function (index, data) {
   6470  //GB colorization:
   6471  this.gbOBJColorizedPalette[index | 1] = this.cachedOBJPaletteConversion[index | ((data >> 2) & 0x03)];
   6472  this.gbOBJColorizedPalette[index | 2] = this.cachedOBJPaletteConversion[index | ((data >> 4) & 0x03)];
   6473  this.gbOBJColorizedPalette[index | 3] = this.cachedOBJPaletteConversion[index | (data >> 6)];
   6474 }
   6475 GameBoyCore.prototype.updateGBCBGPalette = function (index, data) {
   6476  if (this.gbcBGRawPalette[index] != data) {
   6477    this.midScanLineJIT();
   6478    //Update the color palette for BG tiles since it changed:
   6479    this.gbcBGRawPalette[index] = data;
   6480    if ((index & 0x06) == 0) {
   6481      //Palette 0 (Special tile Priority stuff)
   6482      data = 0x2000000 | this.RGBTint((this.gbcBGRawPalette[index | 1] << 8) | this.gbcBGRawPalette[index & 0x3E]);
   6483      index >>= 1;
   6484      this.gbcBGPalette[index] = data;
   6485      this.gbcBGPalette[0x20 | index] = 0x1000000 | data;
   6486    }
   6487    else {
   6488      //Regular Palettes (No special crap)
   6489      data = this.RGBTint((this.gbcBGRawPalette[index | 1] << 8) | this.gbcBGRawPalette[index & 0x3E]);
   6490      index >>= 1;
   6491      this.gbcBGPalette[index] = data;
   6492      this.gbcBGPalette[0x20 | index] = 0x1000000 | data;
   6493    }
   6494  }
   6495 }
   6496 GameBoyCore.prototype.updateGBCOBJPalette = function (index, data) {
   6497  if (this.gbcOBJRawPalette[index] != data) {
   6498    //Update the color palette for OBJ tiles since it changed:
   6499    this.gbcOBJRawPalette[index] = data;
   6500    if ((index & 0x06) > 0) {
   6501      //Regular Palettes (No special crap)
   6502      this.midScanLineJIT();
   6503      this.gbcOBJPalette[index >> 1] = 0x1000000 | this.RGBTint((this.gbcOBJRawPalette[index | 1] << 8) | this.gbcOBJRawPalette[index & 0x3E]);
   6504    }
   6505  }
   6506 }
   6507 GameBoyCore.prototype.BGGBLayerRender = function (scanlineToRender) {
   6508  var scrollYAdjusted = (this.backgroundY + scanlineToRender) & 0xFF;            //The line of the BG we're at.
   6509  var tileYLine = (scrollYAdjusted & 7) << 3;
   6510  var tileYDown = this.gfxBackgroundCHRBankPosition | ((scrollYAdjusted & 0xF8) << 2);  //The row of cached tiles we're fetching from.
   6511  var scrollXAdjusted = (this.backgroundX + this.currentX) & 0xFF;            //The scroll amount of the BG.
   6512  var pixelPosition = this.pixelStart + this.currentX;                  //Current pixel we're working on.
   6513  var pixelPositionEnd = this.pixelStart + ((this.gfxWindowDisplay && (scanlineToRender - this.windowY) >= 0) ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd);  //Make sure we do at most 160 pixels a scanline.
   6514  var tileNumber = tileYDown + (scrollXAdjusted >> 3);
   6515  var chrCode = this.BGCHRBank1[tileNumber];
   6516  if (chrCode < this.gfxBackgroundBankOffset) {
   6517    chrCode |= 0x100;
   6518  }
   6519  var tile = this.tileCache[chrCode];
   6520  for (var texel = (scrollXAdjusted & 0x7); texel < 8 && pixelPosition < pixelPositionEnd && scrollXAdjusted < 0x100; ++scrollXAdjusted) {
   6521    this.frameBuffer[pixelPosition++] = this.BGPalette[tile[tileYLine | texel++]];
   6522  }
   6523  var scrollXAdjustedAligned = Math.min(pixelPositionEnd - pixelPosition, 0x100 - scrollXAdjusted) >> 3;
   6524  scrollXAdjusted += scrollXAdjustedAligned << 3;
   6525  scrollXAdjustedAligned += tileNumber;
   6526  while (tileNumber < scrollXAdjustedAligned) {
   6527    chrCode = this.BGCHRBank1[++tileNumber];
   6528    if (chrCode < this.gfxBackgroundBankOffset) {
   6529      chrCode |= 0x100;
   6530    }
   6531    tile = this.tileCache[chrCode];
   6532    texel = tileYLine;
   6533    this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6534    this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6535    this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6536    this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6537    this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6538    this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6539    this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6540    this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel]];
   6541  }
   6542  if (pixelPosition < pixelPositionEnd) {
   6543    if (scrollXAdjusted < 0x100) {
   6544      chrCode = this.BGCHRBank1[++tileNumber];
   6545      if (chrCode < this.gfxBackgroundBankOffset) {
   6546        chrCode |= 0x100;
   6547      }
   6548      tile = this.tileCache[chrCode];
   6549      for (texel = tileYLine - 1; pixelPosition < pixelPositionEnd && scrollXAdjusted < 0x100; ++scrollXAdjusted) {
   6550        this.frameBuffer[pixelPosition++] = this.BGPalette[tile[++texel]];
   6551      }
   6552    }
   6553    scrollXAdjustedAligned = ((pixelPositionEnd - pixelPosition) >> 3) + tileYDown;
   6554    while (tileYDown < scrollXAdjustedAligned) {
   6555      chrCode = this.BGCHRBank1[tileYDown++];
   6556      if (chrCode < this.gfxBackgroundBankOffset) {
   6557        chrCode |= 0x100;
   6558      }
   6559      tile = this.tileCache[chrCode];
   6560      texel = tileYLine;
   6561      this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6562      this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6563      this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6564      this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6565      this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6566      this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6567      this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6568      this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel]];
   6569    }
   6570    if (pixelPosition < pixelPositionEnd) {
   6571      chrCode = this.BGCHRBank1[tileYDown];
   6572      if (chrCode < this.gfxBackgroundBankOffset) {
   6573        chrCode |= 0x100;
   6574      }
   6575      tile = this.tileCache[chrCode];
   6576      switch (pixelPositionEnd - pixelPosition) {
   6577        case 7:
   6578          this.frameBuffer[pixelPosition + 6] = this.BGPalette[tile[tileYLine | 6]];
   6579        case 6:
   6580          this.frameBuffer[pixelPosition + 5] = this.BGPalette[tile[tileYLine | 5]];
   6581        case 5:
   6582          this.frameBuffer[pixelPosition + 4] = this.BGPalette[tile[tileYLine | 4]];
   6583        case 4:
   6584          this.frameBuffer[pixelPosition + 3] = this.BGPalette[tile[tileYLine | 3]];
   6585        case 3:
   6586          this.frameBuffer[pixelPosition + 2] = this.BGPalette[tile[tileYLine | 2]];
   6587        case 2:
   6588          this.frameBuffer[pixelPosition + 1] = this.BGPalette[tile[tileYLine | 1]];
   6589        case 1:
   6590          this.frameBuffer[pixelPosition] = this.BGPalette[tile[tileYLine]];
   6591      }
   6592    }
   6593  }
   6594 }
   6595 GameBoyCore.prototype.BGGBCLayerRender = function (scanlineToRender) {
   6596  var scrollYAdjusted = (this.backgroundY + scanlineToRender) & 0xFF;            //The line of the BG we're at.
   6597  var tileYLine = (scrollYAdjusted & 7) << 3;
   6598  var tileYDown = this.gfxBackgroundCHRBankPosition | ((scrollYAdjusted & 0xF8) << 2);  //The row of cached tiles we're fetching from.
   6599  var scrollXAdjusted = (this.backgroundX + this.currentX) & 0xFF;            //The scroll amount of the BG.
   6600  var pixelPosition = this.pixelStart + this.currentX;                  //Current pixel we're working on.
   6601  var pixelPositionEnd = this.pixelStart + ((this.gfxWindowDisplay && (scanlineToRender - this.windowY) >= 0) ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd);  //Make sure we do at most 160 pixels a scanline.
   6602  var tileNumber = tileYDown + (scrollXAdjusted >> 3);
   6603  var chrCode = this.BGCHRBank1[tileNumber];
   6604  if (chrCode < this.gfxBackgroundBankOffset) {
   6605    chrCode |= 0x100;
   6606  }
   6607  var attrCode = this.BGCHRBank2[tileNumber];
   6608  var tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6609  var palette = ((attrCode & 0x7) << 2) | ((attrCode & 0x80) >> 2);
   6610  for (var texel = (scrollXAdjusted & 0x7); texel < 8 && pixelPosition < pixelPositionEnd && scrollXAdjusted < 0x100; ++scrollXAdjusted) {
   6611    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[tileYLine | texel++]];
   6612  }
   6613  var scrollXAdjustedAligned = Math.min(pixelPositionEnd - pixelPosition, 0x100 - scrollXAdjusted) >> 3;
   6614  scrollXAdjusted += scrollXAdjustedAligned << 3;
   6615  scrollXAdjustedAligned += tileNumber;
   6616  while (tileNumber < scrollXAdjustedAligned) {
   6617    chrCode = this.BGCHRBank1[++tileNumber];
   6618    if (chrCode < this.gfxBackgroundBankOffset) {
   6619      chrCode |= 0x100;
   6620    }
   6621    attrCode = this.BGCHRBank2[tileNumber];
   6622    tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6623    palette = ((attrCode & 0x7) << 2) | ((attrCode & 0x80) >> 2);
   6624    texel = tileYLine;
   6625    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6626    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6627    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6628    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6629    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6630    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6631    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6632    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
   6633  }
   6634  if (pixelPosition < pixelPositionEnd) {
   6635    if (scrollXAdjusted < 0x100) {
   6636      chrCode = this.BGCHRBank1[++tileNumber];
   6637      if (chrCode < this.gfxBackgroundBankOffset) {
   6638        chrCode |= 0x100;
   6639      }
   6640      attrCode = this.BGCHRBank2[tileNumber];
   6641      tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6642      palette = ((attrCode & 0x7) << 2) | ((attrCode & 0x80) >> 2);
   6643      for (texel = tileYLine - 1; pixelPosition < pixelPositionEnd && scrollXAdjusted < 0x100; ++scrollXAdjusted) {
   6644        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[++texel]];
   6645      }
   6646    }
   6647    scrollXAdjustedAligned = ((pixelPositionEnd - pixelPosition) >> 3) + tileYDown;
   6648    while (tileYDown < scrollXAdjustedAligned) {
   6649      chrCode = this.BGCHRBank1[tileYDown];
   6650      if (chrCode < this.gfxBackgroundBankOffset) {
   6651        chrCode |= 0x100;
   6652      }
   6653      attrCode = this.BGCHRBank2[tileYDown++];
   6654      tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6655      palette = ((attrCode & 0x7) << 2) | ((attrCode & 0x80) >> 2);
   6656      texel = tileYLine;
   6657      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6658      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6659      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6660      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6661      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6662      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6663      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6664      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
   6665    }
   6666    if (pixelPosition < pixelPositionEnd) {
   6667      chrCode = this.BGCHRBank1[tileYDown];
   6668      if (chrCode < this.gfxBackgroundBankOffset) {
   6669        chrCode |= 0x100;
   6670      }
   6671      attrCode = this.BGCHRBank2[tileYDown];
   6672      tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6673      palette = ((attrCode & 0x7) << 2) | ((attrCode & 0x80) >> 2);
   6674      switch (pixelPositionEnd - pixelPosition) {
   6675        case 7:
   6676          this.frameBuffer[pixelPosition + 6] = this.gbcBGPalette[palette | tile[tileYLine | 6]];
   6677        case 6:
   6678          this.frameBuffer[pixelPosition + 5] = this.gbcBGPalette[palette | tile[tileYLine | 5]];
   6679        case 5:
   6680          this.frameBuffer[pixelPosition + 4] = this.gbcBGPalette[palette | tile[tileYLine | 4]];
   6681        case 4:
   6682          this.frameBuffer[pixelPosition + 3] = this.gbcBGPalette[palette | tile[tileYLine | 3]];
   6683        case 3:
   6684          this.frameBuffer[pixelPosition + 2] = this.gbcBGPalette[palette | tile[tileYLine | 2]];
   6685        case 2:
   6686          this.frameBuffer[pixelPosition + 1] = this.gbcBGPalette[palette | tile[tileYLine | 1]];
   6687        case 1:
   6688          this.frameBuffer[pixelPosition] = this.gbcBGPalette[palette | tile[tileYLine]];
   6689      }
   6690    }
   6691  }
   6692 }
   6693 GameBoyCore.prototype.BGGBCLayerRenderNoPriorityFlagging = function (scanlineToRender) {
   6694  var scrollYAdjusted = (this.backgroundY + scanlineToRender) & 0xFF;            //The line of the BG we're at.
   6695  var tileYLine = (scrollYAdjusted & 7) << 3;
   6696  var tileYDown = this.gfxBackgroundCHRBankPosition | ((scrollYAdjusted & 0xF8) << 2);  //The row of cached tiles we're fetching from.
   6697  var scrollXAdjusted = (this.backgroundX + this.currentX) & 0xFF;            //The scroll amount of the BG.
   6698  var pixelPosition = this.pixelStart + this.currentX;                  //Current pixel we're working on.
   6699  var pixelPositionEnd = this.pixelStart + ((this.gfxWindowDisplay && (scanlineToRender - this.windowY) >= 0) ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd);  //Make sure we do at most 160 pixels a scanline.
   6700  var tileNumber = tileYDown + (scrollXAdjusted >> 3);
   6701  var chrCode = this.BGCHRBank1[tileNumber];
   6702  if (chrCode < this.gfxBackgroundBankOffset) {
   6703    chrCode |= 0x100;
   6704  }
   6705  var attrCode = this.BGCHRBank2[tileNumber];
   6706  var tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6707  var palette = (attrCode & 0x7) << 2;
   6708  for (var texel = (scrollXAdjusted & 0x7); texel < 8 && pixelPosition < pixelPositionEnd && scrollXAdjusted < 0x100; ++scrollXAdjusted) {
   6709    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[tileYLine | texel++]];
   6710  }
   6711  var scrollXAdjustedAligned = Math.min(pixelPositionEnd - pixelPosition, 0x100 - scrollXAdjusted) >> 3;
   6712  scrollXAdjusted += scrollXAdjustedAligned << 3;
   6713  scrollXAdjustedAligned += tileNumber;
   6714  while (tileNumber < scrollXAdjustedAligned) {
   6715    chrCode = this.BGCHRBank1[++tileNumber];
   6716    if (chrCode < this.gfxBackgroundBankOffset) {
   6717      chrCode |= 0x100;
   6718    }
   6719    attrCode = this.BGCHRBank2[tileNumber];
   6720    tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6721    palette = (attrCode & 0x7) << 2;
   6722    texel = tileYLine;
   6723    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6724    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6725    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6726    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6727    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6728    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6729    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6730    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
   6731  }
   6732  if (pixelPosition < pixelPositionEnd) {
   6733    if (scrollXAdjusted < 0x100) {
   6734      chrCode = this.BGCHRBank1[++tileNumber];
   6735      if (chrCode < this.gfxBackgroundBankOffset) {
   6736        chrCode |= 0x100;
   6737      }
   6738      attrCode = this.BGCHRBank2[tileNumber];
   6739      tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6740      palette = (attrCode & 0x7) << 2;
   6741      for (texel = tileYLine - 1; pixelPosition < pixelPositionEnd && scrollXAdjusted < 0x100; ++scrollXAdjusted) {
   6742        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[++texel]];
   6743      }
   6744    }
   6745    scrollXAdjustedAligned = ((pixelPositionEnd - pixelPosition) >> 3) + tileYDown;
   6746    while (tileYDown < scrollXAdjustedAligned) {
   6747      chrCode = this.BGCHRBank1[tileYDown];
   6748      if (chrCode < this.gfxBackgroundBankOffset) {
   6749        chrCode |= 0x100;
   6750      }
   6751      attrCode = this.BGCHRBank2[tileYDown++];
   6752      tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6753      palette = (attrCode & 0x7) << 2;
   6754      texel = tileYLine;
   6755      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6756      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6757      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6758      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6759      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6760      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6761      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6762      this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
   6763    }
   6764    if (pixelPosition < pixelPositionEnd) {
   6765      chrCode = this.BGCHRBank1[tileYDown];
   6766      if (chrCode < this.gfxBackgroundBankOffset) {
   6767        chrCode |= 0x100;
   6768      }
   6769      attrCode = this.BGCHRBank2[tileYDown];
   6770      tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6771      palette = (attrCode & 0x7) << 2;
   6772      switch (pixelPositionEnd - pixelPosition) {
   6773        case 7:
   6774          this.frameBuffer[pixelPosition + 6] = this.gbcBGPalette[palette | tile[tileYLine | 6]];
   6775        case 6:
   6776          this.frameBuffer[pixelPosition + 5] = this.gbcBGPalette[palette | tile[tileYLine | 5]];
   6777        case 5:
   6778          this.frameBuffer[pixelPosition + 4] = this.gbcBGPalette[palette | tile[tileYLine | 4]];
   6779        case 4:
   6780          this.frameBuffer[pixelPosition + 3] = this.gbcBGPalette[palette | tile[tileYLine | 3]];
   6781        case 3:
   6782          this.frameBuffer[pixelPosition + 2] = this.gbcBGPalette[palette | tile[tileYLine | 2]];
   6783        case 2:
   6784          this.frameBuffer[pixelPosition + 1] = this.gbcBGPalette[palette | tile[tileYLine | 1]];
   6785        case 1:
   6786          this.frameBuffer[pixelPosition] = this.gbcBGPalette[palette | tile[tileYLine]];
   6787      }
   6788    }
   6789  }
   6790 }
   6791 GameBoyCore.prototype.WindowGBLayerRender = function (scanlineToRender) {
   6792  if (this.gfxWindowDisplay) {                  //Is the window enabled?
   6793    var scrollYAdjusted = scanlineToRender - this.windowY;    //The line of the BG we're at.
   6794    if (scrollYAdjusted >= 0) {
   6795      var scrollXRangeAdjusted = (this.windowX > 0) ? (this.windowX + this.currentX) : this.currentX;
   6796      var pixelPosition = this.pixelStart + scrollXRangeAdjusted;
   6797      var pixelPositionEnd = this.pixelStart + this.pixelEnd;
   6798      if (pixelPosition < pixelPositionEnd) {
   6799        var tileYLine = (scrollYAdjusted & 0x7) << 3;
   6800        var tileNumber = (this.gfxWindowCHRBankPosition | ((scrollYAdjusted & 0xF8) << 2)) + (this.currentX >> 3);
   6801        var chrCode = this.BGCHRBank1[tileNumber];
   6802        if (chrCode < this.gfxBackgroundBankOffset) {
   6803          chrCode |= 0x100;
   6804        }
   6805        var tile = this.tileCache[chrCode];
   6806        var texel = (scrollXRangeAdjusted - this.windowX) & 0x7;
   6807        scrollXRangeAdjusted = Math.min(8, texel + pixelPositionEnd - pixelPosition);
   6808        while (texel < scrollXRangeAdjusted) {
   6809          this.frameBuffer[pixelPosition++] = this.BGPalette[tile[tileYLine | texel++]];
   6810        }
   6811        scrollXRangeAdjusted = tileNumber + ((pixelPositionEnd - pixelPosition) >> 3);
   6812        while (tileNumber < scrollXRangeAdjusted) {
   6813          chrCode = this.BGCHRBank1[++tileNumber];
   6814          if (chrCode < this.gfxBackgroundBankOffset) {
   6815            chrCode |= 0x100;
   6816          }
   6817          tile = this.tileCache[chrCode];
   6818          texel = tileYLine;
   6819          this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6820          this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6821          this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6822          this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6823          this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6824          this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6825          this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel++]];
   6826          this.frameBuffer[pixelPosition++] = this.BGPalette[tile[texel]];
   6827        }
   6828        if (pixelPosition < pixelPositionEnd) {
   6829          chrCode = this.BGCHRBank1[++tileNumber];
   6830          if (chrCode < this.gfxBackgroundBankOffset) {
   6831            chrCode |= 0x100;
   6832          }
   6833          tile = this.tileCache[chrCode];
   6834          switch (pixelPositionEnd - pixelPosition) {
   6835            case 7:
   6836              this.frameBuffer[pixelPosition + 6] = this.BGPalette[tile[tileYLine | 6]];
   6837            case 6:
   6838              this.frameBuffer[pixelPosition + 5] = this.BGPalette[tile[tileYLine | 5]];
   6839            case 5:
   6840              this.frameBuffer[pixelPosition + 4] = this.BGPalette[tile[tileYLine | 4]];
   6841            case 4:
   6842              this.frameBuffer[pixelPosition + 3] = this.BGPalette[tile[tileYLine | 3]];
   6843            case 3:
   6844              this.frameBuffer[pixelPosition + 2] = this.BGPalette[tile[tileYLine | 2]];
   6845            case 2:
   6846              this.frameBuffer[pixelPosition + 1] = this.BGPalette[tile[tileYLine | 1]];
   6847            case 1:
   6848              this.frameBuffer[pixelPosition] = this.BGPalette[tile[tileYLine]];
   6849          }
   6850        }
   6851      }
   6852    }
   6853  }
   6854 }
   6855 GameBoyCore.prototype.WindowGBCLayerRender = function (scanlineToRender) {
   6856  if (this.gfxWindowDisplay) {                  //Is the window enabled?
   6857    var scrollYAdjusted = scanlineToRender - this.windowY;    //The line of the BG we're at.
   6858    if (scrollYAdjusted >= 0) {
   6859      var scrollXRangeAdjusted = (this.windowX > 0) ? (this.windowX + this.currentX) : this.currentX;
   6860      var pixelPosition = this.pixelStart + scrollXRangeAdjusted;
   6861      var pixelPositionEnd = this.pixelStart + this.pixelEnd;
   6862      if (pixelPosition < pixelPositionEnd) {
   6863        var tileYLine = (scrollYAdjusted & 0x7) << 3;
   6864        var tileNumber = (this.gfxWindowCHRBankPosition | ((scrollYAdjusted & 0xF8) << 2)) + (this.currentX >> 3);
   6865        var chrCode = this.BGCHRBank1[tileNumber];
   6866        if (chrCode < this.gfxBackgroundBankOffset) {
   6867          chrCode |= 0x100;
   6868        }
   6869        var attrCode = this.BGCHRBank2[tileNumber];
   6870        var tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6871        var palette = ((attrCode & 0x7) << 2) | ((attrCode & 0x80) >> 2);
   6872        var texel = (scrollXRangeAdjusted - this.windowX) & 0x7;
   6873        scrollXRangeAdjusted = Math.min(8, texel + pixelPositionEnd - pixelPosition);
   6874        while (texel < scrollXRangeAdjusted) {
   6875          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[tileYLine | texel++]];
   6876        }
   6877        scrollXRangeAdjusted = tileNumber + ((pixelPositionEnd - pixelPosition) >> 3);
   6878        while (tileNumber < scrollXRangeAdjusted) {
   6879          chrCode = this.BGCHRBank1[++tileNumber];
   6880          if (chrCode < this.gfxBackgroundBankOffset) {
   6881            chrCode |= 0x100;
   6882          }
   6883          attrCode = this.BGCHRBank2[tileNumber];
   6884          tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6885          palette = ((attrCode & 0x7) << 2) | ((attrCode & 0x80) >> 2);
   6886          texel = tileYLine;
   6887          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6888          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6889          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6890          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6891          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6892          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6893          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6894          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
   6895        }
   6896        if (pixelPosition < pixelPositionEnd) {
   6897          chrCode = this.BGCHRBank1[++tileNumber];
   6898          if (chrCode < this.gfxBackgroundBankOffset) {
   6899            chrCode |= 0x100;
   6900          }
   6901          attrCode = this.BGCHRBank2[tileNumber];
   6902          tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6903          palette = ((attrCode & 0x7) << 2) | ((attrCode & 0x80) >> 2);
   6904          switch (pixelPositionEnd - pixelPosition) {
   6905            case 7:
   6906              this.frameBuffer[pixelPosition + 6] = this.gbcBGPalette[palette | tile[tileYLine | 6]];
   6907            case 6:
   6908              this.frameBuffer[pixelPosition + 5] = this.gbcBGPalette[palette | tile[tileYLine | 5]];
   6909            case 5:
   6910              this.frameBuffer[pixelPosition + 4] = this.gbcBGPalette[palette | tile[tileYLine | 4]];
   6911            case 4:
   6912              this.frameBuffer[pixelPosition + 3] = this.gbcBGPalette[palette | tile[tileYLine | 3]];
   6913            case 3:
   6914              this.frameBuffer[pixelPosition + 2] = this.gbcBGPalette[palette | tile[tileYLine | 2]];
   6915            case 2:
   6916              this.frameBuffer[pixelPosition + 1] = this.gbcBGPalette[palette | tile[tileYLine | 1]];
   6917            case 1:
   6918              this.frameBuffer[pixelPosition] = this.gbcBGPalette[palette | tile[tileYLine]];
   6919          }
   6920        }
   6921      }
   6922    }
   6923  }
   6924 }
   6925 GameBoyCore.prototype.WindowGBCLayerRenderNoPriorityFlagging = function (scanlineToRender) {
   6926  if (this.gfxWindowDisplay) {                  //Is the window enabled?
   6927    var scrollYAdjusted = scanlineToRender - this.windowY;    //The line of the BG we're at.
   6928    if (scrollYAdjusted >= 0) {
   6929      var scrollXRangeAdjusted = (this.windowX > 0) ? (this.windowX + this.currentX) : this.currentX;
   6930      var pixelPosition = this.pixelStart + scrollXRangeAdjusted;
   6931      var pixelPositionEnd = this.pixelStart + this.pixelEnd;
   6932      if (pixelPosition < pixelPositionEnd) {
   6933        var tileYLine = (scrollYAdjusted & 0x7) << 3;
   6934        var tileNumber = (this.gfxWindowCHRBankPosition | ((scrollYAdjusted & 0xF8) << 2)) + (this.currentX >> 3);
   6935        var chrCode = this.BGCHRBank1[tileNumber];
   6936        if (chrCode < this.gfxBackgroundBankOffset) {
   6937          chrCode |= 0x100;
   6938        }
   6939        var attrCode = this.BGCHRBank2[tileNumber];
   6940        var tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6941        var palette = (attrCode & 0x7) << 2;
   6942        var texel = (scrollXRangeAdjusted - this.windowX) & 0x7;
   6943        scrollXRangeAdjusted = Math.min(8, texel + pixelPositionEnd - pixelPosition);
   6944        while (texel < scrollXRangeAdjusted) {
   6945          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[tileYLine | texel++]];
   6946        }
   6947        scrollXRangeAdjusted = tileNumber + ((pixelPositionEnd - pixelPosition) >> 3);
   6948        while (tileNumber < scrollXRangeAdjusted) {
   6949          chrCode = this.BGCHRBank1[++tileNumber];
   6950          if (chrCode < this.gfxBackgroundBankOffset) {
   6951            chrCode |= 0x100;
   6952          }
   6953          attrCode = this.BGCHRBank2[tileNumber];
   6954          tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6955          palette = (attrCode & 0x7) << 2;
   6956          texel = tileYLine;
   6957          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6958          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6959          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6960          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6961          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6962          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6963          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
   6964          this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
   6965        }
   6966        if (pixelPosition < pixelPositionEnd) {
   6967          chrCode = this.BGCHRBank1[++tileNumber];
   6968          if (chrCode < this.gfxBackgroundBankOffset) {
   6969            chrCode |= 0x100;
   6970          }
   6971          attrCode = this.BGCHRBank2[tileNumber];
   6972          tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | chrCode];
   6973          palette = (attrCode & 0x7) << 2;
   6974          switch (pixelPositionEnd - pixelPosition) {
   6975            case 7:
   6976              this.frameBuffer[pixelPosition + 6] = this.gbcBGPalette[palette | tile[tileYLine | 6]];
   6977            case 6:
   6978              this.frameBuffer[pixelPosition + 5] = this.gbcBGPalette[palette | tile[tileYLine | 5]];
   6979            case 5:
   6980              this.frameBuffer[pixelPosition + 4] = this.gbcBGPalette[palette | tile[tileYLine | 4]];
   6981            case 4:
   6982              this.frameBuffer[pixelPosition + 3] = this.gbcBGPalette[palette | tile[tileYLine | 3]];
   6983            case 3:
   6984              this.frameBuffer[pixelPosition + 2] = this.gbcBGPalette[palette | tile[tileYLine | 2]];
   6985            case 2:
   6986              this.frameBuffer[pixelPosition + 1] = this.gbcBGPalette[palette | tile[tileYLine | 1]];
   6987            case 1:
   6988              this.frameBuffer[pixelPosition] = this.gbcBGPalette[palette | tile[tileYLine]];
   6989          }
   6990        }
   6991      }
   6992    }
   6993  }
   6994 }
   6995 GameBoyCore.prototype.SpriteGBLayerRender = function (scanlineToRender) {
   6996  if (this.gfxSpriteShow) {                    //Are sprites enabled?
   6997    var lineAdjusted = scanlineToRender + 0x10;
   6998    var OAMAddress = 0xFE00;
   6999    var yoffset = 0;
   7000    var xcoord = 1;
   7001    var xCoordStart = 0;
   7002    var xCoordEnd = 0;
   7003    var attrCode = 0;
   7004    var palette = 0;
   7005    var tile = null;
   7006    var data = 0;
   7007    var spriteCount = 0;
   7008    var length = 0;
   7009    var currentPixel = 0;
   7010    var linePixel = 0;
   7011    //Clear our x-coord sort buffer:
   7012    while (xcoord < 168) {
   7013      this.sortBuffer[xcoord++] = 0xFF;
   7014    }
   7015    if (this.gfxSpriteNormalHeight) {
   7016      //Draw the visible sprites:
   7017      for (var length = this.findLowestSpriteDrawable(lineAdjusted, 0x7); spriteCount < length; ++spriteCount) {
   7018        OAMAddress = this.OAMAddressCache[spriteCount];
   7019        yoffset = (lineAdjusted - this.memory[OAMAddress]) << 3;
   7020        attrCode = this.memory[OAMAddress | 3];
   7021        palette = (attrCode & 0x10) >> 2;
   7022        tile = this.tileCache[((attrCode & 0x60) << 4) | this.memory[OAMAddress | 0x2]];
   7023        linePixel = xCoordStart = this.memory[OAMAddress | 1];
   7024        xCoordEnd = Math.min(168 - linePixel, 8);
   7025        xcoord = (linePixel > 7) ? 0 : (8 - linePixel);
   7026        for (currentPixel = this.pixelStart + ((linePixel > 8) ? (linePixel - 8) : 0); xcoord < xCoordEnd; ++xcoord, ++currentPixel, ++linePixel) {
   7027          if (this.sortBuffer[linePixel] > xCoordStart) {
   7028            if (this.frameBuffer[currentPixel] >= 0x2000000) {
   7029              data = tile[yoffset | xcoord];
   7030              if (data > 0) {
   7031                this.frameBuffer[currentPixel] = this.OBJPalette[palette | data];
   7032                this.sortBuffer[linePixel] = xCoordStart;
   7033              }
   7034            }
   7035            else if (this.frameBuffer[currentPixel] < 0x1000000) {
   7036              data = tile[yoffset | xcoord];
   7037              if (data > 0 && attrCode < 0x80) {
   7038                this.frameBuffer[currentPixel] = this.OBJPalette[palette | data];
   7039                this.sortBuffer[linePixel] = xCoordStart;
   7040              }
   7041            }
   7042          }
   7043        }
   7044      }
   7045    }
   7046    else {
   7047      //Draw the visible sprites:
   7048      for (var length = this.findLowestSpriteDrawable(lineAdjusted, 0xF); spriteCount < length; ++spriteCount) {
   7049        OAMAddress = this.OAMAddressCache[spriteCount];
   7050        yoffset = (lineAdjusted - this.memory[OAMAddress]) << 3;
   7051        attrCode = this.memory[OAMAddress | 3];
   7052        palette = (attrCode & 0x10) >> 2;
   7053        if ((attrCode & 0x40) == (0x40 & yoffset)) {
   7054          tile = this.tileCache[((attrCode & 0x60) << 4) | (this.memory[OAMAddress | 0x2] & 0xFE)];
   7055        }
   7056        else {
   7057          tile = this.tileCache[((attrCode & 0x60) << 4) | this.memory[OAMAddress | 0x2] | 1];
   7058        }
   7059        yoffset &= 0x3F;
   7060        linePixel = xCoordStart = this.memory[OAMAddress | 1];
   7061        xCoordEnd = Math.min(168 - linePixel, 8);
   7062        xcoord = (linePixel > 7) ? 0 : (8 - linePixel);
   7063        for (currentPixel = this.pixelStart + ((linePixel > 8) ? (linePixel - 8) : 0); xcoord < xCoordEnd; ++xcoord, ++currentPixel, ++linePixel) {
   7064          if (this.sortBuffer[linePixel] > xCoordStart) {
   7065            if (this.frameBuffer[currentPixel] >= 0x2000000) {
   7066              data = tile[yoffset | xcoord];
   7067              if (data > 0) {
   7068                this.frameBuffer[currentPixel] = this.OBJPalette[palette | data];
   7069                this.sortBuffer[linePixel] = xCoordStart;
   7070              }
   7071            }
   7072            else if (this.frameBuffer[currentPixel] < 0x1000000) {
   7073              data = tile[yoffset | xcoord];
   7074              if (data > 0 && attrCode < 0x80) {
   7075                this.frameBuffer[currentPixel] = this.OBJPalette[palette | data];
   7076                this.sortBuffer[linePixel] = xCoordStart;
   7077              }
   7078            }
   7079          }
   7080        }
   7081      }
   7082    }
   7083  }
   7084 }
   7085 GameBoyCore.prototype.findLowestSpriteDrawable = function (scanlineToRender, drawableRange) {
   7086  var address = 0xFE00;
   7087  var spriteCount = 0;
   7088  var diff = 0;
   7089  while (address < 0xFEA0 && spriteCount < 10) {
   7090    diff = scanlineToRender - this.memory[address];
   7091    if ((diff & drawableRange) == diff) {
   7092      this.OAMAddressCache[spriteCount++] = address;
   7093    }
   7094    address += 4;
   7095  }
   7096  return spriteCount;
   7097 }
   7098 GameBoyCore.prototype.SpriteGBCLayerRender = function (scanlineToRender) {
   7099  if (this.gfxSpriteShow) {                    //Are sprites enabled?
   7100    var OAMAddress = 0xFE00;
   7101    var lineAdjusted = scanlineToRender + 0x10;
   7102    var yoffset = 0;
   7103    var xcoord = 0;
   7104    var endX = 0;
   7105    var xCounter = 0;
   7106    var attrCode = 0;
   7107    var palette = 0;
   7108    var tile = null;
   7109    var data = 0;
   7110    var currentPixel = 0;
   7111    var spriteCount = 0;
   7112    if (this.gfxSpriteNormalHeight) {
   7113      for (; OAMAddress < 0xFEA0 && spriteCount < 10; OAMAddress += 4) {
   7114        yoffset = lineAdjusted - this.memory[OAMAddress];
   7115        if ((yoffset & 0x7) == yoffset) {
   7116          xcoord = this.memory[OAMAddress | 1] - 8;
   7117          endX = Math.min(160, xcoord + 8);
   7118          attrCode = this.memory[OAMAddress | 3];
   7119          palette = (attrCode & 7) << 2;
   7120          tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | this.memory[OAMAddress | 2]];
   7121          xCounter = (xcoord > 0) ? xcoord : 0;
   7122          xcoord -= yoffset << 3;
   7123          for (currentPixel = this.pixelStart + xCounter; xCounter < endX; ++xCounter, ++currentPixel) {
   7124            if (this.frameBuffer[currentPixel] >= 0x2000000) {
   7125              data = tile[xCounter - xcoord];
   7126              if (data > 0) {
   7127                this.frameBuffer[currentPixel] = this.gbcOBJPalette[palette | data];
   7128              }
   7129            }
   7130            else if (this.frameBuffer[currentPixel] < 0x1000000) {
   7131              data = tile[xCounter - xcoord];
   7132              if (data > 0 && attrCode < 0x80) {    //Don't optimize for attrCode, as LICM-capable JITs should optimize its checks.
   7133                this.frameBuffer[currentPixel] = this.gbcOBJPalette[palette | data];
   7134              }
   7135            }
   7136          }
   7137          ++spriteCount;
   7138        }
   7139      }
   7140    }
   7141    else {
   7142      for (; OAMAddress < 0xFEA0 && spriteCount < 10; OAMAddress += 4) {
   7143        yoffset = lineAdjusted - this.memory[OAMAddress];
   7144        if ((yoffset & 0xF) == yoffset) {
   7145          xcoord = this.memory[OAMAddress | 1] - 8;
   7146          endX = Math.min(160, xcoord + 8);
   7147          attrCode = this.memory[OAMAddress | 3];
   7148          palette = (attrCode & 7) << 2;
   7149          if ((attrCode & 0x40) == (0x40 & (yoffset << 3))) {
   7150            tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | (this.memory[OAMAddress | 0x2] & 0xFE)];
   7151          }
   7152          else {
   7153            tile = this.tileCache[((attrCode & 0x08) << 8) | ((attrCode & 0x60) << 4) | this.memory[OAMAddress | 0x2] | 1];
   7154          }
   7155          xCounter = (xcoord > 0) ? xcoord : 0;
   7156          xcoord -= (yoffset & 0x7) << 3;
   7157          for (currentPixel = this.pixelStart + xCounter; xCounter < endX; ++xCounter, ++currentPixel) {
   7158            if (this.frameBuffer[currentPixel] >= 0x2000000) {
   7159              data = tile[xCounter - xcoord];
   7160              if (data > 0) {
   7161                this.frameBuffer[currentPixel] = this.gbcOBJPalette[palette | data];
   7162              }
   7163            }
   7164            else if (this.frameBuffer[currentPixel] < 0x1000000) {
   7165              data = tile[xCounter - xcoord];
   7166              if (data > 0 && attrCode < 0x80) {    //Don't optimize for attrCode, as LICM-capable JITs should optimize its checks.
   7167                this.frameBuffer[currentPixel] = this.gbcOBJPalette[palette | data];
   7168              }
   7169            }
   7170          }
   7171          ++spriteCount;
   7172        }
   7173      }
   7174    }
   7175  }
   7176 }
   7177 //Generate only a single tile line for the GB tile cache mode:
   7178 GameBoyCore.prototype.generateGBTileLine = function (address) {
   7179  var lineCopy = (this.memory[0x1 | address] << 8) | this.memory[0x9FFE & address];
   7180  var tileBlock = this.tileCache[(address & 0x1FF0) >> 4];
   7181  address = (address & 0xE) << 2;
   7182  tileBlock[address | 7] = ((lineCopy & 0x100) >> 7) | (lineCopy & 0x1);
   7183  tileBlock[address | 6] = ((lineCopy & 0x200) >> 8) | ((lineCopy & 0x2) >> 1);
   7184  tileBlock[address | 5] = ((lineCopy & 0x400) >> 9) | ((lineCopy & 0x4) >> 2);
   7185  tileBlock[address | 4] = ((lineCopy & 0x800) >> 10) | ((lineCopy & 0x8) >> 3);
   7186  tileBlock[address | 3] = ((lineCopy & 0x1000) >> 11) | ((lineCopy & 0x10) >> 4);
   7187  tileBlock[address | 2] = ((lineCopy & 0x2000) >> 12) | ((lineCopy & 0x20) >> 5);
   7188  tileBlock[address | 1] = ((lineCopy & 0x4000) >> 13) | ((lineCopy & 0x40) >> 6);
   7189  tileBlock[address] = ((lineCopy & 0x8000) >> 14) | ((lineCopy & 0x80) >> 7);
   7190 }
   7191 //Generate only a single tile line for the GBC tile cache mode (Bank 1):
   7192 GameBoyCore.prototype.generateGBCTileLineBank1 = function (address) {
   7193  var lineCopy = (this.memory[0x1 | address] << 8) | this.memory[0x9FFE & address];
   7194  address &= 0x1FFE;
   7195  var tileBlock1 = this.tileCache[address >> 4];
   7196  var tileBlock2 = this.tileCache[0x200 | (address >> 4)];
   7197  var tileBlock3 = this.tileCache[0x400 | (address >> 4)];
   7198  var tileBlock4 = this.tileCache[0x600 | (address >> 4)];
   7199  address = (address & 0xE) << 2;
   7200  var addressFlipped = 0x38 - address;
   7201  tileBlock4[addressFlipped] = tileBlock2[address] = tileBlock3[addressFlipped | 7] = tileBlock1[address | 7] = ((lineCopy & 0x100) >> 7) | (lineCopy & 0x1);
   7202  tileBlock4[addressFlipped | 1] = tileBlock2[address | 1] = tileBlock3[addressFlipped | 6] = tileBlock1[address | 6] = ((lineCopy & 0x200) >> 8) | ((lineCopy & 0x2) >> 1);
   7203  tileBlock4[addressFlipped | 2] = tileBlock2[address | 2] = tileBlock3[addressFlipped | 5] = tileBlock1[address | 5] = ((lineCopy & 0x400) >> 9) | ((lineCopy & 0x4) >> 2);
   7204  tileBlock4[addressFlipped | 3] = tileBlock2[address | 3] = tileBlock3[addressFlipped | 4] = tileBlock1[address | 4] = ((lineCopy & 0x800) >> 10) | ((lineCopy & 0x8) >> 3);
   7205  tileBlock4[addressFlipped | 4] = tileBlock2[address | 4] = tileBlock3[addressFlipped | 3] = tileBlock1[address | 3] = ((lineCopy & 0x1000) >> 11) | ((lineCopy & 0x10) >> 4);
   7206  tileBlock4[addressFlipped | 5] = tileBlock2[address | 5] = tileBlock3[addressFlipped | 2] = tileBlock1[address | 2] = ((lineCopy & 0x2000) >> 12) | ((lineCopy & 0x20) >> 5);
   7207  tileBlock4[addressFlipped | 6] = tileBlock2[address | 6] = tileBlock3[addressFlipped | 1] = tileBlock1[address | 1] = ((lineCopy & 0x4000) >> 13) | ((lineCopy & 0x40) >> 6);
   7208  tileBlock4[addressFlipped | 7] = tileBlock2[address | 7] = tileBlock3[addressFlipped] = tileBlock1[address] = ((lineCopy & 0x8000) >> 14) | ((lineCopy & 0x80) >> 7);
   7209 }
   7210 //Generate all the flip combinations for a full GBC VRAM bank 1 tile:
   7211 GameBoyCore.prototype.generateGBCTileBank1 = function (vramAddress) {
   7212  var address = vramAddress >> 4;
   7213  var tileBlock1 = this.tileCache[address];
   7214  var tileBlock2 = this.tileCache[0x200 | address];
   7215  var tileBlock3 = this.tileCache[0x400 | address];
   7216  var tileBlock4 = this.tileCache[0x600 | address];
   7217  var lineCopy = 0;
   7218  vramAddress |= 0x8000;
   7219  address = 0;
   7220  var addressFlipped = 56;
   7221  do {
   7222    lineCopy = (this.memory[0x1 | vramAddress] << 8) | this.memory[vramAddress];
   7223    tileBlock4[addressFlipped] = tileBlock2[address] = tileBlock3[addressFlipped | 7] = tileBlock1[address | 7] = ((lineCopy & 0x100) >> 7) | (lineCopy & 0x1);
   7224    tileBlock4[addressFlipped | 1] = tileBlock2[address | 1] = tileBlock3[addressFlipped | 6] = tileBlock1[address | 6] = ((lineCopy & 0x200) >> 8) | ((lineCopy & 0x2) >> 1);
   7225    tileBlock4[addressFlipped | 2] = tileBlock2[address | 2] = tileBlock3[addressFlipped | 5] = tileBlock1[address | 5] = ((lineCopy & 0x400) >> 9) | ((lineCopy & 0x4) >> 2);
   7226    tileBlock4[addressFlipped | 3] = tileBlock2[address | 3] = tileBlock3[addressFlipped | 4] = tileBlock1[address | 4] = ((lineCopy & 0x800) >> 10) | ((lineCopy & 0x8) >> 3);
   7227    tileBlock4[addressFlipped | 4] = tileBlock2[address | 4] = tileBlock3[addressFlipped | 3] = tileBlock1[address | 3] = ((lineCopy & 0x1000) >> 11) | ((lineCopy & 0x10) >> 4);
   7228    tileBlock4[addressFlipped | 5] = tileBlock2[address | 5] = tileBlock3[addressFlipped | 2] = tileBlock1[address | 2] = ((lineCopy & 0x2000) >> 12) | ((lineCopy & 0x20) >> 5);
   7229    tileBlock4[addressFlipped | 6] = tileBlock2[address | 6] = tileBlock3[addressFlipped | 1] = tileBlock1[address | 1] = ((lineCopy & 0x4000) >> 13) | ((lineCopy & 0x40) >> 6);
   7230    tileBlock4[addressFlipped | 7] = tileBlock2[address | 7] = tileBlock3[addressFlipped] = tileBlock1[address] = ((lineCopy & 0x8000) >> 14) | ((lineCopy & 0x80) >> 7);
   7231    address += 8;
   7232    addressFlipped -= 8;
   7233    vramAddress += 2;
   7234  } while (addressFlipped > -1);
   7235 }
   7236 //Generate only a single tile line for the GBC tile cache mode (Bank 2):
   7237 GameBoyCore.prototype.generateGBCTileLineBank2 = function (address) {
   7238  var lineCopy = (this.VRAM[0x1 | address] << 8) | this.VRAM[0x1FFE & address];
   7239  var tileBlock1 = this.tileCache[0x800 | (address >> 4)];
   7240  var tileBlock2 = this.tileCache[0xA00 | (address >> 4)];
   7241  var tileBlock3 = this.tileCache[0xC00 | (address >> 4)];
   7242  var tileBlock4 = this.tileCache[0xE00 | (address >> 4)];
   7243  address = (address & 0xE) << 2;
   7244  var addressFlipped = 0x38 - address;
   7245  tileBlock4[addressFlipped] = tileBlock2[address] = tileBlock3[addressFlipped | 7] = tileBlock1[address | 7] = ((lineCopy & 0x100) >> 7) | (lineCopy & 0x1);
   7246  tileBlock4[addressFlipped | 1] = tileBlock2[address | 1] = tileBlock3[addressFlipped | 6] = tileBlock1[address | 6] = ((lineCopy & 0x200) >> 8) | ((lineCopy & 0x2) >> 1);
   7247  tileBlock4[addressFlipped | 2] = tileBlock2[address | 2] = tileBlock3[addressFlipped | 5] = tileBlock1[address | 5] = ((lineCopy & 0x400) >> 9) | ((lineCopy & 0x4) >> 2);
   7248  tileBlock4[addressFlipped | 3] = tileBlock2[address | 3] = tileBlock3[addressFlipped | 4] = tileBlock1[address | 4] = ((lineCopy & 0x800) >> 10) | ((lineCopy & 0x8) >> 3);
   7249  tileBlock4[addressFlipped | 4] = tileBlock2[address | 4] = tileBlock3[addressFlipped | 3] = tileBlock1[address | 3] = ((lineCopy & 0x1000) >> 11) | ((lineCopy & 0x10) >> 4);
   7250  tileBlock4[addressFlipped | 5] = tileBlock2[address | 5] = tileBlock3[addressFlipped | 2] = tileBlock1[address | 2] = ((lineCopy & 0x2000) >> 12) | ((lineCopy & 0x20) >> 5);
   7251  tileBlock4[addressFlipped | 6] = tileBlock2[address | 6] = tileBlock3[addressFlipped | 1] = tileBlock1[address | 1] = ((lineCopy & 0x4000) >> 13) | ((lineCopy & 0x40) >> 6);
   7252  tileBlock4[addressFlipped | 7] = tileBlock2[address | 7] = tileBlock3[addressFlipped] = tileBlock1[address] = ((lineCopy & 0x8000) >> 14) | ((lineCopy & 0x80) >> 7);
   7253 }
   7254 //Generate all the flip combinations for a full GBC VRAM bank 2 tile:
   7255 GameBoyCore.prototype.generateGBCTileBank2 = function (vramAddress) {
   7256  var address = vramAddress >> 4;
   7257  var tileBlock1 = this.tileCache[0x800 | address];
   7258  var tileBlock2 = this.tileCache[0xA00 | address];
   7259  var tileBlock3 = this.tileCache[0xC00 | address];
   7260  var tileBlock4 = this.tileCache[0xE00 | address];
   7261  var lineCopy = 0;
   7262  address = 0;
   7263  var addressFlipped = 56;
   7264  do {
   7265    lineCopy = (this.VRAM[0x1 | vramAddress] << 8) | this.VRAM[vramAddress];
   7266    tileBlock4[addressFlipped] = tileBlock2[address] = tileBlock3[addressFlipped | 7] = tileBlock1[address | 7] = ((lineCopy & 0x100) >> 7) | (lineCopy & 0x1);
   7267    tileBlock4[addressFlipped | 1] = tileBlock2[address | 1] = tileBlock3[addressFlipped | 6] = tileBlock1[address | 6] = ((lineCopy & 0x200) >> 8) | ((lineCopy & 0x2) >> 1);
   7268    tileBlock4[addressFlipped | 2] = tileBlock2[address | 2] = tileBlock3[addressFlipped | 5] = tileBlock1[address | 5] = ((lineCopy & 0x400) >> 9) | ((lineCopy & 0x4) >> 2);
   7269    tileBlock4[addressFlipped | 3] = tileBlock2[address | 3] = tileBlock3[addressFlipped | 4] = tileBlock1[address | 4] = ((lineCopy & 0x800) >> 10) | ((lineCopy & 0x8) >> 3);
   7270    tileBlock4[addressFlipped | 4] = tileBlock2[address | 4] = tileBlock3[addressFlipped | 3] = tileBlock1[address | 3] = ((lineCopy & 0x1000) >> 11) | ((lineCopy & 0x10) >> 4);
   7271    tileBlock4[addressFlipped | 5] = tileBlock2[address | 5] = tileBlock3[addressFlipped | 2] = tileBlock1[address | 2] = ((lineCopy & 0x2000) >> 12) | ((lineCopy & 0x20) >> 5);
   7272    tileBlock4[addressFlipped | 6] = tileBlock2[address | 6] = tileBlock3[addressFlipped | 1] = tileBlock1[address | 1] = ((lineCopy & 0x4000) >> 13) | ((lineCopy & 0x40) >> 6);
   7273    tileBlock4[addressFlipped | 7] = tileBlock2[address | 7] = tileBlock3[addressFlipped] = tileBlock1[address] = ((lineCopy & 0x8000) >> 14) | ((lineCopy & 0x80) >> 7);
   7274    address += 8;
   7275    addressFlipped -= 8;
   7276    vramAddress += 2;
   7277  } while (addressFlipped > -1);
   7278 }
   7279 //Generate only a single tile line for the GB tile cache mode (OAM accessible range):
   7280 GameBoyCore.prototype.generateGBOAMTileLine = function (address) {
   7281  var lineCopy = (this.memory[0x1 | address] << 8) | this.memory[0x9FFE & address];
   7282  address &= 0x1FFE;
   7283  var tileBlock1 = this.tileCache[address >> 4];
   7284  var tileBlock2 = this.tileCache[0x200 | (address >> 4)];
   7285  var tileBlock3 = this.tileCache[0x400 | (address >> 4)];
   7286  var tileBlock4 = this.tileCache[0x600 | (address >> 4)];
   7287  address = (address & 0xE) << 2;
   7288  var addressFlipped = 0x38 - address;
   7289  tileBlock4[addressFlipped] = tileBlock2[address] = tileBlock3[addressFlipped | 7] = tileBlock1[address | 7] = ((lineCopy & 0x100) >> 7) | (lineCopy & 0x1);
   7290  tileBlock4[addressFlipped | 1] = tileBlock2[address | 1] = tileBlock3[addressFlipped | 6] = tileBlock1[address | 6] = ((lineCopy & 0x200) >> 8) | ((lineCopy & 0x2) >> 1);
   7291  tileBlock4[addressFlipped | 2] = tileBlock2[address | 2] = tileBlock3[addressFlipped | 5] = tileBlock1[address | 5] = ((lineCopy & 0x400) >> 9) | ((lineCopy & 0x4) >> 2);
   7292  tileBlock4[addressFlipped | 3] = tileBlock2[address | 3] = tileBlock3[addressFlipped | 4] = tileBlock1[address | 4] = ((lineCopy & 0x800) >> 10) | ((lineCopy & 0x8) >> 3);
   7293  tileBlock4[addressFlipped | 4] = tileBlock2[address | 4] = tileBlock3[addressFlipped | 3] = tileBlock1[address | 3] = ((lineCopy & 0x1000) >> 11) | ((lineCopy & 0x10) >> 4);
   7294  tileBlock4[addressFlipped | 5] = tileBlock2[address | 5] = tileBlock3[addressFlipped | 2] = tileBlock1[address | 2] = ((lineCopy & 0x2000) >> 12) | ((lineCopy & 0x20) >> 5);
   7295  tileBlock4[addressFlipped | 6] = tileBlock2[address | 6] = tileBlock3[addressFlipped | 1] = tileBlock1[address | 1] = ((lineCopy & 0x4000) >> 13) | ((lineCopy & 0x40) >> 6);
   7296  tileBlock4[addressFlipped | 7] = tileBlock2[address | 7] = tileBlock3[addressFlipped] = tileBlock1[address] = ((lineCopy & 0x8000) >> 14) | ((lineCopy & 0x80) >> 7);
   7297 }
   7298 GameBoyCore.prototype.graphicsJIT = function () {
   7299  if (this.LCDisOn) {
   7300    this.totalLinesPassed = 0;      //Mark frame for ensuring a JIT pass for the next framebuffer output.
   7301    this.graphicsJITScanlineGroup();
   7302  }
   7303 }
   7304 GameBoyCore.prototype.graphicsJITVBlank = function () {
   7305  //JIT the graphics to v-blank framing:
   7306  this.totalLinesPassed += this.queuedScanLines;
   7307  this.graphicsJITScanlineGroup();
   7308 }
   7309 GameBoyCore.prototype.graphicsJITScanlineGroup = function () {
   7310  //Normal rendering JIT, where we try to do groups of scanlines at once:
   7311  while (this.queuedScanLines > 0) {
   7312    this.renderScanLine(this.lastUnrenderedLine);
   7313    if (this.lastUnrenderedLine < 143) {
   7314      ++this.lastUnrenderedLine;
   7315    }
   7316    else {
   7317      this.lastUnrenderedLine = 0;
   7318    }
   7319    --this.queuedScanLines;
   7320  }
   7321 }
   7322 GameBoyCore.prototype.incrementScanLineQueue = function () {
   7323  if (this.queuedScanLines < 144) {
   7324    ++this.queuedScanLines;
   7325  }
   7326  else {
   7327    this.currentX = 0;
   7328    this.midScanlineOffset = -1;
   7329    if (this.lastUnrenderedLine < 143) {
   7330      ++this.lastUnrenderedLine;
   7331    }
   7332    else {
   7333      this.lastUnrenderedLine = 0;
   7334    }
   7335  }
   7336 }
   7337 GameBoyCore.prototype.midScanLineJIT = function () {
   7338  this.graphicsJIT();
   7339  this.renderMidScanLine();
   7340 }
   7341 //Check for the highest priority IRQ to fire:
   7342 GameBoyCore.prototype.launchIRQ = function () {
   7343  var bitShift = 0;
   7344  var testbit = 1;
   7345  do {
   7346    //Check to see if an interrupt is enabled AND requested.
   7347    if ((testbit & this.IRQLineMatched) == testbit) {
   7348      this.IME = false;            //Reset the interrupt enabling.
   7349      this.interruptsRequested -= testbit;  //Reset the interrupt request.
   7350      this.IRQLineMatched = 0;        //Reset the IRQ assertion.
   7351      //Interrupts have a certain clock cycle length:
   7352      this.CPUTicks = 20;
   7353      //Set the stack pointer to the current program counter value:
   7354      this.stackPointer = (this.stackPointer - 1) & 0xFFFF;
   7355      this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter >> 8);
   7356      this.stackPointer = (this.stackPointer - 1) & 0xFFFF;
   7357      this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter & 0xFF);
   7358      //Set the program counter to the interrupt's address:
   7359      this.programCounter = 0x40 | (bitShift << 3);
   7360      //Clock the core for mid-instruction updates:
   7361      this.updateCore();
   7362      return;                  //We only want the highest priority interrupt.
   7363    }
   7364    testbit = 1 << ++bitShift;
   7365  } while (bitShift < 5);
   7366 }
   7367 /*
   7368  Check for IRQs to be fired while not in HALT:
   7369 */
   7370 GameBoyCore.prototype.checkIRQMatching = function () {
   7371  if (this.IME) {
   7372    this.IRQLineMatched = this.interruptsEnabled & this.interruptsRequested & 0x1F;
   7373  }
   7374 }
   7375 /*
   7376  Handle the HALT opcode by predicting all IRQ cases correctly,
   7377  then selecting the next closest IRQ firing from the prediction to
   7378  clock up to. This prevents hacky looping that doesn't predict, but
   7379  instead just clocks through the core update procedure by one which
   7380  is very slow. Not many emulators do this because they have to cover
   7381  all the IRQ prediction cases and they usually get them wrong.
   7382 */
   7383 GameBoyCore.prototype.calculateHALTPeriod = function () {
   7384  //Initialize our variables and start our prediction:
   7385  if (!this.halt) {
   7386    this.halt = true;
   7387    var currentClocks = -1;
   7388    var temp_var = 0;
   7389    if (this.LCDisOn) {
   7390      //If the LCD is enabled, then predict the LCD IRQs enabled:
   7391      if ((this.interruptsEnabled & 0x1) == 0x1) {
   7392        currentClocks = ((456 * (((this.modeSTAT == 1) ? 298 : 144) - this.actualScanLine)) - this.LCDTicks) << this.doubleSpeedShifter;
   7393      }
   7394      if ((this.interruptsEnabled & 0x2) == 0x2) {
   7395        if (this.mode0TriggerSTAT) {
   7396          temp_var = (this.clocksUntilMode0() - this.LCDTicks) << this.doubleSpeedShifter;
   7397          if (temp_var <= currentClocks || currentClocks == -1) {
   7398            currentClocks = temp_var;
   7399          }
   7400        }
   7401        if (this.mode1TriggerSTAT && (this.interruptsEnabled & 0x1) == 0) {
   7402          temp_var = ((456 * (((this.modeSTAT == 1) ? 298 : 144) - this.actualScanLine)) - this.LCDTicks) << this.doubleSpeedShifter;
   7403          if (temp_var <= currentClocks || currentClocks == -1) {
   7404            currentClocks = temp_var;
   7405          }
   7406        }
   7407        if (this.mode2TriggerSTAT) {
   7408          temp_var = (((this.actualScanLine >= 143) ? (456 * (154 - this.actualScanLine)) : 456) - this.LCDTicks) << this.doubleSpeedShifter;
   7409          if (temp_var <= currentClocks || currentClocks == -1) {
   7410            currentClocks = temp_var;
   7411          }
   7412        }
   7413        if (this.LYCMatchTriggerSTAT && this.memory[0xFF45] <= 153) {
   7414          temp_var = (this.clocksUntilLYCMatch() - this.LCDTicks) << this.doubleSpeedShifter;
   7415          if (temp_var <= currentClocks || currentClocks == -1) {
   7416            currentClocks = temp_var;
   7417          }
   7418        }
   7419      }
   7420    }
   7421    if (this.TIMAEnabled && (this.interruptsEnabled & 0x4) == 0x4) {
   7422      //CPU timer IRQ prediction:
   7423      temp_var = ((0x100 - this.memory[0xFF05]) * this.TACClocker) - this.timerTicks;
   7424      if (temp_var <= currentClocks || currentClocks == -1) {
   7425        currentClocks = temp_var;
   7426      }
   7427    }
   7428    if (this.serialTimer > 0 && (this.interruptsEnabled & 0x8) == 0x8) {
   7429      //Serial IRQ prediction:
   7430      if (this.serialTimer <= currentClocks || currentClocks == -1) {
   7431        currentClocks = this.serialTimer;
   7432      }
   7433    }
   7434  }
   7435  else {
   7436    var currentClocks = this.remainingClocks;
   7437  }
   7438  var maxClocks = (this.CPUCyclesTotal - this.emulatorTicks) << this.doubleSpeedShifter;
   7439  if (currentClocks >= 0) {
   7440    if (currentClocks <= maxClocks) {
   7441      //Exit out of HALT normally:
   7442      this.CPUTicks = Math.max(currentClocks, this.CPUTicks);
   7443      this.updateCoreFull();
   7444      this.halt = false;
   7445      this.CPUTicks = 0;
   7446    }
   7447    else {
   7448      //Still in HALT, clock only up to the clocks specified per iteration:
   7449      this.CPUTicks = Math.max(maxClocks, this.CPUTicks);
   7450      this.remainingClocks = currentClocks - this.CPUTicks;
   7451    }
   7452  }
   7453  else {
   7454    //Still in HALT, clock only up to the clocks specified per iteration:
   7455    //Will stay in HALT forever (Stuck in HALT forever), but the APU and LCD are still clocked, so don't pause:
   7456    this.CPUTicks += maxClocks;
   7457  }
   7458 }
   7459 //Memory Reading:
   7460 GameBoyCore.prototype.memoryRead = function (address) {
   7461  //Act as a wrapper for reading the returns from the compiled jumps to memory.
   7462  return this.memoryReader[address](this, address);  //This seems to be faster than the usual if/else.
   7463 }
   7464 GameBoyCore.prototype.memoryHighRead = function (address) {
   7465  //Act as a wrapper for reading the returns from the compiled jumps to memory.
   7466  return this.memoryHighReader[address](this, address);  //This seems to be faster than the usual if/else.
   7467 }
   7468 GameBoyCore.prototype.memoryReadJumpCompile = function () {
   7469  //Faster in some browsers, since we are doing less conditionals overall by implementing them in advance.
   7470  for (var index = 0x0000; index <= 0xFFFF; index++) {
   7471    if (index < 0x4000) {
   7472      this.memoryReader[index] = this.memoryReadNormal;
   7473    }
   7474    else if (index < 0x8000) {
   7475      this.memoryReader[index] = this.memoryReadROM;
   7476    }
   7477    else if (index < 0x9800) {
   7478      this.memoryReader[index] = (this.cGBC) ? this.VRAMDATAReadCGBCPU : this.VRAMDATAReadDMGCPU;
   7479    }
   7480    else if (index < 0xA000) {
   7481      this.memoryReader[index] = (this.cGBC) ? this.VRAMCHRReadCGBCPU : this.VRAMCHRReadDMGCPU;
   7482    }
   7483    else if (index >= 0xA000 && index < 0xC000) {
   7484      if ((this.numRAMBanks == 1 / 16 && index < 0xA200) || this.numRAMBanks >= 1) {
   7485        if (this.cMBC7) {
   7486          this.memoryReader[index] = this.memoryReadMBC7;
   7487        }
   7488        else if (!this.cMBC3) {
   7489          this.memoryReader[index] = this.memoryReadMBC;
   7490        }
   7491        else {
   7492          //MBC3 RTC + RAM:
   7493          this.memoryReader[index] = this.memoryReadMBC3;
   7494        }
   7495      }
   7496      else {
   7497        this.memoryReader[index] = this.memoryReadBAD;
   7498      }
   7499    }
   7500    else if (index >= 0xC000 && index < 0xE000) {
   7501      if (!this.cGBC || index < 0xD000) {
   7502        this.memoryReader[index] = this.memoryReadNormal;
   7503      }
   7504      else {
   7505        this.memoryReader[index] = this.memoryReadGBCMemory;
   7506      }
   7507    }
   7508    else if (index >= 0xE000 && index < 0xFE00) {
   7509      if (!this.cGBC || index < 0xF000) {
   7510        this.memoryReader[index] = this.memoryReadECHONormal;
   7511      }
   7512      else {
   7513        this.memoryReader[index] = this.memoryReadECHOGBCMemory;
   7514      }
   7515    }
   7516    else if (index < 0xFEA0) {
   7517      this.memoryReader[index] = this.memoryReadOAM;
   7518    }
   7519    else if (this.cGBC && index >= 0xFEA0 && index < 0xFF00) {
   7520      this.memoryReader[index] = this.memoryReadNormal;
   7521    }
   7522    else if (index >= 0xFF00) {
   7523      switch (index) {
   7524        case 0xFF00:
   7525          //JOYPAD:
   7526          this.memoryHighReader[0] = this.memoryReader[0xFF00] = function (parentObj, address) {
   7527            return 0xC0 | parentObj.memory[0xFF00];  //Top nibble returns as set.
   7528          }
   7529          break;
   7530        case 0xFF01:
   7531          //SB
   7532          this.memoryHighReader[0x01] = this.memoryReader[0xFF01] = function (parentObj, address) {
   7533            return (parentObj.memory[0xFF02] < 0x80) ? parentObj.memory[0xFF01] : 0xFF;
   7534          }
   7535          break;
   7536        case 0xFF02:
   7537          //SC
   7538          if (this.cGBC) {
   7539            this.memoryHighReader[0x02] = this.memoryReader[0xFF02] = function (parentObj, address) {
   7540              return ((parentObj.serialTimer <= 0) ? 0x7C : 0xFC) | parentObj.memory[0xFF02];
   7541            }
   7542          }
   7543          else {
   7544            this.memoryHighReader[0x02] = this.memoryReader[0xFF02] = function (parentObj, address) {
   7545              return ((parentObj.serialTimer <= 0) ? 0x7E : 0xFE) | parentObj.memory[0xFF02];
   7546            }
   7547          }
   7548          break;
   7549        case 0xFF04:
   7550          //DIV
   7551          this.memoryHighReader[0x04] = this.memoryReader[0xFF04] = function (parentObj, address) {
   7552            parentObj.memory[0xFF04] = (parentObj.memory[0xFF04] + (parentObj.DIVTicks >> 8)) & 0xFF;
   7553            parentObj.DIVTicks &= 0xFF;
   7554            return parentObj.memory[0xFF04];
   7555 
   7556          }
   7557          break;
   7558        case 0xFF07:
   7559          this.memoryHighReader[0x07] = this.memoryReader[0xFF07] = function (parentObj, address) {
   7560            return 0xF8 | parentObj.memory[0xFF07];
   7561          }
   7562          break;
   7563        case 0xFF0F:
   7564          //IF
   7565          this.memoryHighReader[0x0F] = this.memoryReader[0xFF0F] = function (parentObj, address) {
   7566            return 0xE0 | parentObj.interruptsRequested;
   7567          }
   7568          break;
   7569        case 0xFF10:
   7570          this.memoryHighReader[0x10] = this.memoryReader[0xFF10] = function (parentObj, address) {
   7571            return 0x80 | parentObj.memory[0xFF10];
   7572          }
   7573          break;
   7574        case 0xFF11:
   7575          this.memoryHighReader[0x11] = this.memoryReader[0xFF11] = function (parentObj, address) {
   7576            return 0x3F | parentObj.memory[0xFF11];
   7577          }
   7578          break;
   7579        case 0xFF13:
   7580          this.memoryHighReader[0x13] = this.memoryReader[0xFF13] = this.memoryReadBAD;
   7581          break;
   7582        case 0xFF14:
   7583          this.memoryHighReader[0x14] = this.memoryReader[0xFF14] = function (parentObj, address) {
   7584            return 0xBF | parentObj.memory[0xFF14];
   7585          }
   7586          break;
   7587        case 0xFF16:
   7588          this.memoryHighReader[0x16] = this.memoryReader[0xFF16] = function (parentObj, address) {
   7589            return 0x3F | parentObj.memory[0xFF16];
   7590          }
   7591          break;
   7592        case 0xFF18:
   7593          this.memoryHighReader[0x18] = this.memoryReader[0xFF18] = this.memoryReadBAD;
   7594          break;
   7595        case 0xFF19:
   7596          this.memoryHighReader[0x19] = this.memoryReader[0xFF19] = function (parentObj, address) {
   7597            return 0xBF | parentObj.memory[0xFF19];
   7598          }
   7599          break;
   7600        case 0xFF1A:
   7601          this.memoryHighReader[0x1A] = this.memoryReader[0xFF1A] = function (parentObj, address) {
   7602            return 0x7F | parentObj.memory[0xFF1A];
   7603          }
   7604          break;
   7605        case 0xFF1B:
   7606          this.memoryHighReader[0x1B] = this.memoryReader[0xFF1B] = this.memoryReadBAD;
   7607          break;
   7608        case 0xFF1C:
   7609          this.memoryHighReader[0x1C] = this.memoryReader[0xFF1C] = function (parentObj, address) {
   7610            return 0x9F | parentObj.memory[0xFF1C];
   7611          }
   7612          break;
   7613        case 0xFF1D:
   7614          this.memoryHighReader[0x1D] = this.memoryReader[0xFF1D] = function (parentObj, address) {
   7615            return 0xFF;
   7616          }
   7617          break;
   7618        case 0xFF1E:
   7619          this.memoryHighReader[0x1E] = this.memoryReader[0xFF1E] = function (parentObj, address) {
   7620            return 0xBF | parentObj.memory[0xFF1E];
   7621          }
   7622          break;
   7623        case 0xFF1F:
   7624        case 0xFF20:
   7625          this.memoryHighReader[index & 0xFF] = this.memoryReader[index] = this.memoryReadBAD;
   7626          break;
   7627        case 0xFF23:
   7628          this.memoryHighReader[0x23] = this.memoryReader[0xFF23] = function (parentObj, address) {
   7629            return 0xBF | parentObj.memory[0xFF23];
   7630          }
   7631          break;
   7632        case 0xFF26:
   7633          this.memoryHighReader[0x26] = this.memoryReader[0xFF26] = function (parentObj, address) {
   7634            parentObj.audioJIT();
   7635            return 0x70 | parentObj.memory[0xFF26];
   7636          }
   7637          break;
   7638        case 0xFF27:
   7639        case 0xFF28:
   7640        case 0xFF29:
   7641        case 0xFF2A:
   7642        case 0xFF2B:
   7643        case 0xFF2C:
   7644        case 0xFF2D:
   7645        case 0xFF2E:
   7646        case 0xFF2F:
   7647          this.memoryHighReader[index & 0xFF] = this.memoryReader[index] = this.memoryReadBAD;
   7648          break;
   7649        case 0xFF30:
   7650        case 0xFF31:
   7651        case 0xFF32:
   7652        case 0xFF33:
   7653        case 0xFF34:
   7654        case 0xFF35:
   7655        case 0xFF36:
   7656        case 0xFF37:
   7657        case 0xFF38:
   7658        case 0xFF39:
   7659        case 0xFF3A:
   7660        case 0xFF3B:
   7661        case 0xFF3C:
   7662        case 0xFF3D:
   7663        case 0xFF3E:
   7664        case 0xFF3F:
   7665          this.memoryReader[index] = function (parentObj, address) {
   7666            return (parentObj.channel3canPlay) ? parentObj.memory[0xFF00 | (parentObj.channel3lastSampleLookup >> 1)] : parentObj.memory[address];
   7667          }
   7668          this.memoryHighReader[index & 0xFF] = function (parentObj, address) {
   7669            return (parentObj.channel3canPlay) ? parentObj.memory[0xFF00 | (parentObj.channel3lastSampleLookup >> 1)] : parentObj.memory[0xFF00 | address];
   7670          }
   7671          break;
   7672        case 0xFF41:
   7673          this.memoryHighReader[0x41] = this.memoryReader[0xFF41] = function (parentObj, address) {
   7674            return 0x80 | parentObj.memory[0xFF41] | parentObj.modeSTAT;
   7675          }
   7676          break;
   7677        case 0xFF42:
   7678          this.memoryHighReader[0x42] = this.memoryReader[0xFF42] = function (parentObj, address) {
   7679            return parentObj.backgroundY;
   7680          }
   7681          break;
   7682        case 0xFF43:
   7683          this.memoryHighReader[0x43] = this.memoryReader[0xFF43] = function (parentObj, address) {
   7684            return parentObj.backgroundX;
   7685          }
   7686          break;
   7687        case 0xFF44:
   7688          this.memoryHighReader[0x44] = this.memoryReader[0xFF44] = function (parentObj, address) {
   7689            return ((parentObj.LCDisOn) ? parentObj.memory[0xFF44] : 0);
   7690          }
   7691          break;
   7692        case 0xFF4A:
   7693          //WY
   7694          this.memoryHighReader[0x4A] = this.memoryReader[0xFF4A] = function (parentObj, address) {
   7695            return parentObj.windowY;
   7696          }
   7697          break;
   7698        case 0xFF4F:
   7699          this.memoryHighReader[0x4F] = this.memoryReader[0xFF4F] = function (parentObj, address) {
   7700            return parentObj.currVRAMBank;
   7701          }
   7702          break;
   7703        case 0xFF55:
   7704          if (this.cGBC) {
   7705            this.memoryHighReader[0x55] = this.memoryReader[0xFF55] = function (parentObj, address) {
   7706              if (!parentObj.LCDisOn && parentObj.hdmaRunning) {  //Undocumented behavior alert: HDMA becomes GDMA when LCD is off (Worms Armageddon Fix).
   7707                //DMA
   7708                parentObj.DMAWrite((parentObj.memory[0xFF55] & 0x7F) + 1);
   7709                parentObj.memory[0xFF55] = 0xFF;  //Transfer completed.
   7710                parentObj.hdmaRunning = false;
   7711              }
   7712              return parentObj.memory[0xFF55];
   7713            }
   7714          }
   7715          else {
   7716            this.memoryReader[0xFF55] = this.memoryReadNormal;
   7717            this.memoryHighReader[0x55] = this.memoryHighReadNormal;
   7718          }
   7719          break;
   7720        case 0xFF56:
   7721          if (this.cGBC) {
   7722            this.memoryHighReader[0x56] = this.memoryReader[0xFF56] = function (parentObj, address) {
   7723              //Return IR "not connected" status:
   7724              return 0x3C | ((parentObj.memory[0xFF56] >= 0xC0) ? (0x2 | (parentObj.memory[0xFF56] & 0xC1)) : (parentObj.memory[0xFF56] & 0xC3));
   7725            }
   7726          }
   7727          else {
   7728            this.memoryReader[0xFF56] = this.memoryReadNormal;
   7729            this.memoryHighReader[0x56] = this.memoryHighReadNormal;
   7730          }
   7731          break;
   7732        case 0xFF6C:
   7733          if (this.cGBC) {
   7734            this.memoryHighReader[0x6C] = this.memoryReader[0xFF6C] = function (parentObj, address) {
   7735              return 0xFE | parentObj.memory[0xFF6C];
   7736            }
   7737          }
   7738          else {
   7739            this.memoryHighReader[0x6C] = this.memoryReader[0xFF6C] = this.memoryReadBAD;
   7740          }
   7741          break;
   7742        case 0xFF70:
   7743          if (this.cGBC) {
   7744            //SVBK
   7745            this.memoryHighReader[0x70] = this.memoryReader[0xFF70] = function (parentObj, address) {
   7746              return 0x40 | parentObj.memory[0xFF70];
   7747            }
   7748          }
   7749          else {
   7750            this.memoryHighReader[0x70] = this.memoryReader[0xFF70] = this.memoryReadBAD;
   7751          }
   7752          break;
   7753        case 0xFF75:
   7754          this.memoryHighReader[0x75] = this.memoryReader[0xFF75] = function (parentObj, address) {
   7755            return 0x8F | parentObj.memory[0xFF75];
   7756          }
   7757          break;
   7758        case 0xFF76:
   7759        case 0xFF77:
   7760          this.memoryHighReader[index & 0xFF] = this.memoryReader[index] = function (parentObj, address) {
   7761            return 0;
   7762          }
   7763          break;
   7764        case 0xFFFF:
   7765          //IE
   7766          this.memoryHighReader[0xFF] = this.memoryReader[0xFFFF] = function (parentObj, address) {
   7767            return parentObj.interruptsEnabled;
   7768          }
   7769          break;
   7770        default:
   7771          this.memoryReader[index] = this.memoryReadNormal;
   7772          this.memoryHighReader[index & 0xFF] = this.memoryHighReadNormal;
   7773      }
   7774    }
   7775    else {
   7776      this.memoryReader[index] = this.memoryReadBAD;
   7777    }
   7778  }
   7779 }
   7780 GameBoyCore.prototype.memoryReadNormal = function (parentObj, address) {
   7781  return parentObj.memory[address];
   7782 }
   7783 GameBoyCore.prototype.memoryHighReadNormal = function (parentObj, address) {
   7784  return parentObj.memory[0xFF00 | address];
   7785 }
   7786 GameBoyCore.prototype.memoryReadROM = function (parentObj, address) {
   7787  return parentObj.ROM[parentObj.currentROMBank + address];
   7788 }
   7789 GameBoyCore.prototype.memoryReadMBC = function (parentObj, address) {
   7790  //Switchable RAM
   7791  if (parentObj.MBCRAMBanksEnabled || settings[10]) {
   7792    return parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition];
   7793  }
   7794  //cout("Reading from disabled RAM.", 1);
   7795  return 0xFF;
   7796 }
   7797 GameBoyCore.prototype.memoryReadMBC7 = function (parentObj, address) {
   7798  //Switchable RAM
   7799  if (parentObj.MBCRAMBanksEnabled || settings[10]) {
   7800    switch (address) {
   7801      case 0xA000:
   7802      case 0xA060:
   7803      case 0xA070:
   7804        return 0;
   7805      case 0xA080:
   7806        //TODO: Gyro Control Register
   7807        return 0;
   7808      case 0xA050:
   7809        //Y High Byte
   7810        return parentObj.highY;
   7811      case 0xA040:
   7812        //Y Low Byte
   7813        return parentObj.lowY;
   7814      case 0xA030:
   7815        //X High Byte
   7816        return parentObj.highX;
   7817      case 0xA020:
   7818        //X Low Byte:
   7819        return parentObj.lowX;
   7820      default:
   7821        return parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition];
   7822    }
   7823  }
   7824  //cout("Reading from disabled RAM.", 1);
   7825  return 0xFF;
   7826 }
   7827 GameBoyCore.prototype.memoryReadMBC3 = function (parentObj, address) {
   7828  //Switchable RAM
   7829  if (parentObj.MBCRAMBanksEnabled || settings[10]) {
   7830    switch (parentObj.currMBCRAMBank) {
   7831      case 0x00:
   7832      case 0x01:
   7833      case 0x02:
   7834      case 0x03:
   7835        return parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition];
   7836        break;
   7837      case 0x08:
   7838        return parentObj.latchedSeconds;
   7839        break;
   7840      case 0x09:
   7841        return parentObj.latchedMinutes;
   7842        break;
   7843      case 0x0A:
   7844        return parentObj.latchedHours;
   7845        break;
   7846      case 0x0B:
   7847        return parentObj.latchedLDays;
   7848        break;
   7849      case 0x0C:
   7850        return (((parentObj.RTCDayOverFlow) ? 0x80 : 0) + ((parentObj.RTCHALT) ? 0x40 : 0)) + parentObj.latchedHDays;
   7851    }
   7852  }
   7853  //cout("Reading from invalid or disabled RAM.", 1);
   7854  return 0xFF;
   7855 }
   7856 GameBoyCore.prototype.memoryReadGBCMemory = function (parentObj, address) {
   7857  return parentObj.GBCMemory[address + parentObj.gbcRamBankPosition];
   7858 }
   7859 GameBoyCore.prototype.memoryReadOAM = function (parentObj, address) {
   7860  return (parentObj.modeSTAT > 1) ?  0xFF : parentObj.memory[address];
   7861 }
   7862 GameBoyCore.prototype.memoryReadECHOGBCMemory = function (parentObj, address) {
   7863  return parentObj.GBCMemory[address + parentObj.gbcRamBankPositionECHO];
   7864 }
   7865 GameBoyCore.prototype.memoryReadECHONormal = function (parentObj, address) {
   7866  return parentObj.memory[address - 0x2000];
   7867 }
   7868 GameBoyCore.prototype.memoryReadBAD = function (parentObj, address) {
   7869  return 0xFF;
   7870 }
   7871 GameBoyCore.prototype.VRAMDATAReadCGBCPU = function (parentObj, address) {
   7872  //CPU Side Reading The VRAM (Optimized for GameBoy Color)
   7873  return (parentObj.modeSTAT > 2) ? 0xFF : ((parentObj.currVRAMBank == 0) ? parentObj.memory[address] : parentObj.VRAM[address & 0x1FFF]);
   7874 }
   7875 GameBoyCore.prototype.VRAMDATAReadDMGCPU = function (parentObj, address) {
   7876  //CPU Side Reading The VRAM (Optimized for classic GameBoy)
   7877  return (parentObj.modeSTAT > 2) ? 0xFF : parentObj.memory[address];
   7878 }
   7879 GameBoyCore.prototype.VRAMCHRReadCGBCPU = function (parentObj, address) {
   7880  //CPU Side Reading the Character Data Map:
   7881  return (parentObj.modeSTAT > 2) ? 0xFF : parentObj.BGCHRCurrentBank[address & 0x7FF];
   7882 }
   7883 GameBoyCore.prototype.VRAMCHRReadDMGCPU = function (parentObj, address) {
   7884  //CPU Side Reading the Character Data Map:
   7885  return (parentObj.modeSTAT > 2) ? 0xFF : parentObj.BGCHRBank1[address & 0x7FF];
   7886 }
   7887 GameBoyCore.prototype.setCurrentMBC1ROMBank = function () {
   7888  //Read the cartridge ROM data from RAM memory:
   7889  switch (this.ROMBank1offs) {
   7890    case 0x00:
   7891    case 0x20:
   7892    case 0x40:
   7893    case 0x60:
   7894      //Bank calls for 0x00, 0x20, 0x40, and 0x60 are really for 0x01, 0x21, 0x41, and 0x61.
   7895      this.currentROMBank = (this.ROMBank1offs % this.ROMBankEdge) << 14;
   7896      break;
   7897    default:
   7898      this.currentROMBank = ((this.ROMBank1offs % this.ROMBankEdge) - 1) << 14;
   7899  }
   7900 }
   7901 GameBoyCore.prototype.setCurrentMBC2AND3ROMBank = function () {
   7902  //Read the cartridge ROM data from RAM memory:
   7903  //Only map bank 0 to bank 1 here (MBC2 is like MBC1, but can only do 16 banks, so only the bank 0 quirk appears for MBC2):
   7904  this.currentROMBank = Math.max((this.ROMBank1offs % this.ROMBankEdge) - 1, 0) << 14;
   7905 }
   7906 GameBoyCore.prototype.setCurrentMBC5ROMBank = function () {
   7907  //Read the cartridge ROM data from RAM memory:
   7908  this.currentROMBank = ((this.ROMBank1offs % this.ROMBankEdge) - 1) << 14;
   7909 }
   7910 //Memory Writing:
   7911 GameBoyCore.prototype.memoryWrite = function (address, data) {
   7912  //Act as a wrapper for writing by compiled jumps to specific memory writing functions.
   7913  this.memoryWriter[address](this, address, data);
   7914 }
   7915 //0xFFXX fast path:
   7916 GameBoyCore.prototype.memoryHighWrite = function (address, data) {
   7917  //Act as a wrapper for writing by compiled jumps to specific memory writing functions.
   7918  this.memoryHighWriter[address](this, address, data);
   7919 }
   7920 GameBoyCore.prototype.memoryWriteJumpCompile = function () {
   7921  //Faster in some browsers, since we are doing less conditionals overall by implementing them in advance.
   7922  for (var index = 0x0000; index <= 0xFFFF; index++) {
   7923    if (index < 0x8000) {
   7924      if (this.cMBC1) {
   7925        if (index < 0x2000) {
   7926          this.memoryWriter[index] = this.MBCWriteEnable;
   7927        }
   7928        else if (index < 0x4000) {
   7929          this.memoryWriter[index] = this.MBC1WriteROMBank;
   7930        }
   7931        else if (index < 0x6000) {
   7932          this.memoryWriter[index] = this.MBC1WriteRAMBank;
   7933        }
   7934        else {
   7935          this.memoryWriter[index] = this.MBC1WriteType;
   7936        }
   7937      }
   7938      else if (this.cMBC2) {
   7939        if (index < 0x1000) {
   7940          this.memoryWriter[index] = this.MBCWriteEnable;
   7941        }
   7942        else if (index >= 0x2100 && index < 0x2200) {
   7943          this.memoryWriter[index] = this.MBC2WriteROMBank;
   7944        }
   7945        else {
   7946          this.memoryWriter[index] = this.cartIgnoreWrite;
   7947        }
   7948      }
   7949      else if (this.cMBC3) {
   7950        if (index < 0x2000) {
   7951          this.memoryWriter[index] = this.MBCWriteEnable;
   7952        }
   7953        else if (index < 0x4000) {
   7954          this.memoryWriter[index] = this.MBC3WriteROMBank;
   7955        }
   7956        else if (index < 0x6000) {
   7957          this.memoryWriter[index] = this.MBC3WriteRAMBank;
   7958        }
   7959        else {
   7960          this.memoryWriter[index] = this.MBC3WriteRTCLatch;
   7961        }
   7962      }
   7963      else if (this.cMBC5 || this.cRUMBLE || this.cMBC7) {
   7964        if (index < 0x2000) {
   7965          this.memoryWriter[index] = this.MBCWriteEnable;
   7966        }
   7967        else if (index < 0x3000) {
   7968          this.memoryWriter[index] = this.MBC5WriteROMBankLow;
   7969        }
   7970        else if (index < 0x4000) {
   7971          this.memoryWriter[index] = this.MBC5WriteROMBankHigh;
   7972        }
   7973        else if (index < 0x6000) {
   7974          this.memoryWriter[index] = (this.cRUMBLE) ? this.RUMBLEWriteRAMBank : this.MBC5WriteRAMBank;
   7975        }
   7976        else {
   7977          this.memoryWriter[index] = this.cartIgnoreWrite;
   7978        }
   7979      }
   7980      else if (this.cHuC3) {
   7981        if (index < 0x2000) {
   7982          this.memoryWriter[index] = this.MBCWriteEnable;
   7983        }
   7984        else if (index < 0x4000) {
   7985          this.memoryWriter[index] = this.MBC3WriteROMBank;
   7986        }
   7987        else if (index < 0x6000) {
   7988          this.memoryWriter[index] = this.HuC3WriteRAMBank;
   7989        }
   7990        else {
   7991          this.memoryWriter[index] = this.cartIgnoreWrite;
   7992        }
   7993      }
   7994      else {
   7995        this.memoryWriter[index] = this.cartIgnoreWrite;
   7996      }
   7997    }
   7998    else if (index < 0x9000) {
   7999      this.memoryWriter[index] = (this.cGBC) ? this.VRAMGBCDATAWrite : this.VRAMGBDATAWrite;
   8000    }
   8001    else if (index < 0x9800) {
   8002      this.memoryWriter[index] = (this.cGBC) ? this.VRAMGBCDATAWrite : this.VRAMGBDATAUpperWrite;
   8003    }
   8004    else if (index < 0xA000) {
   8005      this.memoryWriter[index] = (this.cGBC) ? this.VRAMGBCCHRMAPWrite : this.VRAMGBCHRMAPWrite;
   8006    }
   8007    else if (index < 0xC000) {
   8008      if ((this.numRAMBanks == 1 / 16 && index < 0xA200) || this.numRAMBanks >= 1) {
   8009        if (!this.cMBC3) {
   8010          this.memoryWriter[index] = this.memoryWriteMBCRAM;
   8011        }
   8012        else {
   8013          //MBC3 RTC + RAM:
   8014          this.memoryWriter[index] = this.memoryWriteMBC3RAM;
   8015        }
   8016      }
   8017      else {
   8018        this.memoryWriter[index] = this.cartIgnoreWrite;
   8019      }
   8020    }
   8021    else if (index < 0xE000) {
   8022      if (this.cGBC && index >= 0xD000) {
   8023        this.memoryWriter[index] = this.memoryWriteGBCRAM;
   8024      }
   8025      else {
   8026        this.memoryWriter[index] = this.memoryWriteNormal;
   8027      }
   8028    }
   8029    else if (index < 0xFE00) {
   8030      if (this.cGBC && index >= 0xF000) {
   8031        this.memoryWriter[index] = this.memoryWriteECHOGBCRAM;
   8032      }
   8033      else {
   8034        this.memoryWriter[index] = this.memoryWriteECHONormal;
   8035      }
   8036    }
   8037    else if (index <= 0xFEA0) {
   8038      this.memoryWriter[index] = this.memoryWriteOAMRAM;
   8039    }
   8040    else if (index < 0xFF00) {
   8041      if (this.cGBC) {                      //Only GBC has access to this RAM.
   8042        this.memoryWriter[index] = this.memoryWriteNormal;
   8043      }
   8044      else {
   8045        this.memoryWriter[index] = this.cartIgnoreWrite;
   8046      }
   8047    }
   8048    else {
   8049      //Start the I/O initialization by filling in the slots as normal memory:
   8050      this.memoryWriter[index] = this.memoryWriteNormal;
   8051      this.memoryHighWriter[index & 0xFF] = this.memoryHighWriteNormal;
   8052    }
   8053  }
   8054  this.registerWriteJumpCompile();        //Compile the I/O write functions separately...
   8055 }
   8056 GameBoyCore.prototype.MBCWriteEnable = function (parentObj, address, data) {
   8057  //MBC RAM Bank Enable/Disable:
   8058  parentObj.MBCRAMBanksEnabled = ((data & 0x0F) == 0x0A);  //If lower nibble is 0x0A, then enable, otherwise disable.
   8059 }
   8060 GameBoyCore.prototype.MBC1WriteROMBank = function (parentObj, address, data) {
   8061  //MBC1 ROM bank switching:
   8062  parentObj.ROMBank1offs = (parentObj.ROMBank1offs & 0x60) | (data & 0x1F);
   8063  parentObj.setCurrentMBC1ROMBank();
   8064 }
   8065 GameBoyCore.prototype.MBC1WriteRAMBank = function (parentObj, address, data) {
   8066  //MBC1 RAM bank switching
   8067  if (parentObj.MBC1Mode) {
   8068    //4/32 Mode
   8069    parentObj.currMBCRAMBank = data & 0x03;
   8070    parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
   8071  }
   8072  else {
   8073    //16/8 Mode
   8074    parentObj.ROMBank1offs = ((data & 0x03) << 5) | (parentObj.ROMBank1offs & 0x1F);
   8075    parentObj.setCurrentMBC1ROMBank();
   8076  }
   8077 }
   8078 GameBoyCore.prototype.MBC1WriteType = function (parentObj, address, data) {
   8079  //MBC1 mode setting:
   8080  parentObj.MBC1Mode = ((data & 0x1) == 0x1);
   8081  if (parentObj.MBC1Mode) {
   8082    parentObj.ROMBank1offs &= 0x1F;
   8083    parentObj.setCurrentMBC1ROMBank();
   8084  }
   8085  else {
   8086    parentObj.currMBCRAMBank = 0;
   8087    parentObj.currMBCRAMBankPosition = -0xA000;
   8088  }
   8089 }
   8090 GameBoyCore.prototype.MBC2WriteROMBank = function (parentObj, address, data) {
   8091  //MBC2 ROM bank switching:
   8092  parentObj.ROMBank1offs = data & 0x0F;
   8093  parentObj.setCurrentMBC2AND3ROMBank();
   8094 }
   8095 GameBoyCore.prototype.MBC3WriteROMBank = function (parentObj, address, data) {
   8096  //MBC3 ROM bank switching:
   8097  parentObj.ROMBank1offs = data & 0x7F;
   8098  parentObj.setCurrentMBC2AND3ROMBank();
   8099 }
   8100 GameBoyCore.prototype.MBC3WriteRAMBank = function (parentObj, address, data) {
   8101  parentObj.currMBCRAMBank = data;
   8102  if (data < 4) {
   8103    //MBC3 RAM bank switching
   8104    parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
   8105  }
   8106 }
   8107 GameBoyCore.prototype.MBC3WriteRTCLatch = function (parentObj, address, data) {
   8108  if (data == 0) {
   8109    parentObj.RTCisLatched = false;
   8110  }
   8111  else if (!parentObj.RTCisLatched) {
   8112    //Copy over the current RTC time for reading.
   8113    parentObj.RTCisLatched = true;
   8114    parentObj.latchedSeconds = parentObj.RTCSeconds | 0;
   8115    parentObj.latchedMinutes = parentObj.RTCMinutes;
   8116    parentObj.latchedHours = parentObj.RTCHours;
   8117    parentObj.latchedLDays = (parentObj.RTCDays & 0xFF);
   8118    parentObj.latchedHDays = parentObj.RTCDays >> 8;
   8119  }
   8120 }
   8121 GameBoyCore.prototype.MBC5WriteROMBankLow = function (parentObj, address, data) {
   8122  //MBC5 ROM bank switching:
   8123  parentObj.ROMBank1offs = (parentObj.ROMBank1offs & 0x100) | data;
   8124  parentObj.setCurrentMBC5ROMBank();
   8125 }
   8126 GameBoyCore.prototype.MBC5WriteROMBankHigh = function (parentObj, address, data) {
   8127  //MBC5 ROM bank switching (by least significant bit):
   8128  parentObj.ROMBank1offs  = ((data & 0x01) << 8) | (parentObj.ROMBank1offs & 0xFF);
   8129  parentObj.setCurrentMBC5ROMBank();
   8130 }
   8131 GameBoyCore.prototype.MBC5WriteRAMBank = function (parentObj, address, data) {
   8132  //MBC5 RAM bank switching
   8133  parentObj.currMBCRAMBank = data & 0xF;
   8134  parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
   8135 }
   8136 GameBoyCore.prototype.RUMBLEWriteRAMBank = function (parentObj, address, data) {
   8137  //MBC5 RAM bank switching
   8138  //Like MBC5, but bit 3 of the lower nibble is used for rumbling and bit 2 is ignored.
   8139  parentObj.currMBCRAMBank = data & 0x03;
   8140  parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
   8141 }
   8142 GameBoyCore.prototype.HuC3WriteRAMBank = function (parentObj, address, data) {
   8143  //HuC3 RAM bank switching
   8144  parentObj.currMBCRAMBank = data & 0x03;
   8145  parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
   8146 }
   8147 GameBoyCore.prototype.cartIgnoreWrite = function (parentObj, address, data) {
   8148  //We might have encountered illegal RAM writing or such, so just do nothing...
   8149 }
   8150 GameBoyCore.prototype.memoryWriteNormal = function (parentObj, address, data) {
   8151  parentObj.memory[address] = data;
   8152 }
   8153 GameBoyCore.prototype.memoryHighWriteNormal = function (parentObj, address, data) {
   8154  parentObj.memory[0xFF00 | address] = data;
   8155 }
   8156 GameBoyCore.prototype.memoryWriteMBCRAM = function (parentObj, address, data) {
   8157  if (parentObj.MBCRAMBanksEnabled || settings[10]) {
   8158    parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition] = data;
   8159  }
   8160 }
   8161 GameBoyCore.prototype.memoryWriteMBC3RAM = function (parentObj, address, data) {
   8162  if (parentObj.MBCRAMBanksEnabled || settings[10]) {
   8163    switch (parentObj.currMBCRAMBank) {
   8164      case 0x00:
   8165      case 0x01:
   8166      case 0x02:
   8167      case 0x03:
   8168        parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition] = data;
   8169        break;
   8170      case 0x08:
   8171        if (data < 60) {
   8172          parentObj.RTCSeconds = data;
   8173        }
   8174        else {
   8175          cout("(Bank #" + parentObj.currMBCRAMBank + ") RTC write out of range: " + data, 1);
   8176        }
   8177        break;
   8178      case 0x09:
   8179        if (data < 60) {
   8180          parentObj.RTCMinutes = data;
   8181        }
   8182        else {
   8183          cout("(Bank #" + parentObj.currMBCRAMBank + ") RTC write out of range: " + data, 1);
   8184        }
   8185        break;
   8186      case 0x0A:
   8187        if (data < 24) {
   8188          parentObj.RTCHours = data;
   8189        }
   8190        else {
   8191          cout("(Bank #" + parentObj.currMBCRAMBank + ") RTC write out of range: " + data, 1);
   8192        }
   8193        break;
   8194      case 0x0B:
   8195        parentObj.RTCDays = (data & 0xFF) | (parentObj.RTCDays & 0x100);
   8196        break;
   8197      case 0x0C:
   8198        parentObj.RTCDayOverFlow = (data > 0x7F);
   8199        parentObj.RTCHalt = (data & 0x40) == 0x40;
   8200        parentObj.RTCDays = ((data & 0x1) << 8) | (parentObj.RTCDays & 0xFF);
   8201        break;
   8202      default:
   8203        cout("Invalid MBC3 bank address selected: " + parentObj.currMBCRAMBank, 0);
   8204    }
   8205  }
   8206 }
   8207 GameBoyCore.prototype.memoryWriteGBCRAM = function (parentObj, address, data) {
   8208  parentObj.GBCMemory[address + parentObj.gbcRamBankPosition] = data;
   8209 }
   8210 GameBoyCore.prototype.memoryWriteOAMRAM = function (parentObj, address, data) {
   8211  if (parentObj.modeSTAT < 2) {    //OAM RAM cannot be written to in mode 2 & 3
   8212    if (parentObj.memory[address] != data) {
   8213      parentObj.graphicsJIT();
   8214      parentObj.memory[address] = data;
   8215    }
   8216  }
   8217 }
   8218 GameBoyCore.prototype.memoryWriteECHOGBCRAM = function (parentObj, address, data) {
   8219  parentObj.GBCMemory[address + parentObj.gbcRamBankPositionECHO] = data;
   8220 }
   8221 GameBoyCore.prototype.memoryWriteECHONormal = function (parentObj, address, data) {
   8222  parentObj.memory[address - 0x2000] = data;
   8223 }
   8224 GameBoyCore.prototype.VRAMGBDATAWrite = function (parentObj, address, data) {
   8225  if (parentObj.modeSTAT < 3) {  //VRAM cannot be written to during mode 3
   8226    if (parentObj.memory[address] != data) {
   8227      //JIT the graphics render queue:
   8228      parentObj.graphicsJIT();
   8229      parentObj.memory[address] = data;
   8230      parentObj.generateGBOAMTileLine(address);
   8231    }
   8232  }
   8233 }
   8234 GameBoyCore.prototype.VRAMGBDATAUpperWrite = function (parentObj, address, data) {
   8235  if (parentObj.modeSTAT < 3) {  //VRAM cannot be written to during mode 3
   8236    if (parentObj.memory[address] != data) {
   8237      //JIT the graphics render queue:
   8238      parentObj.graphicsJIT();
   8239      parentObj.memory[address] = data;
   8240      parentObj.generateGBTileLine(address);
   8241    }
   8242  }
   8243 }
   8244 GameBoyCore.prototype.VRAMGBCDATAWrite = function (parentObj, address, data) {
   8245  if (parentObj.modeSTAT < 3) {  //VRAM cannot be written to during mode 3
   8246    if (parentObj.currVRAMBank == 0) {
   8247      if (parentObj.memory[address] != data) {
   8248        //JIT the graphics render queue:
   8249        parentObj.graphicsJIT();
   8250        parentObj.memory[address] = data;
   8251        parentObj.generateGBCTileLineBank1(address);
   8252      }
   8253    }
   8254    else {
   8255      address &= 0x1FFF;
   8256      if (parentObj.VRAM[address] != data) {
   8257        //JIT the graphics render queue:
   8258        parentObj.graphicsJIT();
   8259        parentObj.VRAM[address] = data;
   8260        parentObj.generateGBCTileLineBank2(address);
   8261      }
   8262    }
   8263  }
   8264 }
   8265 GameBoyCore.prototype.VRAMGBCHRMAPWrite = function (parentObj, address, data) {
   8266  if (parentObj.modeSTAT < 3) {  //VRAM cannot be written to during mode 3
   8267    address &= 0x7FF;
   8268    if (parentObj.BGCHRBank1[address] != data) {
   8269      //JIT the graphics render queue:
   8270      parentObj.graphicsJIT();
   8271      parentObj.BGCHRBank1[address] = data;
   8272    }
   8273  }
   8274 }
   8275 GameBoyCore.prototype.VRAMGBCCHRMAPWrite = function (parentObj, address, data) {
   8276  if (parentObj.modeSTAT < 3) {  //VRAM cannot be written to during mode 3
   8277    address &= 0x7FF;
   8278    if (parentObj.BGCHRCurrentBank[address] != data) {
   8279      //JIT the graphics render queue:
   8280      parentObj.graphicsJIT();
   8281      parentObj.BGCHRCurrentBank[address] = data;
   8282    }
   8283  }
   8284 }
   8285 GameBoyCore.prototype.DMAWrite = function (tilesToTransfer) {
   8286  if (!this.halt) {
   8287    //Clock the CPU for the DMA transfer (CPU is halted during the transfer):
   8288    this.CPUTicks += 4 | ((tilesToTransfer << 5) << this.doubleSpeedShifter);
   8289  }
   8290  //Source address of the transfer:
   8291  var source = (this.memory[0xFF51] << 8) | this.memory[0xFF52];
   8292  //Destination address in the VRAM memory range:
   8293  var destination = (this.memory[0xFF53] << 8) | this.memory[0xFF54];
   8294  //Creating some references:
   8295  var memoryReader = this.memoryReader;
   8296  //JIT the graphics render queue:
   8297  this.graphicsJIT();
   8298  var memory = this.memory;
   8299  //Determining which bank we're working on so we can optimize:
   8300  if (this.currVRAMBank == 0) {
   8301    //DMA transfer for VRAM bank 0:
   8302    do {
   8303      if (destination < 0x1800) {
   8304        memory[0x8000 | destination] = memoryReader[source](this, source++);
   8305        memory[0x8001 | destination] = memoryReader[source](this, source++);
   8306        memory[0x8002 | destination] = memoryReader[source](this, source++);
   8307        memory[0x8003 | destination] = memoryReader[source](this, source++);
   8308        memory[0x8004 | destination] = memoryReader[source](this, source++);
   8309        memory[0x8005 | destination] = memoryReader[source](this, source++);
   8310        memory[0x8006 | destination] = memoryReader[source](this, source++);
   8311        memory[0x8007 | destination] = memoryReader[source](this, source++);
   8312        memory[0x8008 | destination] = memoryReader[source](this, source++);
   8313        memory[0x8009 | destination] = memoryReader[source](this, source++);
   8314        memory[0x800A | destination] = memoryReader[source](this, source++);
   8315        memory[0x800B | destination] = memoryReader[source](this, source++);
   8316        memory[0x800C | destination] = memoryReader[source](this, source++);
   8317        memory[0x800D | destination] = memoryReader[source](this, source++);
   8318        memory[0x800E | destination] = memoryReader[source](this, source++);
   8319        memory[0x800F | destination] = memoryReader[source](this, source++);
   8320        this.generateGBCTileBank1(destination);
   8321        destination += 0x10;
   8322      }
   8323      else {
   8324        destination &= 0x7F0;
   8325        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8326        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8327        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8328        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8329        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8330        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8331        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8332        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8333        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8334        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8335        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8336        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8337        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8338        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8339        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8340        this.BGCHRBank1[destination++] = memoryReader[source](this, source++);
   8341        destination = (destination + 0x1800) & 0x1FF0;
   8342      }
   8343      source &= 0xFFF0;
   8344      --tilesToTransfer;
   8345    } while (tilesToTransfer > 0);
   8346  }
   8347  else {
   8348    var VRAM = this.VRAM;
   8349    //DMA transfer for VRAM bank 1:
   8350    do {
   8351      if (destination < 0x1800) {
   8352        VRAM[destination] = memoryReader[source](this, source++);
   8353        VRAM[destination | 0x1] = memoryReader[source](this, source++);
   8354        VRAM[destination | 0x2] = memoryReader[source](this, source++);
   8355        VRAM[destination | 0x3] = memoryReader[source](this, source++);
   8356        VRAM[destination | 0x4] = memoryReader[source](this, source++);
   8357        VRAM[destination | 0x5] = memoryReader[source](this, source++);
   8358        VRAM[destination | 0x6] = memoryReader[source](this, source++);
   8359        VRAM[destination | 0x7] = memoryReader[source](this, source++);
   8360        VRAM[destination | 0x8] = memoryReader[source](this, source++);
   8361        VRAM[destination | 0x9] = memoryReader[source](this, source++);
   8362        VRAM[destination | 0xA] = memoryReader[source](this, source++);
   8363        VRAM[destination | 0xB] = memoryReader[source](this, source++);
   8364        VRAM[destination | 0xC] = memoryReader[source](this, source++);
   8365        VRAM[destination | 0xD] = memoryReader[source](this, source++);
   8366        VRAM[destination | 0xE] = memoryReader[source](this, source++);
   8367        VRAM[destination | 0xF] = memoryReader[source](this, source++);
   8368        this.generateGBCTileBank2(destination);
   8369        destination += 0x10;
   8370      }
   8371      else {
   8372        destination &= 0x7F0;
   8373        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8374        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8375        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8376        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8377        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8378        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8379        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8380        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8381        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8382        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8383        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8384        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8385        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8386        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8387        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8388        this.BGCHRBank2[destination++] = memoryReader[source](this, source++);
   8389        destination = (destination + 0x1800) & 0x1FF0;
   8390      }
   8391      source &= 0xFFF0;
   8392      --tilesToTransfer;
   8393    } while (tilesToTransfer > 0);
   8394  }
   8395  //Update the HDMA registers to their next addresses:
   8396  memory[0xFF51] = source >> 8;
   8397  memory[0xFF52] = source & 0xF0;
   8398  memory[0xFF53] = destination >> 8;
   8399  memory[0xFF54] = destination & 0xF0;
   8400 }
   8401 GameBoyCore.prototype.registerWriteJumpCompile = function () {
   8402  //I/O Registers (GB + GBC):
   8403  //JoyPad
   8404  this.memoryHighWriter[0] = this.memoryWriter[0xFF00] = function (parentObj, address, data) {
   8405    parentObj.memory[0xFF00] = (data & 0x30) | ((((data & 0x20) == 0) ? (parentObj.JoyPad >> 4) : 0xF) & (((data & 0x10) == 0) ? (parentObj.JoyPad & 0xF) : 0xF));
   8406  }
   8407  //SB (Serial Transfer Data)
   8408  this.memoryHighWriter[0x1] = this.memoryWriter[0xFF01] = function (parentObj, address, data) {
   8409    if (parentObj.memory[0xFF02] < 0x80) {  //Cannot write while a serial transfer is active.
   8410      parentObj.memory[0xFF01] = data;
   8411    }
   8412  }
   8413  //DIV
   8414  this.memoryHighWriter[0x4] = this.memoryWriter[0xFF04] = function (parentObj, address, data) {
   8415    parentObj.DIVTicks &= 0xFF;  //Update DIV for realignment.
   8416    parentObj.memory[0xFF04] = 0;
   8417  }
   8418  //TIMA
   8419  this.memoryHighWriter[0x5] = this.memoryWriter[0xFF05] = function (parentObj, address, data) {
   8420    parentObj.memory[0xFF05] = data;
   8421  }
   8422  //TMA
   8423  this.memoryHighWriter[0x6] = this.memoryWriter[0xFF06] = function (parentObj, address, data) {
   8424    parentObj.memory[0xFF06] = data;
   8425  }
   8426  //TAC
   8427  this.memoryHighWriter[0x7] = this.memoryWriter[0xFF07] = function (parentObj, address, data) {
   8428    parentObj.memory[0xFF07] = data & 0x07;
   8429    parentObj.TIMAEnabled = (data & 0x04) == 0x04;
   8430    parentObj.TACClocker = Math.pow(4, ((data & 0x3) != 0) ? (data & 0x3) : 4) << 2;  //TODO: Find a way to not make a conditional in here...
   8431  }
   8432  //IF (Interrupt Request)
   8433  this.memoryHighWriter[0xF] = this.memoryWriter[0xFF0F] = function (parentObj, address, data) {
   8434    parentObj.interruptsRequested = data;
   8435    parentObj.checkIRQMatching();
   8436  }
   8437  this.memoryHighWriter[0x10] = this.memoryWriter[0xFF10] = function (parentObj, address, data) {
   8438    if (parentObj.soundMasterEnabled) {
   8439      parentObj.audioJIT();
   8440      if (parentObj.channel1decreaseSweep && (data & 0x08) == 0) {
   8441        if (parentObj.channel1numSweep != parentObj.channel1frequencySweepDivider) {
   8442          parentObj.channel1SweepFault = true;
   8443        }
   8444      }
   8445      parentObj.channel1lastTimeSweep = (data & 0x70) >> 4;
   8446      parentObj.channel1frequencySweepDivider = data & 0x07;
   8447      parentObj.channel1decreaseSweep = ((data & 0x08) == 0x08);
   8448      parentObj.memory[0xFF10] = data;
   8449      parentObj.channel1EnableCheck();
   8450    }
   8451  }
   8452  this.memoryHighWriter[0x11] = this.memoryWriter[0xFF11] = function (parentObj, address, data) {
   8453    if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
   8454      if (parentObj.soundMasterEnabled) {
   8455        parentObj.audioJIT();
   8456      }
   8457      else {
   8458        data &= 0x3F;
   8459      }
   8460      parentObj.channel1CachedDuty = parentObj.dutyLookup[data >> 6];
   8461      parentObj.channel1totalLength = 0x40 - (data & 0x3F);
   8462      parentObj.memory[0xFF11] = data & 0xC0;
   8463      parentObj.channel1EnableCheck();
   8464    }
   8465  }
   8466  this.memoryHighWriter[0x12] = this.memoryWriter[0xFF12] = function (parentObj, address, data) {
   8467    if (parentObj.soundMasterEnabled) {
   8468      parentObj.audioJIT();
   8469      if (parentObj.channel1Enabled && parentObj.channel1envelopeSweeps == 0) {
   8470        //Zombie Volume PAPU Bug:
   8471        if (((parentObj.memory[0xFF12] ^ data) & 0x8) == 0x8) {
   8472          if ((parentObj.memory[0xFF12] & 0x8) == 0) {
   8473            if ((parentObj.memory[0xFF12] & 0x7) == 0x7) {
   8474              parentObj.channel1envelopeVolume += 2;
   8475            }
   8476            else {
   8477              ++parentObj.channel1envelopeVolume;
   8478            }
   8479          }
   8480          parentObj.channel1envelopeVolume = (16 - parentObj.channel1envelopeVolume) & 0xF;
   8481        }
   8482        else if ((parentObj.memory[0xFF12] & 0xF) == 0x8) {
   8483          parentObj.channel1envelopeVolume = (1 + parentObj.channel1envelopeVolume) & 0xF;
   8484        }
   8485        parentObj.channel1OutputLevelCache();
   8486      }
   8487      parentObj.channel1envelopeType = ((data & 0x08) == 0x08);
   8488      parentObj.memory[0xFF12] = data;
   8489      parentObj.channel1VolumeEnableCheck();
   8490    }
   8491  }
   8492  this.memoryHighWriter[0x13] = this.memoryWriter[0xFF13] = function (parentObj, address, data) {
   8493    if (parentObj.soundMasterEnabled) {
   8494      parentObj.audioJIT();
   8495      parentObj.channel1frequency = (parentObj.channel1frequency & 0x700) | data;
   8496      parentObj.channel1FrequencyTracker = (0x800 - parentObj.channel1frequency) << 2;
   8497      parentObj.memory[0xFF13] = data;
   8498    }
   8499  }
   8500  this.memoryHighWriter[0x14] = this.memoryWriter[0xFF14] = function (parentObj, address, data) {
   8501    if (parentObj.soundMasterEnabled) {
   8502      parentObj.audioJIT();
   8503      parentObj.channel1consecutive = ((data & 0x40) == 0x0);
   8504      parentObj.channel1frequency = ((data & 0x7) << 8) | (parentObj.channel1frequency & 0xFF);
   8505      parentObj.channel1FrequencyTracker = (0x800 - parentObj.channel1frequency) << 2;
   8506      if (data > 0x7F) {
   8507        //Reload 0xFF10:
   8508        parentObj.channel1timeSweep = parentObj.channel1lastTimeSweep;
   8509        parentObj.channel1numSweep = parentObj.channel1frequencySweepDivider;
   8510        //Reload 0xFF12:
   8511        var nr12 = parentObj.memory[0xFF12];
   8512        parentObj.channel1envelopeVolume = nr12 >> 4;
   8513        parentObj.channel1OutputLevelCache();
   8514        parentObj.channel1envelopeSweepsLast = (nr12 & 0x7) - 1;
   8515        if (parentObj.channel1totalLength == 0) {
   8516          parentObj.channel1totalLength = 0x40;
   8517        }
   8518        if (parentObj.channel1lastTimeSweep > 0 || parentObj.channel1frequencySweepDivider > 0) {
   8519          parentObj.memory[0xFF26] |= 0x1;
   8520        }
   8521        else {
   8522          parentObj.memory[0xFF26] &= 0xFE;
   8523        }
   8524        if ((data & 0x40) == 0x40) {
   8525          parentObj.memory[0xFF26] |= 0x1;
   8526        }
   8527        parentObj.channel1ShadowFrequency = parentObj.channel1frequency;
   8528        //Reset frequency overflow check + frequency sweep type check:
   8529        parentObj.channel1SweepFault = false;
   8530        //Supposed to run immediately:
   8531        parentObj.runAudioSweep();
   8532      }
   8533      parentObj.channel1EnableCheck();
   8534      parentObj.memory[0xFF14] = data & 0x40;
   8535    }
   8536  }
   8537  this.memoryHighWriter[0x16] = this.memoryWriter[0xFF16] = function (parentObj, address, data) {
   8538    if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
   8539      if (parentObj.soundMasterEnabled) {
   8540        parentObj.audioJIT();
   8541      }
   8542      else {
   8543        data &= 0x3F;
   8544      }
   8545      parentObj.channel2CachedDuty = parentObj.dutyLookup[data >> 6];
   8546      parentObj.channel2totalLength = 0x40 - (data & 0x3F);
   8547      parentObj.memory[0xFF16] = data & 0xC0;
   8548      parentObj.channel2EnableCheck();
   8549    }
   8550  }
   8551  this.memoryHighWriter[0x17] = this.memoryWriter[0xFF17] = function (parentObj, address, data) {
   8552    if (parentObj.soundMasterEnabled) {
   8553      parentObj.audioJIT();
   8554      if (parentObj.channel2Enabled && parentObj.channel2envelopeSweeps == 0) {
   8555        //Zombie Volume PAPU Bug:
   8556        if (((parentObj.memory[0xFF17] ^ data) & 0x8) == 0x8) {
   8557          if ((parentObj.memory[0xFF17] & 0x8) == 0) {
   8558            if ((parentObj.memory[0xFF17] & 0x7) == 0x7) {
   8559              parentObj.channel2envelopeVolume += 2;
   8560            }
   8561            else {
   8562              ++parentObj.channel2envelopeVolume;
   8563            }
   8564          }
   8565          parentObj.channel2envelopeVolume = (16 - parentObj.channel2envelopeVolume) & 0xF;
   8566        }
   8567        else if ((parentObj.memory[0xFF17] & 0xF) == 0x8) {
   8568          parentObj.channel2envelopeVolume = (1 + parentObj.channel2envelopeVolume) & 0xF;
   8569        }
   8570        parentObj.channel2OutputLevelCache();
   8571      }
   8572      parentObj.channel2envelopeType = ((data & 0x08) == 0x08);
   8573      parentObj.memory[0xFF17] = data;
   8574      parentObj.channel2VolumeEnableCheck();
   8575    }
   8576  }
   8577  this.memoryHighWriter[0x18] = this.memoryWriter[0xFF18] = function (parentObj, address, data) {
   8578    if (parentObj.soundMasterEnabled) {
   8579      parentObj.audioJIT();
   8580      parentObj.channel2frequency = (parentObj.channel2frequency & 0x700) | data;
   8581      parentObj.channel2FrequencyTracker = (0x800 - parentObj.channel2frequency) << 2;
   8582      parentObj.memory[0xFF18] = data;
   8583    }
   8584  }
   8585  this.memoryHighWriter[0x19] = this.memoryWriter[0xFF19] = function (parentObj, address, data) {
   8586    if (parentObj.soundMasterEnabled) {
   8587      parentObj.audioJIT();
   8588      if (data > 0x7F) {
   8589        //Reload 0xFF17:
   8590        var nr22 = parentObj.memory[0xFF17];
   8591        parentObj.channel2envelopeVolume = nr22 >> 4;
   8592        parentObj.channel2OutputLevelCache();
   8593        parentObj.channel2envelopeSweepsLast = (nr22 & 0x7) - 1;
   8594        if (parentObj.channel2totalLength == 0) {
   8595          parentObj.channel2totalLength = 0x40;
   8596        }
   8597        if ((data & 0x40) == 0x40) {
   8598          parentObj.memory[0xFF26] |= 0x2;
   8599        }
   8600      }
   8601      parentObj.channel2consecutive = ((data & 0x40) == 0x0);
   8602      parentObj.channel2frequency = ((data & 0x7) << 8) | (parentObj.channel2frequency & 0xFF);
   8603      parentObj.channel2FrequencyTracker = (0x800 - parentObj.channel2frequency) << 2;
   8604      parentObj.memory[0xFF19] = data & 0x40;
   8605      parentObj.channel2EnableCheck();
   8606    }
   8607  }
   8608  this.memoryHighWriter[0x1A] = this.memoryWriter[0xFF1A] = function (parentObj, address, data) {
   8609    if (parentObj.soundMasterEnabled) {
   8610      parentObj.audioJIT();
   8611      if (!parentObj.channel3canPlay && data >= 0x80) {
   8612        parentObj.channel3lastSampleLookup = 0;
   8613        parentObj.channel3UpdateCache();
   8614      }
   8615      parentObj.channel3canPlay = (data > 0x7F);
   8616      if (parentObj.channel3canPlay && parentObj.memory[0xFF1A] > 0x7F && !parentObj.channel3consecutive) {
   8617        parentObj.memory[0xFF26] |= 0x4;
   8618      }
   8619      parentObj.memory[0xFF1A] = data & 0x80;
   8620      //parentObj.channel3EnableCheck();
   8621    }
   8622  }
   8623  this.memoryHighWriter[0x1B] = this.memoryWriter[0xFF1B] = function (parentObj, address, data) {
   8624    if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
   8625      if (parentObj.soundMasterEnabled) {
   8626        parentObj.audioJIT();
   8627      }
   8628      parentObj.channel3totalLength = 0x100 - data;
   8629      parentObj.memory[0xFF1B] = data;
   8630      parentObj.channel3EnableCheck();
   8631    }
   8632  }
   8633  this.memoryHighWriter[0x1C] = this.memoryWriter[0xFF1C] = function (parentObj, address, data) {
   8634    if (parentObj.soundMasterEnabled) {
   8635      parentObj.audioJIT();
   8636      data &= 0x60;
   8637      parentObj.memory[0xFF1C] = data;
   8638      parentObj.channel3patternType = (data == 0) ? 4 : ((data >> 5) - 1);
   8639    }
   8640  }
   8641  this.memoryHighWriter[0x1D] = this.memoryWriter[0xFF1D] = function (parentObj, address, data) {
   8642    if (parentObj.soundMasterEnabled) {
   8643      parentObj.audioJIT();
   8644      parentObj.channel3frequency = (parentObj.channel3frequency & 0x700) | data;
   8645      parentObj.channel3FrequencyPeriod = (0x800 - parentObj.channel3frequency) << 1;
   8646      parentObj.memory[0xFF1D] = data;
   8647    }
   8648  }
   8649  this.memoryHighWriter[0x1E] = this.memoryWriter[0xFF1E] = function (parentObj, address, data) {
   8650    if (parentObj.soundMasterEnabled) {
   8651      parentObj.audioJIT();
   8652      if (data > 0x7F) {
   8653        if (parentObj.channel3totalLength == 0) {
   8654          parentObj.channel3totalLength = 0x100;
   8655        }
   8656        parentObj.channel3lastSampleLookup = 0;
   8657        if ((data & 0x40) == 0x40) {
   8658          parentObj.memory[0xFF26] |= 0x4;
   8659        }
   8660      }
   8661      parentObj.channel3consecutive = ((data & 0x40) == 0x0);
   8662      parentObj.channel3frequency = ((data & 0x7) << 8) | (parentObj.channel3frequency & 0xFF);
   8663      parentObj.channel3FrequencyPeriod = (0x800 - parentObj.channel3frequency) << 1;
   8664      parentObj.memory[0xFF1E] = data & 0x40;
   8665      parentObj.channel3EnableCheck();
   8666    }
   8667  }
   8668  this.memoryHighWriter[0x20] = this.memoryWriter[0xFF20] = function (parentObj, address, data) {
   8669    if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
   8670      if (parentObj.soundMasterEnabled) {
   8671        parentObj.audioJIT();
   8672      }
   8673      parentObj.channel4totalLength = 0x40 - (data & 0x3F);
   8674      parentObj.memory[0xFF20] = data | 0xC0;
   8675      parentObj.channel4EnableCheck();
   8676    }
   8677  }
   8678  this.memoryHighWriter[0x21] = this.memoryWriter[0xFF21] = function (parentObj, address, data) {
   8679    if (parentObj.soundMasterEnabled) {
   8680      parentObj.audioJIT();
   8681      if (parentObj.channel4Enabled && parentObj.channel4envelopeSweeps == 0) {
   8682        //Zombie Volume PAPU Bug:
   8683        if (((parentObj.memory[0xFF21] ^ data) & 0x8) == 0x8) {
   8684          if ((parentObj.memory[0xFF21] & 0x8) == 0) {
   8685            if ((parentObj.memory[0xFF21] & 0x7) == 0x7) {
   8686              parentObj.channel4envelopeVolume += 2;
   8687            }
   8688            else {
   8689              ++parentObj.channel4envelopeVolume;
   8690            }
   8691          }
   8692          parentObj.channel4envelopeVolume = (16 - parentObj.channel4envelopeVolume) & 0xF;
   8693        }
   8694        else if ((parentObj.memory[0xFF21] & 0xF) == 0x8) {
   8695          parentObj.channel4envelopeVolume = (1 + parentObj.channel4envelopeVolume) & 0xF;
   8696        }
   8697        parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << parentObj.channel4VolumeShifter;
   8698      }
   8699      parentObj.channel4envelopeType = ((data & 0x08) == 0x08);
   8700      parentObj.memory[0xFF21] = data;
   8701      parentObj.channel4UpdateCache();
   8702      parentObj.channel4VolumeEnableCheck();
   8703    }
   8704  }
   8705  this.memoryHighWriter[0x22] = this.memoryWriter[0xFF22] = function (parentObj, address, data) {
   8706    if (parentObj.soundMasterEnabled) {
   8707      parentObj.audioJIT();
   8708      parentObj.channel4FrequencyPeriod = Math.max((data & 0x7) << 4, 8) << (data >> 4);
   8709      var bitWidth = (data & 0x8);
   8710      if ((bitWidth == 0x8 && parentObj.channel4BitRange == 0x7FFF) || (bitWidth == 0 && parentObj.channel4BitRange == 0x7F)) {
   8711        parentObj.channel4lastSampleLookup = 0;
   8712        parentObj.channel4BitRange = (bitWidth == 0x8) ? 0x7F : 0x7FFF;
   8713        parentObj.channel4VolumeShifter = (bitWidth == 0x8) ? 7 : 15;
   8714        parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << parentObj.channel4VolumeShifter;
   8715        parentObj.noiseSampleTable = (bitWidth == 0x8) ? parentObj.LSFR7Table : parentObj.LSFR15Table;
   8716      }
   8717      parentObj.memory[0xFF22] = data;
   8718      parentObj.channel4UpdateCache();
   8719    }
   8720  }
   8721  this.memoryHighWriter[0x23] = this.memoryWriter[0xFF23] = function (parentObj, address, data) {
   8722    if (parentObj.soundMasterEnabled) {
   8723      parentObj.audioJIT();
   8724      parentObj.memory[0xFF23] = data;
   8725      parentObj.channel4consecutive = ((data & 0x40) == 0x0);
   8726      if (data > 0x7F) {
   8727        var nr42 = parentObj.memory[0xFF21];
   8728        parentObj.channel4envelopeVolume = nr42 >> 4;
   8729        parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << parentObj.channel4VolumeShifter;
   8730        parentObj.channel4envelopeSweepsLast = (nr42 & 0x7) - 1;
   8731        if (parentObj.channel4totalLength == 0) {
   8732          parentObj.channel4totalLength = 0x40;
   8733        }
   8734        if ((data & 0x40) == 0x40) {
   8735          parentObj.memory[0xFF26] |= 0x8;
   8736        }
   8737      }
   8738      parentObj.channel4EnableCheck();
   8739    }
   8740  }
   8741  this.memoryHighWriter[0x24] = this.memoryWriter[0xFF24] = function (parentObj, address, data) {
   8742    if (parentObj.soundMasterEnabled && parentObj.memory[0xFF24] != data) {
   8743      parentObj.audioJIT();
   8744      parentObj.memory[0xFF24] = data;
   8745      parentObj.VinLeftChannelMasterVolume = ((data >> 4) & 0x07) + 1;
   8746      parentObj.VinRightChannelMasterVolume = (data & 0x07) + 1;
   8747      parentObj.mixerOutputLevelCache();
   8748    }
   8749  }
   8750  this.memoryHighWriter[0x25] = this.memoryWriter[0xFF25] = function (parentObj, address, data) {
   8751    if (parentObj.soundMasterEnabled && parentObj.memory[0xFF25] != data) {
   8752      parentObj.audioJIT();
   8753      parentObj.memory[0xFF25] = data;
   8754      parentObj.rightChannel1 = ((data & 0x01) == 0x01);
   8755      parentObj.rightChannel2 = ((data & 0x02) == 0x02);
   8756      parentObj.rightChannel3 = ((data & 0x04) == 0x04);
   8757      parentObj.rightChannel4 = ((data & 0x08) == 0x08);
   8758      parentObj.leftChannel1 = ((data & 0x10) == 0x10);
   8759      parentObj.leftChannel2 = ((data & 0x20) == 0x20);
   8760      parentObj.leftChannel3 = ((data & 0x40) == 0x40);
   8761      parentObj.leftChannel4 = (data > 0x7F);
   8762      parentObj.channel1OutputLevelCache();
   8763      parentObj.channel2OutputLevelCache();
   8764      parentObj.channel3OutputLevelCache();
   8765      parentObj.channel4OutputLevelCache();
   8766    }
   8767  }
   8768  this.memoryHighWriter[0x26] = this.memoryWriter[0xFF26] = function (parentObj, address, data) {
   8769    parentObj.audioJIT();
   8770    if (!parentObj.soundMasterEnabled && data > 0x7F) {
   8771      parentObj.memory[0xFF26] = 0x80;
   8772      parentObj.soundMasterEnabled = true;
   8773      parentObj.initializeAudioStartState();
   8774    }
   8775    else if (parentObj.soundMasterEnabled && data < 0x80) {
   8776      parentObj.memory[0xFF26] = 0;
   8777      parentObj.soundMasterEnabled = false;
   8778      //GBDev wiki says the registers are written with zeros on power off:
   8779      for (var index = 0xFF10; index < 0xFF26; index++) {
   8780        parentObj.memoryWriter[index](parentObj, index, 0);
   8781      }
   8782    }
   8783  }
   8784  //0xFF27 to 0xFF2F don't do anything...
   8785  this.memoryHighWriter[0x27] = this.memoryWriter[0xFF27] = this.cartIgnoreWrite;
   8786  this.memoryHighWriter[0x28] = this.memoryWriter[0xFF28] = this.cartIgnoreWrite;
   8787  this.memoryHighWriter[0x29] = this.memoryWriter[0xFF29] = this.cartIgnoreWrite;
   8788  this.memoryHighWriter[0x2A] = this.memoryWriter[0xFF2A] = this.cartIgnoreWrite;
   8789  this.memoryHighWriter[0x2B] = this.memoryWriter[0xFF2B] = this.cartIgnoreWrite;
   8790  this.memoryHighWriter[0x2C] = this.memoryWriter[0xFF2C] = this.cartIgnoreWrite;
   8791  this.memoryHighWriter[0x2D] = this.memoryWriter[0xFF2D] = this.cartIgnoreWrite;
   8792  this.memoryHighWriter[0x2E] = this.memoryWriter[0xFF2E] = this.cartIgnoreWrite;
   8793  this.memoryHighWriter[0x2F] = this.memoryWriter[0xFF2F] = this.cartIgnoreWrite;
   8794  //WAVE PCM RAM:
   8795  this.memoryHighWriter[0x30] = this.memoryWriter[0xFF30] = function (parentObj, address, data) {
   8796    parentObj.channel3WriteRAM(0, data);
   8797  }
   8798  this.memoryHighWriter[0x31] = this.memoryWriter[0xFF31] = function (parentObj, address, data) {
   8799    parentObj.channel3WriteRAM(0x1, data);
   8800  }
   8801  this.memoryHighWriter[0x32] = this.memoryWriter[0xFF32] = function (parentObj, address, data) {
   8802    parentObj.channel3WriteRAM(0x2, data);
   8803  }
   8804  this.memoryHighWriter[0x33] = this.memoryWriter[0xFF33] = function (parentObj, address, data) {
   8805    parentObj.channel3WriteRAM(0x3, data);
   8806  }
   8807  this.memoryHighWriter[0x34] = this.memoryWriter[0xFF34] = function (parentObj, address, data) {
   8808    parentObj.channel3WriteRAM(0x4, data);
   8809  }
   8810  this.memoryHighWriter[0x35] = this.memoryWriter[0xFF35] = function (parentObj, address, data) {
   8811    parentObj.channel3WriteRAM(0x5, data);
   8812  }
   8813  this.memoryHighWriter[0x36] = this.memoryWriter[0xFF36] = function (parentObj, address, data) {
   8814    parentObj.channel3WriteRAM(0x6, data);
   8815  }
   8816  this.memoryHighWriter[0x37] = this.memoryWriter[0xFF37] = function (parentObj, address, data) {
   8817    parentObj.channel3WriteRAM(0x7, data);
   8818  }
   8819  this.memoryHighWriter[0x38] = this.memoryWriter[0xFF38] = function (parentObj, address, data) {
   8820    parentObj.channel3WriteRAM(0x8, data);
   8821  }
   8822  this.memoryHighWriter[0x39] = this.memoryWriter[0xFF39] = function (parentObj, address, data) {
   8823    parentObj.channel3WriteRAM(0x9, data);
   8824  }
   8825  this.memoryHighWriter[0x3A] = this.memoryWriter[0xFF3A] = function (parentObj, address, data) {
   8826    parentObj.channel3WriteRAM(0xA, data);
   8827  }
   8828  this.memoryHighWriter[0x3B] = this.memoryWriter[0xFF3B] = function (parentObj, address, data) {
   8829    parentObj.channel3WriteRAM(0xB, data);
   8830  }
   8831  this.memoryHighWriter[0x3C] = this.memoryWriter[0xFF3C] = function (parentObj, address, data) {
   8832    parentObj.channel3WriteRAM(0xC, data);
   8833  }
   8834  this.memoryHighWriter[0x3D] = this.memoryWriter[0xFF3D] = function (parentObj, address, data) {
   8835    parentObj.channel3WriteRAM(0xD, data);
   8836  }
   8837  this.memoryHighWriter[0x3E] = this.memoryWriter[0xFF3E] = function (parentObj, address, data) {
   8838    parentObj.channel3WriteRAM(0xE, data);
   8839  }
   8840  this.memoryHighWriter[0x3F] = this.memoryWriter[0xFF3F] = function (parentObj, address, data) {
   8841    parentObj.channel3WriteRAM(0xF, data);
   8842  }
   8843  //SCY
   8844  this.memoryHighWriter[0x42] = this.memoryWriter[0xFF42] = function (parentObj, address, data) {
   8845    if (parentObj.backgroundY != data) {
   8846      parentObj.midScanLineJIT();
   8847      parentObj.backgroundY = data;
   8848    }
   8849  }
   8850  //SCX
   8851  this.memoryHighWriter[0x43] = this.memoryWriter[0xFF43] = function (parentObj, address, data) {
   8852    if (parentObj.backgroundX != data) {
   8853      parentObj.midScanLineJIT();
   8854      parentObj.backgroundX = data;
   8855    }
   8856  }
   8857  //LY
   8858  this.memoryHighWriter[0x44] = this.memoryWriter[0xFF44] = function (parentObj, address, data) {
   8859    //Read Only:
   8860    if (parentObj.LCDisOn) {
   8861      //Gambatte says to do this:
   8862      parentObj.modeSTAT = 2;
   8863      parentObj.midScanlineOffset = -1;
   8864      parentObj.totalLinesPassed = parentObj.currentX = parentObj.queuedScanLines = parentObj.lastUnrenderedLine = parentObj.LCDTicks = parentObj.STATTracker = parentObj.actualScanLine = parentObj.memory[0xFF44] = 0;
   8865    }
   8866  }
   8867  //LYC
   8868  this.memoryHighWriter[0x45] = this.memoryWriter[0xFF45] = function (parentObj, address, data) {
   8869    if (parentObj.memory[0xFF45] != data) {
   8870      parentObj.memory[0xFF45] = data;
   8871      if (parentObj.LCDisOn) {
   8872        parentObj.matchLYC();  //Get the compare of the first scan line.
   8873      }
   8874    }
   8875  }
   8876  //WY
   8877  this.memoryHighWriter[0x4A] = this.memoryWriter[0xFF4A] = function (parentObj, address, data) {
   8878    if (parentObj.windowY != data) {
   8879      parentObj.midScanLineJIT();
   8880      parentObj.windowY = data;
   8881    }
   8882  }
   8883  //WX
   8884  this.memoryHighWriter[0x4B] = this.memoryWriter[0xFF4B] = function (parentObj, address, data) {
   8885    if (parentObj.memory[0xFF4B] != data) {
   8886      parentObj.midScanLineJIT();
   8887      parentObj.memory[0xFF4B] = data;
   8888      parentObj.windowX = data - 7;
   8889    }
   8890  }
   8891  this.memoryHighWriter[0x72] = this.memoryWriter[0xFF72] = function (parentObj, address, data) {
   8892    parentObj.memory[0xFF72] = data;
   8893  }
   8894  this.memoryHighWriter[0x73] = this.memoryWriter[0xFF73] = function (parentObj, address, data) {
   8895    parentObj.memory[0xFF73] = data;
   8896  }
   8897  this.memoryHighWriter[0x75] = this.memoryWriter[0xFF75] = function (parentObj, address, data) {
   8898    parentObj.memory[0xFF75] = data;
   8899  }
   8900  this.memoryHighWriter[0x76] = this.memoryWriter[0xFF76] = this.cartIgnoreWrite;
   8901  this.memoryHighWriter[0x77] = this.memoryWriter[0xFF77] = this.cartIgnoreWrite;
   8902  //IE (Interrupt Enable)
   8903  this.memoryHighWriter[0xFF] = this.memoryWriter[0xFFFF] = function (parentObj, address, data) {
   8904    parentObj.interruptsEnabled = data;
   8905    parentObj.checkIRQMatching();
   8906  }
   8907  this.recompileModelSpecificIOWriteHandling();
   8908  this.recompileBootIOWriteHandling();
   8909 }
   8910 GameBoyCore.prototype.recompileModelSpecificIOWriteHandling = function () {
   8911  if (this.cGBC) {
   8912    //GameBoy Color Specific I/O:
   8913    //SC (Serial Transfer Control Register)
   8914    this.memoryHighWriter[0x2] = this.memoryWriter[0xFF02] = function (parentObj, address, data) {
   8915      if (((data & 0x1) == 0x1)) {
   8916        //Internal clock:
   8917        parentObj.memory[0xFF02] = (data & 0x7F);
   8918        parentObj.serialTimer = ((data & 0x2) == 0) ? 4096 : 128;  //Set the Serial IRQ counter.
   8919        parentObj.serialShiftTimer = parentObj.serialShiftTimerAllocated = ((data & 0x2) == 0) ? 512 : 16;  //Set the transfer data shift counter.
   8920      }
   8921      else {
   8922        //External clock:
   8923        parentObj.memory[0xFF02] = data;
   8924        parentObj.serialShiftTimer = parentObj.serialShiftTimerAllocated = parentObj.serialTimer = 0;  //Zero the timers, since we're emulating as if nothing is connected.
   8925      }
   8926    }
   8927    this.memoryHighWriter[0x40] = this.memoryWriter[0xFF40] = function (parentObj, address, data) {
   8928      if (parentObj.memory[0xFF40] != data) {
   8929        parentObj.midScanLineJIT();
   8930        var temp_var = (data > 0x7F);
   8931        if (temp_var != parentObj.LCDisOn) {
   8932          //When the display mode changes...
   8933          parentObj.LCDisOn = temp_var;
   8934          parentObj.memory[0xFF41] &= 0x78;
   8935          parentObj.midScanlineOffset = -1;
   8936          parentObj.totalLinesPassed = parentObj.currentX = parentObj.queuedScanLines = parentObj.lastUnrenderedLine = parentObj.STATTracker = parentObj.LCDTicks = parentObj.actualScanLine = parentObj.memory[0xFF44] = 0;
   8937          if (parentObj.LCDisOn) {
   8938            parentObj.modeSTAT = 2;
   8939            parentObj.matchLYC();  //Get the compare of the first scan line.
   8940            parentObj.LCDCONTROL = parentObj.LINECONTROL;
   8941          }
   8942          else {
   8943            parentObj.modeSTAT = 0;
   8944            parentObj.LCDCONTROL = parentObj.DISPLAYOFFCONTROL;
   8945            parentObj.DisplayShowOff();
   8946          }
   8947          parentObj.interruptsRequested &= 0xFD;
   8948        }
   8949        parentObj.gfxWindowCHRBankPosition = ((data & 0x40) == 0x40) ? 0x400 : 0;
   8950        parentObj.gfxWindowDisplay = ((data & 0x20) == 0x20);
   8951        parentObj.gfxBackgroundBankOffset = ((data & 0x10) == 0x10) ? 0 : 0x80;
   8952        parentObj.gfxBackgroundCHRBankPosition = ((data & 0x08) == 0x08) ? 0x400 : 0;
   8953        parentObj.gfxSpriteNormalHeight = ((data & 0x04) == 0);
   8954        parentObj.gfxSpriteShow = ((data & 0x02) == 0x02);
   8955        parentObj.BGPriorityEnabled = ((data & 0x01) == 0x01);
   8956        parentObj.priorityFlaggingPathRebuild();  //Special case the priority flagging as an optimization.
   8957        parentObj.memory[0xFF40] = data;
   8958      }
   8959    }
   8960    this.memoryHighWriter[0x41] = this.memoryWriter[0xFF41] = function (parentObj, address, data) {
   8961      parentObj.LYCMatchTriggerSTAT = ((data & 0x40) == 0x40);
   8962      parentObj.mode2TriggerSTAT = ((data & 0x20) == 0x20);
   8963      parentObj.mode1TriggerSTAT = ((data & 0x10) == 0x10);
   8964      parentObj.mode0TriggerSTAT = ((data & 0x08) == 0x08);
   8965      parentObj.memory[0xFF41] = data & 0x78;
   8966    }
   8967    this.memoryHighWriter[0x46] = this.memoryWriter[0xFF46] = function (parentObj, address, data) {
   8968      parentObj.memory[0xFF46] = data;
   8969      if (data < 0xE0) {
   8970        data <<= 8;
   8971        address = 0xFE00;
   8972        var stat = parentObj.modeSTAT;
   8973        parentObj.modeSTAT = 0;
   8974        var newData = 0;
   8975        do {
   8976          newData = parentObj.memoryReader[data](parentObj, data++);
   8977          if (newData != parentObj.memory[address]) {
   8978            //JIT the graphics render queue:
   8979            parentObj.modeSTAT = stat;
   8980            parentObj.graphicsJIT();
   8981            parentObj.modeSTAT = 0;
   8982            parentObj.memory[address++] = newData;
   8983            break;
   8984          }
   8985        } while (++address < 0xFEA0);
   8986        if (address < 0xFEA0) {
   8987          do {
   8988            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
   8989            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
   8990            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
   8991            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
   8992          } while (address < 0xFEA0);
   8993        }
   8994        parentObj.modeSTAT = stat;
   8995      }
   8996    }
   8997    //KEY1
   8998    this.memoryHighWriter[0x4D] = this.memoryWriter[0xFF4D] = function (parentObj, address, data) {
   8999      parentObj.memory[0xFF4D] = (data & 0x7F) | (parentObj.memory[0xFF4D] & 0x80);
   9000    }
   9001    this.memoryHighWriter[0x4F] = this.memoryWriter[0xFF4F] = function (parentObj, address, data) {
   9002      parentObj.currVRAMBank = data & 0x01;
   9003      if (parentObj.currVRAMBank > 0) {
   9004        parentObj.BGCHRCurrentBank = parentObj.BGCHRBank2;
   9005      }
   9006      else {
   9007        parentObj.BGCHRCurrentBank = parentObj.BGCHRBank1;
   9008      }
   9009      //Only writable by GBC.
   9010    }
   9011    this.memoryHighWriter[0x51] = this.memoryWriter[0xFF51] = function (parentObj, address, data) {
   9012      if (!parentObj.hdmaRunning) {
   9013        parentObj.memory[0xFF51] = data;
   9014      }
   9015    }
   9016    this.memoryHighWriter[0x52] = this.memoryWriter[0xFF52] = function (parentObj, address, data) {
   9017      if (!parentObj.hdmaRunning) {
   9018        parentObj.memory[0xFF52] = data & 0xF0;
   9019      }
   9020    }
   9021    this.memoryHighWriter[0x53] = this.memoryWriter[0xFF53] = function (parentObj, address, data) {
   9022      if (!parentObj.hdmaRunning) {
   9023        parentObj.memory[0xFF53] = data & 0x1F;
   9024      }
   9025    }
   9026    this.memoryHighWriter[0x54] = this.memoryWriter[0xFF54] = function (parentObj, address, data) {
   9027      if (!parentObj.hdmaRunning) {
   9028        parentObj.memory[0xFF54] = data & 0xF0;
   9029      }
   9030    }
   9031    this.memoryHighWriter[0x55] = this.memoryWriter[0xFF55] = function (parentObj, address, data) {
   9032      if (!parentObj.hdmaRunning) {
   9033        if ((data & 0x80) == 0) {
   9034          //DMA
   9035          parentObj.DMAWrite((data & 0x7F) + 1);
   9036          parentObj.memory[0xFF55] = 0xFF;  //Transfer completed.
   9037        }
   9038        else {
   9039          //H-Blank DMA
   9040          parentObj.hdmaRunning = true;
   9041          parentObj.memory[0xFF55] = data & 0x7F;
   9042        }
   9043      }
   9044      else if ((data & 0x80) == 0) {
   9045        //Stop H-Blank DMA
   9046        parentObj.hdmaRunning = false;
   9047        parentObj.memory[0xFF55] |= 0x80;
   9048      }
   9049      else {
   9050        parentObj.memory[0xFF55] = data & 0x7F;
   9051      }
   9052    }
   9053    this.memoryHighWriter[0x68] = this.memoryWriter[0xFF68] = function (parentObj, address, data) {
   9054      parentObj.memory[0xFF69] = parentObj.gbcBGRawPalette[data & 0x3F];
   9055      parentObj.memory[0xFF68] = data;
   9056    }
   9057    this.memoryHighWriter[0x69] = this.memoryWriter[0xFF69] = function (parentObj, address, data) {
   9058      parentObj.updateGBCBGPalette(parentObj.memory[0xFF68] & 0x3F, data);
   9059      if (parentObj.memory[0xFF68] > 0x7F) { // high bit = autoincrement
   9060        var next = ((parentObj.memory[0xFF68] + 1) & 0x3F);
   9061        parentObj.memory[0xFF68] = (next | 0x80);
   9062        parentObj.memory[0xFF69] = parentObj.gbcBGRawPalette[next];
   9063      }
   9064      else {
   9065        parentObj.memory[0xFF69] = data;
   9066      }
   9067    }
   9068    this.memoryHighWriter[0x6A] = this.memoryWriter[0xFF6A] = function (parentObj, address, data) {
   9069      parentObj.memory[0xFF6B] = parentObj.gbcOBJRawPalette[data & 0x3F];
   9070      parentObj.memory[0xFF6A] = data;
   9071    }
   9072    this.memoryHighWriter[0x6B] = this.memoryWriter[0xFF6B] = function (parentObj, address, data) {
   9073      parentObj.updateGBCOBJPalette(parentObj.memory[0xFF6A] & 0x3F, data);
   9074      if (parentObj.memory[0xFF6A] > 0x7F) { // high bit = autoincrement
   9075        var next = ((parentObj.memory[0xFF6A] + 1) & 0x3F);
   9076        parentObj.memory[0xFF6A] = (next | 0x80);
   9077        parentObj.memory[0xFF6B] = parentObj.gbcOBJRawPalette[next];
   9078      }
   9079      else {
   9080        parentObj.memory[0xFF6B] = data;
   9081      }
   9082    }
   9083    //SVBK
   9084    this.memoryHighWriter[0x70] = this.memoryWriter[0xFF70] = function (parentObj, address, data) {
   9085      var addressCheck = (parentObj.memory[0xFF51] << 8) | parentObj.memory[0xFF52];  //Cannot change the RAM bank while WRAM is the source of a running HDMA.
   9086      if (!parentObj.hdmaRunning || addressCheck < 0xD000 || addressCheck >= 0xE000) {
   9087        parentObj.gbcRamBank = Math.max(data & 0x07, 1);  //Bank range is from 1-7
   9088        parentObj.gbcRamBankPosition = ((parentObj.gbcRamBank - 1) << 12) - 0xD000;
   9089        parentObj.gbcRamBankPositionECHO = parentObj.gbcRamBankPosition - 0x2000;
   9090      }
   9091      parentObj.memory[0xFF70] = data;  //Bit 6 cannot be written to.
   9092    }
   9093    this.memoryHighWriter[0x74] = this.memoryWriter[0xFF74] = function (parentObj, address, data) {
   9094      parentObj.memory[0xFF74] = data;
   9095    }
   9096  }
   9097  else {
   9098    //Fill in the GameBoy Color I/O registers as normal RAM for GameBoy compatibility:
   9099    //SC (Serial Transfer Control Register)
   9100    this.memoryHighWriter[0x2] = this.memoryWriter[0xFF02] = function (parentObj, address, data) {
   9101      if (((data & 0x1) == 0x1)) {
   9102        //Internal clock:
   9103        parentObj.memory[0xFF02] = (data & 0x7F);
   9104        parentObj.serialTimer = 4096;  //Set the Serial IRQ counter.
   9105        parentObj.serialShiftTimer = parentObj.serialShiftTimerAllocated = 512;  //Set the transfer data shift counter.
   9106      }
   9107      else {
   9108        //External clock:
   9109        parentObj.memory[0xFF02] = data;
   9110        parentObj.serialShiftTimer = parentObj.serialShiftTimerAllocated = parentObj.serialTimer = 0;  //Zero the timers, since we're emulating as if nothing is connected.
   9111      }
   9112    }
   9113    this.memoryHighWriter[0x40] = this.memoryWriter[0xFF40] = function (parentObj, address, data) {
   9114      if (parentObj.memory[0xFF40] != data) {
   9115        parentObj.midScanLineJIT();
   9116        var temp_var = (data > 0x7F);
   9117        if (temp_var != parentObj.LCDisOn) {
   9118          //When the display mode changes...
   9119          parentObj.LCDisOn = temp_var;
   9120          parentObj.memory[0xFF41] &= 0x78;
   9121          parentObj.midScanlineOffset = -1;
   9122          parentObj.totalLinesPassed = parentObj.currentX = parentObj.queuedScanLines = parentObj.lastUnrenderedLine = parentObj.STATTracker = parentObj.LCDTicks = parentObj.actualScanLine = parentObj.memory[0xFF44] = 0;
   9123          if (parentObj.LCDisOn) {
   9124            parentObj.modeSTAT = 2;
   9125            parentObj.matchLYC();  //Get the compare of the first scan line.
   9126            parentObj.LCDCONTROL = parentObj.LINECONTROL;
   9127          }
   9128          else {
   9129            parentObj.modeSTAT = 0;
   9130            parentObj.LCDCONTROL = parentObj.DISPLAYOFFCONTROL;
   9131            parentObj.DisplayShowOff();
   9132          }
   9133          parentObj.interruptsRequested &= 0xFD;
   9134        }
   9135        parentObj.gfxWindowCHRBankPosition = ((data & 0x40) == 0x40) ? 0x400 : 0;
   9136        parentObj.gfxWindowDisplay = (data & 0x20) == 0x20;
   9137        parentObj.gfxBackgroundBankOffset = ((data & 0x10) == 0x10) ? 0 : 0x80;
   9138        parentObj.gfxBackgroundCHRBankPosition = ((data & 0x08) == 0x08) ? 0x400 : 0;
   9139        parentObj.gfxSpriteNormalHeight = ((data & 0x04) == 0);
   9140        parentObj.gfxSpriteShow = (data & 0x02) == 0x02;
   9141        parentObj.bgEnabled = ((data & 0x01) == 0x01);
   9142        parentObj.memory[0xFF40] = data;
   9143      }
   9144    }
   9145    this.memoryHighWriter[0x41] = this.memoryWriter[0xFF41] = function (parentObj, address, data) {
   9146      parentObj.LYCMatchTriggerSTAT = ((data & 0x40) == 0x40);
   9147      parentObj.mode2TriggerSTAT = ((data & 0x20) == 0x20);
   9148      parentObj.mode1TriggerSTAT = ((data & 0x10) == 0x10);
   9149      parentObj.mode0TriggerSTAT = ((data & 0x08) == 0x08);
   9150      parentObj.memory[0xFF41] = data & 0x78;
   9151      if ((!parentObj.usedBootROM || !parentObj.usedGBCBootROM) && parentObj.LCDisOn && parentObj.modeSTAT < 2) {
   9152        parentObj.interruptsRequested |= 0x2;
   9153        parentObj.checkIRQMatching();
   9154      }
   9155    }
   9156    this.memoryHighWriter[0x46] = this.memoryWriter[0xFF46] = function (parentObj, address, data) {
   9157      parentObj.memory[0xFF46] = data;
   9158      if (data > 0x7F && data < 0xE0) {  //DMG cannot DMA from the ROM banks.
   9159        data <<= 8;
   9160        address = 0xFE00;
   9161        var stat = parentObj.modeSTAT;
   9162        parentObj.modeSTAT = 0;
   9163        var newData = 0;
   9164        do {
   9165          newData = parentObj.memoryReader[data](parentObj, data++);
   9166          if (newData != parentObj.memory[address]) {
   9167            //JIT the graphics render queue:
   9168            parentObj.modeSTAT = stat;
   9169            parentObj.graphicsJIT();
   9170            parentObj.modeSTAT = 0;
   9171            parentObj.memory[address++] = newData;
   9172            break;
   9173          }
   9174        } while (++address < 0xFEA0);
   9175        if (address < 0xFEA0) {
   9176          do {
   9177            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
   9178            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
   9179            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
   9180            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
   9181          } while (address < 0xFEA0);
   9182        }
   9183        parentObj.modeSTAT = stat;
   9184      }
   9185    }
   9186    this.memoryHighWriter[0x47] = this.memoryWriter[0xFF47] = function (parentObj, address, data) {
   9187      if (parentObj.memory[0xFF47] != data) {
   9188        parentObj.midScanLineJIT();
   9189        parentObj.updateGBBGPalette(data);
   9190        parentObj.memory[0xFF47] = data;
   9191      }
   9192    }
   9193    this.memoryHighWriter[0x48] = this.memoryWriter[0xFF48] = function (parentObj, address, data) {
   9194      if (parentObj.memory[0xFF48] != data) {
   9195        parentObj.midScanLineJIT();
   9196        parentObj.updateGBOBJPalette(0, data);
   9197        parentObj.memory[0xFF48] = data;
   9198      }
   9199    }
   9200    this.memoryHighWriter[0x49] = this.memoryWriter[0xFF49] = function (parentObj, address, data) {
   9201      if (parentObj.memory[0xFF49] != data) {
   9202        parentObj.midScanLineJIT();
   9203        parentObj.updateGBOBJPalette(4, data);
   9204        parentObj.memory[0xFF49] = data;
   9205      }
   9206    }
   9207    this.memoryHighWriter[0x4D] = this.memoryWriter[0xFF4D] = function (parentObj, address, data) {
   9208      parentObj.memory[0xFF4D] = data;
   9209    }
   9210    this.memoryHighWriter[0x4F] = this.memoryWriter[0xFF4F] = this.cartIgnoreWrite;  //Not writable in DMG mode.
   9211    this.memoryHighWriter[0x55] = this.memoryWriter[0xFF55] = this.cartIgnoreWrite;
   9212    this.memoryHighWriter[0x68] = this.memoryWriter[0xFF68] = this.cartIgnoreWrite;
   9213    this.memoryHighWriter[0x69] = this.memoryWriter[0xFF69] = this.cartIgnoreWrite;
   9214    this.memoryHighWriter[0x6A] = this.memoryWriter[0xFF6A] = this.cartIgnoreWrite;
   9215    this.memoryHighWriter[0x6B] = this.memoryWriter[0xFF6B] = this.cartIgnoreWrite;
   9216    this.memoryHighWriter[0x6C] = this.memoryWriter[0xFF6C] = this.cartIgnoreWrite;
   9217    this.memoryHighWriter[0x70] = this.memoryWriter[0xFF70] = this.cartIgnoreWrite;
   9218    this.memoryHighWriter[0x74] = this.memoryWriter[0xFF74] = this.cartIgnoreWrite;
   9219  }
   9220 }
   9221 GameBoyCore.prototype.recompileBootIOWriteHandling = function () {
   9222  //Boot I/O Registers:
   9223  if (this.inBootstrap) {
   9224    this.memoryHighWriter[0x50] = this.memoryWriter[0xFF50] = function (parentObj, address, data) {
   9225      cout("Boot ROM reads blocked: Bootstrap process has ended.", 0);
   9226      parentObj.inBootstrap = false;
   9227      parentObj.disableBootROM();      //Fill in the boot ROM ranges with ROM  bank 0 ROM ranges
   9228      parentObj.memory[0xFF50] = data;  //Bits are sustained in memory?
   9229    }
   9230    if (this.cGBC) {
   9231      this.memoryHighWriter[0x6C] = this.memoryWriter[0xFF6C] = function (parentObj, address, data) {
   9232        if (parentObj.inBootstrap) {
   9233          parentObj.cGBC = ((data & 0x1) == 0);
   9234          //Exception to the GBC identifying code:
   9235          if (parentObj.name + parentObj.gameCode + parentObj.ROM[0x143] == "Game and Watch 50") {
   9236            parentObj.cGBC = true;
   9237            cout("Created a boot exception for Game and Watch Gallery 2 (GBC ID byte is wrong on the cartridge).", 1);
   9238          }
   9239          cout("Booted to GBC Mode: " + parentObj.cGBC, 0);
   9240        }
   9241        parentObj.memory[0xFF6C] = data;
   9242      }
   9243    }
   9244  }
   9245  else {
   9246    //Lockout the ROMs from accessing the BOOT ROM control register:
   9247    this.memoryHighWriter[0x50] = this.memoryWriter[0xFF50] = this.cartIgnoreWrite;
   9248  }
   9249 }
   9250 //Helper Functions
   9251 GameBoyCore.prototype.toTypedArray = function (baseArray, memtype) {
   9252  try {
   9253    // The following line was modified for benchmarking:
   9254    if (settings[5] || (memtype != "float32" && GameBoyWindow.opera && this.checkForOperaMathBug())) {
   9255      return baseArray;
   9256    }
   9257    if (!baseArray || !baseArray.length) {
   9258      return [];
   9259    }
   9260    var length = baseArray.length;
   9261    switch (memtype) {
   9262      case "uint8":
   9263        var typedArrayTemp = new Uint8Array(length);
   9264        break;
   9265      case "int8":
   9266        var typedArrayTemp = new Int8Array(length);
   9267        break;
   9268      case "int32":
   9269        var typedArrayTemp = new Int32Array(length);
   9270        break;
   9271      case "float32":
   9272        var typedArrayTemp = new Float32Array(length);
   9273    }
   9274    for (var index = 0; index < length; index++) {
   9275      typedArrayTemp[index] = baseArray[index];
   9276    }
   9277    return typedArrayTemp;
   9278  }
   9279  catch (error) {
   9280    cout("Could not convert an array to a typed array: " + error.message, 1);
   9281    return baseArray;
   9282  }
   9283 }
   9284 GameBoyCore.prototype.fromTypedArray = function (baseArray) {
   9285  try {
   9286    if (!baseArray || !baseArray.length) {
   9287      return [];
   9288    }
   9289    var arrayTemp = [];
   9290    for (var index = 0; index < baseArray.length; ++index) {
   9291      arrayTemp[index] = baseArray[index];
   9292    }
   9293    return arrayTemp;
   9294  }
   9295  catch (error) {
   9296    cout("Conversion from a typed array failed: " + error.message, 1);
   9297    return baseArray;
   9298  }
   9299 }
   9300 GameBoyCore.prototype.getTypedArray = function (length, defaultValue, numberType) {
   9301  try {
   9302    if (settings[5]) {
   9303      throw(new Error(""));
   9304    }
   9305    // The following line was modified for benchmarking:
   9306    if (numberType != "float32" && GameBoyWindow.opera && this.checkForOperaMathBug()) {
   9307      //Caught Opera breaking typed array math:
   9308      throw(new Error(""));
   9309    }
   9310    switch (numberType) {
   9311      case "int8":
   9312        var arrayHandle = new Int8Array(length);
   9313        break;
   9314      case "uint8":
   9315        var arrayHandle = new Uint8Array(length);
   9316        break;
   9317      case "int32":
   9318        var arrayHandle = new Int32Array(length);
   9319        break;
   9320      case "float32":
   9321        var arrayHandle = new Float32Array(length);
   9322    }
   9323    if (defaultValue != 0) {
   9324      var index = 0;
   9325      while (index < length) {
   9326        arrayHandle[index++] = defaultValue;
   9327      }
   9328    }
   9329  }
   9330  catch (error) {
   9331    cout("Could not convert an array to a typed array: " + error.message, 1);
   9332    var arrayHandle = [];
   9333    var index = 0;
   9334    while (index < length) {
   9335      arrayHandle[index++] = defaultValue;
   9336    }
   9337  }
   9338  return arrayHandle;
   9339 }
   9340 GameBoyCore.prototype.checkForOperaMathBug = function () {
   9341  var testTypedArray = new Uint8Array(1);
   9342  testTypedArray[0] = -1;
   9343  testTypedArray[0] >>= 0;
   9344  if (testTypedArray[0] != 0xFF) {
   9345    cout("Detected faulty math by your browser.", 2);
   9346    return true;
   9347  }
   9348  else {
   9349    return false;
   9350  }
   9351 }
   9352 
   9353 // End of js/GameBoyCore.js file.
   9354 
   9355 // Start of js/GameBoyIO.js file.
   9356 
   9357 "use strict";
   9358 var gameboy = null;            //GameBoyCore object.
   9359 var gbRunInterval = null;        //GameBoyCore Timer
   9360 var settings = [            //Some settings.
   9361  true,                 //Turn on sound.
   9362  false,                //Boot with boot ROM first? (set to false for benchmarking)
   9363  false,                //Give priority to GameBoy mode
   9364  [39, 37, 38, 40, 88, 90, 16, 13],  //Keyboard button map.
   9365  true,                //Colorize GB mode?
   9366  false,                //Disallow typed arrays?
   9367  4,                  //Interval for the emulator loop.
   9368  15,                  //Audio buffer minimum span amount over x interpreter iterations.
   9369  30,                  //Audio buffer maximum span amount over x interpreter iterations.
   9370  false,                //Override to allow for MBC1 instead of ROM only (compatibility for broken 3rd-party cartridges).
   9371  false,                //Override MBC RAM disabling and always allow reading and writing to the banks.
   9372  false,                //Use the GameBoy boot ROM instead of the GameBoy Color boot ROM.
   9373  false,                //Scale the canvas in JS, or let the browser scale the canvas?
   9374  0x10,                //Internal audio buffer pre-interpolation factor.
   9375  1                  //Volume level set.
   9376 ];
   9377 function start(canvas, ROM) {
   9378  clearLastEmulation();
   9379  autoSave();  //If we are about to load a new game, then save the last one...
   9380  gameboy = new GameBoyCore(canvas, ROM);
   9381  gameboy.openMBC = openSRAM;
   9382  gameboy.openRTC = openRTC;
   9383  gameboy.start();
   9384  run();
   9385 }
   9386 function run() {
   9387  if (GameBoyEmulatorInitialized()) {
   9388    if (!GameBoyEmulatorPlaying()) {
   9389      gameboy.stopEmulator &= 1;
   9390      cout("Starting the iterator.", 0);
   9391      var dateObj = new_Date();  // The line is changed for benchmarking.
   9392      gameboy.firstIteration = dateObj.getTime();
   9393      gameboy.iterations = 0;
   9394      // The following lines are commented out for benchmarking.
   9395      // gbRunInterval = setInterval(function () {
   9396      //  if (!document.hidden && !document.msHidden && !document.mozHidden && !document.webkitHidden) {
   9397      //    gameboy.run();
   9398      // }
   9399      // }, settings[6]);
   9400    }
   9401    else {
   9402      cout("The GameBoy core is already running.", 1);
   9403    }
   9404  }
   9405  else {
   9406    cout("GameBoy core cannot run while it has not been initialized.", 1);
   9407  }
   9408 }
   9409 function pause() {
   9410  if (GameBoyEmulatorInitialized()) {
   9411    if (GameBoyEmulatorPlaying()) {
   9412      clearLastEmulation();
   9413    }
   9414    else {
   9415      cout("GameBoy core has already been paused.", 1);
   9416    }
   9417  }
   9418  else {
   9419    cout("GameBoy core cannot be paused while it has not been initialized.", 1);
   9420  }
   9421 }
   9422 function clearLastEmulation() {
   9423  if (GameBoyEmulatorInitialized() && GameBoyEmulatorPlaying()) {
   9424    clearInterval(gbRunInterval);
   9425    gameboy.stopEmulator |= 2;
   9426    cout("The previous emulation has been cleared.", 0);
   9427  }
   9428  else {
   9429    cout("No previous emulation was found to be cleared.", 0);
   9430  }
   9431 }
   9432 function save() {
   9433  if (GameBoyEmulatorInitialized()) {
   9434    try {
   9435      var state_suffix = 0;
   9436      while (findValue("FREEZE_" + gameboy.name + "_" + state_suffix) != null) {
   9437        state_suffix++;
   9438      }
   9439      setValue("FREEZE_" + gameboy.name + "_" + state_suffix, gameboy.saveState());
   9440      cout("Saved the current state as: FREEZE_" + gameboy.name + "_" + state_suffix, 0);
   9441    }
   9442    catch (error) {
   9443      cout("Could not save the current emulation state(\"" + error.message + "\").", 2);
   9444    }
   9445  }
   9446  else {
   9447    cout("GameBoy core cannot be saved while it has not been initialized.", 1);
   9448  }
   9449 }
   9450 function saveSRAM() {
   9451  if (GameBoyEmulatorInitialized()) {
   9452    if (gameboy.cBATT) {
   9453      try {
   9454        var sram = gameboy.saveSRAMState();
   9455        if (sram.length > 0) {
   9456          cout("Saving the SRAM...", 0);
   9457          if (findValue("SRAM_" + gameboy.name) != null) {
   9458            //Remove the outdated storage format save:
   9459            cout("Deleting the old SRAM save due to outdated format.", 0);
   9460            deleteValue("SRAM_" + gameboy.name);
   9461          }
   9462          setValue("B64_SRAM_" + gameboy.name, arrayToBase64(sram));
   9463        }
   9464        else {
   9465          cout("SRAM could not be saved because it was empty.", 1);
   9466        }
   9467      }
   9468      catch (error) {
   9469        cout("Could not save the current emulation state(\"" + error.message + "\").", 2);
   9470      }
   9471    }
   9472    else {
   9473      cout("Cannot save a game that does not have battery backed SRAM specified.", 1);
   9474    }
   9475    saveRTC();
   9476  }
   9477  else {
   9478    cout("GameBoy core cannot be saved while it has not been initialized.", 1);
   9479  }
   9480 }
   9481 function saveRTC() {  //Execute this when SRAM is being saved as well.
   9482  if (GameBoyEmulatorInitialized()) {
   9483    if (gameboy.cTIMER) {
   9484      try {
   9485        cout("Saving the RTC...", 0);
   9486        setValue("RTC_" + gameboy.name, gameboy.saveRTCState());
   9487      }
   9488      catch (error) {
   9489        cout("Could not save the RTC of the current emulation state(\"" + error.message + "\").", 2);
   9490      }
   9491    }
   9492  }
   9493  else {
   9494    cout("GameBoy core cannot be saved while it has not been initialized.", 1);
   9495  }
   9496 }
   9497 function autoSave() {
   9498  if (GameBoyEmulatorInitialized()) {
   9499    cout("Automatically saving the SRAM.", 0);
   9500    saveSRAM();
   9501    saveRTC();
   9502  }
   9503 }
   9504 function openSRAM(filename) {
   9505  try {
   9506    if (findValue("B64_SRAM_" + filename) != null) {
   9507      cout("Found a previous SRAM state (Will attempt to load).", 0);
   9508      return base64ToArray(findValue("B64_SRAM_" + filename));
   9509    }
   9510    else if (findValue("SRAM_" + filename) != null) {
   9511      cout("Found a previous SRAM state (Will attempt to load).", 0);
   9512      return findValue("SRAM_" + filename);
   9513    }
   9514    else {
   9515      cout("Could not find any previous SRAM copy for the current ROM.", 0);
   9516    }
   9517  }
   9518  catch (error) {
   9519    cout("Could not open the  SRAM of the saved emulation state.", 2);
   9520  }
   9521  return [];
   9522 }
   9523 function openRTC(filename) {
   9524  try {
   9525    if (findValue("RTC_" + filename) != null) {
   9526      cout("Found a previous RTC state (Will attempt to load).", 0);
   9527      return findValue("RTC_" + filename);
   9528    }
   9529    else {
   9530      cout("Could not find any previous RTC copy for the current ROM.", 0);
   9531    }
   9532  }
   9533  catch (error) {
   9534    cout("Could not open the RTC data of the saved emulation state.", 2);
   9535  }
   9536  return [];
   9537 }
   9538 function openState(filename, canvas) {
   9539  try {
   9540    if (findValue(filename) != null) {
   9541      try {
   9542        clearLastEmulation();
   9543        cout("Attempting to run a saved emulation state.", 0);
   9544        gameboy = new GameBoyCore(canvas, "");
   9545        gameboy.savedStateFileName = filename;
   9546        gameboy.returnFromState(findValue(filename));
   9547        run();
   9548      }
   9549      catch (error) {
   9550        alert(error.message + " file: " + error.fileName + " line: " + error.lineNumber);
   9551      }
   9552    }
   9553    else {
   9554      cout("Could not find the save state " + filename + "\".", 2);
   9555    }
   9556  }
   9557  catch (error) {
   9558    cout("Could not open the saved emulation state.", 2);
   9559  }
   9560 }
   9561 function import_save(blobData) {
   9562  blobData = decodeBlob(blobData);
   9563  if (blobData && blobData.blobs) {
   9564    if (blobData.blobs.length > 0) {
   9565      for (var index = 0; index < blobData.blobs.length; ++index) {
   9566        cout("Importing blob \"" + blobData.blobs[index].blobID + "\"", 0);
   9567        if (blobData.blobs[index].blobContent) {
   9568          if (blobData.blobs[index].blobID.substring(0, 5) == "SRAM_") {
   9569            setValue("B64_" + blobData.blobs[index].blobID, base64(blobData.blobs[index].blobContent));
   9570          }
   9571          else {
   9572            setValue(blobData.blobs[index].blobID, JSON.parse(blobData.blobs[index].blobContent));
   9573          }
   9574        }
   9575        else if (blobData.blobs[index].blobID) {
   9576          cout("Save file imported had blob \"" + blobData.blobs[index].blobID + "\" with no blob data interpretable.", 2);
   9577        }
   9578        else {
   9579          cout("Blob chunk information missing completely.", 2);
   9580        }
   9581      }
   9582    }
   9583    else {
   9584      cout("Could not decode the imported file.", 2);
   9585    }
   9586  }
   9587  else {
   9588    cout("Could not decode the imported file.", 2);
   9589  }
   9590 }
   9591 function generateBlob(keyName, encodedData) {
   9592  //Append the file format prefix:
   9593  var saveString = "EMULATOR_DATA";
   9594  var consoleID = "GameBoy";
   9595  //Figure out the length:
   9596  var totalLength = (saveString.length + 4 + (1 + consoleID.length)) + ((1 + keyName.length) + (4 + encodedData.length));
   9597  //Append the total length in bytes:
   9598  saveString += to_little_endian_dword(totalLength);
   9599  //Append the console ID text's length:
   9600  saveString += to_byte(consoleID.length);
   9601  //Append the console ID text:
   9602  saveString += consoleID;
   9603  //Append the blob ID:
   9604  saveString += to_byte(keyName.length);
   9605  saveString += keyName;
   9606  //Now append the save data:
   9607  saveString += to_little_endian_dword(encodedData.length);
   9608  saveString += encodedData;
   9609  return saveString;
   9610 }
   9611 function generateMultiBlob(blobPairs) {
   9612  var consoleID = "GameBoy";
   9613  //Figure out the initial length:
   9614  var totalLength = 13 + 4 + 1 + consoleID.length;
   9615  //Append the console ID text's length:
   9616  var saveString = to_byte(consoleID.length);
   9617  //Append the console ID text:
   9618  saveString += consoleID;
   9619  var keyName = "";
   9620  var encodedData = "";
   9621  //Now append all the blobs:
   9622  for (var index = 0; index < blobPairs.length; ++index) {
   9623    keyName = blobPairs[index][0];
   9624    encodedData = blobPairs[index][1];
   9625    //Append the blob ID:
   9626    saveString += to_byte(keyName.length);
   9627    saveString += keyName;
   9628    //Now append the save data:
   9629    saveString += to_little_endian_dword(encodedData.length);
   9630    saveString += encodedData;
   9631    //Update the total length:
   9632    totalLength += 1 + keyName.length + 4 + encodedData.length;
   9633  }
   9634  //Now add the prefix:
   9635  saveString = "EMULATOR_DATA" + to_little_endian_dword(totalLength) + saveString;
   9636  return saveString;
   9637 }
   9638 function decodeBlob(blobData) {
   9639  /*Format is as follows:
   9640    - 13 byte string "EMULATOR_DATA"
   9641    - 4 byte total size (including these 4 bytes).
   9642    - 1 byte Console type ID length
   9643    - Console type ID text of 8 bit size
   9644    blobs {
   9645      - 1 byte blob ID length
   9646      - blob ID text (Used to say what the data is (SRAM/freeze state/etc...))
   9647      - 4 byte blob length
   9648      - blob length of 32 bit size
   9649    }
   9650  */
   9651  var length = blobData.length;
   9652  var blobProperties = {};
   9653  blobProperties.consoleID = null;
   9654  var blobsCount = -1;
   9655  blobProperties.blobs = [];
   9656  if (length > 17) {
   9657    if (blobData.substring(0, 13) == "EMULATOR_DATA") {
   9658      var length = Math.min(((blobData.charCodeAt(16) & 0xFF) << 24) | ((blobData.charCodeAt(15) & 0xFF) << 16) | ((blobData.charCodeAt(14) & 0xFF) << 8) | (blobData.charCodeAt(13) & 0xFF), length);
   9659      var consoleIDLength = blobData.charCodeAt(17) & 0xFF;
   9660      if (length > 17 + consoleIDLength) {
   9661        blobProperties.consoleID = blobData.substring(18, 18 + consoleIDLength);
   9662        var blobIDLength = 0;
   9663        var blobLength = 0;
   9664        for (var index = 18 + consoleIDLength; index < length;) {
   9665          blobIDLength = blobData.charCodeAt(index++) & 0xFF;
   9666          if (index + blobIDLength < length) {
   9667            blobProperties.blobs[++blobsCount] = {};
   9668            blobProperties.blobs[blobsCount].blobID = blobData.substring(index, index + blobIDLength);
   9669            index += blobIDLength;
   9670            if (index + 4 < length) {
   9671              blobLength = ((blobData.charCodeAt(index + 3) & 0xFF) << 24) | ((blobData.charCodeAt(index + 2) & 0xFF) << 16) | ((blobData.charCodeAt(index + 1) & 0xFF) << 8) | (blobData.charCodeAt(index) & 0xFF);
   9672              index += 4;
   9673              if (index + blobLength <= length) {
   9674                blobProperties.blobs[blobsCount].blobContent =  blobData.substring(index, index + blobLength);
   9675                index += blobLength;
   9676              }
   9677              else {
   9678                cout("Blob length check failed, blob determined to be incomplete.", 2);
   9679                break;
   9680              }
   9681            }
   9682            else {
   9683              cout("Blob was incomplete, bailing out.", 2);
   9684              break;
   9685            }
   9686          }
   9687          else {
   9688            cout("Blob was incomplete, bailing out.", 2);
   9689            break;
   9690          }
   9691        }
   9692      }
   9693    }
   9694  }
   9695  return blobProperties;
   9696 }
   9697 function matchKey(key) {  //Maps a keyboard key to a gameboy key.
   9698  //Order: Right, Left, Up, Down, A, B, Select, Start
   9699  for (var index = 0; index < settings[3].length; index++) {
   9700    if (settings[3][index] == key) {
   9701      return index;
   9702    }
   9703  }
   9704  return -1;
   9705 }
   9706 function GameBoyEmulatorInitialized() {
   9707  return (typeof gameboy == "object" && gameboy != null);
   9708 }
   9709 function GameBoyEmulatorPlaying() {
   9710  return ((gameboy.stopEmulator & 2) == 0);
   9711 }
   9712 function GameBoyKeyDown(e) {
   9713  if (GameBoyEmulatorInitialized() && GameBoyEmulatorPlaying()) {
   9714    var keycode = matchKey(e.keyCode);
   9715    if (keycode >= 0 && keycode < 8) {
   9716      gameboy.JoyPadEvent(keycode, true);
   9717      try {
   9718        e.preventDefault();
   9719      }
   9720      catch (error) { }
   9721    }
   9722  }
   9723 }
   9724 function GameBoyKeyUp(e) {
   9725  if (GameBoyEmulatorInitialized() && GameBoyEmulatorPlaying()) {
   9726    var keycode = matchKey(e.keyCode);
   9727    if (keycode >= 0 && keycode < 8) {
   9728      gameboy.JoyPadEvent(keycode, false);
   9729      try {
   9730        e.preventDefault();
   9731      }
   9732      catch (error) { }
   9733    }
   9734  }
   9735 }
   9736 function GameBoyGyroSignalHandler(e) {
   9737  if (GameBoyEmulatorInitialized() && GameBoyEmulatorPlaying()) {
   9738    if (e.gamma || e.beta) {
   9739      gameboy.GyroEvent(e.gamma * Math.PI / 180, e.beta * Math.PI / 180);
   9740    }
   9741    else {
   9742      gameboy.GyroEvent(e.x, e.y);
   9743    }
   9744    try {
   9745      e.preventDefault();
   9746    }
   9747    catch (error) { }
   9748  }
   9749 }
   9750 //The emulator will call this to sort out the canvas properties for (re)initialization.
   9751 function initNewCanvas() {
   9752  if (GameBoyEmulatorInitialized()) {
   9753    gameboy.canvas.width = gameboy.canvas.clientWidth;
   9754    gameboy.canvas.height = gameboy.canvas.clientHeight;
   9755  }
   9756 }
   9757 //Call this when resizing the canvas:
   9758 function initNewCanvasSize() {
   9759  if (GameBoyEmulatorInitialized()) {
   9760    if (!settings[12]) {
   9761      if (gameboy.onscreenWidth != 160 || gameboy.onscreenHeight != 144) {
   9762        gameboy.initLCD();
   9763      }
   9764    }
   9765    else {
   9766      if (gameboy.onscreenWidth != gameboy.canvas.clientWidth || gameboy.onscreenHeight != gameboy.canvas.clientHeight) {
   9767        gameboy.initLCD();
   9768      }
   9769    }
   9770  }
   9771 }
   9772 
   9773 // End of js/GameBoyIO.js file.
   9774 
   9775 // Start of realtime.js file.
   9776 // ROM code from Public Domain LPC2000 Demo "realtime" by AGO.
   9777 
   9778 var gameboy_rom='r+BPyZiEZwA+AeBPySAobeEq6gAgKlYj5WJv6SRmZjjhKuXqACDJ/////////////////////////////////xgHZwCYhGcA2fX6/3/1xdXlIRPKNgHN9f/h0cHx6gAg+hLKtyAC8cnwgLcoF/CC7hjgUT6Q4FOv4FLgVOCAPv/gVfHZ8IG3IALx2fBA7gjgQA8PD+YB7gHgT/CC4FHuEOCCPojgU6/gUuBU4IE+/uBV4ID6NMs86jTL8dkKCgoKbWFkZSBieSBhZ28uIGVtYWlsOmdvYnV6b3ZAeWFob28uY29tCnVybDogc3BlY2N5LmRhLnJ1CgoKCv///////wDDSgnO7WZmzA0ACwNzAIMADAANAAgRH4iJAA7czG7m3d3Zmbu7Z2NuDuzM3dyZn7u5Mz5BR08nUyBSRUFMVElNRSCAAAAAAgEDADMBSTQeIUD/y37I8P/1y4fg//BE/pEg+su+8eD/yT7A4EY+KD0g/cnF1eWvEQPK1RITEhMGAyEAyuXFTgYAIWAMCQkqEhMqEhPB4SMFIOrhrwYIzYsU4dHByf////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAgMFBggJCwwOEBETFBYXGBobHR4fISIjJSYnKSorLC0uLzAxMjM0NTY3ODg5Ojo7PDw9PT4+Pj8/Pz9AQEBAQEBAQEBAPz8/Pz4+PT08PDs7Ojk5ODc2NTU0MzIxMC8uLCsqKSgmJSQjISAfHRwaGRcWFRMSEA8NCwoIBwUEAgH//fz6+ff29PPx8O7t6+ro5+Xk4uHg3t3c2tnY19bU09LR0M/OzczLysnJyMfGxsXFxMPDw8LCwcHBwcDAwMDAwMDAwMDBwcHBwsLDw8PExcXGxsfIycnKy8zNzs/Q0dLT1NXX2Nna3N3e4OHi5OXn6Onr7O7v8fL09vf5+vz9AAEECRAZJDFAUWR5kKnE4QAhRGmQueQRQHGk2RBJhMEAQYTJEFmk8UCR5DmQ6UShAGHEKZD5ZNFAsSSZEIkEgQCBBIkQmSSxQNFk+ZApxGEAoUTpkDnkkUDxpFkQyYRBAMGESRDZpHFAEeS5kGlEIQDhxKmQeWRRQDEkGRAJBAEAAQQJEBkkMUBRZHmQqcThACFEaZC55BFAcaTZEEmEwQBBhMkQWaTxQJHkOZDpRKEAYcQpkPlk0UCxJJkQiQSBAIEEiRCZJLFA0WT5kCnEYQChROmQOeSRQPGkWRDJhEEAwYRJENmkcUAR5LmQaUQhAOHEqZB5ZFFAMSQZEAkEAQAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAgICAgIDAwMDBAQEBAUFBQUGBgYHBwcICAkJCQoKCgsLDAwNDQ4ODw8QEBEREhITExQUFRUWFxcYGRkaGhscHB0eHh8gISEiIyQkJSYnJygpKisrLC0uLzAxMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1FSU1RVVldZWltcXV9gYWJkZWZnaWprbG5vcHJzdHZ3eXp7fX5/gYKEhYeIiouNjpCRk5SWl5manJ2foKKkpaepqqytr7GytLa3ubu9vsDCxMXHycvMztDS1NXX2dvd3+Hi5Obo6uzu8PL09vj6/P4A//z38Ofcz8CvnIdwVzwfAN+8l3BHHO/Aj1wn8Ld8PwC/fDfwp1wPwG8cx3AXvF8AnzzXcAecL8BP3Gfwd/x/AH/8d/Bn3E/AL5wHcNc8nwBfvBdwxxxvwA9cp/A3fL8AP3y38Cdcj8DvHEdwl7zfAB88V3CHnK/Az9zn8Pf8/wD//Pfw59zPwK+ch3BXPB8A37yXcEcc78CPXCfwt3w/AL98N/CnXA/AbxzHcBe8XwCfPNdwB5wvwE/cZ/B3/H8Af/x38GfcT8AvnAdw1zyfAF+8F3DHHG/AD1yn8Dd8vwA/fLfwJ1yPwO8cR3CXvN8AHzxXcIecr8DP3Ofw9/z/AP/////////////////////+/v7+/v79/f39/fz8/Pz8+/v7+vr6+vn5+fj4+Pf39/b29fX19PTz8/Ly8fHw8PDv7u7t7ezs6+vq6uno6Ofn5uXl5OPj4uHh4N/e3t3c3Nva2djY19bV1NTT0tHQz8/OzczLysnIx8bFxMPCwcDAvr28u7q5uLe2tbSzsrGwr62sq6qpqKalpKOioJ+enZyamZiWlZSTkZCPjYyLiYiHhYSCgYB+fXt6eHd1dHJxcG5sa2loZmVjYmBfXVtaWFdVU1JQTk1LSUhGREJBPz08Ojg2NDMxLy0rKigmJCIgHx0bGRcVExEPDQsJBwUDAf9/Px8PBwMBgEAgEAgEAgEAAQEBAQEBAQEBAQEA//////////////+AEAcAAQABAAEBAAEBAAEA/wD//wD//wD/AP+AKwcBAAEAAQD/AP8A/wD/AP8A/wABAAEAAQCARgcBAQEBAQD//////////////wABAQEBAQGAYQf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+AwODw+Pz+/xEAwAGxwj4E9cU+BfUKbwMKZ37+gCALI34LAiN+AwILGOsahhIDHBwcHPE9IN7BIRAAGVRdPgX1Cm8DCmcalhIjfAILfQIDAx0dHR3xPSDnIRgAGVRd8T0grskRAcAB6cI+BPUKbwMKZ37+gCALI34LAiN+AwILGOs+CvUahhIcHBwc8T0g9CN8Agt9AgMD8T0g0MkgIEZJTExFRCAgIFBPTFlHT05TIEhFTElDT1BURVJJTiBBQ1RJT04gIQDADgpwLHQsGhPWICI2ACwNIPE+oOoQyngBCQDlYmsJVF3hDMYKR3AsdCwaG9YgIjYALA0g8a/qEcrJ+hDK/jDI1gTqEMpHPqCQ/lA4Aj5QDgAM1ggw+3ghAcARBAB3xggZDSD5+hHKg+oRykf+UDgCPlAOAAzWCDD7eC4td9YIGQ0g+ckh9grzMf/PzVABr+Am4P/gD+BD4EL2SOBFPkDgQT4E4AfN9RM+CuoAAA4HeeBwJqCvIstsKPsNIPIh/v8yy30g+wEKABH1/yFpAc3kE+cCAVYAEQDBIVt2zeQTrwYYIWsOzYsUIYsOzaQUxwGwAxEAgCGhF8XlzeQT4cERAIjN5BMhAJgRAwABYMDHcc9yIwUg+BQdIPHN9RMhuxUGAc2WE82JEz5E4EGv4EU+A+D/+z4B6hLK4E0QAAB4zccTBSD6zZATxwEACFkhAIhzIwt4sSD5IQDHPv9FdyRwJCJ3JXclcCwg8x5/IQCYx3PPNgDL1DYIx3PLlCPLVCjuPoABDxARIAAhIpjF5XfL1HfLlDwZDSD1POEswQUg7D486jPLr+o0yz3qL8s+oOCCPgLqG8vNiRM+ROBBr+BFPgPg/68+ACEXyyI+CiI+IHev6h7L4ITgluodyz4B6h/L6g/D6g3KBlARnAjNxAjNcwsBLAHFzTsLzQAJwQt4sSDzzZATxwEACFkhAIhzIwt4sSD5zfUTeQYQIYMOzYsUPv/qKcsGgBGwCM3ECM2JEwEsAcXNbAzNAAnBC3ixIPOv6hLKzZATPpDgU/PHAbADEQCIIaEXzeQTzfUTIQIWBgHNlhPNiRM+ROBBr+BFPgPg//sY/j4D6gAgzcRGBgMhF8t+gCJ+gDwifoB3zckP+jDLb/oxy2fNtgs+AeCB8IG3IPv6Dcq3KAPNcwHJ+h3LBgARTg2Hb2AZKmZvTgkq4ItfKjzgjD1PKuCNe4eHg0cRAMUqEhwFIPp5h4eBRxEAxCoSHAUg+n3qMMt86jHLyfCL4I7wjOCP8I3gkBEAw9XlzcoQ4dHwpeaAEhwBAwAJ8JA94JAg6CEAxQYPKk+gXxq3IB95yzegXxq3IBYqT6BfGrcgD3nLN6BfGrcgBiwsLBhHLOXNyhDwlrcoKwYB8KXGP0/LfygBBcXwpMY/Vx4AzZMOe8H18KPGP1ceAM2TDsHhJCJwGAzhJPCjxj8i8KTGPyIsJRbDBg/wjj3gjsLiCz4C6gAgw1JhfBjcHwAL7mpIYL9vBgMhF8t+gCJ+gDwifoB3zckPIcsNEQDGzf4MI+U+A+oAICEgy83+DPocy9YIb+ocy82vYAYDESDLIWIOxeXVzcoQ4fCjxhQi8KQiNg8jVF3hIyMjwQUg5M3ERsE+AeoAIAr+/ygiEQDGbyYAKRnlAwoDbyYAKRleI1bhKmZvxc0xHMwAQMEY2T4B4IHwgbcg+8l+PMjl1c3KEAYB8KVPy38oAQXF8KTLf/UoAi88Vx4AzZMO8XsgAi88xn/B9fCjy3/1KAIvPFceAM2TDvF7KAIvPMZ/wdESE3gSE+EjIyMYsFANAgAIDAYCRCgoFANEKAAUE0QAABQSRAAoFAJVKCjsA1UoAOwTVQAA7BJVACjsAAAEBQAAAAEFAAEBAwIGAQEDBwYCAgAHAwICAAcEAwMBAgYDAwEFBgQEAAECBAQAAwIFBQQFBgUFBAcGMgAAzgAAADIAAM4AAAAyAADOKAAAHhEAChEAAAAACu8AHu8AFAAKFAD2FAAPCgAF6AAC4gAQ3gAQ4gD+CgD74g4C3Q4C4QAC4vIC3fIC4AAM4PsM4PsQ4/sJ3fsJ/wABAQICAwMEBAUFAAAGAQYCBgMGBAYFBgAHAQcCBwMHBAcFBwYICQoKCwsMDA0NDgoPDxAQEQoSEhMTERQVFRYVFxUYCBkIGggb/yAAD/AbD/DlD/9//3+XEQAAAGD/f5cRAAAYAP9/lxEAAIB8lxH/f/9/QHz/f18IAADLI8sSeC9HeS9PAyEAAH2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEssoyxkJ0BPJ+hfLJgJvfuCcLzzgnn3GQG9+4Jvgn6/gmOCZ4JrgneChPkDgl/oYy29OfcZAb0bFeOCgeeCizdMQ8KPgpvCk4KnwpeCsr+Cg4KI+QOChzdMQ8KPgp/Ck4KrwpeCtwXkvPOCgr+CheOCizdMQ8KPgmfCk4JzwpeCf8Kbgl/Cp4JrwrOCd8KfgmPCq4JvwreCe+hnLJgJvTn3GQG9GxXjgoHkvPOChr+CizdMQ8KPgpvCk4KnwpeCswXngoHjgoa/gos3TEPCj4KfwpOCq8KXgra/goOChPkDgos3TEPCj4JnwpOCc8KXgn/Cm4JfwqeCa8KzgnfCn4JjwquCb8K3gnskq4KAq4KEq4KLwl1/woCYGV8t6ICDLe3soJy88X3qTMAIvPG96g1YlXiVvfiVuZxl8LzwYH3ovPFfLeyjhey88X5IwAi88b3qDViVeJW9+JW5nGXxH8Jhf8KEmBlfLeiAgy3t7KCcvPF96kzACLzxveoNWJV4lb34lbmcZfC88GB96LzxXy3so4XsvPF+SMAIvPG96g1YlXiVvfiVuZxl8T/CZX/CiJgZXy3ogIMt7eygnLzxfepMwAi88b3qDViVeJW9+JW5nGXwvPBgfei88V8t7KOF7LzxfkjACLzxveoNWJV4lb34lbmcZfICB4KPwml/woCYGV8t6ICDLe3soJy88X3qTMAIvPG96g1YlXiVvfiVuZxl8LzwYH3ovPFfLeyjhey88X5IwAi88b3qDViVeJW9+JW5nGXxH8Jtf8KEmBlfLeiAgy3t7KCcvPF96kzACLzxveoNWJV4lb34lbmcZfC88GB96LzxXy3so4XsvPF+SMAIvPG96g1YlXiVvfiVuZxl8T/CcX/CiJgZXy3ogIMt7eygnLzxfepMwAi88b3qDViVeJW9+JW5nGXwvPBgfei88V8t7KOF7LzxfkjACLzxveoNWJV4lb34lbmcZfICB4KTwnV/woCYGV8t6ICDLe3soJy88X3qTMAIvPG96g1YlXiVvfiVuZxl8LzwYH3ovPFfLeyjhey88X5IwAi88b3qDViVeJW9+JW5nGXxH8J5f8KEmBlfLeiAgy3t7KCcvPF96kzACLzxveoNWJV4lb34lbmcZfC88GB96LzxXy3so4XsvPF+SMAIvPG96g1YlXiVvfiVuZxl8T/CfX/CiJgZXy3ogIMt7eygnLzxfepMwAi88b3qDViVeJW9+JW5nGXwvPBgfei88V8t7KOF7LzxfkjACLzxveoNWJV4lb34lbmcZfICB4KXJ9T6D4EDxyfWv4EDxyfXF1eXHKv7/KFD+FiAaTiMqh4eHVF1vJgApKXgGmAlHelRne11vGNzGYBLPeBIcGNN2ACETyjQ1KPc1yfvFBmR2AAUg+8HJ+3YABSD7yfXF1eUqEhMLeLEg+OHRwfHJxeUBAKAhAMDNAxThwcnF5XEjBSD74cHJxdXlAQCAIZXKzQMU4dHBycXV5a/qFcuwIAwaEyIaEzIEDXjqFcvlxRq+EyAPIxq+IAkTIw0gCMHhGBkrGyMjBSDmecFPBBoTIhoTIiEVyzThDSDS+hXL4dHBydVfzXIUuzD60cnF9cH6FMrLD6mAR/CLkR+AR/AFqOoUysHJ9cXltxcXF/aA4Ggq4GkFIPo+5OBH4cHxyfXF5bcXFxf2gOBqKuBrBSD6PuTgSOBJ4cHxyT4Q4ADwAC/LN+bwRz4g4ADwAC/mD7DqFsvJzyEAgK8GIE8+CCINIPwFIPnHIQCABiBPIg0g/AUg+cnFzQMVSs0eFcHJxc0RFUjNGRVLzSMVwcnFBgHNKxXBycUGABj2xQYDGPHFBgLNKxXByfXlh4eAJsBvceHxyfXlh4cmwG9GI04jXiNW4fHJ9cXV5eCDKjzK8BPWIF/wg835FF95xghPezwY6PXF1eXF1c13FdHBex4FIS3LGNUBKssR8NjNlRURGPzNlRURnP/NlRUR9v/NlRUR//8+LzwZOPwCA3ovV3svXxMZyTAwRlBT/zAwUE5UU/8wMExJTkVT/xYFB1dFTENPTUUgVE8WBQgtUkVBTFRJTUUtFgAJREVNTyBNQURFIEVTUEVDSUFMTFkWAQpGT1IgTENQJzIwMDAgUEFSVFn/FgAAR1JFRVRJTlg6ICAgICAgICAgICAWAAFEU0MsUEFOLFNBQixGQVRBTElUWRYAAkpFRkYgRlJPSFdFSU4sSUNBUlVTFgADRE9YLFFVQU5HLEFCWVNTICAgICAWAAQgICAgICAgICAgICAgICAgICAgIBYABUNSRURJVFM6ICAgICAgICAgICAgFgAGQUxMIEdGWCZDT0RFIEJZIEFHTyAWAAdIRUxJQ09QVEVSIDNEIE1PREVMIBYACENSRUFURUQgQlkgQlVTWSAgICAgFgAJICAgICAgICAgICAgICAgICAgICAWAApVU0VEIFNPRlRXQVJFOiAgICAgIBYAC1JHQkRTLE5PJENBU0gsRkFSICAgFgAMICAgICAgICAgICAgICAgICAgICAWAA1DT05UQUNUOiAgICAgICAgICAgIBYADkdPQlVaT1ZAWUFIT08uQ09NICAgFgAPSFRUUDovL1NQRUNDWS5EQS5SVSAWABAgICAgICAgICAgICAgICAgICAgIBYAEVNFRSBZT1UgT04gR0JERVYyMDAw/wAAAAAAAAAAAAAAAAAAAAAICBwUHBQ4KDgoMDBwUCAgKCh8VHxUKCgAAAAAAAAAABQUPip/QT4qfFT+gnxUKCgICDw0fkL8rP6Cfmr8hHhYJCR+Wn5SPCR4SPyU/LRISBgYPCR+Wjwkflr8tH5KNDQQEDgocFAgIAAAAAAAAAAABAQOChwUOCg4KDgoHBQICBAQOCgcFBwUHBQ4KHBQICAAABQUPio8NH5CPCx8VCgoAAAICBwUPDR+QjwsOCgQEAAAAAAAAAAAEBA4KHBQcFAAAAAAAAB8fP6CfHwAAAAAAAAAAAAAAAAwMHhIeEgwMAQEDgoeEjwkeEjwkOCgQEAYGDwkflr+qv6q/LR4SDAwGBg8JHxUPDQ4KHxs/oJ8fBwcPiJ+Wjw0eEj8vP6CfHwcHD4iflo8NE5K/LR4SDAwJCR+Wn5afFT8tP6CfGwQEBwcPiJ8XPyEfnr8tHhIMDAYGDwkeFj8pP66/LR4SDAwPDx+Qv66XFQ4KHBQcFAgIBwcPiJ+Wjwkflr8tPiIcHAcHD4iflr+sn5KfHT4iHBwAAAAAAgIHBQICBAQOCgQEAAACAgcFAgIEBA4KDgocFAAAAAAHBQ4KHBQcFA4KAAAAAAAADw8fkJ8fPyEeHgAAAAAAAA4KBwUHBQ4KHBQAAAYGDwkflr8tHhoEBA4KBAQHBw+In5a/rL8pPi4+IhwcBwcPiJ+Wv66/oL+uvy0SEg4OHxEflr8pP6a/LT4iHBwHBw+In5a5qbgoP6y/IxwcDAweEh8VH5a7qr+uvyEeHgcHD4ifFx8RHhY/Lz+gnx8HBw+Inxc/IT4uOCg4KBAQBwcPiJ+Wvy8/qL+uvyEeHgkJH5a/rr+gv66/LT8tEhIPDx+QjwsOChwUHhY/IR4eDw8fkI+Og4KXFT8tHhIMDAkJH5afFR+Qv66/LT8tEhIICBwUHBQ4KDkpP66fEQ4OCgofFR+Qv6q/rr8tPy0SEgkJH5a/pr+qv6y7qr8tEhIHBw+In5a7qruqvy0+IhwcBwcPiJ+Wv66/IT4uOCgQEAcHD4iflr+uv6q/LT+inZ2HBw+In5a/LT4iPy0/LRISBwcPiJ8XP6Cfnr8tPiIcHB8fP6CfGw4KHBQcFBwUCAgJCR+Wn5a7qruqvy0eEgwMERE7qruqnxUfFR4SHBQICAkJH5aflr+uv6q/KR8VCgoJCR+WnxUOCg8JH5a/LRISCQkflr8tPy0eEhwUHBQICA8PH5C/LT46Dwsflr8hHh4HBw+IjwsOChwUHhYfEQ4OEBA4KDwkHhIPCQeEg4KBAQ4OHxEPDQcFDgoeGj4iHBwGBg8JH5a7qpERAAAAAAAAAAAAAAAAAAAAAB8fP6CfHx81rdPfJJne5X1MAIvPEevyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxnLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEeRcvT/F5MAIvPIVvJrcBAAA+t7zLEbrLED6/vcsRu8sQPj+8P8sRuj/LEL0/yxG7P8sQeLHIeKHAebcgB3xiV31rX3jLH9L/HD5AlU97lW96lPUwAi88R6/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYV5Fy9P8XkwAi88hGcuQMMxHMsf0pcdPkCUT3qUZ3uV9TACLzxHr8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhHkXL0/xeTACLzyFbyZAwzEcyx/SoRt91r9PfZNvepT1MAIvPEevyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxnLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFeRcvT/F5MAIvPIRnLr/DMRz//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////3q8MAVUZ3tdb3u90pdAfZNPepRfkTA+V3nLPy88g+CDPn+R5YdPbyYARCkpKQkBkVIJweV41kAXb3nWQB8fH+YPZ/CChGd55gcGB/YITwpP8INHLMl5S1+RV3nLPy88g+CDPneR5YdPbyYARCkpKQkBklsJweV41kAXb3nWQB8fH+YPZ/CChGd55gcGB/YITwpP8INHLMmVT3qUX5EwPld5yz8vPIPggz5/keWHT28mAEQpKSkJAR9BCcHleNZAF2951kAfHx/mD2fwgoRneeYHBgf2CE8KT/CDRyzJeUtfkVd5yz8vPIPggz53keWHT28mAEQpKSkJASBKCcHleNZAF2951kAfHx/mD2fwgoRneeYHBgf2CE8KT/CDRyzJfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkyX6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALMl+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASXJfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsyf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wHRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyIxDsrh+eEWwxgNIf3Er+oLyuoMyiwsLPCPPcjgj14sGrcqKPDGeeCT+g3Ktygm+gvKPP4DIAI+AeoLyiAH+gzKPOoMyvoMyl8WyvCT1nkSe8bH4JMqTypHKuUmxl+Hh4M8PG8qX1Z5h4eBPDxveE4sh4eARjw8bypmb3y6OAViV31rX3y4OAVgR31pT3q4OAVQR3tZT3iU4JR8h+CV5dXFr+CSzUpifeCS0eHVzUpi0eE+AeCSzUpi8JRfPniTZy5Hr8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdxkBnCA7KMQDC5fCVb8l7vTBVfZNPepRfkTAkV3nLPy88Rz5/kU3Fh09vJgBEKSkJAfdiCcHlJsLwkm94BoDJeUtfkVd5yz8vPEc+d5FNxYdPbyYARCkpCQH4ZwnB5SbC8JJveAaAyZVPepRfkTAkV3nLPy88Rz5/kU3Fh09vJgBEKSkJAalsCcHlJsLwkm94BoDJeUtfkVd5yz8vPEc+d5FNxYdPbyYARCkpCQGqcQnB5SbC8JJveAaAyYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNyXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDcmDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDMlxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggzJxg+Hh+oawXovpl96obMiei+mX3qgszIkeRgAInAtJCJwLSQicC0kInAtJCJwLSQicC0kInAtJCJwLSQicC0kInAtJCJwLSQicC0kInAtJCJwLSQW/8n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+qqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINnMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBCqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlUC4XIscAl7InAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJcixwCXsicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCXIscAl7InAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJcixwCXsicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCXIscAl7InAJInAJInAJInAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAkicAkicAkicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJInAJInAJInAJcixwCXsicAkicAkicAkicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCXIscAl7InAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAkicAkicAkicAkicAkicAkicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJcixwCXsicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCXIscAl7InAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAlyLHAJeyJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJcixwCXsicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCXIscAl7LCwly2XIJGjJycnJydE+t5LI4IXmB8RSRPCFHx8focjlzTJE4XkicCwicCwicCwicCwicCwicCwicCwicCzJ+ABUXWhHeZAfyx1nATNZCfCCMQCv/qAoAzEAvwH/AOlHPgeQVF1HDjOvyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxlHIbRXCeViaz7/AQ8Ayfoay2/6G8uFZ/4UIAU+/y0YBtbsIAU8LOoby3zqGsvNr2AhlEbNyhDwpMagV/Cjxn9f1SGXRs3KEPCkxqBn8KPGf2/RzTEcKAsf2hhZH9oYWcPERny6OAViV31rX+XNmkbh1Xu90sxFe9ZA4Ih9k0884Il6lF/ghjzgij2RMGvgh3nLPy88g+CF8IIBDwBvVHzWQBfLN6GFZ3rmBxdvGAjwij3KAETgivCJX/CGV/CFGASCHSgLy38g+Ffwh4LghR3NYkUY2nvgifCIg1/l5gf2CG8mB1Z7aB8fHx/LHR/LHeYDxkBnrx7/6XnghpPgh3vLPy88geCF8IIBDwBvVHzWQBfLN6GFZ3rmBxdv8Ilf8IZX8IXLfyAHV/CHgh0YAYLghc1iRfCKPcoAROCKGN171kDgiHuVTzzgiXqUX+CGPOCKPZEwa+CHecs/LzyD4IXwggEPAG9UfNZAF8s3oYVneuYHF28YCPCKPcoAROCK8Ilf8IZX8IUYBIIdKAvLfyD4V/CHguCFHc0qRhjae+CJ8IiTX+XmB/YQbyYHVntoHx8fH8sdH8sd5gPGQGc+/1jpeeCGk+CHe8s/LzyB4IXwggEPAG9UfNZAF8s3oYVneuYHF2/wiV/whlfwhct/IAdX8IeCHRgBguCFzSpG8Io9ygBE4IoY3UYAALoAAHzWQMhPHx8f5h9HeeYHKAsE/gUwBvUhylblBT4PkCHJRoRn5fCCZ69vyfCCZ69vIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIsnxAQ8APcqEVz0odj0oOj0idwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwksLCXLZSgCJGgidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwksLCXLZSgCJGgidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwksLCXLZSgCJGgidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkid8kicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAloyfgAVF3wgjEAr/6gKAMxAL8B/wDFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcVia/nJJgJ+4JovPOCYfcZAb37gl+Cbr+CZ4JzgneCePkDgn8n/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Aw==';
   9779 
   9780 // End of realtime.js file.