no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / js / src / octane / gbemu-part2.js
blobb4c9a8d19da7927e8ec91f949fb43f2393ee94dc
1 // Portions copyright 2013 Google, Inc
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.
13 // The code has been adapted for use as a benchmark by Google.
15 // Previous files are in gbemu-part1.js, since they need to run in sloppy mode.
17 // Start of js/GameBoyCore.js file.
19 "use strict";
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();
291 // Start of code changed for benchmarking (removed ROM):
292 GameBoyCore.prototype.GBBOOTROM = [];
293 GameBoyCore.prototype.GBCBOOTROM = [];
294 // End of code changed for benchmarking.
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
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   }
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   }
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
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
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
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
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
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
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
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
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   }
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   }
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   ];
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;
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   }
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.
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");
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;
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;
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.
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();
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;
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.
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   }
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;
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();
4987 GameBoyCore.prototype.MBCRAMUtilized = function () {
4988   return this.cMBC1 || this.cMBC2 || this.cMBC3 || this.cMBC5 || this.cMBC7 || this.cRUMBLE;
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;
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   }
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   }
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;
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;
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   }
5109 GameBoyCore.prototype.changeVolume = function () {
5110   if (settings[0] && this.audioHandle) {
5111     try {
5112       this.audioHandle.changeVolume(settings[14]);
5113     }
5114     catch (error) { }
5115   }
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");
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   }
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   }
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();
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);
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   }
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   }
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;
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   }
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   }
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   }
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   }
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   }
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   }
5554 GameBoyCore.prototype.channel1EnableCheck = function () {
5555   this.channel1Enabled = ((this.channel1consecutive || this.channel1totalLength > 0) && !this.channel1SweepFault && this.channel1canPlay);
5556   this.channel1OutputLevelSecondaryCache();
5558 GameBoyCore.prototype.channel1VolumeEnableCheck = function () {
5559   this.channel1canPlay = (this.memory[0xFF12] > 7);
5560   this.channel1EnableCheck();
5561   this.channel1OutputLevelSecondaryCache();
5563 GameBoyCore.prototype.channel1OutputLevelCache = function () {
5564   this.channel1currentSampleLeft = (this.leftChannel1) ? this.channel1envelopeVolume : 0;
5565   this.channel1currentSampleRight = (this.rightChannel1) ? this.channel1envelopeVolume : 0;
5566   this.channel1OutputLevelSecondaryCache();
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();
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();
5590 GameBoyCore.prototype.channel2EnableCheck = function () {
5591   this.channel2Enabled = ((this.channel2consecutive || this.channel2totalLength > 0) && this.channel2canPlay);
5592   this.channel2OutputLevelSecondaryCache();
5594 GameBoyCore.prototype.channel2VolumeEnableCheck = function () {
5595   this.channel2canPlay = (this.memory[0xFF17] > 7);
5596   this.channel2EnableCheck();
5597   this.channel2OutputLevelSecondaryCache();
5599 GameBoyCore.prototype.channel2OutputLevelCache = function () {
5600   this.channel2currentSampleLeft = (this.leftChannel2) ? this.channel2envelopeVolume : 0;
5601   this.channel2currentSampleRight = (this.rightChannel2) ? this.channel2envelopeVolume : 0;
5602   this.channel2OutputLevelSecondaryCache();
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();
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();
5626 GameBoyCore.prototype.channel3EnableCheck = function () {
5627   this.channel3Enabled = (/*this.channel3canPlay && */(this.channel3consecutive || this.channel3totalLength > 0));
5628   this.channel3OutputLevelSecondaryCache();
5630 GameBoyCore.prototype.channel3OutputLevelCache = function () {
5631   this.channel3currentSampleLeft = (this.leftChannel3) ? this.cachedChannel3Sample : 0;
5632   this.channel3currentSampleRight = (this.rightChannel3) ? this.cachedChannel3Sample : 0;
5633   this.channel3OutputLevelSecondaryCache();
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();
5646 GameBoyCore.prototype.channel4EnableCheck = function () {
5647   this.channel4Enabled = ((this.channel4consecutive || this.channel4totalLength > 0) && this.channel4canPlay);
5648   this.channel4OutputLevelSecondaryCache();
5650 GameBoyCore.prototype.channel4VolumeEnableCheck = function () {
5651   this.channel4canPlay = (this.memory[0xFF21] > 7);
5652   this.channel4EnableCheck();
5653   this.channel4OutputLevelSecondaryCache();
5655 GameBoyCore.prototype.channel4OutputLevelCache = function () {
5656   this.channel4currentSampleLeft = (this.leftChannel4) ? this.cachedChannel4Sample : 0;
5657   this.channel4currentSampleRight = (this.rightChannel4) ? this.cachedChannel4Sample : 0;
5658   this.channel4OutputLevelSecondaryCache();
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();
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));
5675 GameBoyCore.prototype.channel3UpdateCache = function () {
5676   this.cachedChannel3Sample = this.channel3PCM[this.channel3lastSampleLookup] >> this.channel3patternType;
5677   this.channel3OutputLevelCache();
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;
5689 GameBoyCore.prototype.channel4UpdateCache = function () {
5690   this.cachedChannel4Sample = this.noiseSampleTable[this.channel4currentVolume | this.channel4lastSampleLookup];
5691   this.channel4OutputLevelCache();
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   }
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   }
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   }
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   }
5833 GameBoyCore.prototype.recalculateIterationClockLimit = function () {
5834   var endModulus = this.CPUCyclesTotalCurrent % 4;
5835   this.CPUCyclesTotal = this.CPUCyclesTotalBase + this.CPUCyclesTotalCurrent - endModulus;
5836   this.CPUCyclesTotalCurrent = endModulus;
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   }
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   }
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   }
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;
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   }
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   }
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   }
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   }
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   }
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   }
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;
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   }
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   }
6212 GameBoyCore.prototype.prepareFrame = function () {
6213   //Copy the internal frame buffer to the output buffer:
6214   this.swizzleFrameBuffer();
6215   this.drewFrame = true;
6217 GameBoyCore.prototype.requestDraw = function () {
6218   if (this.drewFrame) {
6219     this.dispatchDraw();
6220   }
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   }
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   }
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   }
6264 GameBoyCore.prototype.resizeFrameBuffer = function () {
6265   //Return a reference to the generated resized framebuffer:
6266   return this.resizer.resize(this.swizzledFrame);
6268 GameBoyCore.prototype.compileResizeFrameBufferFunction = function () {
6269   if (this.offscreenRGBCount > 0) {
6270     this.resizer = new Resize(160, 144, this.offscreenWidth, this.offscreenHeight, false, true);
6271   }
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;
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   }
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();
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();
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   }
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   }
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;
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();
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;
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;
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];
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];
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];
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)];
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   }
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   }
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   }
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   }
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   }
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   }
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   }
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   }
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   }
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;
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   }
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);
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);
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);
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);
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);
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);
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   }
7304 GameBoyCore.prototype.graphicsJITVBlank = function () {
7305   //JIT the graphics to v-blank framing:
7306   this.totalLinesPassed += this.queuedScanLines;
7307   this.graphicsJITScanlineGroup();
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   }
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   }
7337 GameBoyCore.prototype.midScanLineJIT = function () {
7338   this.graphicsJIT();
7339   this.renderMidScanLine();
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);
7368   Check for IRQs to be fired while not in HALT:
7370 GameBoyCore.prototype.checkIRQMatching = function () {
7371   if (this.IME) {
7372     this.IRQLineMatched = this.interruptsEnabled & this.interruptsRequested & 0x1F;
7373   }
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.
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   }
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.
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.
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];
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   }
7780 GameBoyCore.prototype.memoryReadNormal = function (parentObj, address) {
7781   return parentObj.memory[address];
7783 GameBoyCore.prototype.memoryHighReadNormal = function (parentObj, address) {
7784   return parentObj.memory[0xFF00 | address];
7786 GameBoyCore.prototype.memoryReadROM = function (parentObj, address) {
7787   return parentObj.ROM[parentObj.currentROMBank + address];
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;
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;
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;
7856 GameBoyCore.prototype.memoryReadGBCMemory = function (parentObj, address) {
7857   return parentObj.GBCMemory[address + parentObj.gbcRamBankPosition];
7859 GameBoyCore.prototype.memoryReadOAM = function (parentObj, address) {
7860   return (parentObj.modeSTAT > 1) ?  0xFF : parentObj.memory[address];
7862 GameBoyCore.prototype.memoryReadECHOGBCMemory = function (parentObj, address) {
7863   return parentObj.GBCMemory[address + parentObj.gbcRamBankPositionECHO];
7865 GameBoyCore.prototype.memoryReadECHONormal = function (parentObj, address) {
7866   return parentObj.memory[address - 0x2000];
7868 GameBoyCore.prototype.memoryReadBAD = function (parentObj, address) {
7869   return 0xFF;
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]);
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];
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];
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];
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   }
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;
7906 GameBoyCore.prototype.setCurrentMBC5ROMBank = function () {
7907   //Read the cartridge ROM data from RAM memory:
7908   this.currentROMBank = ((this.ROMBank1offs % this.ROMBankEdge) - 1) << 14;
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);
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);
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...
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.
8060 GameBoyCore.prototype.MBC1WriteROMBank = function (parentObj, address, data) {
8061   //MBC1 ROM bank switching:
8062   parentObj.ROMBank1offs = (parentObj.ROMBank1offs & 0x60) | (data & 0x1F);
8063   parentObj.setCurrentMBC1ROMBank();
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   }
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   }
8090 GameBoyCore.prototype.MBC2WriteROMBank = function (parentObj, address, data) {
8091   //MBC2 ROM bank switching:
8092   parentObj.ROMBank1offs = data & 0x0F;
8093   parentObj.setCurrentMBC2AND3ROMBank();
8095 GameBoyCore.prototype.MBC3WriteROMBank = function (parentObj, address, data) {
8096   //MBC3 ROM bank switching:
8097   parentObj.ROMBank1offs = data & 0x7F;
8098   parentObj.setCurrentMBC2AND3ROMBank();
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   }
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   }
8121 GameBoyCore.prototype.MBC5WriteROMBankLow = function (parentObj, address, data) {
8122   //MBC5 ROM bank switching:
8123   parentObj.ROMBank1offs = (parentObj.ROMBank1offs & 0x100) | data;
8124   parentObj.setCurrentMBC5ROMBank();
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();
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;
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;
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;
8147 GameBoyCore.prototype.cartIgnoreWrite = function (parentObj, address, data) {
8148   //We might have encountered illegal RAM writing or such, so just do nothing...
8150 GameBoyCore.prototype.memoryWriteNormal = function (parentObj, address, data) {
8151   parentObj.memory[address] = data;
8153 GameBoyCore.prototype.memoryHighWriteNormal = function (parentObj, address, data) {
8154   parentObj.memory[0xFF00 | address] = data;
8156 GameBoyCore.prototype.memoryWriteMBCRAM = function (parentObj, address, data) {
8157   if (parentObj.MBCRAMBanksEnabled || settings[10]) {
8158     parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition] = data;
8159   }
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   }
8207 GameBoyCore.prototype.memoryWriteGBCRAM = function (parentObj, address, data) {
8208   parentObj.GBCMemory[address + parentObj.gbcRamBankPosition] = data;
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   }
8218 GameBoyCore.prototype.memoryWriteECHOGBCRAM = function (parentObj, address, data) {
8219   parentObj.GBCMemory[address + parentObj.gbcRamBankPositionECHO] = data;
8221 GameBoyCore.prototype.memoryWriteECHONormal = function (parentObj, address, data) {
8222   parentObj.memory[address - 0x2000] = data;
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   }
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   }
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   }
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   }
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   }
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;
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();
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   }
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   }
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   }
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   }
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;
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   }
9353 // End of js/GameBoyCore.js file.
9355 // Start of js/GameBoyIO.js file.
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.
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();
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   }
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   }
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   }
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   }
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   }
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   }
9497 function autoSave() {
9498   if (GameBoyEmulatorInitialized()) {
9499     cout("Automatically saving the SRAM.", 0);
9500     saveSRAM();
9501     saveRTC();
9502   }
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 [];
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 [];
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   }
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   }
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;
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;
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;
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;
9706 function GameBoyEmulatorInitialized() {
9707   return (typeof gameboy == "object" && gameboy != null);
9709 function GameBoyEmulatorPlaying() {
9710   return ((gameboy.stopEmulator & 2) == 0);
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   }
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   }
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   }
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   }
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   }
9773 // End of js/GameBoyIO.js file.
9775 // Start of realtime.js file.
9776 // ROM code from Public Domain LPC2000 Demo "realtime" by AGO.
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==';
9780 // End of realtime.js file.