Guest User

Untitled

a guest
Mar 12th, 2011
634
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 299.38 KB | None | 0 0
  1. /*
  2. * JavaScript GameBoy Color Emulator
  3. * Copyright (C) 2010 Grant Galitz
  4. *
  5. * Ported the video engine (advanced gfx one), some HDMA handling, and the double speed mode procedure (STOP opcode procedure) from MeBoy 2.2
  6. * http://arktos.se/meboy/
  7. * Copyright (C) 2005-2009 Bjorn Carlin
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * version 2 as published by the Free Software Foundation.
  12. * The full license is available at http://www.gnu.org/licenses/gpl.html
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. */
  20. /**
  21. *TODO:
  22. - Working On Right Now:
  23. - Make I/O bit reading and writing more accurate.
  24. - Now able to start up the Demotronic Final Demo, but still some issues with that ROM.
  25. - Started already, but far from merging into here:
  26. - Serial port link for multiplayer type stuff
  27. - Returns default and triggers serial interrupts when requested for now.
  28. - IR port
  29. - Returns default for now.
  30. - GBA (ARM7TDMI CPU Core) support will be coming when I feel like working on it more.
  31. - Could be split off into a separate project, because the CPU is completely different.
  32. - Afterwards....
  33. - Fix some boogs.
  34. - A Bit Later... Byte Later... Which ever comes first :P
  35. - Add some more MBC support (I haven't seen any game except one so far that uses an unsupported MBC)
  36. - MBC7, TAMA5, HuC1, etc.
  37. **/
  38. function GameBoyCore(canvas, canvasAlt, ROMImage) {
  39. //Params, etc...
  40. this.canvas = canvas; //Canvas DOM object for drawing out the graphics to.
  41. this.canvasAlt = canvasAlt; //Image DOM object for drawing out the graphics to as an alternate means.
  42. this.canvasFallbackHappened = false; //Used for external scripts to tell if we're really using the canvas or not (Helpful with fullscreen switching).
  43. this.drawContext = null; // LCD Context
  44. this.ROMImage = ROMImage; //The game's ROM.
  45. //CPU Registers and Flags:
  46. this.registerA = 0x01; //Register A (Accumulator)
  47. this.FZero = true; //Register F - Result was zero
  48. this.FSubtract = false; //Register F - Subtraction was executed
  49. this.FHalfCarry = true; //Register F - Half carry or half borrow
  50. this.FCarry = true; //Register F - Carry or borrow
  51. this.registerB = 0x00; //Register B
  52. this.registerC = 0x13; //Register C
  53. this.registerD = 0x00; //Register D
  54. this.registerE = 0xD8; //Register E
  55. this.registersHL = 0x014D; //Registers H and L combined
  56. this.stackPointer = 0xFFFE; //Stack Pointer
  57. this.programCounter = 0x0100; //Program Counter
  58. //Some CPU Emulation State Variables:
  59. this.inBootstrap = true; //Whether we're in the GBC boot ROM.
  60. this.usedBootROM = false; //Updated upon ROM loading...
  61. this.halt = false; //Has the CPU been suspended until the next interrupt?
  62. this.skipPCIncrement = false; //Did we trip the DMG Halt bug?
  63. this.stopEmulator = 3; //Has the emulation been paused or a frame has ended?
  64. this.IME = true; //Are interrupts enabled?
  65. this.hdmaRunning = false; //HDMA Transfer Flag - GBC only
  66. this.CPUTicks = 0; //The number of clock cycles emulated.
  67. this.multiplier = 1; //GBC Speed Multiplier
  68. this.JoyPad = 0xFF; //Joypad State (two four-bit states actually)
  69. //Main RAM, MBC RAM, GBC Main RAM, VRAM, etc.
  70. this.memoryReader = []; //Array of functions mapped to read back memory
  71. this.memoryWriter = []; //Array of functions mapped to write to memory
  72. this.ROM = []; //The full ROM file dumped to an array.
  73. this.memory = []; //Main Core Memory
  74. this.MBCRam = []; //Switchable RAM (Used by games for more RAM) for the main memory range 0xA000 - 0xC000.
  75. this.VRAM = []; //Extra VRAM bank for GBC.
  76. this.tileBankOffset = 0;
  77. this.GBCMemory = []; //GBC main RAM Banks
  78. this.MBC1Mode = false; //MBC1 Type (4/32, 16/8)
  79. this.MBCRAMBanksEnabled = false; //MBC RAM Access Control.
  80. this.currMBCRAMBank = 0; //MBC Currently Indexed RAM Bank
  81. this.currMBCRAMBankPosition = -0xA000; //MBC Position Adder;
  82. this.cGBC = false; //GameBoy Color detection.
  83. this.gbcRamBank = 1; //Currently Switched GameBoy Color ram bank
  84. this.gbcRamBankPosition = -0xD000; //GBC RAM offset from address start.
  85. this.gbcRamBankPositionECHO = -0xF000; //GBC RAM (ECHO mirroring) offset from address start.
  86. this.RAMBanks = [0, 1, 2, 4, 16]; //Used to map the RAM banks to maximum size the MBC used can do.
  87. this.ROMBank1offs = 0; //Offset of the ROM bank switching.
  88. this.currentROMBank = 0; //The parsed current ROM bank selection.
  89. this.cartridgeType = 0; //Cartridge Type
  90. this.name = ""; //Name of the game
  91. this.gameCode = ""; //Game code (Suffix for older games)
  92. this.fromSaveState = false; //A boolean to see if this was loaded in as a save state.
  93. this.savedStateFileName = ""; //When loaded in as a save state, this will not be empty.
  94. this.STATTracker = 0; //Tracker for STAT triggering.
  95. this.modeSTAT = 0; //The scan line mode (for lines 1-144 it's 2-3-0, for 145-154 it's 1)
  96. this.spriteCount = 0; //Mode 3 extra clocking counter (Depends on how many sprites are on the current line.).
  97. this.LYCMatchTriggerSTAT = false; //Should we trigger an interrupt if LY==LYC?
  98. this.mode2TriggerSTAT = false; //Should we trigger an interrupt if in mode 2?
  99. this.mode1TriggerSTAT = false; //Should we trigger an interrupt if in mode 1?
  100. this.mode0TriggerSTAT = false; //Should we trigger an interrupt if in mode 0?
  101. this.LCDisOn = false; //Is the emulated LCD controller on?
  102. this.LINECONTROL = new Array(154); //Array of functions to handle each scan line we do (onscreen + offscreen)
  103. this.DISPLAYOFFCONTROL = new Array(function (parentObj) {
  104. //Array of line 0 function to handle the LCD controller when it's off (Do nothing!).
  105. });
  106. this.LCDCONTROL = null; //Pointer to either LINECONTROL or DISPLAYOFFCONTROL.
  107. //RTC (Real Time Clock for MBC3):
  108. this.RTCisLatched = false;
  109. this.latchedSeconds = 0; //RTC latched seconds.
  110. this.latchedMinutes = 0; //RTC latched minutes.
  111. this.latchedHours = 0; //RTC latched hours.
  112. this.latchedLDays = 0; //RTC latched lower 8-bits of the day counter.
  113. this.latchedHDays = 0; //RTC latched high-bit of the day counter.
  114. this.RTCSeconds = 0; //RTC seconds counter.
  115. this.RTCMinutes = 0; //RTC minutes counter.
  116. this.RTCHours = 0; //RTC hours counter.
  117. this.RTCDays = 0; //RTC days counter.
  118. this.RTCDayOverFlow = false; //Did the RTC overflow and wrap the day counter?
  119. this.RTCHALT = false; //Is the RTC allowed to clock up?
  120. //Sound variables:
  121. this.audioHandle = null; //Audio object or the WAV PCM generator wrapper
  122. this.outTracker = 0; //Buffering counter for the WAVE PCM output.
  123. this.outTrackerLimit = 0; //Buffering limiter for WAVE PCM output.
  124. this.numSamplesTotal = 0; //Length of the sound buffers.
  125. this.sampleSize = 0; //Length of the sound buffer for one channel.
  126. this.dutyLookup = [0.125, 0.25, 0.5, 0.75]; //Map the duty values given to ones we can work with.
  127. this.audioSamples = []; //The audio buffer we're working on (When not overflowing).
  128. this.audioBackup = []; //Audio overflow buffer.
  129. this.usingBackupAsMain = 0; //Don't copy over the backup buffer to the main buffer on the next iteration, instead make the backup the main buffer (vice versa).
  130. this.currentBuffer = this.audioSamples; //Pointer to the sample workbench.
  131. this.initializeAudioStartState();
  132. this.soundMasterEnabled = false; //As its name implies
  133. this.audioType = -1; //Track what method we're using for audio output.
  134. //Vin Shit:
  135. this.VinLeftChannelEnabled = false; //Is the VIN left channel enabled?
  136. this.VinRightChannelEnabled = false; //Is the VIN right channel enabled?
  137. this.VinLeftChannelMasterVolume = 1; //Computed post-mixing volume.
  138. this.VinRightChannelMasterVolume = 1; //Computed post-mixing volume.
  139. //Channels Enabled:
  140. this.leftChannel = this.ArrayPad(4, false); //Which channels are enabled for left side stereo / mono?
  141. this.rightChannel = this.ArrayPad(4, false);//Which channels are enabled for right side stereo?
  142. //Current Samples Being Computed:
  143. this.currentSampleLeft = -1;
  144. this.currentSampleRight = -1;
  145. this.channel3Tracker = 0;
  146. //Pre-multipliers to cache some calculations:
  147. this.initializeTiming();
  148. this.samplesOut = 0; //Premultiplier for audio samples per instruction.
  149. //Audio generation counters:
  150. this.audioOverflow = false; //Safety boolean to check for whether we're about to overwrite our buffers.
  151. this.audioTicks = 0; //Used to sample the audio system every x CPU instructions.
  152. this.audioIndex = 0; //Used to keep alignment on audio generation.
  153. this.rollover = 0; //Used to keep alignment on the number of samples to output (Realign from counter alias).
  154. //Timing Variables
  155. this.emulatorTicks = 0; //Times for how many instructions to execute before ending the loop.
  156. this.DIVTicks = 14; //DIV Ticks Counter (Invisible lower 8-bit)
  157. this.LCDTicks = 15; //Counter for how many instructions have been executed on a scanline so far.
  158. this.timerTicks = 0; //Counter for the TIMA timer.
  159. this.TIMAEnabled = false; //Is TIMA enabled?
  160. this.TACClocker = 256; //Timer Max Ticks
  161. this.untilEnable = 0; //Are the interrupts on queue to be enabled?
  162. var dateVar = new Date();
  163. this.lastIteration = dateVar.getTime();//The last time we iterated the main loop.
  164. this.actualScanLine = 0; //Actual scan line...
  165. //ROM Cartridge Components:
  166. this.cMBC1 = false; //Does the cartridge use MBC1?
  167. this.cMBC2 = false; //Does the cartridge use MBC2?
  168. this.cMBC3 = false; //Does the cartridge use MBC3?
  169. this.cMBC5 = false; //Does the cartridge use MBC5?
  170. this.cSRAM = false; //Does the cartridge use save RAM?
  171. this.cMMMO1 = false; //...
  172. this.cRUMBLE = false; //Does the cartridge use the RUMBLE addressing (modified MBC5)?
  173. this.cCamera = false; //Is the cartridge actually a GameBoy Camera?
  174. this.cTAMA5 = false; //Does the cartridge use TAMA5? (Tamagotchi Cartridge)
  175. this.cHuC3 = false; //Does the cartridge use HuC3 (Hudson Soft / modified MBC3)?
  176. this.cHuC1 = false; //Does the cartridge use HuC1 (Hudson Soft / modified MBC1)?
  177. this.cTIMER = false; //Does the cartridge have an RTC?
  178. this.ROMBanks = [ // 1 Bank = 16 KBytes = 256 Kbits
  179. 2, 4, 8, 16, 32, 64, 128, 256, 512
  180. ];
  181. this.ROMBanks[0x52] = 72;
  182. this.ROMBanks[0x53] = 80;
  183. this.ROMBanks[0x54] = 96;
  184. this.numRAMBanks = 0; //How many RAM banks were actually allocated?
  185. ////Graphics Variables
  186. this.currVRAMBank = 0; //Current VRAM bank for GBC.
  187. this.gfxWindowDisplay = false;
  188. this.gfxSpriteShow = false;
  189. this.gfxSpriteDouble = false;
  190. this.bgEnabled = true;
  191. this.BGPriorityEnabled = 0x1000000;
  192. this.gfxWindowCHRBankPosition = 0;
  193. this.gfxBackgroundCHRBankPosition = 0;
  194. this.gfxBackgroundBankOffset = 0x80;
  195. this.drewBlank = 0; //To prevent the repeating of drawing a blank screen.
  196. //Sprite Bounds Cache:
  197. this.spriteLineStart = this.getTypedArray(23040, 0, "uint8");
  198. //BG Tile Pointer Caches:
  199. this.BGCHRBank1Pointer = this.getTypedArray(0x800, 0, "uint16");
  200. this.BGCHRBank2Pointer = this.getTypedArray(0x800, 0, "uint16");
  201. this.BGCHRCurrentBank = this.BGCHRBank1Pointer;
  202. //Tile Data Cache
  203. this.tileCache = this.ArrayPad(0x300, this.ArrayPad(8, this.getTypedArray(0x8, "uint8")));
  204. this.tileOBJCache = this.ArrayPad(0x200, this.ArrayPad(8, this.getTypedArray(0x8, "uint8")));
  205. this.colors = new Array(0xEFFFDE, 0xADD794, 0x529273, 0x183442); //"Classic" GameBoy palette colors.
  206. this.OBJPalette = null;
  207. this.BGPalette = null;
  208. this.gbcOBJRawPalette = this.getTypedArray(0x40, 0, "uint32");
  209. this.gbcBGRawPalette = this.getTypedArray(0x40, 0, "uint32");
  210. this.gbOBJPalette = this.getTypedArray(8, 0, "uint32");
  211. this.gbBGPalette = this.getTypedArray(4, 0, "uint32");
  212. this.gbcOBJPalette = this.getTypedArray(0x20, 0, "uint32");
  213. this.gbcBGPalette = this.getTypedArray(0x20, 0, "uint32");
  214. this.gbBGColorizedPalette = this.getTypedArray(4, 0, "uint32");
  215. this.gbOBJColorizedPalette = this.getTypedArray(8, 0, "uint32");
  216. this.cachedBGPaletteConversion = this.getTypedArray(4, 0, "uint32");
  217. this.cachedOBJPaletteConversion = this.getTypedArray(8, 0, "uint32");
  218. this.frameBuffer = [];
  219. this.scaledFrameBuffer = [];
  220. this.canvasBuffer = null;
  221. this.frameCount = settings[12]; //Frame skip tracker
  222. this.width = 160;
  223. this.height = 144;
  224. this.pixelCount = this.width * this.height;
  225. this.rgbCount = this.pixelCount * 4;
  226. this.widthRatio = 160 / this.width;
  227. this.heightRatio = 144 / this.height;
  228. }
  229. GameBoyCore.prototype.DAATable = new Array( // DAA lookup array from VBA-M (I need to make an algo to generate this on startup instead. <_< )
  230. 0x0080, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500,
  231. 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, 0x1800, 0x1900, 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500,
  232. 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2600, 0x2700, 0x2800, 0x2900, 0x3000, 0x3100, 0x3200, 0x3300, 0x3400, 0x3500,
  233. 0x3000, 0x3100, 0x3200, 0x3300, 0x3400, 0x3500, 0x3600, 0x3700, 0x3800, 0x3900, 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500,
  234. 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500,
  235. 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, 0x5800, 0x5900, 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500,
  236. 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600, 0x6700, 0x6800, 0x6900, 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500,
  237. 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, 0x7600, 0x7700, 0x7800, 0x7900, 0x8000, 0x8100, 0x8200, 0x8300, 0x8400, 0x8500,
  238. 0x8000, 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800, 0x8900, 0x9000, 0x9100, 0x9200, 0x9300, 0x9400, 0x9500,
  239. 0x9000, 0x9100, 0x9200, 0x9300, 0x9400, 0x9500, 0x9600, 0x9700, 0x9800, 0x9900, 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510,
  240. 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, 0x0810, 0x0910, 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510,
  241. 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, 0x1810, 0x1910, 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510,
  242. 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, 0x2810, 0x2910, 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510,
  243. 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, 0x3810, 0x3910, 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510,
  244. 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, 0x4810, 0x4910, 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510,
  245. 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, 0x5810, 0x5910, 0x6010, 0x6110, 0x6210, 0x6310, 0x6410, 0x6510,
  246. 0x6010, 0x6110, 0x6210, 0x6310, 0x6410, 0x6510, 0x6610, 0x6710, 0x6810, 0x6910, 0x7010, 0x7110, 0x7210, 0x7310, 0x7410, 0x7510,
  247. 0x7010, 0x7110, 0x7210, 0x7310, 0x7410, 0x7510, 0x7610, 0x7710, 0x7810, 0x7910, 0x8010, 0x8110, 0x8210, 0x8310, 0x8410, 0x8510,
  248. 0x8010, 0x8110, 0x8210, 0x8310, 0x8410, 0x8510, 0x8610, 0x8710, 0x8810, 0x8910, 0x9010, 0x9110, 0x9210, 0x9310, 0x9410, 0x9510,
  249. 0x9010, 0x9110, 0x9210, 0x9310, 0x9410, 0x9510, 0x9610, 0x9710, 0x9810, 0x9910, 0xA010, 0xA110, 0xA210, 0xA310, 0xA410, 0xA510,
  250. 0xA010, 0xA110, 0xA210, 0xA310, 0xA410, 0xA510, 0xA610, 0xA710, 0xA810, 0xA910, 0xB010, 0xB110, 0xB210, 0xB310, 0xB410, 0xB510,
  251. 0xB010, 0xB110, 0xB210, 0xB310, 0xB410, 0xB510, 0xB610, 0xB710, 0xB810, 0xB910, 0xC010, 0xC110, 0xC210, 0xC310, 0xC410, 0xC510,
  252. 0xC010, 0xC110, 0xC210, 0xC310, 0xC410, 0xC510, 0xC610, 0xC710, 0xC810, 0xC910, 0xD010, 0xD110, 0xD210, 0xD310, 0xD410, 0xD510,
  253. 0xD010, 0xD110, 0xD210, 0xD310, 0xD410, 0xD510, 0xD610, 0xD710, 0xD810, 0xD910, 0xE010, 0xE110, 0xE210, 0xE310, 0xE410, 0xE510,
  254. 0xE010, 0xE110, 0xE210, 0xE310, 0xE410, 0xE510, 0xE610, 0xE710, 0xE810, 0xE910, 0xF010, 0xF110, 0xF210, 0xF310, 0xF410, 0xF510,
  255. 0xF010, 0xF110, 0xF210, 0xF310, 0xF410, 0xF510, 0xF610, 0xF710, 0xF810, 0xF910, 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510,
  256. 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, 0x0810, 0x0910, 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510,
  257. 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, 0x1810, 0x1910, 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510,
  258. 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, 0x2810, 0x2910, 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510,
  259. 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, 0x3810, 0x3910, 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510,
  260. 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, 0x4810, 0x4910, 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510,
  261. 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, 0x5810, 0x5910, 0x6010, 0x6110, 0x6210, 0x6310, 0x6410, 0x6510,
  262. 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500,
  263. 0x1600, 0x1700, 0x1800, 0x1900, 0x1A00, 0x1B00, 0x1C00, 0x1D00, 0x1E00, 0x1F00, 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500,
  264. 0x2600, 0x2700, 0x2800, 0x2900, 0x2A00, 0x2B00, 0x2C00, 0x2D00, 0x2E00, 0x2F00, 0x3000, 0x3100, 0x3200, 0x3300, 0x3400, 0x3500,
  265. 0x3600, 0x3700, 0x3800, 0x3900, 0x3A00, 0x3B00, 0x3C00, 0x3D00, 0x3E00, 0x3F00, 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500,
  266. 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, 0x4B00, 0x4C00, 0x4D00, 0x4E00, 0x4F00, 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500,
  267. 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x5C00, 0x5D00, 0x5E00, 0x5F00, 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500,
  268. 0x6600, 0x6700, 0x6800, 0x6900, 0x6A00, 0x6B00, 0x6C00, 0x6D00, 0x6E00, 0x6F00, 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500,
  269. 0x7600, 0x7700, 0x7800, 0x7900, 0x7A00, 0x7B00, 0x7C00, 0x7D00, 0x7E00, 0x7F00, 0x8000, 0x8100, 0x8200, 0x8300, 0x8400, 0x8500,
  270. 0x8600, 0x8700, 0x8800, 0x8900, 0x8A00, 0x8B00, 0x8C00, 0x8D00, 0x8E00, 0x8F00, 0x9000, 0x9100, 0x9200, 0x9300, 0x9400, 0x9500,
  271. 0x9600, 0x9700, 0x9800, 0x9900, 0x9A00, 0x9B00, 0x9C00, 0x9D00, 0x9E00, 0x9F00, 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510,
  272. 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, 0x0E10, 0x0F10, 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510,
  273. 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, 0x1E10, 0x1F10, 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510,
  274. 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, 0x2E10, 0x2F10, 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510,
  275. 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, 0x3E10, 0x3F10, 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510,
  276. 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, 0x4E10, 0x4F10, 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510,
  277. 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, 0x5E10, 0x5F10, 0x6010, 0x6110, 0x6210, 0x6310, 0x6410, 0x6510,
  278. 0x6610, 0x6710, 0x6810, 0x6910, 0x6A10, 0x6B10, 0x6C10, 0x6D10, 0x6E10, 0x6F10, 0x7010, 0x7110, 0x7210, 0x7310, 0x7410, 0x7510,
  279. 0x7610, 0x7710, 0x7810, 0x7910, 0x7A10, 0x7B10, 0x7C10, 0x7D10, 0x7E10, 0x7F10, 0x8010, 0x8110, 0x8210, 0x8310, 0x8410, 0x8510,
  280. 0x8610, 0x8710, 0x8810, 0x8910, 0x8A10, 0x8B10, 0x8C10, 0x8D10, 0x8E10, 0x8F10, 0x9010, 0x9110, 0x9210, 0x9310, 0x9410, 0x9510,
  281. 0x9610, 0x9710, 0x9810, 0x9910, 0x9A10, 0x9B10, 0x9C10, 0x9D10, 0x9E10, 0x9F10, 0xA010, 0xA110, 0xA210, 0xA310, 0xA410, 0xA510,
  282. 0xA610, 0xA710, 0xA810, 0xA910, 0xAA10, 0xAB10, 0xAC10, 0xAD10, 0xAE10, 0xAF10, 0xB010, 0xB110, 0xB210, 0xB310, 0xB410, 0xB510,
  283. 0xB610, 0xB710, 0xB810, 0xB910, 0xBA10, 0xBB10, 0xBC10, 0xBD10, 0xBE10, 0xBF10, 0xC010, 0xC110, 0xC210, 0xC310, 0xC410, 0xC510,
  284. 0xC610, 0xC710, 0xC810, 0xC910, 0xCA10, 0xCB10, 0xCC10, 0xCD10, 0xCE10, 0xCF10, 0xD010, 0xD110, 0xD210, 0xD310, 0xD410, 0xD510,
  285. 0xD610, 0xD710, 0xD810, 0xD910, 0xDA10, 0xDB10, 0xDC10, 0xDD10, 0xDE10, 0xDF10, 0xE010, 0xE110, 0xE210, 0xE310, 0xE410, 0xE510,
  286. 0xE610, 0xE710, 0xE810, 0xE910, 0xEA10, 0xEB10, 0xEC10, 0xED10, 0xEE10, 0xEF10, 0xF010, 0xF110, 0xF210, 0xF310, 0xF410, 0xF510,
  287. 0xF610, 0xF710, 0xF810, 0xF910, 0xFA10, 0xFB10, 0xFC10, 0xFD10, 0xFE10, 0xFF10, 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510,
  288. 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, 0x0E10, 0x0F10, 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510,
  289. 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, 0x1E10, 0x1F10, 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510,
  290. 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, 0x2E10, 0x2F10, 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510,
  291. 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, 0x3E10, 0x3F10, 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510,
  292. 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, 0x4E10, 0x4F10, 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510,
  293. 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, 0x5E10, 0x5F10, 0x6010, 0x6110, 0x6210, 0x6310, 0x6410, 0x6510,
  294. 0x00C0, 0x0140, 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940, 0x0A40, 0x0B40, 0x0C40, 0x0D40, 0x0E40, 0x0F40,
  295. 0x1040, 0x1140, 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940, 0x1A40, 0x1B40, 0x1C40, 0x1D40, 0x1E40, 0x1F40,
  296. 0x2040, 0x2140, 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940, 0x2A40, 0x2B40, 0x2C40, 0x2D40, 0x2E40, 0x2F40,
  297. 0x3040, 0x3140, 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940, 0x3A40, 0x3B40, 0x3C40, 0x3D40, 0x3E40, 0x3F40,
  298. 0x4040, 0x4140, 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940, 0x4A40, 0x4B40, 0x4C40, 0x4D40, 0x4E40, 0x4F40,
  299. 0x5040, 0x5140, 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940, 0x5A40, 0x5B40, 0x5C40, 0x5D40, 0x5E40, 0x5F40,
  300. 0x6040, 0x6140, 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940, 0x6A40, 0x6B40, 0x6C40, 0x6D40, 0x6E40, 0x6F40,
  301. 0x7040, 0x7140, 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940, 0x7A40, 0x7B40, 0x7C40, 0x7D40, 0x7E40, 0x7F40,
  302. 0x8040, 0x8140, 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940, 0x8A40, 0x8B40, 0x8C40, 0x8D40, 0x8E40, 0x8F40,
  303. 0x9040, 0x9140, 0x9240, 0x9340, 0x9440, 0x9540, 0x9640, 0x9740, 0x9840, 0x9940, 0x9A40, 0x9B40, 0x9C40, 0x9D40, 0x9E40, 0x9F40,
  304. 0xA040, 0xA140, 0xA240, 0xA340, 0xA440, 0xA540, 0xA640, 0xA740, 0xA840, 0xA940, 0xAA40, 0xAB40, 0xAC40, 0xAD40, 0xAE40, 0xAF40,
  305. 0xB040, 0xB140, 0xB240, 0xB340, 0xB440, 0xB540, 0xB640, 0xB740, 0xB840, 0xB940, 0xBA40, 0xBB40, 0xBC40, 0xBD40, 0xBE40, 0xBF40,
  306. 0xC040, 0xC140, 0xC240, 0xC340, 0xC440, 0xC540, 0xC640, 0xC740, 0xC840, 0xC940, 0xCA40, 0xCB40, 0xCC40, 0xCD40, 0xCE40, 0xCF40,
  307. 0xD040, 0xD140, 0xD240, 0xD340, 0xD440, 0xD540, 0xD640, 0xD740, 0xD840, 0xD940, 0xDA40, 0xDB40, 0xDC40, 0xDD40, 0xDE40, 0xDF40,
  308. 0xE040, 0xE140, 0xE240, 0xE340, 0xE440, 0xE540, 0xE640, 0xE740, 0xE840, 0xE940, 0xEA40, 0xEB40, 0xEC40, 0xED40, 0xEE40, 0xEF40,
  309. 0xF040, 0xF140, 0xF240, 0xF340, 0xF440, 0xF540, 0xF640, 0xF740, 0xF840, 0xF940, 0xFA40, 0xFB40, 0xFC40, 0xFD40, 0xFE40, 0xFF40,
  310. 0xA050, 0xA150, 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950, 0xAA50, 0xAB50, 0xAC50, 0xAD50, 0xAE50, 0xAF50,
  311. 0xB050, 0xB150, 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950, 0xBA50, 0xBB50, 0xBC50, 0xBD50, 0xBE50, 0xBF50,
  312. 0xC050, 0xC150, 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950, 0xCA50, 0xCB50, 0xCC50, 0xCD50, 0xCE50, 0xCF50,
  313. 0xD050, 0xD150, 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950, 0xDA50, 0xDB50, 0xDC50, 0xDD50, 0xDE50, 0xDF50,
  314. 0xE050, 0xE150, 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950, 0xEA50, 0xEB50, 0xEC50, 0xED50, 0xEE50, 0xEF50,
  315. 0xF050, 0xF150, 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950, 0xFA50, 0xFB50, 0xFC50, 0xFD50, 0xFE50, 0xFF50,
  316. 0x00D0, 0x0150, 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950, 0x0A50, 0x0B50, 0x0C50, 0x0D50, 0x0E50, 0x0F50,
  317. 0x1050, 0x1150, 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950, 0x1A50, 0x1B50, 0x1C50, 0x1D50, 0x1E50, 0x1F50,
  318. 0x2050, 0x2150, 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950, 0x2A50, 0x2B50, 0x2C50, 0x2D50, 0x2E50, 0x2F50,
  319. 0x3050, 0x3150, 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, 0x3A50, 0x3B50, 0x3C50, 0x3D50, 0x3E50, 0x3F50,
  320. 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, 0x4A50, 0x4B50, 0x4C50, 0x4D50, 0x4E50, 0x4F50,
  321. 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, 0x5A50, 0x5B50, 0x5C50, 0x5D50, 0x5E50, 0x5F50,
  322. 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, 0x6A50, 0x6B50, 0x6C50, 0x6D50, 0x6E50, 0x6F50,
  323. 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, 0x7A50, 0x7B50, 0x7C50, 0x7D50, 0x7E50, 0x7F50,
  324. 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, 0x8A50, 0x8B50, 0x8C50, 0x8D50, 0x8E50, 0x8F50,
  325. 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, 0x9A50, 0x9B50, 0x9C50, 0x9D50, 0x9E50, 0x9F50,
  326. 0xFA40, 0xFB40, 0xFC40, 0xFD40, 0xFE40, 0xFF40, 0x00C0, 0x0140, 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940,
  327. 0x0A40, 0x0B40, 0x0C40, 0x0D40, 0x0E40, 0x0F40, 0x1040, 0x1140, 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940,
  328. 0x1A40, 0x1B40, 0x1C40, 0x1D40, 0x1E40, 0x1F40, 0x2040, 0x2140, 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940,
  329. 0x2A40, 0x2B40, 0x2C40, 0x2D40, 0x2E40, 0x2F40, 0x3040, 0x3140, 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940,
  330. 0x3A40, 0x3B40, 0x3C40, 0x3D40, 0x3E40, 0x3F40, 0x4040, 0x4140, 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940,
  331. 0x4A40, 0x4B40, 0x4C40, 0x4D40, 0x4E40, 0x4F40, 0x5040, 0x5140, 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940,
  332. 0x5A40, 0x5B40, 0x5C40, 0x5D40, 0x5E40, 0x5F40, 0x6040, 0x6140, 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940,
  333. 0x6A40, 0x6B40, 0x6C40, 0x6D40, 0x6E40, 0x6F40, 0x7040, 0x7140, 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940,
  334. 0x7A40, 0x7B40, 0x7C40, 0x7D40, 0x7E40, 0x7F40, 0x8040, 0x8140, 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940,
  335. 0x8A40, 0x8B40, 0x8C40, 0x8D40, 0x8E40, 0x8F40, 0x9040, 0x9140, 0x9240, 0x9340, 0x9440, 0x9540, 0x9640, 0x9740, 0x9840, 0x9940,
  336. 0x9A40, 0x9B40, 0x9C40, 0x9D40, 0x9E40, 0x9F40, 0xA040, 0xA140, 0xA240, 0xA340, 0xA440, 0xA540, 0xA640, 0xA740, 0xA840, 0xA940,
  337. 0xAA40, 0xAB40, 0xAC40, 0xAD40, 0xAE40, 0xAF40, 0xB040, 0xB140, 0xB240, 0xB340, 0xB440, 0xB540, 0xB640, 0xB740, 0xB840, 0xB940,
  338. 0xBA40, 0xBB40, 0xBC40, 0xBD40, 0xBE40, 0xBF40, 0xC040, 0xC140, 0xC240, 0xC340, 0xC440, 0xC540, 0xC640, 0xC740, 0xC840, 0xC940,
  339. 0xCA40, 0xCB40, 0xCC40, 0xCD40, 0xCE40, 0xCF40, 0xD040, 0xD140, 0xD240, 0xD340, 0xD440, 0xD540, 0xD640, 0xD740, 0xD840, 0xD940,
  340. 0xDA40, 0xDB40, 0xDC40, 0xDD40, 0xDE40, 0xDF40, 0xE040, 0xE140, 0xE240, 0xE340, 0xE440, 0xE540, 0xE640, 0xE740, 0xE840, 0xE940,
  341. 0xEA40, 0xEB40, 0xEC40, 0xED40, 0xEE40, 0xEF40, 0xF040, 0xF140, 0xF240, 0xF340, 0xF440, 0xF540, 0xF640, 0xF740, 0xF840, 0xF940,
  342. 0x9A50, 0x9B50, 0x9C50, 0x9D50, 0x9E50, 0x9F50, 0xA050, 0xA150, 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950,
  343. 0xAA50, 0xAB50, 0xAC50, 0xAD50, 0xAE50, 0xAF50, 0xB050, 0xB150, 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950,
  344. 0xBA50, 0xBB50, 0xBC50, 0xBD50, 0xBE50, 0xBF50, 0xC050, 0xC150, 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950,
  345. 0xCA50, 0xCB50, 0xCC50, 0xCD50, 0xCE50, 0xCF50, 0xD050, 0xD150, 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950,
  346. 0xDA50, 0xDB50, 0xDC50, 0xDD50, 0xDE50, 0xDF50, 0xE050, 0xE150, 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950,
  347. 0xEA50, 0xEB50, 0xEC50, 0xED50, 0xEE50, 0xEF50, 0xF050, 0xF150, 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950,
  348. 0xFA50, 0xFB50, 0xFC50, 0xFD50, 0xFE50, 0xFF50, 0x00D0, 0x0150, 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950,
  349. 0x0A50, 0x0B50, 0x0C50, 0x0D50, 0x0E50, 0x0F50, 0x1050, 0x1150, 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950,
  350. 0x1A50, 0x1B50, 0x1C50, 0x1D50, 0x1E50, 0x1F50, 0x2050, 0x2150, 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950,
  351. 0x2A50, 0x2B50, 0x2C50, 0x2D50, 0x2E50, 0x2F50, 0x3050, 0x3150, 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950,
  352. 0x3A50, 0x3B50, 0x3C50, 0x3D50, 0x3E50, 0x3F50, 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950,
  353. 0x4A50, 0x4B50, 0x4C50, 0x4D50, 0x4E50, 0x4F50, 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950,
  354. 0x5A50, 0x5B50, 0x5C50, 0x5D50, 0x5E50, 0x5F50, 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950,
  355. 0x6A50, 0x6B50, 0x6C50, 0x6D50, 0x6E50, 0x6F50, 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950,
  356. 0x7A50, 0x7B50, 0x7C50, 0x7D50, 0x7E50, 0x7F50, 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950,
  357. 0x8A50, 0x8B50, 0x8C50, 0x8D50, 0x8E50, 0x8F50, 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950
  358. );
  359. GameBoyCore.prototype.GBCBOOTROM = new Array( //GBC BOOT ROM (Thanks to Costis for the binary dump that I converted to this):
  360. //This way of loading in the BOOT ROM reminds me of when people had to punchcard the data in. :P
  361. 0x31, 0xfe, 0xff, 0x3e, 0x02, 0xc3, 0x7c, 0x00, 0xd3, 0x00, 0x98, 0xa0, 0x12, 0xd3, 0x00, 0x80,
  362. 0x00, 0x40, 0x1e, 0x53, 0xd0, 0x00, 0x1f, 0x42, 0x1c, 0x00, 0x14, 0x2a, 0x4d, 0x19, 0x8c, 0x7e,
  363. 0x00, 0x7c, 0x31, 0x6e, 0x4a, 0x45, 0x52, 0x4a, 0x00, 0x00, 0xff, 0x53, 0x1f, 0x7c, 0xff, 0x03,
  364. 0x1f, 0x00, 0xff, 0x1f, 0xa7, 0x00, 0xef, 0x1b, 0x1f, 0x00, 0xef, 0x1b, 0x00, 0x7c, 0x00, 0x00,
  365. 0xff, 0x03, 0xce, 0xed, 0x66, 0x66, 0xcc, 0x0d, 0x00, 0x0b, 0x03, 0x73, 0x00, 0x83, 0x00, 0x0c,
  366. 0x00, 0x0d, 0x00, 0x08, 0x11, 0x1f, 0x88, 0x89, 0x00, 0x0e, 0xdc, 0xcc, 0x6e, 0xe6, 0xdd, 0xdd,
  367. 0xd9, 0x99, 0xbb, 0xbb, 0x67, 0x63, 0x6e, 0x0e, 0xec, 0xcc, 0xdd, 0xdc, 0x99, 0x9f, 0xbb, 0xb9,
  368. 0x33, 0x3e, 0x3c, 0x42, 0xb9, 0xa5, 0xb9, 0xa5, 0x42, 0x3c, 0x58, 0x43, 0xe0, 0x70, 0x3e, 0xfc,
  369. 0xe0, 0x47, 0xcd, 0x75, 0x02, 0xcd, 0x00, 0x02, 0x26, 0xd0, 0xcd, 0x03, 0x02, 0x21, 0x00, 0xfe,
  370. 0x0e, 0xa0, 0xaf, 0x22, 0x0d, 0x20, 0xfc, 0x11, 0x04, 0x01, 0x21, 0x10, 0x80, 0x4c, 0x1a, 0xe2,
  371. 0x0c, 0xcd, 0xc6, 0x03, 0xcd, 0xc7, 0x03, 0x13, 0x7b, 0xfe, 0x34, 0x20, 0xf1, 0x11, 0x72, 0x00,
  372. 0x06, 0x08, 0x1a, 0x13, 0x22, 0x23, 0x05, 0x20, 0xf9, 0xcd, 0xf0, 0x03, 0x3e, 0x01, 0xe0, 0x4f,
  373. 0x3e, 0x91, 0xe0, 0x40, 0x21, 0xb2, 0x98, 0x06, 0x4e, 0x0e, 0x44, 0xcd, 0x91, 0x02, 0xaf, 0xe0,
  374. 0x4f, 0x0e, 0x80, 0x21, 0x42, 0x00, 0x06, 0x18, 0xf2, 0x0c, 0xbe, 0x20, 0xfe, 0x23, 0x05, 0x20,
  375. 0xf7, 0x21, 0x34, 0x01, 0x06, 0x19, 0x78, 0x86, 0x2c, 0x05, 0x20, 0xfb, 0x86, 0x20, 0xfe, 0xcd,
  376. 0x1c, 0x03, 0x18, 0x02, 0x00, 0x00, 0xcd, 0xd0, 0x05, 0xaf, 0xe0, 0x70, 0x3e, 0x11, 0xe0, 0x50,
  377. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  378. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  379. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  380. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  381. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  382. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  383. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  384. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  385. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  386. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  387. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  388. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  389. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  390. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  391. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  392. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  393. 0x21, 0x00, 0x80, 0xaf, 0x22, 0xcb, 0x6c, 0x28, 0xfb, 0xc9, 0x2a, 0x12, 0x13, 0x0d, 0x20, 0xfa,
  394. 0xc9, 0xe5, 0x21, 0x0f, 0xff, 0xcb, 0x86, 0xcb, 0x46, 0x28, 0xfc, 0xe1, 0xc9, 0x11, 0x00, 0xff,
  395. 0x21, 0x03, 0xd0, 0x0e, 0x0f, 0x3e, 0x30, 0x12, 0x3e, 0x20, 0x12, 0x1a, 0x2f, 0xa1, 0xcb, 0x37,
  396. 0x47, 0x3e, 0x10, 0x12, 0x1a, 0x2f, 0xa1, 0xb0, 0x4f, 0x7e, 0xa9, 0xe6, 0xf0, 0x47, 0x2a, 0xa9,
  397. 0xa1, 0xb0, 0x32, 0x47, 0x79, 0x77, 0x3e, 0x30, 0x12, 0xc9, 0x3e, 0x80, 0xe0, 0x68, 0xe0, 0x6a,
  398. 0x0e, 0x6b, 0x2a, 0xe2, 0x05, 0x20, 0xfb, 0x4a, 0x09, 0x43, 0x0e, 0x69, 0x2a, 0xe2, 0x05, 0x20,
  399. 0xfb, 0xc9, 0xc5, 0xd5, 0xe5, 0x21, 0x00, 0xd8, 0x06, 0x01, 0x16, 0x3f, 0x1e, 0x40, 0xcd, 0x4a,
  400. 0x02, 0xe1, 0xd1, 0xc1, 0xc9, 0x3e, 0x80, 0xe0, 0x26, 0xe0, 0x11, 0x3e, 0xf3, 0xe0, 0x12, 0xe0,
  401. 0x25, 0x3e, 0x77, 0xe0, 0x24, 0x21, 0x30, 0xff, 0xaf, 0x0e, 0x10, 0x22, 0x2f, 0x0d, 0x20, 0xfb,
  402. 0xc9, 0xcd, 0x11, 0x02, 0xcd, 0x62, 0x02, 0x79, 0xfe, 0x38, 0x20, 0x14, 0xe5, 0xaf, 0xe0, 0x4f,
  403. 0x21, 0xa7, 0x99, 0x3e, 0x38, 0x22, 0x3c, 0xfe, 0x3f, 0x20, 0xfa, 0x3e, 0x01, 0xe0, 0x4f, 0xe1,
  404. 0xc5, 0xe5, 0x21, 0x43, 0x01, 0xcb, 0x7e, 0xcc, 0x89, 0x05, 0xe1, 0xc1, 0xcd, 0x11, 0x02, 0x79,
  405. 0xd6, 0x30, 0xd2, 0x06, 0x03, 0x79, 0xfe, 0x01, 0xca, 0x06, 0x03, 0x7d, 0xfe, 0xd1, 0x28, 0x21,
  406. 0xc5, 0x06, 0x03, 0x0e, 0x01, 0x16, 0x03, 0x7e, 0xe6, 0xf8, 0xb1, 0x22, 0x15, 0x20, 0xf8, 0x0c,
  407. 0x79, 0xfe, 0x06, 0x20, 0xf0, 0x11, 0x11, 0x00, 0x19, 0x05, 0x20, 0xe7, 0x11, 0xa1, 0xff, 0x19,
  408. 0xc1, 0x04, 0x78, 0x1e, 0x83, 0xfe, 0x62, 0x28, 0x06, 0x1e, 0xc1, 0xfe, 0x64, 0x20, 0x07, 0x7b,
  409. 0xe0, 0x13, 0x3e, 0x87, 0xe0, 0x14, 0xfa, 0x02, 0xd0, 0xfe, 0x00, 0x28, 0x0a, 0x3d, 0xea, 0x02,
  410. 0xd0, 0x79, 0xfe, 0x01, 0xca, 0x91, 0x02, 0x0d, 0xc2, 0x91, 0x02, 0xc9, 0x0e, 0x26, 0xcd, 0x4a,
  411. 0x03, 0xcd, 0x11, 0x02, 0xcd, 0x62, 0x02, 0x0d, 0x20, 0xf4, 0xcd, 0x11, 0x02, 0x3e, 0x01, 0xe0,
  412. 0x4f, 0xcd, 0x3e, 0x03, 0xcd, 0x41, 0x03, 0xaf, 0xe0, 0x4f, 0xcd, 0x3e, 0x03, 0xc9, 0x21, 0x08,
  413. 0x00, 0x11, 0x51, 0xff, 0x0e, 0x05, 0xcd, 0x0a, 0x02, 0xc9, 0xc5, 0xd5, 0xe5, 0x21, 0x40, 0xd8,
  414. 0x0e, 0x20, 0x7e, 0xe6, 0x1f, 0xfe, 0x1f, 0x28, 0x01, 0x3c, 0x57, 0x2a, 0x07, 0x07, 0x07, 0xe6,
  415. 0x07, 0x47, 0x3a, 0x07, 0x07, 0x07, 0xe6, 0x18, 0xb0, 0xfe, 0x1f, 0x28, 0x01, 0x3c, 0x0f, 0x0f,
  416. 0x0f, 0x47, 0xe6, 0xe0, 0xb2, 0x22, 0x78, 0xe6, 0x03, 0x5f, 0x7e, 0x0f, 0x0f, 0xe6, 0x1f, 0xfe,
  417. 0x1f, 0x28, 0x01, 0x3c, 0x07, 0x07, 0xb3, 0x22, 0x0d, 0x20, 0xc7, 0xe1, 0xd1, 0xc1, 0xc9, 0x0e,
  418. 0x00, 0x1a, 0xe6, 0xf0, 0xcb, 0x49, 0x28, 0x02, 0xcb, 0x37, 0x47, 0x23, 0x7e, 0xb0, 0x22, 0x1a,
  419. 0xe6, 0x0f, 0xcb, 0x49, 0x20, 0x02, 0xcb, 0x37, 0x47, 0x23, 0x7e, 0xb0, 0x22, 0x13, 0xcb, 0x41,
  420. 0x28, 0x0d, 0xd5, 0x11, 0xf8, 0xff, 0xcb, 0x49, 0x28, 0x03, 0x11, 0x08, 0x00, 0x19, 0xd1, 0x0c,
  421. 0x79, 0xfe, 0x18, 0x20, 0xcc, 0xc9, 0x47, 0xd5, 0x16, 0x04, 0x58, 0xcb, 0x10, 0x17, 0xcb, 0x13,
  422. 0x17, 0x15, 0x20, 0xf6, 0xd1, 0x22, 0x23, 0x22, 0x23, 0xc9, 0x3e, 0x19, 0xea, 0x10, 0x99, 0x21,
  423. 0x2f, 0x99, 0x0e, 0x0c, 0x3d, 0x28, 0x08, 0x32, 0x0d, 0x20, 0xf9, 0x2e, 0x0f, 0x18, 0xf3, 0xc9,
  424. 0x3e, 0x01, 0xe0, 0x4f, 0xcd, 0x00, 0x02, 0x11, 0x07, 0x06, 0x21, 0x80, 0x80, 0x0e, 0xc0, 0x1a,
  425. 0x22, 0x23, 0x22, 0x23, 0x13, 0x0d, 0x20, 0xf7, 0x11, 0x04, 0x01, 0xcd, 0x8f, 0x03, 0x01, 0xa8,
  426. 0xff, 0x09, 0xcd, 0x8f, 0x03, 0x01, 0xf8, 0xff, 0x09, 0x11, 0x72, 0x00, 0x0e, 0x08, 0x23, 0x1a,
  427. 0x22, 0x13, 0x0d, 0x20, 0xf9, 0x21, 0xc2, 0x98, 0x06, 0x08, 0x3e, 0x08, 0x0e, 0x10, 0x22, 0x0d,
  428. 0x20, 0xfc, 0x11, 0x10, 0x00, 0x19, 0x05, 0x20, 0xf3, 0xaf, 0xe0, 0x4f, 0x21, 0xc2, 0x98, 0x3e,
  429. 0x08, 0x22, 0x3c, 0xfe, 0x18, 0x20, 0x02, 0x2e, 0xe2, 0xfe, 0x28, 0x20, 0x03, 0x21, 0x02, 0x99,
  430. 0xfe, 0x38, 0x20, 0xed, 0x21, 0xd8, 0x08, 0x11, 0x40, 0xd8, 0x06, 0x08, 0x3e, 0xff, 0x12, 0x13,
  431. 0x12, 0x13, 0x0e, 0x02, 0xcd, 0x0a, 0x02, 0x3e, 0x00, 0x12, 0x13, 0x12, 0x13, 0x13, 0x13, 0x05,
  432. 0x20, 0xea, 0xcd, 0x62, 0x02, 0x21, 0x4b, 0x01, 0x7e, 0xfe, 0x33, 0x20, 0x0b, 0x2e, 0x44, 0x1e,
  433. 0x30, 0x2a, 0xbb, 0x20, 0x49, 0x1c, 0x18, 0x04, 0x2e, 0x4b, 0x1e, 0x01, 0x2a, 0xbb, 0x20, 0x3e,
  434. 0x2e, 0x34, 0x01, 0x10, 0x00, 0x2a, 0x80, 0x47, 0x0d, 0x20, 0xfa, 0xea, 0x00, 0xd0, 0x21, 0xc7,
  435. 0x06, 0x0e, 0x00, 0x2a, 0xb8, 0x28, 0x08, 0x0c, 0x79, 0xfe, 0x4f, 0x20, 0xf6, 0x18, 0x1f, 0x79,
  436. 0xd6, 0x41, 0x38, 0x1c, 0x21, 0x16, 0x07, 0x16, 0x00, 0x5f, 0x19, 0xfa, 0x37, 0x01, 0x57, 0x7e,
  437. 0xba, 0x28, 0x0d, 0x11, 0x0e, 0x00, 0x19, 0x79, 0x83, 0x4f, 0xd6, 0x5e, 0x38, 0xed, 0x0e, 0x00,
  438. 0x21, 0x33, 0x07, 0x06, 0x00, 0x09, 0x7e, 0xe6, 0x1f, 0xea, 0x08, 0xd0, 0x7e, 0xe6, 0xe0, 0x07,
  439. 0x07, 0x07, 0xea, 0x0b, 0xd0, 0xcd, 0xe9, 0x04, 0xc9, 0x11, 0x91, 0x07, 0x21, 0x00, 0xd9, 0xfa,
  440. 0x0b, 0xd0, 0x47, 0x0e, 0x1e, 0xcb, 0x40, 0x20, 0x02, 0x13, 0x13, 0x1a, 0x22, 0x20, 0x02, 0x1b,
  441. 0x1b, 0xcb, 0x48, 0x20, 0x02, 0x13, 0x13, 0x1a, 0x22, 0x13, 0x13, 0x20, 0x02, 0x1b, 0x1b, 0xcb,
  442. 0x50, 0x28, 0x05, 0x1b, 0x2b, 0x1a, 0x22, 0x13, 0x1a, 0x22, 0x13, 0x0d, 0x20, 0xd7, 0x21, 0x00,
  443. 0xd9, 0x11, 0x00, 0xda, 0xcd, 0x64, 0x05, 0xc9, 0x21, 0x12, 0x00, 0xfa, 0x05, 0xd0, 0x07, 0x07,
  444. 0x06, 0x00, 0x4f, 0x09, 0x11, 0x40, 0xd8, 0x06, 0x08, 0xe5, 0x0e, 0x02, 0xcd, 0x0a, 0x02, 0x13,
  445. 0x13, 0x13, 0x13, 0x13, 0x13, 0xe1, 0x05, 0x20, 0xf0, 0x11, 0x42, 0xd8, 0x0e, 0x02, 0xcd, 0x0a,
  446. 0x02, 0x11, 0x4a, 0xd8, 0x0e, 0x02, 0xcd, 0x0a, 0x02, 0x2b, 0x2b, 0x11, 0x44, 0xd8, 0x0e, 0x02,
  447. 0xcd, 0x0a, 0x02, 0xc9, 0x0e, 0x60, 0x2a, 0xe5, 0xc5, 0x21, 0xe8, 0x07, 0x06, 0x00, 0x4f, 0x09,
  448. 0x0e, 0x08, 0xcd, 0x0a, 0x02, 0xc1, 0xe1, 0x0d, 0x20, 0xec, 0xc9, 0xfa, 0x08, 0xd0, 0x11, 0x18,
  449. 0x00, 0x3c, 0x3d, 0x28, 0x03, 0x19, 0x20, 0xfa, 0xc9, 0xcd, 0x1d, 0x02, 0x78, 0xe6, 0xff, 0x28,
  450. 0x0f, 0x21, 0xe4, 0x08, 0x06, 0x00, 0x2a, 0xb9, 0x28, 0x08, 0x04, 0x78, 0xfe, 0x0c, 0x20, 0xf6,
  451. 0x18, 0x2d, 0x78, 0xea, 0x05, 0xd0, 0x3e, 0x1e, 0xea, 0x02, 0xd0, 0x11, 0x0b, 0x00, 0x19, 0x56,
  452. 0x7a, 0xe6, 0x1f, 0x5f, 0x21, 0x08, 0xd0, 0x3a, 0x22, 0x7b, 0x77, 0x7a, 0xe6, 0xe0, 0x07, 0x07,
  453. 0x07, 0x5f, 0x21, 0x0b, 0xd0, 0x3a, 0x22, 0x7b, 0x77, 0xcd, 0xe9, 0x04, 0xcd, 0x28, 0x05, 0xc9,
  454. 0xcd, 0x11, 0x02, 0xfa, 0x43, 0x01, 0xcb, 0x7f, 0x28, 0x04, 0xe0, 0x4c, 0x18, 0x28, 0x3e, 0x04,
  455. 0xe0, 0x4c, 0x3e, 0x01, 0xe0, 0x6c, 0x21, 0x00, 0xda, 0xcd, 0x7b, 0x05, 0x06, 0x10, 0x16, 0x00,
  456. 0x1e, 0x08, 0xcd, 0x4a, 0x02, 0x21, 0x7a, 0x00, 0xfa, 0x00, 0xd0, 0x47, 0x0e, 0x02, 0x2a, 0xb8,
  457. 0xcc, 0xda, 0x03, 0x0d, 0x20, 0xf8, 0xc9, 0x01, 0x0f, 0x3f, 0x7e, 0xff, 0xff, 0xc0, 0x00, 0xc0,
  458. 0xf0, 0xf1, 0x03, 0x7c, 0xfc, 0xfe, 0xfe, 0x03, 0x07, 0x07, 0x0f, 0xe0, 0xe0, 0xf0, 0xf0, 0x1e,
  459. 0x3e, 0x7e, 0xfe, 0x0f, 0x0f, 0x1f, 0x1f, 0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0xff,
  460. 0xff, 0xe1, 0xe0, 0xc0, 0xf0, 0xf9, 0xfb, 0x1f, 0x7f, 0xf8, 0xe0, 0xf3, 0xfd, 0x3e, 0x1e, 0xe0,
  461. 0xf0, 0xf9, 0x7f, 0x3e, 0x7c, 0xf8, 0xe0, 0xf8, 0xf0, 0xf0, 0xf8, 0x00, 0x00, 0x7f, 0x7f, 0x07,
  462. 0x0f, 0x9f, 0xbf, 0x9e, 0x1f, 0xff, 0xff, 0x0f, 0x1e, 0x3e, 0x3c, 0xf1, 0xfb, 0x7f, 0x7f, 0xfe,
  463. 0xde, 0xdf, 0x9f, 0x1f, 0x3f, 0x3e, 0x3c, 0xf8, 0xf8, 0x00, 0x00, 0x03, 0x03, 0x07, 0x07, 0xff,
  464. 0xff, 0xc1, 0xc0, 0xf3, 0xe7, 0xf7, 0xf3, 0xc0, 0xc0, 0xc0, 0xc0, 0x1f, 0x1f, 0x1e, 0x3e, 0x3f,
  465. 0x1f, 0x3e, 0x3e, 0x80, 0x00, 0x00, 0x00, 0x7c, 0x1f, 0x07, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x7c,
  466. 0xf8, 0xf0, 0x00, 0x1f, 0x0f, 0x0f, 0x00, 0x7c, 0xf8, 0xf8, 0x00, 0x3f, 0x3e, 0x1c, 0x00, 0x0f,
  467. 0x0f, 0x0f, 0x00, 0x7c, 0xff, 0xff, 0x00, 0x00, 0xf8, 0xf8, 0x00, 0x07, 0x0f, 0x0f, 0x00, 0x81,
  468. 0xff, 0xff, 0x00, 0xf3, 0xe1, 0x80, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0xfc, 0xf0, 0xc0, 0x00, 0x3e,
  469. 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x16, 0x36, 0xd1, 0xdb, 0xf2, 0x3c, 0x8c,
  470. 0x92, 0x3d, 0x5c, 0x58, 0xc9, 0x3e, 0x70, 0x1d, 0x59, 0x69, 0x19, 0x35, 0xa8, 0x14, 0xaa, 0x75,
  471. 0x95, 0x99, 0x34, 0x6f, 0x15, 0xff, 0x97, 0x4b, 0x90, 0x17, 0x10, 0x39, 0xf7, 0xf6, 0xa2, 0x49,
  472. 0x4e, 0x43, 0x68, 0xe0, 0x8b, 0xf0, 0xce, 0x0c, 0x29, 0xe8, 0xb7, 0x86, 0x9a, 0x52, 0x01, 0x9d,
  473. 0x71, 0x9c, 0xbd, 0x5d, 0x6d, 0x67, 0x3f, 0x6b, 0xb3, 0x46, 0x28, 0xa5, 0xc6, 0xd3, 0x27, 0x61,
  474. 0x18, 0x66, 0x6a, 0xbf, 0x0d, 0xf4, 0x42, 0x45, 0x46, 0x41, 0x41, 0x52, 0x42, 0x45, 0x4b, 0x45,
  475. 0x4b, 0x20, 0x52, 0x2d, 0x55, 0x52, 0x41, 0x52, 0x20, 0x49, 0x4e, 0x41, 0x49, 0x4c, 0x49, 0x43,
  476. 0x45, 0x20, 0x52, 0x7c, 0x08, 0x12, 0xa3, 0xa2, 0x07, 0x87, 0x4b, 0x20, 0x12, 0x65, 0xa8, 0x16,
  477. 0xa9, 0x86, 0xb1, 0x68, 0xa0, 0x87, 0x66, 0x12, 0xa1, 0x30, 0x3c, 0x12, 0x85, 0x12, 0x64, 0x1b,
  478. 0x07, 0x06, 0x6f, 0x6e, 0x6e, 0xae, 0xaf, 0x6f, 0xb2, 0xaf, 0xb2, 0xa8, 0xab, 0x6f, 0xaf, 0x86,
  479. 0xae, 0xa2, 0xa2, 0x12, 0xaf, 0x13, 0x12, 0xa1, 0x6e, 0xaf, 0xaf, 0xad, 0x06, 0x4c, 0x6e, 0xaf,
  480. 0xaf, 0x12, 0x7c, 0xac, 0xa8, 0x6a, 0x6e, 0x13, 0xa0, 0x2d, 0xa8, 0x2b, 0xac, 0x64, 0xac, 0x6d,
  481. 0x87, 0xbc, 0x60, 0xb4, 0x13, 0x72, 0x7c, 0xb5, 0xae, 0xae, 0x7c, 0x7c, 0x65, 0xa2, 0x6c, 0x64,
  482. 0x85, 0x80, 0xb0, 0x40, 0x88, 0x20, 0x68, 0xde, 0x00, 0x70, 0xde, 0x20, 0x78, 0x20, 0x20, 0x38,
  483. 0x20, 0xb0, 0x90, 0x20, 0xb0, 0xa0, 0xe0, 0xb0, 0xc0, 0x98, 0xb6, 0x48, 0x80, 0xe0, 0x50, 0x1e,
  484. 0x1e, 0x58, 0x20, 0xb8, 0xe0, 0x88, 0xb0, 0x10, 0x20, 0x00, 0x10, 0x20, 0xe0, 0x18, 0xe0, 0x18,
  485. 0x00, 0x18, 0xe0, 0x20, 0xa8, 0xe0, 0x20, 0x18, 0xe0, 0x00, 0x20, 0x18, 0xd8, 0xc8, 0x18, 0xe0,
  486. 0x00, 0xe0, 0x40, 0x28, 0x28, 0x28, 0x18, 0xe0, 0x60, 0x20, 0x18, 0xe0, 0x00, 0x00, 0x08, 0xe0,
  487. 0x18, 0x30, 0xd0, 0xd0, 0xd0, 0x20, 0xe0, 0xe8, 0xff, 0x7f, 0xbf, 0x32, 0xd0, 0x00, 0x00, 0x00,
  488. 0x9f, 0x63, 0x79, 0x42, 0xb0, 0x15, 0xcb, 0x04, 0xff, 0x7f, 0x31, 0x6e, 0x4a, 0x45, 0x00, 0x00,
  489. 0xff, 0x7f, 0xef, 0x1b, 0x00, 0x02, 0x00, 0x00, 0xff, 0x7f, 0x1f, 0x42, 0xf2, 0x1c, 0x00, 0x00,
  490. 0xff, 0x7f, 0x94, 0x52, 0x4a, 0x29, 0x00, 0x00, 0xff, 0x7f, 0xff, 0x03, 0x2f, 0x01, 0x00, 0x00,
  491. 0xff, 0x7f, 0xef, 0x03, 0xd6, 0x01, 0x00, 0x00, 0xff, 0x7f, 0xb5, 0x42, 0xc8, 0x3d, 0x00, 0x00,
  492. 0x74, 0x7e, 0xff, 0x03, 0x80, 0x01, 0x00, 0x00, 0xff, 0x67, 0xac, 0x77, 0x13, 0x1a, 0x6b, 0x2d,
  493. 0xd6, 0x7e, 0xff, 0x4b, 0x75, 0x21, 0x00, 0x00, 0xff, 0x53, 0x5f, 0x4a, 0x52, 0x7e, 0x00, 0x00,
  494. 0xff, 0x4f, 0xd2, 0x7e, 0x4c, 0x3a, 0xe0, 0x1c, 0xed, 0x03, 0xff, 0x7f, 0x5f, 0x25, 0x00, 0x00,
  495. 0x6a, 0x03, 0x1f, 0x02, 0xff, 0x03, 0xff, 0x7f, 0xff, 0x7f, 0xdf, 0x01, 0x12, 0x01, 0x00, 0x00,
  496. 0x1f, 0x23, 0x5f, 0x03, 0xf2, 0x00, 0x09, 0x00, 0xff, 0x7f, 0xea, 0x03, 0x1f, 0x01, 0x00, 0x00,
  497. 0x9f, 0x29, 0x1a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x7f, 0x02, 0x1f, 0x00, 0x00, 0x00,
  498. 0xff, 0x7f, 0xe0, 0x03, 0x06, 0x02, 0x20, 0x01, 0xff, 0x7f, 0xeb, 0x7e, 0x1f, 0x00, 0x00, 0x7c,
  499. 0xff, 0x7f, 0xff, 0x3f, 0x00, 0x7e, 0x1f, 0x00, 0xff, 0x7f, 0xff, 0x03, 0x1f, 0x00, 0x00, 0x00,
  500. 0xff, 0x03, 0x1f, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x3f, 0x03, 0x93, 0x01, 0x00, 0x00,
  501. 0x00, 0x00, 0x00, 0x42, 0x7f, 0x03, 0xff, 0x7f, 0xff, 0x7f, 0x8c, 0x7e, 0x00, 0x7c, 0x00, 0x00,
  502. 0xff, 0x7f, 0xef, 0x1b, 0x80, 0x61, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x7c, 0xe0, 0x03, 0x1f, 0x7c,
  503. 0x1f, 0x00, 0xff, 0x03, 0x40, 0x41, 0x42, 0x20, 0x21, 0x22, 0x80, 0x81, 0x82, 0x10, 0x11, 0x12,
  504. 0x12, 0xb0, 0x79, 0xb8, 0xad, 0x16, 0x17, 0x07, 0xba, 0x05, 0x7c, 0x13, 0x00, 0x00, 0x00, 0x00
  505. );
  506. GameBoyCore.prototype.ffxxDump = new Array( //Dump of the post-BOOT I/O register state (From gambatte):
  507. 0x0F, 0x00, 0x7C, 0xFF, 0x43, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
  508. 0x80, 0xBF, 0xF3, 0xFF, 0xBF, 0xFF, 0x3F, 0x00, 0xFF, 0xBF, 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, 0xFF,
  509. 0xFF, 0x00, 0x00, 0xBF, 0x77, 0xF3, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  510. 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  511. 0x91, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7E, 0xFF, 0xFE,
  512. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  513. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xC1, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
  514. 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  515. 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D,
  516. 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E, 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99,
  517. 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC, 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E,
  518. 0x45, 0xEC, 0x52, 0xFA, 0x08, 0xB7, 0x07, 0x5D, 0x01, 0xFD, 0xC0, 0xFF, 0x08, 0xFC, 0x00, 0xE5,
  519. 0x0B, 0xF8, 0xC2, 0xCE, 0xF4, 0xF9, 0x0F, 0x7F, 0x45, 0x6D, 0x3D, 0xFE, 0x46, 0x97, 0x33, 0x5E,
  520. 0x08, 0xEF, 0xF1, 0xFF, 0x86, 0x83, 0x24, 0x74, 0x12, 0xFC, 0x00, 0x9F, 0xB4, 0xB7, 0x06, 0xD5,
  521. 0xD0, 0x7A, 0x00, 0x9E, 0x04, 0x5F, 0x41, 0x2F, 0x1D, 0x77, 0x36, 0x75, 0x81, 0xAA, 0x70, 0x3A,
  522. 0x98, 0xD1, 0x71, 0x02, 0x4D, 0x01, 0xC1, 0xFF, 0x0D, 0x00, 0xD3, 0x05, 0xF9, 0x00, 0x0B, 0x00
  523. );
  524. GameBoyCore.prototype.OPCODE = new Array(
  525. //NOP
  526. //#0x00:
  527. function (parentObj) {
  528. //Do Nothing...
  529. },
  530. //LD BC, nn
  531. //#0x01:
  532. function (parentObj) {
  533. parentObj.registerC = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  534. parentObj.registerB = parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF);
  535. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  536. },
  537. //LD (BC), A
  538. //#0x02:
  539. function (parentObj) {
  540. parentObj.memoryWrite((parentObj.registerB << 8) | parentObj.registerC, parentObj.registerA);
  541. },
  542. //INC BC
  543. //#0x03:
  544. function (parentObj) {
  545. var temp_var = (((parentObj.registerB << 8) | parentObj.registerC) + 1);
  546. parentObj.registerB = ((temp_var >> 8) & 0xFF);
  547. parentObj.registerC = (temp_var & 0xFF);
  548. },
  549. //INC B
  550. //#0x04:
  551. function (parentObj) {
  552. parentObj.registerB = ((parentObj.registerB + 1) & 0xFF);
  553. parentObj.FZero = (parentObj.registerB == 0);
  554. parentObj.FHalfCarry = ((parentObj.registerB & 0xF) == 0);
  555. parentObj.FSubtract = false;
  556. },
  557. //DEC B
  558. //#0x05:
  559. function (parentObj) {
  560. parentObj.registerB = (parentObj.registerB - 1) & 0xFF;
  561. parentObj.FZero = (parentObj.registerB == 0);
  562. parentObj.FHalfCarry = ((parentObj.registerB & 0xF) == 0xF);
  563. parentObj.FSubtract = true;
  564. },
  565. //LD B, n
  566. //#0x06:
  567. function (parentObj) {
  568. parentObj.registerB = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  569. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  570. },
  571. //RLCA
  572. //#0x07:
  573. function (parentObj) {
  574. parentObj.FCarry = ((parentObj.registerA & 0x80) == 0x80);
  575. parentObj.registerA = ((parentObj.registerA << 1) & 0xFF) | (parentObj.registerA >> 7);
  576. parentObj.FZero = parentObj.FSubtract = parentObj.FHalfCarry = false;
  577. },
  578. //LD (nn), SP
  579. //#0x08:
  580. function (parentObj) {
  581. var temp_var = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  582. parentObj.memoryWrite(temp_var, parentObj.stackPointer & 0xFF);
  583. parentObj.memoryWrite((temp_var + 1) & 0xFFFF, parentObj.stackPointer >> 8);
  584. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  585. },
  586. //ADD HL, BC
  587. //#0x09:
  588. function (parentObj) {
  589. var n2 = (parentObj.registerB << 8) | parentObj.registerC;
  590. var dirtySum = parentObj.registersHL + n2;
  591. parentObj.FHalfCarry = ((parentObj.registersHL & 0xFFF) + (n2 & 0xFFF) > 0xFFF);
  592. parentObj.FCarry = (dirtySum > 0xFFFF);
  593. parentObj.registersHL = (dirtySum & 0xFFFF);
  594. parentObj.FSubtract = false;
  595. },
  596. //LD A, (BC)
  597. //#0x0A:
  598. function (parentObj) {
  599. parentObj.registerA = parentObj.memoryRead((parentObj.registerB << 8) | parentObj.registerC);
  600. },
  601. //DEC BC
  602. //#0x0B:
  603. function (parentObj) {
  604. var temp_var = (((parentObj.registerB << 8) | parentObj.registerC) - 1) & 0xFFFF;
  605. parentObj.registerB = (temp_var >> 8);
  606. parentObj.registerC = (temp_var & 0xFF);
  607. },
  608. //INC C
  609. //#0x0C:
  610. function (parentObj) {
  611. parentObj.registerC = ((parentObj.registerC + 1) & 0xFF);
  612. parentObj.FZero = (parentObj.registerC == 0);
  613. parentObj.FHalfCarry = ((parentObj.registerC & 0xF) == 0);
  614. parentObj.FSubtract = false;
  615. },
  616. //DEC C
  617. //#0x0D:
  618. function (parentObj) {
  619. parentObj.registerC = (parentObj.registerC - 1) & 0xFF;
  620. parentObj.FZero = (parentObj.registerC == 0);
  621. parentObj.FHalfCarry = ((parentObj.registerC & 0xF) == 0xF);
  622. parentObj.FSubtract = true;
  623. },
  624. //LD C, n
  625. //#0x0E:
  626. function (parentObj) {
  627. parentObj.registerC = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  628. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  629. },
  630. //RRCA
  631. //#0x0F:
  632. function (parentObj) {
  633. parentObj.FCarry = ((parentObj.registerA & 1) == 1);
  634. parentObj.registerA = (parentObj.registerA >> 1) | ((parentObj.registerA & 1) << 7);
  635. parentObj.FZero = parentObj.FSubtract = parentObj.FHalfCarry = false;
  636. },
  637. //STOP
  638. //#0x10:
  639. function (parentObj) {
  640. if (parentObj.cGBC) {
  641. /*TODO: Emulate the speed switch delay:
  642. Delay Amount:
  643. 16 ms when going to double-speed.
  644. 32 ms when going to single-speed.
  645. Also, bits 4 and 5 of 0xFF00 should read as set (1), while the switch is in process.
  646. */
  647. if ((parentObj.memory[0xFF4D] & 0x01) == 0x01) { //Speed change requested.
  648. if ((parentObj.memory[0xFF4D] & 0x80) == 0x80) { //Go back to single speed mode.
  649. cout("Going into single clock speed mode.", 0);
  650. parentObj.multiplier = 1; //TODO: Move this into the delay done code.
  651. parentObj.memory[0xFF4D] &= 0x7F; //Clear the double speed mode flag.
  652. }
  653. else { //Go to double speed mode.
  654. cout("Going into double clock speed mode.", 0);
  655. parentObj.multiplier = 2; //TODO: Move this into the delay done code.
  656. parentObj.memory[0xFF4D] |= 0x80; //Set the double speed mode flag.
  657. }
  658. parentObj.memory[0xFF4D] &= 0xFE; //Reset the request bit.
  659. }
  660. }
  661. },
  662. //LD DE, nn
  663. //#0x11:
  664. function (parentObj) {
  665. parentObj.registerE = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  666. parentObj.registerD = parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF);
  667. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  668. },
  669. //LD (DE), A
  670. //#0x12:
  671. function (parentObj) {
  672. parentObj.memoryWrite((parentObj.registerD << 8) | parentObj.registerE, parentObj.registerA);
  673. },
  674. //INC DE
  675. //#0x13:
  676. function (parentObj) {
  677. var temp_var = (((parentObj.registerD << 8) | parentObj.registerE) + 1);
  678. parentObj.registerD = ((temp_var >> 8) & 0xFF);
  679. parentObj.registerE = (temp_var & 0xFF);
  680. },
  681. //INC D
  682. //#0x14:
  683. function (parentObj) {
  684. parentObj.registerD = ((parentObj.registerD + 1) & 0xFF);
  685. parentObj.FZero = (parentObj.registerD == 0);
  686. parentObj.FHalfCarry = ((parentObj.registerD & 0xF) == 0);
  687. parentObj.FSubtract = false;
  688. },
  689. //DEC D
  690. //#0x15:
  691. function (parentObj) {
  692. parentObj.registerD = (parentObj.registerD - 1) & 0xFF;
  693. parentObj.FZero = (parentObj.registerD == 0);
  694. parentObj.FHalfCarry = ((parentObj.registerD & 0xF) == 0xF);
  695. parentObj.FSubtract = true;
  696. },
  697. //LD D, n
  698. //#0x16:
  699. function (parentObj) {
  700. parentObj.registerD = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  701. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  702. },
  703. //RLA
  704. //#0x17:
  705. function (parentObj) {
  706. var carry_flag = (parentObj.FCarry) ? 1 : 0;
  707. parentObj.FCarry = ((parentObj.registerA & 0x80) == 0x80);
  708. parentObj.registerA = ((parentObj.registerA << 1) & 0xFF) | carry_flag;
  709. parentObj.FZero = parentObj.FSubtract = parentObj.FHalfCarry = false;
  710. },
  711. //JR n
  712. //#0x18:
  713. function (parentObj) {
  714. parentObj.programCounter = (parentObj.programCounter + parentObj.usbtsb(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter)) + 1) & 0xFFFF;
  715. },
  716. //ADD HL, DE
  717. //#0x19:
  718. function (parentObj) {
  719. var n2 = (parentObj.registerD << 8) | parentObj.registerE;
  720. var dirtySum = parentObj.registersHL + n2;
  721. parentObj.FHalfCarry = ((parentObj.registersHL & 0xFFF) + (n2 & 0xFFF) > 0xFFF);
  722. parentObj.FCarry = (dirtySum > 0xFFFF);
  723. parentObj.registersHL = (dirtySum & 0xFFFF);
  724. parentObj.FSubtract = false;
  725. },
  726. //LD A, (DE)
  727. //#0x1A:
  728. function (parentObj) {
  729. parentObj.registerA = parentObj.memoryRead((parentObj.registerD << 8) | parentObj.registerE);
  730. },
  731. //DEC DE
  732. //#0x1B:
  733. function (parentObj) {
  734. var temp_var = (((parentObj.registerD << 8) | parentObj.registerE) - 1) & 0xFFFF;
  735. parentObj.registerD = (temp_var >> 8);
  736. parentObj.registerE = (temp_var & 0xFF);
  737. },
  738. //INC E
  739. //#0x1C:
  740. function (parentObj) {
  741. parentObj.registerE = ((parentObj.registerE + 1) & 0xFF);
  742. parentObj.FZero = (parentObj.registerE == 0);
  743. parentObj.FHalfCarry = ((parentObj.registerE & 0xF) == 0);
  744. parentObj.FSubtract = false;
  745. },
  746. //DEC E
  747. //#0x1D:
  748. function (parentObj) {
  749. parentObj.registerE = (parentObj.registerE - 1) & 0xFF;
  750. parentObj.FZero = (parentObj.registerE == 0);
  751. parentObj.FHalfCarry = ((parentObj.registerE & 0xF) == 0xF);
  752. parentObj.FSubtract = true;
  753. },
  754. //LD E, n
  755. //#0x1E:
  756. function (parentObj) {
  757. parentObj.registerE = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  758. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  759. },
  760. //RRA
  761. //#0x1F:
  762. function (parentObj) {
  763. var carry_flag = (parentObj.FCarry) ? 0x80 : 0;
  764. parentObj.FCarry = ((parentObj.registerA & 1) == 1);
  765. parentObj.registerA = (parentObj.registerA >> 1) + carry_flag;
  766. parentObj.FZero = parentObj.FSubtract = parentObj.FHalfCarry = false;
  767. },
  768. //JR NZ, n
  769. //#0x20:
  770. function (parentObj) {
  771. if (!parentObj.FZero) {
  772. parentObj.programCounter = (parentObj.programCounter + parentObj.usbtsb(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter)) + 1) & 0xFFFF;
  773. parentObj.CPUTicks++;
  774. }
  775. else {
  776. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  777. }
  778. },
  779. //LD HL, nn
  780. //#0x21:
  781. function (parentObj) {
  782. parentObj.registersHL = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  783. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  784. },
  785. //LDI (HL), A
  786. //#0x22:
  787. function (parentObj) {
  788. parentObj.memoryWrite(parentObj.registersHL, parentObj.registerA);
  789. parentObj.registersHL = ((parentObj.registersHL + 1) & 0xFFFF);
  790. },
  791. //INC HL
  792. //#0x23:
  793. function (parentObj) {
  794. parentObj.registersHL = ((parentObj.registersHL + 1) & 0xFFFF);
  795. },
  796. //INC H
  797. //#0x24:
  798. function (parentObj) {
  799. var H = (((parentObj.registersHL >> 8) + 1) & 0xFF);
  800. parentObj.FZero = (H == 0);
  801. parentObj.FHalfCarry = ((H & 0xF) == 0);
  802. parentObj.FSubtract = false;
  803. parentObj.registersHL = (H << 8) | (parentObj.registersHL & 0xFF);
  804. },
  805. //DEC H
  806. //#0x25:
  807. function (parentObj) {
  808. var H = ((parentObj.registersHL >> 8) - 1) & 0xFF;
  809. parentObj.FZero = (H == 0);
  810. parentObj.FHalfCarry = ((H & 0xF) == 0xF);
  811. parentObj.FSubtract = true;
  812. parentObj.registersHL = (H << 8) | (parentObj.registersHL & 0xFF);
  813. },
  814. //LD H, n
  815. //#0x26:
  816. function (parentObj) {
  817. parentObj.registersHL = (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << 8) | (parentObj.registersHL & 0xFF);
  818. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  819. },
  820. //DAA
  821. //#0x27:
  822. function (parentObj) {
  823. var temp_var = parentObj.registerA;
  824. if (parentObj.FCarry) {
  825. temp_var |= 0x100;
  826. }
  827. if (parentObj.FHalfCarry) {
  828. temp_var |= 0x200;
  829. }
  830. if (parentObj.FSubtract) {
  831. temp_var |= 0x400;
  832. }
  833. parentObj.registerA = (temp_var = parentObj.DAATable[temp_var]) >> 8;
  834. parentObj.FZero = ((temp_var & 0x80) == 0x80);
  835. parentObj.FSubtract = ((temp_var & 0x40) == 0x40);
  836. parentObj.FHalfCarry = ((temp_var & 0x20) == 0x20);
  837. parentObj.FCarry = ((temp_var & 0x10) == 0x10);
  838. },
  839. //JR Z, n
  840. //#0x28:
  841. function (parentObj) {
  842. if (parentObj.FZero) {
  843. parentObj.programCounter = (parentObj.programCounter + parentObj.usbtsb(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter)) + 1) & 0xFFFF;
  844. parentObj.CPUTicks++;
  845. }
  846. else {
  847. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  848. }
  849. },
  850. //ADD HL, HL
  851. //#0x29:
  852. function (parentObj) {;
  853. parentObj.FHalfCarry = ((parentObj.registersHL & 0xFFF) > 0x7FF);
  854. parentObj.FCarry = (parentObj.registersHL > 0x7FFF);
  855. parentObj.registersHL = ((2 * parentObj.registersHL) & 0xFFFF);
  856. parentObj.FSubtract = false;
  857. },
  858. //LDI A, (HL)
  859. //#0x2A:
  860. function (parentObj) {
  861. parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  862. parentObj.registersHL = ((parentObj.registersHL + 1) & 0xFFFF);
  863. },
  864. //DEC HL
  865. //#0x2B:
  866. function (parentObj) {
  867. parentObj.registersHL = (parentObj.registersHL - 1) & 0xFFFF;
  868. },
  869. //INC L
  870. //#0x2C:
  871. function (parentObj) {
  872. var L = ((parentObj.registersHL + 1) & 0xFF);
  873. parentObj.FZero = (L == 0);
  874. parentObj.FHalfCarry = ((L & 0xF) == 0);
  875. parentObj.FSubtract = false;
  876. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | L;
  877. },
  878. //DEC L
  879. //#0x2D:
  880. function (parentObj) {
  881. var L = ((parentObj.registersHL - 1) & 0xFF);
  882. parentObj.FZero = (L == 0);
  883. parentObj.FHalfCarry = ((L & 0xF) == 0xF);
  884. parentObj.FSubtract = true;
  885. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | L;
  886. },
  887. //LD L, n
  888. //#0x2E:
  889. function (parentObj) {
  890. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  891. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  892. },
  893. //CPL
  894. //#0x2F:
  895. function (parentObj) {
  896. parentObj.registerA ^= 0xFF;
  897. parentObj.FSubtract = parentObj.FHalfCarry = true;
  898. },
  899. //JR NC, n
  900. //#0x30:
  901. function (parentObj) {
  902. if (!parentObj.FCarry) {
  903. parentObj.programCounter = (parentObj.programCounter + parentObj.usbtsb(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter)) + 1) & 0xFFFF;
  904. parentObj.CPUTicks++;
  905. }
  906. else {
  907. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  908. }
  909. },
  910. //LD SP, nn
  911. //#0x31:
  912. function (parentObj) {
  913. parentObj.stackPointer = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  914. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  915. },
  916. //LDD (HL), A
  917. //#0x32:
  918. function (parentObj) {
  919. parentObj.memoryWrite(parentObj.registersHL, parentObj.registerA);
  920. parentObj.registersHL = (parentObj.registersHL - 1) & 0xFFFF;
  921. },
  922. //INC SP
  923. //#0x33:
  924. function (parentObj) {
  925. parentObj.stackPointer = (parentObj.stackPointer + 1) & 0xFFFF;
  926. },
  927. //INC (HL)
  928. //#0x34:
  929. function (parentObj) {
  930. var temp_var = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) + 1) & 0xFF);
  931. parentObj.FZero = (temp_var == 0);
  932. parentObj.FHalfCarry = ((temp_var & 0xF) == 0);
  933. parentObj.FSubtract = false;
  934. parentObj.memoryWrite(parentObj.registersHL, temp_var);
  935. },
  936. //DEC (HL)
  937. //#0x35:
  938. function (parentObj) {
  939. var temp_var = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) - 1) & 0xFF;
  940. parentObj.FZero = (temp_var == 0);
  941. parentObj.FHalfCarry = ((temp_var & 0xF) == 0xF);
  942. parentObj.FSubtract = true;
  943. parentObj.memoryWrite(parentObj.registersHL, temp_var);
  944. },
  945. //LD (HL), n
  946. //#0x36:
  947. function (parentObj) {
  948. parentObj.memoryWrite(parentObj.registersHL, parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
  949. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  950. },
  951. //SCF
  952. //#0x37:
  953. function (parentObj) {
  954. parentObj.FCarry = true;
  955. parentObj.FSubtract = parentObj.FHalfCarry = false;
  956. },
  957. //JR C, n
  958. //#0x38:
  959. function (parentObj) {
  960. if (parentObj.FCarry) {
  961. parentObj.programCounter = (parentObj.programCounter + parentObj.usbtsb(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter)) + 1) & 0xFFFF;
  962. parentObj.CPUTicks++;
  963. }
  964. else {
  965. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  966. }
  967. },
  968. //ADD HL, SP
  969. //#0x39:
  970. function (parentObj) {
  971. var dirtySum = parentObj.registersHL + parentObj.stackPointer;
  972. parentObj.FHalfCarry = ((parentObj.registersHL & 0xFFF) + (parentObj.stackPointer & 0xFFF) > 0xFFF);
  973. parentObj.FCarry = (dirtySum > 0xFFFF);
  974. parentObj.registersHL = (dirtySum & 0xFFFF);
  975. parentObj.FSubtract = false;
  976. },
  977. // LDD A, (HL)
  978. //#0x3A:
  979. function (parentObj) {
  980. parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  981. parentObj.registersHL = (parentObj.registersHL - 1) & 0xFFFF;
  982. },
  983. //DEC SP
  984. //#0x3B:
  985. function (parentObj) {
  986. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  987. },
  988. //INC A
  989. //#0x3C:
  990. function (parentObj) {
  991. parentObj.registerA = ((parentObj.registerA + 1) & 0xFF);
  992. parentObj.FZero = (parentObj.registerA == 0);
  993. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) == 0);
  994. parentObj.FSubtract = false;
  995. },
  996. //DEC A
  997. //#0x3D:
  998. function (parentObj) {
  999. parentObj.registerA = ((parentObj.registerA - 1) & 0xFF);
  1000. parentObj.FZero = (parentObj.registerA == 0);
  1001. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) == 0xF);
  1002. parentObj.FSubtract = true;
  1003. },
  1004. //LD A, n
  1005. //#0x3E:
  1006. function (parentObj) {
  1007. parentObj.registerA = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  1008. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  1009. },
  1010. //CCF
  1011. //#0x3F:
  1012. function (parentObj) {
  1013. parentObj.FCarry = !parentObj.FCarry;
  1014. parentObj.FSubtract = parentObj.FHalfCarry = false;
  1015. },
  1016. //LD B, B
  1017. //#0x40:
  1018. function (parentObj) {
  1019. //Do nothing...
  1020. },
  1021. //LD B, C
  1022. //#0x41:
  1023. function (parentObj) {
  1024. parentObj.registerB = parentObj.registerC;
  1025. },
  1026. //LD B, D
  1027. //#0x42:
  1028. function (parentObj) {
  1029. parentObj.registerB = parentObj.registerD;
  1030. },
  1031. //LD B, E
  1032. //#0x43:
  1033. function (parentObj) {
  1034. parentObj.registerB = parentObj.registerE;
  1035. },
  1036. //LD B, H
  1037. //#0x44:
  1038. function (parentObj) {
  1039. parentObj.registerB = (parentObj.registersHL >> 8);
  1040. },
  1041. //LD B, L
  1042. //#0x45:
  1043. function (parentObj) {
  1044. parentObj.registerB = (parentObj.registersHL & 0xFF);
  1045. },
  1046. //LD B, (HL)
  1047. //#0x46:
  1048. function (parentObj) {
  1049. parentObj.registerB = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1050. },
  1051. //LD B, A
  1052. //#0x47:
  1053. function (parentObj) {
  1054. parentObj.registerB = parentObj.registerA;
  1055. },
  1056. //LD C, B
  1057. //#0x48:
  1058. function (parentObj) {
  1059. parentObj.registerC = parentObj.registerB;
  1060. },
  1061. //LD C, C
  1062. //#0x49:
  1063. function (parentObj) {
  1064. //Do nothing...
  1065. },
  1066. //LD C, D
  1067. //#0x4A:
  1068. function (parentObj) {
  1069. parentObj.registerC = parentObj.registerD;
  1070. },
  1071. //LD C, E
  1072. //#0x4B:
  1073. function (parentObj) {
  1074. parentObj.registerC = parentObj.registerE;
  1075. },
  1076. //LD C, H
  1077. //#0x4C:
  1078. function (parentObj) {
  1079. parentObj.registerC = (parentObj.registersHL >> 8);
  1080. },
  1081. //LD C, L
  1082. //#0x4D:
  1083. function (parentObj) {
  1084. parentObj.registerC = (parentObj.registersHL & 0xFF);
  1085. },
  1086. //LD C, (HL)
  1087. //#0x4E:
  1088. function (parentObj) {
  1089. parentObj.registerC = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1090. },
  1091. //LD C, A
  1092. //#0x4F:
  1093. function (parentObj) {
  1094. parentObj.registerC = parentObj.registerA;
  1095. },
  1096. //LD D, B
  1097. //#0x50:
  1098. function (parentObj) {
  1099. parentObj.registerD = parentObj.registerB;
  1100. },
  1101. //LD D, C
  1102. //#0x51:
  1103. function (parentObj) {
  1104. parentObj.registerD = parentObj.registerC;
  1105. },
  1106. //LD D, D
  1107. //#0x52:
  1108. function (parentObj) {
  1109. //Do nothing...
  1110. },
  1111. //LD D, E
  1112. //#0x53:
  1113. function (parentObj) {
  1114. parentObj.registerD = parentObj.registerE;
  1115. },
  1116. //LD D, H
  1117. //#0x54:
  1118. function (parentObj) {
  1119. parentObj.registerD = (parentObj.registersHL >> 8);
  1120. },
  1121. //LD D, L
  1122. //#0x55:
  1123. function (parentObj) {
  1124. parentObj.registerD = (parentObj.registersHL & 0xFF);
  1125. },
  1126. //LD D, (HL)
  1127. //#0x56:
  1128. function (parentObj) {
  1129. parentObj.registerD = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1130. },
  1131. //LD D, A
  1132. //#0x57:
  1133. function (parentObj) {
  1134. parentObj.registerD = parentObj.registerA;
  1135. },
  1136. //LD E, B
  1137. //#0x58:
  1138. function (parentObj) {
  1139. parentObj.registerE = parentObj.registerB;
  1140. },
  1141. //LD E, C
  1142. //#0x59:
  1143. function (parentObj) {
  1144. parentObj.registerE = parentObj.registerC;
  1145. },
  1146. //LD E, D
  1147. //#0x5A:
  1148. function (parentObj) {
  1149. parentObj.registerE = parentObj.registerD;
  1150. },
  1151. //LD E, E
  1152. //#0x5B:
  1153. function (parentObj) {
  1154. //Do nothing...
  1155. },
  1156. //LD E, H
  1157. //#0x5C:
  1158. function (parentObj) {
  1159. parentObj.registerE = (parentObj.registersHL >> 8);
  1160. },
  1161. //LD E, L
  1162. //#0x5D:
  1163. function (parentObj) {
  1164. parentObj.registerE = (parentObj.registersHL & 0xFF);
  1165. },
  1166. //LD E, (HL)
  1167. //#0x5E:
  1168. function (parentObj) {
  1169. parentObj.registerE = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1170. },
  1171. //LD E, A
  1172. //#0x5F:
  1173. function (parentObj) {
  1174. parentObj.registerE = parentObj.registerA;
  1175. },
  1176. //LD H, B
  1177. //#0x60:
  1178. function (parentObj) {
  1179. parentObj.registersHL = (parentObj.registerB << 8) | (parentObj.registersHL & 0xFF);
  1180. },
  1181. //LD H, C
  1182. //#0x61:
  1183. function (parentObj) {
  1184. parentObj.registersHL = (parentObj.registerC << 8) | (parentObj.registersHL & 0xFF);
  1185. },
  1186. //LD H, D
  1187. //#0x62:
  1188. function (parentObj) {
  1189. parentObj.registersHL = (parentObj.registerD << 8) | (parentObj.registersHL & 0xFF);
  1190. },
  1191. //LD H, E
  1192. //#0x63:
  1193. function (parentObj) {
  1194. parentObj.registersHL = (parentObj.registerE << 8) | (parentObj.registersHL & 0xFF);
  1195. },
  1196. //LD H, H
  1197. //#0x64:
  1198. function (parentObj) {
  1199. //Do nothing...
  1200. },
  1201. //LD H, L
  1202. //#0x65:
  1203. function (parentObj) {
  1204. parentObj.registersHL = (parentObj.registersHL & 0xFF) * 0x101;
  1205. },
  1206. //LD H, (HL)
  1207. //#0x66:
  1208. function (parentObj) {
  1209. parentObj.registersHL = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) << 8) | (parentObj.registersHL & 0xFF);
  1210. },
  1211. //LD H, A
  1212. //#0x67:
  1213. function (parentObj) {
  1214. parentObj.registersHL = (parentObj.registerA << 8) | (parentObj.registersHL & 0xFF);
  1215. },
  1216. //LD L, B
  1217. //#0x68:
  1218. function (parentObj) {
  1219. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerB;
  1220. },
  1221. //LD L, C
  1222. //#0x69:
  1223. function (parentObj) {
  1224. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerC;
  1225. },
  1226. //LD L, D
  1227. //#0x6A:
  1228. function (parentObj) {
  1229. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerD;
  1230. },
  1231. //LD L, E
  1232. //#0x6B:
  1233. function (parentObj) {
  1234. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerE;
  1235. },
  1236. //LD L, H
  1237. //#0x6C:
  1238. function (parentObj) {
  1239. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | (parentObj.registersHL >> 8);
  1240. },
  1241. //LD L, L
  1242. //#0x6D:
  1243. function (parentObj) {
  1244. //Do nothing...
  1245. },
  1246. //LD L, (HL)
  1247. //#0x6E:
  1248. function (parentObj) {
  1249. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1250. },
  1251. //LD L, A
  1252. //#0x6F:
  1253. function (parentObj) {
  1254. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | parentObj.registerA;
  1255. },
  1256. //LD (HL), B
  1257. //#0x70:
  1258. function (parentObj) {
  1259. parentObj.memoryWrite(parentObj.registersHL, parentObj.registerB);
  1260. },
  1261. //LD (HL), C
  1262. //#0x71:
  1263. function (parentObj) {
  1264. parentObj.memoryWrite(parentObj.registersHL, parentObj.registerC);
  1265. },
  1266. //LD (HL), D
  1267. //#0x72:
  1268. function (parentObj) {
  1269. parentObj.memoryWrite(parentObj.registersHL, parentObj.registerD);
  1270. },
  1271. //LD (HL), E
  1272. //#0x73:
  1273. function (parentObj) {
  1274. parentObj.memoryWrite(parentObj.registersHL, parentObj.registerE);
  1275. },
  1276. //LD (HL), H
  1277. //#0x74:
  1278. function (parentObj) {
  1279. parentObj.memoryWrite(parentObj.registersHL, parentObj.registersHL >> 8);
  1280. },
  1281. //LD (HL), L
  1282. //#0x75:
  1283. function (parentObj) {
  1284. parentObj.memoryWrite(parentObj.registersHL, parentObj.registersHL & 0xFF);
  1285. },
  1286. //HALT
  1287. //#0x76:
  1288. function (parentObj) {
  1289. if (parentObj.untilEnable == 1) {
  1290. /*VBA-M says this fixes Torpedo Range (Seems to work):
  1291. Involves an edge case where an EI is placed right before a HALT.
  1292. EI in this case actually is immediate, so we adjust (Hacky?).*/
  1293. parentObj.programCounter = (parentObj.programCounter - 1) & 0xFFFF;
  1294. }
  1295. else {
  1296. if (!parentObj.halt && !parentObj.IME && !parentObj.cGBC && !parentObj.usedBootROM && (parentObj.memory[0xFF0F] & parentObj.memory[0xFFFF] & 0x1F) > 0) {
  1297. parentObj.skipPCIncrement = true;
  1298. }
  1299. parentObj.halt = true;
  1300. while (parentObj.halt && (parentObj.stopEmulator & 1) == 0) {
  1301. /*We're hijacking the main interpreter loop to do this dirty business
  1302. in order to not slow down the main interpreter loop code with halt state handling.*/
  1303. var bitShift = 0;
  1304. var testbit = 1;
  1305. var interrupts = parentObj.memory[0xFFFF] & parentObj.memory[0xFF0F];
  1306. while (bitShift < 5) {
  1307. //Check to see if an interrupt is enabled AND requested.
  1308. if ((testbit & interrupts) == testbit) {
  1309. parentObj.halt = false; //Get out of halt state if in halt state.
  1310. return; //Let the main interrupt handler compute the interrupt.
  1311. }
  1312. testbit = 1 << ++bitShift;
  1313. }
  1314. parentObj.CPUTicks = 1; //1 machine cycle under HALT...
  1315. //Timing:
  1316. parentObj.updateCore();
  1317. }
  1318. throw(new Error("HALT_OVERRUN")); //Throw an error on purpose to exit out of the loop.
  1319. }
  1320. },
  1321. //LD (HL), A
  1322. //#0x77:
  1323. function (parentObj) {
  1324. parentObj.memoryWrite(parentObj.registersHL, parentObj.registerA);
  1325. },
  1326. //LD A, B
  1327. //#0x78:
  1328. function (parentObj) {
  1329. parentObj.registerA = parentObj.registerB;
  1330. },
  1331. //LD A, C
  1332. //#0x79:
  1333. function (parentObj) {
  1334. parentObj.registerA = parentObj.registerC;
  1335. },
  1336. //LD A, D
  1337. //#0x7A:
  1338. function (parentObj) {
  1339. parentObj.registerA = parentObj.registerD;
  1340. },
  1341. //LD A, E
  1342. //#0x7B:
  1343. function (parentObj) {
  1344. parentObj.registerA = parentObj.registerE;
  1345. },
  1346. //LD A, H
  1347. //#0x7C:
  1348. function (parentObj) {
  1349. parentObj.registerA = (parentObj.registersHL >> 8);
  1350. },
  1351. //LD A, L
  1352. //#0x7D:
  1353. function (parentObj) {
  1354. parentObj.registerA = (parentObj.registersHL & 0xFF);
  1355. },
  1356. //LD, A, (HL)
  1357. //#0x7E:
  1358. function (parentObj) {
  1359. parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1360. },
  1361. //LD A, A
  1362. //#0x7F:
  1363. function (parentObj) {
  1364. //Do Nothing...
  1365. },
  1366. //ADD A, B
  1367. //#0x80:
  1368. function (parentObj) {
  1369. var dirtySum = parentObj.registerA + parentObj.registerB;
  1370. parentObj.FHalfCarry = (dirtySum & 0xF) < (parentObj.registerA & 0xF);
  1371. parentObj.FCarry = (dirtySum > 0xFF);
  1372. parentObj.registerA = dirtySum & 0xFF;
  1373. parentObj.FZero = (parentObj.registerA == 0);
  1374. parentObj.FSubtract = false;
  1375. },
  1376. //ADD A, C
  1377. //#0x81:
  1378. function (parentObj) {
  1379. var dirtySum = parentObj.registerA + parentObj.registerC;
  1380. parentObj.FHalfCarry = (dirtySum & 0xF) < (parentObj.registerA & 0xF);
  1381. parentObj.FCarry = (dirtySum > 0xFF);
  1382. parentObj.registerA = dirtySum & 0xFF;
  1383. parentObj.FZero = (parentObj.registerA == 0);
  1384. parentObj.FSubtract = false;
  1385. },
  1386. //ADD A, D
  1387. //#0x82:
  1388. function (parentObj) {
  1389. var dirtySum = parentObj.registerA + parentObj.registerD;
  1390. parentObj.FHalfCarry = (dirtySum & 0xF) < (parentObj.registerA & 0xF);
  1391. parentObj.FCarry = (dirtySum > 0xFF);
  1392. parentObj.registerA = dirtySum & 0xFF;
  1393. parentObj.FZero = (parentObj.registerA == 0);
  1394. parentObj.FSubtract = false;
  1395. },
  1396. //ADD A, E
  1397. //#0x83:
  1398. function (parentObj) {
  1399. var dirtySum = parentObj.registerA + parentObj.registerE;
  1400. parentObj.FHalfCarry = (dirtySum & 0xF) < (parentObj.registerA & 0xF);
  1401. parentObj.FCarry = (dirtySum > 0xFF);
  1402. parentObj.registerA = dirtySum & 0xFF;
  1403. parentObj.FZero = (parentObj.registerA == 0);
  1404. parentObj.FSubtract = false;
  1405. },
  1406. //ADD A, H
  1407. //#0x84:
  1408. function (parentObj) {
  1409. var dirtySum = parentObj.registerA + (parentObj.registersHL >> 8);
  1410. parentObj.FHalfCarry = (dirtySum & 0xF) < (parentObj.registerA & 0xF);
  1411. parentObj.FCarry = (dirtySum > 0xFF);
  1412. parentObj.registerA = dirtySum & 0xFF;
  1413. parentObj.FZero = (parentObj.registerA == 0);
  1414. parentObj.FSubtract = false;
  1415. },
  1416. //ADD A, L
  1417. //#0x85:
  1418. function (parentObj) {
  1419. var dirtySum = parentObj.registerA + (parentObj.registersHL & 0xFF);
  1420. parentObj.FHalfCarry = (dirtySum & 0xF) < (parentObj.registerA & 0xF);
  1421. parentObj.FCarry = (dirtySum > 0xFF);
  1422. parentObj.registerA = dirtySum & 0xFF;
  1423. parentObj.FZero = (parentObj.registerA == 0);
  1424. parentObj.FSubtract = false;
  1425. },
  1426. //ADD A, (HL)
  1427. //#0x86:
  1428. function (parentObj) {
  1429. var dirtySum = parentObj.registerA + parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1430. parentObj.FHalfCarry = (dirtySum & 0xF) < (parentObj.registerA & 0xF);
  1431. parentObj.FCarry = (dirtySum > 0xFF);
  1432. parentObj.registerA = dirtySum & 0xFF;
  1433. parentObj.FZero = (parentObj.registerA == 0);
  1434. parentObj.FSubtract = false;
  1435. },
  1436. //ADD A, A
  1437. //#0x87:
  1438. function (parentObj) {
  1439. parentObj.FHalfCarry = ((parentObj.registerA & 0x8) == 0x8);
  1440. parentObj.FCarry = (parentObj.registerA > 0x7F);
  1441. parentObj.registerA = (parentObj.registerA * 2) & 0xFF;
  1442. parentObj.FZero = (parentObj.registerA == 0);
  1443. parentObj.FSubtract = false;
  1444. },
  1445. //ADC A, B
  1446. //#0x88:
  1447. function (parentObj) {
  1448. var dirtySum = parentObj.registerA + parentObj.registerB + ((parentObj.FCarry) ? 1 : 0);
  1449. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (parentObj.registerB & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
  1450. parentObj.FCarry = (dirtySum > 0xFF);
  1451. parentObj.registerA = dirtySum & 0xFF;
  1452. parentObj.FZero = (parentObj.registerA == 0);
  1453. parentObj.FSubtract = false;
  1454. },
  1455. //ADC A, C
  1456. //#0x89:
  1457. function (parentObj) {
  1458. var dirtySum = parentObj.registerA + parentObj.registerC + ((parentObj.FCarry) ? 1 : 0);
  1459. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (parentObj.registerC & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
  1460. parentObj.FCarry = (dirtySum > 0xFF);
  1461. parentObj.registerA = dirtySum & 0xFF;
  1462. parentObj.FZero = (parentObj.registerA == 0);
  1463. parentObj.FSubtract = false;
  1464. },
  1465. //ADC A, D
  1466. //#0x8A:
  1467. function (parentObj) {
  1468. var dirtySum = parentObj.registerA + parentObj.registerD + ((parentObj.FCarry) ? 1 : 0);
  1469. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (parentObj.registerD & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
  1470. parentObj.FCarry = (dirtySum > 0xFF);
  1471. parentObj.registerA = dirtySum & 0xFF;
  1472. parentObj.FZero = (parentObj.registerA == 0);
  1473. parentObj.FSubtract = false;
  1474. },
  1475. //ADC A, E
  1476. //#0x8B:
  1477. function (parentObj) {
  1478. var dirtySum = parentObj.registerA + parentObj.registerE + ((parentObj.FCarry) ? 1 : 0);
  1479. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (parentObj.registerE & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
  1480. parentObj.FCarry = (dirtySum > 0xFF);
  1481. parentObj.registerA = dirtySum & 0xFF;
  1482. parentObj.FZero = (parentObj.registerA == 0);
  1483. parentObj.FSubtract = false;
  1484. },
  1485. //ADC A, H
  1486. //#0x8C:
  1487. function (parentObj) {
  1488. var tempValue = (parentObj.registersHL >> 8);
  1489. var dirtySum = parentObj.registerA + tempValue + ((parentObj.FCarry) ? 1 : 0);
  1490. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (tempValue & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
  1491. parentObj.FCarry = (dirtySum > 0xFF);
  1492. parentObj.registerA = dirtySum & 0xFF;
  1493. parentObj.FZero = (parentObj.registerA == 0);
  1494. parentObj.FSubtract = false;
  1495. },
  1496. //ADC A, L
  1497. //#0x8D:
  1498. function (parentObj) {
  1499. var tempValue = (parentObj.registersHL & 0xFF);
  1500. var dirtySum = parentObj.registerA + tempValue + ((parentObj.FCarry) ? 1 : 0);
  1501. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (tempValue & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
  1502. parentObj.FCarry = (dirtySum > 0xFF);
  1503. parentObj.registerA = dirtySum & 0xFF;
  1504. parentObj.FZero = (parentObj.registerA == 0);
  1505. parentObj.FSubtract = false;
  1506. },
  1507. //ADC A, (HL)
  1508. //#0x8E:
  1509. function (parentObj) {
  1510. var tempValue = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1511. var dirtySum = parentObj.registerA + tempValue + ((parentObj.FCarry) ? 1 : 0);
  1512. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (tempValue & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
  1513. parentObj.FCarry = (dirtySum > 0xFF);
  1514. parentObj.registerA = dirtySum & 0xFF;
  1515. parentObj.FZero = (parentObj.registerA == 0);
  1516. parentObj.FSubtract = false;
  1517. },
  1518. //ADC A, A
  1519. //#0x8F:
  1520. function (parentObj) {
  1521. var dirtySum = (parentObj.registerA * 2) + ((parentObj.FCarry) ? 1 : 0);
  1522. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (parentObj.registerA & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
  1523. parentObj.FCarry = (dirtySum > 0xFF);
  1524. parentObj.registerA = dirtySum & 0xFF;
  1525. parentObj.FZero = (parentObj.registerA == 0);
  1526. parentObj.FSubtract = false;
  1527. },
  1528. //SUB A, B
  1529. //#0x90:
  1530. function (parentObj) {
  1531. var dirtySum = parentObj.registerA - parentObj.registerB;
  1532. parentObj.FHalfCarry = (parentObj.registerA & 0xF) < (parentObj.registerB & 0xF);
  1533. parentObj.FCarry = (dirtySum < 0);
  1534. parentObj.registerA = dirtySum & 0xFF;
  1535. parentObj.FZero = (parentObj.registerA == 0);
  1536. parentObj.FSubtract = true;
  1537. },
  1538. //SUB A, C
  1539. //#0x91:
  1540. function (parentObj) {
  1541. var dirtySum = parentObj.registerA - parentObj.registerC;
  1542. parentObj.FHalfCarry = (parentObj.registerA & 0xF) < (parentObj.registerC & 0xF);
  1543. parentObj.FCarry = (dirtySum < 0);
  1544. parentObj.registerA = dirtySum & 0xFF;
  1545. parentObj.FZero = (parentObj.registerA == 0);
  1546. parentObj.FSubtract = true;
  1547. },
  1548. //SUB A, D
  1549. //#0x92:
  1550. function (parentObj) {
  1551. var dirtySum = parentObj.registerA - parentObj.registerD;
  1552. parentObj.FHalfCarry = (parentObj.registerA & 0xF) < (parentObj.registerD & 0xF);
  1553. parentObj.FCarry = (dirtySum < 0);
  1554. parentObj.registerA = dirtySum & 0xFF;
  1555. parentObj.FZero = (parentObj.registerA == 0);
  1556. parentObj.FSubtract = true;
  1557. },
  1558. //SUB A, E
  1559. //#0x93:
  1560. function (parentObj) {
  1561. var dirtySum = parentObj.registerA - parentObj.registerE;
  1562. parentObj.FHalfCarry = (parentObj.registerA & 0xF) < (parentObj.registerE & 0xF);
  1563. parentObj.FCarry = (dirtySum < 0);
  1564. parentObj.registerA = dirtySum & 0xFF;
  1565. parentObj.FZero = (parentObj.registerA == 0);
  1566. parentObj.FSubtract = true;
  1567. },
  1568. //SUB A, H
  1569. //#0x94:
  1570. function (parentObj) {
  1571. var temp_var = parentObj.registersHL >> 8;
  1572. var dirtySum = parentObj.registerA - temp_var;
  1573. parentObj.FHalfCarry = (parentObj.registerA & 0xF) < (temp_var & 0xF);
  1574. parentObj.FCarry = (dirtySum < 0);
  1575. parentObj.registerA = dirtySum & 0xFF;
  1576. parentObj.FZero = (parentObj.registerA == 0);
  1577. parentObj.FSubtract = true;
  1578. },
  1579. //SUB A, L
  1580. //#0x95:
  1581. function (parentObj) {
  1582. var dirtySum = parentObj.registerA - (parentObj.registersHL & 0xFF);
  1583. parentObj.FHalfCarry = (parentObj.registerA & 0xF) < (parentObj.registersHL & 0xF);
  1584. parentObj.FCarry = (dirtySum < 0);
  1585. parentObj.registerA = dirtySum & 0xFF;
  1586. parentObj.FZero = (parentObj.registerA == 0);
  1587. parentObj.FSubtract = true;
  1588. },
  1589. //SUB A, (HL)
  1590. //#0x96:
  1591. function (parentObj) {
  1592. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1593. var dirtySum = parentObj.registerA - temp_var;
  1594. parentObj.FHalfCarry = (parentObj.registerA & 0xF) < (temp_var & 0xF);
  1595. parentObj.FCarry = (dirtySum < 0);
  1596. parentObj.registerA = dirtySum & 0xFF;
  1597. parentObj.FZero = (parentObj.registerA == 0);
  1598. parentObj.FSubtract = true;
  1599. },
  1600. //SUB A, A
  1601. //#0x97:
  1602. function (parentObj) {
  1603. //number - same number == 0
  1604. parentObj.registerA = 0;
  1605. parentObj.FHalfCarry = parentObj.FCarry = false;
  1606. parentObj.FZero = parentObj.FSubtract = true;
  1607. },
  1608. //SBC A, B
  1609. //#0x98:
  1610. function (parentObj) {
  1611. var dirtySum = parentObj.registerA - parentObj.registerB - ((parentObj.FCarry) ? 1 : 0);
  1612. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registerB & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
  1613. parentObj.FCarry = (dirtySum < 0);
  1614. parentObj.registerA = dirtySum & 0xFF;
  1615. parentObj.FZero = (parentObj.registerA == 0);
  1616. parentObj.FSubtract = true;
  1617. },
  1618. //SBC A, C
  1619. //#0x99:
  1620. function (parentObj) {
  1621. var dirtySum = parentObj.registerA - parentObj.registerC - ((parentObj.FCarry) ? 1 : 0);
  1622. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registerC & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
  1623. parentObj.FCarry = (dirtySum < 0);
  1624. parentObj.registerA = dirtySum & 0xFF;
  1625. parentObj.FZero = (parentObj.registerA == 0);
  1626. parentObj.FSubtract = true;
  1627. },
  1628. //SBC A, D
  1629. //#0x9A:
  1630. function (parentObj) {
  1631. var dirtySum = parentObj.registerA - parentObj.registerD - ((parentObj.FCarry) ? 1 : 0);
  1632. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registerD & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
  1633. parentObj.FCarry = (dirtySum < 0);
  1634. parentObj.registerA = dirtySum & 0xFF;
  1635. parentObj.FZero = (parentObj.registerA == 0);
  1636. parentObj.FSubtract = true;
  1637. },
  1638. //SBC A, E
  1639. //#0x9B:
  1640. function (parentObj) {
  1641. var dirtySum = parentObj.registerA - parentObj.registerE - ((parentObj.FCarry) ? 1 : 0);
  1642. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registerE & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
  1643. parentObj.FCarry = (dirtySum < 0);
  1644. parentObj.registerA = dirtySum & 0xFF;
  1645. parentObj.FZero = (parentObj.registerA == 0);
  1646. parentObj.FSubtract = true;
  1647. },
  1648. //SBC A, H
  1649. //#0x9C:
  1650. function (parentObj) {
  1651. var temp_var = parentObj.registersHL >> 8;
  1652. var dirtySum = parentObj.registerA - temp_var - ((parentObj.FCarry) ? 1 : 0);
  1653. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (temp_var & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
  1654. parentObj.FCarry = (dirtySum < 0);
  1655. parentObj.registerA = dirtySum & 0xFF;
  1656. parentObj.FZero = (parentObj.registerA == 0);
  1657. parentObj.FSubtract = true;
  1658. },
  1659. //SBC A, L
  1660. //#0x9D:
  1661. function (parentObj) {
  1662. var dirtySum = parentObj.registerA - (parentObj.registersHL & 0xFF) - ((parentObj.FCarry) ? 1 : 0);
  1663. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (parentObj.registersHL & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
  1664. parentObj.FCarry = (dirtySum < 0);
  1665. parentObj.registerA = dirtySum & 0xFF;
  1666. parentObj.FZero = (parentObj.registerA == 0);
  1667. parentObj.FSubtract = true;
  1668. },
  1669. //SBC A, (HL)
  1670. //#0x9E:
  1671. function (parentObj) {
  1672. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1673. var dirtySum = parentObj.registerA - temp_var - ((parentObj.FCarry) ? 1 : 0);
  1674. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (temp_var & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
  1675. parentObj.FCarry = (dirtySum < 0);
  1676. parentObj.registerA = dirtySum & 0xFF;
  1677. parentObj.FZero = (parentObj.registerA == 0);
  1678. parentObj.FSubtract = true;
  1679. },
  1680. //SBC A, A
  1681. //#0x9F:
  1682. function (parentObj) {
  1683. //Optimized SBC A:
  1684. if (parentObj.FCarry) {
  1685. parentObj.FZero = false;
  1686. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = true;
  1687. parentObj.registerA = 0xFF;
  1688. }
  1689. else {
  1690. parentObj.FHalfCarry = parentObj.FCarry = false;
  1691. parentObj.FSubtract = parentObj.FZero = true;
  1692. parentObj.registerA = 0;
  1693. }
  1694. },
  1695. //AND B
  1696. //#0xA0:
  1697. function (parentObj) {
  1698. parentObj.registerA &= parentObj.registerB;
  1699. parentObj.FZero = (parentObj.registerA == 0);
  1700. parentObj.FHalfCarry = true;
  1701. parentObj.FSubtract = parentObj.FCarry = false;
  1702. },
  1703. //AND C
  1704. //#0xA1:
  1705. function (parentObj) {
  1706. parentObj.registerA &= parentObj.registerC;
  1707. parentObj.FZero = (parentObj.registerA == 0);
  1708. parentObj.FHalfCarry = true;
  1709. parentObj.FSubtract = parentObj.FCarry = false;
  1710. },
  1711. //AND D
  1712. //#0xA2:
  1713. function (parentObj) {
  1714. parentObj.registerA &= parentObj.registerD;
  1715. parentObj.FZero = (parentObj.registerA == 0);
  1716. parentObj.FHalfCarry = true;
  1717. parentObj.FSubtract = parentObj.FCarry = false;
  1718. },
  1719. //AND E
  1720. //#0xA3:
  1721. function (parentObj) {
  1722. parentObj.registerA &= parentObj.registerE;
  1723. parentObj.FZero = (parentObj.registerA == 0);
  1724. parentObj.FHalfCarry = true;
  1725. parentObj.FSubtract = parentObj.FCarry = false;
  1726. },
  1727. //AND H
  1728. //#0xA4:
  1729. function (parentObj) {
  1730. parentObj.registerA &= (parentObj.registersHL >> 8);
  1731. parentObj.FZero = (parentObj.registerA == 0);
  1732. parentObj.FHalfCarry = true;
  1733. parentObj.FSubtract = parentObj.FCarry = false;
  1734. },
  1735. //AND L
  1736. //#0xA5:
  1737. function (parentObj) {
  1738. parentObj.registerA &= parentObj.registersHL;
  1739. parentObj.FZero = (parentObj.registerA == 0);
  1740. parentObj.FHalfCarry = true;
  1741. parentObj.FSubtract = parentObj.FCarry = false;
  1742. },
  1743. //AND (HL)
  1744. //#0xA6:
  1745. function (parentObj) {
  1746. parentObj.registerA &= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1747. parentObj.FZero = (parentObj.registerA == 0);
  1748. parentObj.FHalfCarry = true;
  1749. parentObj.FSubtract = parentObj.FCarry = false;
  1750. },
  1751. //AND A
  1752. //#0xA7:
  1753. function (parentObj) {
  1754. //number & same number = same number
  1755. parentObj.FZero = (parentObj.registerA == 0);
  1756. parentObj.FHalfCarry = true;
  1757. parentObj.FSubtract = parentObj.FCarry = false;
  1758. },
  1759. //XOR B
  1760. //#0xA8:
  1761. function (parentObj) {
  1762. parentObj.registerA ^= parentObj.registerB;
  1763. parentObj.FZero = (parentObj.registerA == 0);
  1764. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
  1765. },
  1766. //XOR C
  1767. //#0xA9:
  1768. function (parentObj) {
  1769. parentObj.registerA ^= parentObj.registerC;
  1770. parentObj.FZero = (parentObj.registerA == 0);
  1771. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
  1772. },
  1773. //XOR D
  1774. //#0xAA:
  1775. function (parentObj) {
  1776. parentObj.registerA ^= parentObj.registerD;
  1777. parentObj.FZero = (parentObj.registerA == 0);
  1778. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
  1779. },
  1780. //XOR E
  1781. //#0xAB:
  1782. function (parentObj) {
  1783. parentObj.registerA ^= parentObj.registerE;
  1784. parentObj.FZero = (parentObj.registerA == 0);
  1785. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
  1786. },
  1787. //XOR H
  1788. //#0xAC:
  1789. function (parentObj) {
  1790. parentObj.registerA ^= (parentObj.registersHL >> 8);
  1791. parentObj.FZero = (parentObj.registerA == 0);
  1792. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
  1793. },
  1794. //XOR L
  1795. //#0xAD:
  1796. function (parentObj) {
  1797. parentObj.registerA ^= (parentObj.registersHL & 0xFF);
  1798. parentObj.FZero = (parentObj.registerA == 0);
  1799. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
  1800. },
  1801. //XOR (HL)
  1802. //#0xAE:
  1803. function (parentObj) {
  1804. parentObj.registerA ^= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1805. parentObj.FZero = (parentObj.registerA == 0);
  1806. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
  1807. },
  1808. //XOR A
  1809. //#0xAF:
  1810. function (parentObj) {
  1811. //number ^ same number == 0
  1812. parentObj.registerA = 0;
  1813. parentObj.FZero = true;
  1814. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
  1815. },
  1816. //OR B
  1817. //#0xB0:
  1818. function (parentObj) {
  1819. parentObj.registerA |= parentObj.registerB;
  1820. parentObj.FZero = (parentObj.registerA == 0);
  1821. parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
  1822. },
  1823. //OR C
  1824. //#0xB1:
  1825. function (parentObj) {
  1826. parentObj.registerA |= parentObj.registerC;
  1827. parentObj.FZero = (parentObj.registerA == 0);
  1828. parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
  1829. },
  1830. //OR D
  1831. //#0xB2:
  1832. function (parentObj) {
  1833. parentObj.registerA |= parentObj.registerD;
  1834. parentObj.FZero = (parentObj.registerA == 0);
  1835. parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
  1836. },
  1837. //OR E
  1838. //#0xB3:
  1839. function (parentObj) {
  1840. parentObj.registerA |= parentObj.registerE;
  1841. parentObj.FZero = (parentObj.registerA == 0);
  1842. parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
  1843. },
  1844. //OR H
  1845. //#0xB4:
  1846. function (parentObj) {
  1847. parentObj.registerA |= (parentObj.registersHL >> 8);
  1848. parentObj.FZero = (parentObj.registerA == 0);
  1849. parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
  1850. },
  1851. //OR L
  1852. //#0xB5:
  1853. function (parentObj) {
  1854. parentObj.registerA |= (parentObj.registersHL & 0xFF);
  1855. parentObj.FZero = (parentObj.registerA == 0);
  1856. parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
  1857. },
  1858. //OR (HL)
  1859. //#0xB6:
  1860. function (parentObj) {
  1861. parentObj.registerA |= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1862. parentObj.FZero = (parentObj.registerA == 0);
  1863. parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
  1864. },
  1865. //OR A
  1866. //#0xB7:
  1867. function (parentObj) {
  1868. //number | same number == same number
  1869. parentObj.FZero = (parentObj.registerA == 0);
  1870. parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
  1871. },
  1872. //CP B
  1873. //#0xB8:
  1874. function (parentObj) {
  1875. var dirtySum = parentObj.registerA - parentObj.registerB;
  1876. parentObj.FHalfCarry = (dirtySum & 0xF) > (parentObj.registerA & 0xF);
  1877. parentObj.FCarry = (dirtySum < 0);
  1878. parentObj.FZero = (dirtySum == 0);
  1879. parentObj.FSubtract = true;
  1880. },
  1881. //CP C
  1882. //#0xB9:
  1883. function (parentObj) {
  1884. var dirtySum = parentObj.registerA - parentObj.registerC;
  1885. parentObj.FHalfCarry = (dirtySum & 0xF) > (parentObj.registerA & 0xF);
  1886. parentObj.FCarry = (dirtySum < 0);
  1887. parentObj.FZero = (dirtySum == 0);
  1888. parentObj.FSubtract = true;
  1889. },
  1890. //CP D
  1891. //#0xBA:
  1892. function (parentObj) {
  1893. var dirtySum = parentObj.registerA - parentObj.registerD;
  1894. parentObj.FHalfCarry = (dirtySum & 0xF) > (parentObj.registerA & 0xF);
  1895. parentObj.FCarry = (dirtySum < 0);
  1896. parentObj.FZero = (dirtySum == 0);
  1897. parentObj.FSubtract = true;
  1898. },
  1899. //CP E
  1900. //#0xBB:
  1901. function (parentObj) {
  1902. var dirtySum = parentObj.registerA - parentObj.registerE;
  1903. parentObj.FHalfCarry = (dirtySum & 0xF) > (parentObj.registerA & 0xF);
  1904. parentObj.FCarry = (dirtySum < 0);
  1905. parentObj.FZero = (dirtySum == 0);
  1906. parentObj.FSubtract = true;
  1907. },
  1908. //CP H
  1909. //#0xBC:
  1910. function (parentObj) {
  1911. var dirtySum = parentObj.registerA - (parentObj.registersHL >> 8);
  1912. parentObj.FHalfCarry = (dirtySum & 0xF) > (parentObj.registerA & 0xF);
  1913. parentObj.FCarry = (dirtySum < 0);
  1914. parentObj.FZero = (dirtySum == 0);
  1915. parentObj.FSubtract = true;
  1916. },
  1917. //CP L
  1918. //#0xBD:
  1919. function (parentObj) {
  1920. var dirtySum = parentObj.registerA - (parentObj.registersHL & 0xFF);
  1921. parentObj.FHalfCarry = (dirtySum & 0xF) > (parentObj.registerA & 0xF);
  1922. parentObj.FCarry = (dirtySum < 0);
  1923. parentObj.FZero = (dirtySum == 0);
  1924. parentObj.FSubtract = true;
  1925. },
  1926. //CP (HL)
  1927. //#0xBE:
  1928. function (parentObj) {
  1929. var dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  1930. parentObj.FHalfCarry = (dirtySum & 0xF) > (parentObj.registerA & 0xF);
  1931. parentObj.FCarry = (dirtySum < 0);
  1932. parentObj.FZero = (dirtySum == 0);
  1933. parentObj.FSubtract = true;
  1934. },
  1935. //CP A
  1936. //#0xBF:
  1937. function (parentObj) {
  1938. parentObj.FHalfCarry = parentObj.FCarry = false;
  1939. parentObj.FZero = parentObj.FSubtract = true;
  1940. },
  1941. //RET !FZ
  1942. //#0xC0:
  1943. function (parentObj) {
  1944. if (!parentObj.FZero) {
  1945. parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  1946. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  1947. parentObj.CPUTicks += 3;
  1948. }
  1949. },
  1950. //POP BC
  1951. //#0xC1:
  1952. function (parentObj) {
  1953. parentObj.registerC = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  1954. parentObj.registerB = parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF);
  1955. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  1956. },
  1957. //JP !FZ, nn
  1958. //#0xC2:
  1959. function (parentObj) {
  1960. if (!parentObj.FZero) {
  1961. parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  1962. parentObj.CPUTicks++;
  1963. }
  1964. else {
  1965. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  1966. }
  1967. },
  1968. //JP nn
  1969. //#0xC3:
  1970. function (parentObj) {
  1971. parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  1972. },
  1973. //CALL !FZ, nn
  1974. //#0xC4:
  1975. function (parentObj) {
  1976. if (!parentObj.FZero) {
  1977. var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  1978. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  1979. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  1980. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  1981. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  1982. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  1983. parentObj.programCounter = temp_pc;
  1984. parentObj.CPUTicks += 3;
  1985. }
  1986. else {
  1987. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  1988. }
  1989. },
  1990. //PUSH BC
  1991. //#0xC5:
  1992. function (parentObj) {
  1993. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  1994. parentObj.memoryWrite(parentObj.stackPointer, parentObj.registerB);
  1995. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  1996. parentObj.memoryWrite(parentObj.stackPointer, parentObj.registerC);
  1997. },
  1998. //ADD, n
  1999. //#0xC6:
  2000. function (parentObj) {
  2001. var dirtySum = parentObj.registerA + parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2002. parentObj.FHalfCarry = (dirtySum & 0xF) < (parentObj.registerA & 0xF);
  2003. parentObj.FCarry = (dirtySum > 0xFF);
  2004. parentObj.registerA = dirtySum & 0xFF;
  2005. parentObj.FZero = (parentObj.registerA == 0);
  2006. parentObj.FSubtract = false;
  2007. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2008. },
  2009. //RST 0
  2010. //#0xC7:
  2011. function (parentObj) {
  2012. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2013. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2014. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2015. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2016. parentObj.programCounter = 0;
  2017. },
  2018. //RET FZ
  2019. //#0xC8:
  2020. function (parentObj) {
  2021. if (parentObj.FZero) {
  2022. parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  2023. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  2024. parentObj.CPUTicks += 3;
  2025. }
  2026. },
  2027. //RET
  2028. //#0xC9:
  2029. function (parentObj) {
  2030. parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  2031. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  2032. },
  2033. //JP FZ, nn
  2034. //#0xCA:
  2035. function (parentObj) {
  2036. if (parentObj.FZero) {
  2037. parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2038. parentObj.CPUTicks++;
  2039. }
  2040. else {
  2041. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2042. }
  2043. },
  2044. //Secondary OP Code Set:
  2045. //#0xCB:
  2046. function (parentObj) {
  2047. var opcode = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2048. //Increment the program counter to the next instruction:
  2049. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2050. //Get how many CPU cycles the current 0xCBXX op code counts for:
  2051. parentObj.CPUTicks = parentObj.SecondaryTICKTable[opcode];
  2052. //Execute secondary OP codes for the 0xCB OP code call.
  2053. parentObj.CBOPCODE[opcode](parentObj);
  2054. },
  2055. //CALL FZ, nn
  2056. //#0xCC:
  2057. function (parentObj) {
  2058. if (parentObj.FZero) {
  2059. var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2060. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2061. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2062. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2063. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2064. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2065. parentObj.programCounter = temp_pc;
  2066. parentObj.CPUTicks += 3;
  2067. }
  2068. else {
  2069. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2070. }
  2071. },
  2072. //CALL nn
  2073. //#0xCD:
  2074. function (parentObj) {
  2075. var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2076. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2077. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2078. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2079. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2080. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2081. parentObj.programCounter = temp_pc;
  2082. },
  2083. //ADC A, n
  2084. //#0xCE:
  2085. function (parentObj) {
  2086. var tempValue = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2087. var dirtySum = parentObj.registerA + tempValue + ((parentObj.FCarry) ? 1 : 0);
  2088. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) + (tempValue & 0xF) + ((parentObj.FCarry) ? 1 : 0) > 0xF);
  2089. parentObj.FCarry = (dirtySum > 0xFF);
  2090. parentObj.registerA = dirtySum & 0xFF;
  2091. parentObj.FZero = (parentObj.registerA == 0);
  2092. parentObj.FSubtract = false;
  2093. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2094. },
  2095. //RST 0x8
  2096. //#0xCF:
  2097. function (parentObj) {
  2098. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2099. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2100. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2101. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2102. parentObj.programCounter = 0x8;
  2103. },
  2104. //RET !FC
  2105. //#0xD0:
  2106. function (parentObj) {
  2107. if (!parentObj.FCarry) {
  2108. parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  2109. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  2110. parentObj.CPUTicks += 3;
  2111. }
  2112. },
  2113. //POP DE
  2114. //#0xD1:
  2115. function (parentObj) {
  2116. parentObj.registerE = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  2117. parentObj.registerD = parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF);
  2118. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  2119. },
  2120. //JP !FC, nn
  2121. //#0xD2:
  2122. function (parentObj) {
  2123. if (!parentObj.FCarry) {
  2124. parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2125. parentObj.CPUTicks++;
  2126. }
  2127. else {
  2128. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2129. }
  2130. },
  2131. //0xD3 - Illegal
  2132. //#0xD3:
  2133. function (parentObj) {
  2134. cout("Illegal op code 0xD3 called, pausing emulation.", 2);
  2135. pause();
  2136. },
  2137. //CALL !FC, nn
  2138. //#0xD4:
  2139. function (parentObj) {
  2140. if (!parentObj.FCarry) {
  2141. var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2142. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2143. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2144. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2145. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2146. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2147. parentObj.programCounter = temp_pc;
  2148. parentObj.CPUTicks += 3;
  2149. }
  2150. else {
  2151. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2152. }
  2153. },
  2154. //PUSH DE
  2155. //#0xD5:
  2156. function (parentObj) {
  2157. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2158. parentObj.memoryWrite(parentObj.stackPointer, parentObj.registerD);
  2159. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2160. parentObj.memoryWrite(parentObj.stackPointer, parentObj.registerE);
  2161. },
  2162. //SUB A, n
  2163. //#0xD6:
  2164. function (parentObj) {
  2165. var temp_var = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2166. var dirtySum = parentObj.registerA - temp_var;
  2167. parentObj.FHalfCarry = (parentObj.registerA & 0xF) < (temp_var & 0xF);
  2168. parentObj.FCarry = (dirtySum < 0);
  2169. parentObj.registerA = dirtySum & 0xFF;
  2170. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2171. parentObj.FZero = (parentObj.registerA == 0);
  2172. parentObj.FSubtract = true;
  2173. },
  2174. //RST 0x10
  2175. //#0xD7:
  2176. function (parentObj) {
  2177. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2178. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2179. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2180. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2181. parentObj.programCounter = 0x10;
  2182. },
  2183. //RET FC
  2184. //#0xD8:
  2185. function (parentObj) {
  2186. if (parentObj.FCarry) {
  2187. parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  2188. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  2189. parentObj.CPUTicks += 3;
  2190. }
  2191. },
  2192. //RETI
  2193. //#0xD9:
  2194. function (parentObj) {
  2195. parentObj.programCounter = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  2196. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  2197. //parentObj.IME = true;
  2198. parentObj.untilEnable = 2;
  2199. },
  2200. //JP FC, nn
  2201. //#0xDA:
  2202. function (parentObj) {
  2203. if (parentObj.FCarry) {
  2204. parentObj.programCounter = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2205. parentObj.CPUTicks++;
  2206. }
  2207. else {
  2208. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2209. }
  2210. },
  2211. //0xDB - Illegal
  2212. //#0xDB:
  2213. function (parentObj) {
  2214. cout("Illegal op code 0xDB called, pausing emulation.", 2);
  2215. pause();
  2216. },
  2217. //CALL FC, nn
  2218. //#0xDC:
  2219. function (parentObj) {
  2220. if (parentObj.FCarry) {
  2221. var temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2222. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2223. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2224. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2225. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2226. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2227. parentObj.programCounter = temp_pc;
  2228. parentObj.CPUTicks += 3;
  2229. }
  2230. else {
  2231. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2232. }
  2233. },
  2234. //0xDD - Illegal
  2235. //#0xDD:
  2236. function (parentObj) {
  2237. cout("Illegal op code 0xDD called, pausing emulation.", 2);
  2238. pause();
  2239. },
  2240. //SBC A, n
  2241. //#0xDE:
  2242. function (parentObj) {
  2243. var temp_var = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2244. var dirtySum = parentObj.registerA - temp_var - ((parentObj.FCarry) ? 1 : 0);
  2245. parentObj.FHalfCarry = ((parentObj.registerA & 0xF) - (temp_var & 0xF) - ((parentObj.FCarry) ? 1 : 0) < 0);
  2246. parentObj.FCarry = (dirtySum < 0);
  2247. parentObj.registerA = dirtySum & 0xFF;
  2248. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2249. parentObj.FZero = (parentObj.registerA == 0);
  2250. parentObj.FSubtract = true;
  2251. },
  2252. //RST 0x18
  2253. //#0xDF:
  2254. function (parentObj) {
  2255. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2256. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2257. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2258. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2259. parentObj.programCounter = 0x18;
  2260. },
  2261. //LDH (n), A
  2262. //#0xE0:
  2263. function (parentObj) {
  2264. parentObj.memoryWrite(0xFF00 | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter), parentObj.registerA);
  2265. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2266. },
  2267. //POP HL
  2268. //#0xE1:
  2269. function (parentObj) {
  2270. parentObj.registersHL = (parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  2271. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  2272. },
  2273. //LD (0xFF00 + C), A
  2274. //#0xE2:
  2275. function (parentObj) {
  2276. parentObj.memoryWrite(0xFF00 | parentObj.registerC, parentObj.registerA);
  2277. },
  2278. //0xE3 - Illegal
  2279. //#0xE3:
  2280. function (parentObj) {
  2281. cout("Illegal op code 0xE3 called, pausing emulation.", 2);
  2282. pause();
  2283. },
  2284. //0xE4 - Illegal
  2285. //#0xE4:
  2286. function (parentObj) {
  2287. cout("Illegal op code 0xE4 called, pausing emulation.", 2);
  2288. pause();
  2289. },
  2290. //PUSH HL
  2291. //#0xE5:
  2292. function (parentObj) {
  2293. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2294. parentObj.memoryWrite(parentObj.stackPointer, parentObj.registersHL >> 8);
  2295. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2296. parentObj.memoryWrite(parentObj.stackPointer, parentObj.registersHL & 0xFF);
  2297. },
  2298. //AND n
  2299. //#0xE6:
  2300. function (parentObj) {
  2301. parentObj.registerA &= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2302. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2303. parentObj.FZero = (parentObj.registerA == 0);
  2304. parentObj.FHalfCarry = true;
  2305. parentObj.FSubtract = parentObj.FCarry = false;
  2306. },
  2307. //RST 0x20
  2308. //#0xE7:
  2309. function (parentObj) {
  2310. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2311. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2312. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2313. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2314. parentObj.programCounter = 0x20;
  2315. },
  2316. //ADD SP, n
  2317. //#0xE8:
  2318. function (parentObj) {
  2319. var signedByte = parentObj.usbtsb(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
  2320. var temp_value = (parentObj.stackPointer + signedByte) & 0xFFFF;
  2321. parentObj.FCarry = (((parentObj.stackPointer ^ signedByte ^ temp_value) & 0x100) == 0x100);
  2322. parentObj.FHalfCarry = (((parentObj.stackPointer ^ signedByte ^ temp_value) & 0x10) == 0x10);
  2323. parentObj.stackPointer = temp_value;
  2324. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2325. parentObj.FZero = parentObj.FSubtract = false;
  2326. },
  2327. //JP, (HL)
  2328. //#0xE9:
  2329. function (parentObj) {
  2330. parentObj.programCounter = parentObj.registersHL;
  2331. },
  2332. //LD n, A
  2333. //#0xEA:
  2334. function (parentObj) {
  2335. parentObj.memoryWrite((parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter), parentObj.registerA);
  2336. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2337. },
  2338. //0xEB - Illegal
  2339. //#0xEB:
  2340. function (parentObj) {
  2341. cout("Illegal op code 0xEB called, pausing emulation.", 2);
  2342. pause();
  2343. },
  2344. //0xEC - Illegal
  2345. //#0xEC:
  2346. function (parentObj) {
  2347. cout("Illegal op code 0xEC called, pausing emulation.", 2);
  2348. pause();
  2349. },
  2350. //0xED - Illegal
  2351. //#0xED:
  2352. function (parentObj) {
  2353. cout("Illegal op code 0xED called, pausing emulation.", 2);
  2354. pause();
  2355. },
  2356. //XOR n
  2357. //#0xEE:
  2358. function (parentObj) {
  2359. parentObj.registerA ^= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2360. parentObj.FZero = (parentObj.registerA == 0);
  2361. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2362. parentObj.FSubtract = parentObj.FHalfCarry = parentObj.FCarry = false;
  2363. },
  2364. //RST 0x28
  2365. //#0xEF:
  2366. function (parentObj) {
  2367. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2368. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2369. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2370. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2371. parentObj.programCounter = 0x28;
  2372. },
  2373. //LDH A, (n)
  2374. //#0xF0:
  2375. function (parentObj) {
  2376. parentObj.registerA = parentObj.memoryRead(0xFF00 | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
  2377. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2378. },
  2379. //POP AF
  2380. //#0xF1:
  2381. function (parentObj) {
  2382. var temp_var = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
  2383. parentObj.FZero = ((temp_var & 0x80) == 0x80);
  2384. parentObj.FSubtract = ((temp_var & 0x40) == 0x40);
  2385. parentObj.FHalfCarry = ((temp_var & 0x20) == 0x20);
  2386. parentObj.FCarry = ((temp_var & 0x10) == 0x10);
  2387. parentObj.registerA = parentObj.memoryRead((parentObj.stackPointer + 1) & 0xFFFF);
  2388. parentObj.stackPointer = (parentObj.stackPointer + 2) & 0xFFFF;
  2389. },
  2390. //LD A, (0xFF00 + C)
  2391. //#0xF2:
  2392. function (parentObj) {
  2393. parentObj.registerA = parentObj.memoryRead(0xFF00 | parentObj.registerC);
  2394. },
  2395. //DI
  2396. //#0xF3:
  2397. function (parentObj) {
  2398. parentObj.IME = false;
  2399. parentObj.untilEnable = 0;
  2400. },
  2401. //0xF4 - Illegal
  2402. //#0xF4:
  2403. function (parentObj) {
  2404. cout("Illegal op code 0xF4 called, pausing emulation.", 2);
  2405. pause();
  2406. },
  2407. //PUSH AF
  2408. //#0xF5:
  2409. function (parentObj) {
  2410. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2411. parentObj.memoryWrite(parentObj.stackPointer, parentObj.registerA);
  2412. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2413. parentObj.memoryWrite(parentObj.stackPointer, ((parentObj.FZero) ? 0x80 : 0) | ((parentObj.FSubtract) ? 0x40 : 0) | ((parentObj.FHalfCarry) ? 0x20 : 0) | ((parentObj.FCarry) ? 0x10 : 0));
  2414. },
  2415. //OR n
  2416. //#0xF6:
  2417. function (parentObj) {
  2418. parentObj.registerA |= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2419. parentObj.FZero = (parentObj.registerA == 0);
  2420. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2421. parentObj.FSubtract = parentObj.FCarry = parentObj.FHalfCarry = false;
  2422. },
  2423. //RST 0x30
  2424. //#0xF7:
  2425. function (parentObj) {
  2426. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2427. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter >> 8);
  2428. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2429. parentObj.memoryWrite(parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2430. parentObj.programCounter = 0x30;
  2431. },
  2432. //LDHL SP, n
  2433. //#0xF8:
  2434. function (parentObj) {
  2435. var signedByte = parentObj.usbtsb(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
  2436. parentObj.registersHL = (parentObj.stackPointer + signedByte) & 0xFFFF;
  2437. parentObj.FCarry = (((parentObj.stackPointer ^ signedByte ^ parentObj.registersHL) & 0x100) == 0x100);
  2438. parentObj.FHalfCarry = (((parentObj.stackPointer ^ signedByte ^ parentObj.registersHL) & 0x10) == 0x10);
  2439. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2440. parentObj.FZero = parentObj.FSubtract = false;
  2441. },
  2442. //LD SP, HL
  2443. //#0xF9:
  2444. function (parentObj) {
  2445. parentObj.stackPointer = parentObj.registersHL;
  2446. },
  2447. //LD A, (nn)
  2448. //#0xFA:
  2449. function (parentObj) {
  2450. parentObj.registerA = parentObj.memoryRead((parentObj.memoryRead((parentObj.programCounter + 1) & 0xFFFF) << 8) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
  2451. parentObj.programCounter = (parentObj.programCounter + 2) & 0xFFFF;
  2452. },
  2453. //EI
  2454. //#0xFB:
  2455. function (parentObj) {
  2456. parentObj.untilEnable = 2;
  2457. },
  2458. //0xFC - Illegal
  2459. //#0xFC:
  2460. function (parentObj) {
  2461. cout("Illegal op code 0xFC called, pausing emulation.", 2);
  2462. pause();
  2463. },
  2464. //0xFD - Illegal
  2465. //#0xFD:
  2466. function (parentObj) {
  2467. cout("Illegal op code 0xFD called, pausing emulation.", 2);
  2468. pause();
  2469. },
  2470. //CP n
  2471. //#0xFE:
  2472. function (parentObj) {
  2473. var dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
  2474. parentObj.FHalfCarry = (dirtySum & 0xF) > (parentObj.registerA & 0xF);
  2475. parentObj.FCarry = (dirtySum < 0);
  2476. parentObj.FZero = (dirtySum == 0);
  2477. parentObj.programCounter = (parentObj.programCounter + 1) & 0xFFFF;
  2478. parentObj.FSubtract = true;
  2479. },
  2480. //RST 0x38
  2481. //#0xFF:
  2482. function (parentObj) {
  2483. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2484. parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> 8);
  2485. parentObj.stackPointer = (parentObj.stackPointer - 1) & 0xFFFF;
  2486. parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & 0xFF);
  2487. parentObj.programCounter = 0x38;
  2488. }
  2489. );
  2490. GameBoyCore.prototype.CBOPCODE = new Array(
  2491. //#0x00:
  2492. function (parentObj) {
  2493. parentObj.FCarry = ((parentObj.registerB & 0x80) == 0x80);
  2494. parentObj.registerB = ((parentObj.registerB << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2495. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2496. parentObj.FZero = (parentObj.registerB == 0);
  2497. }
  2498. //#0x01:
  2499. ,function (parentObj) {
  2500. parentObj.FCarry = ((parentObj.registerC & 0x80) == 0x80);
  2501. parentObj.registerC = ((parentObj.registerC << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2502. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2503. parentObj.FZero = (parentObj.registerC == 0);
  2504. }
  2505. //#0x02:
  2506. ,function (parentObj) {
  2507. parentObj.FCarry = ((parentObj.registerD & 0x80) == 0x80);
  2508. parentObj.registerD = ((parentObj.registerD << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2509. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2510. parentObj.FZero = (parentObj.registerD == 0);
  2511. }
  2512. //#0x03:
  2513. ,function (parentObj) {
  2514. parentObj.FCarry = ((parentObj.registerE & 0x80) == 0x80);
  2515. parentObj.registerE = ((parentObj.registerE << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2516. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2517. parentObj.FZero = (parentObj.registerE == 0);
  2518. }
  2519. //#0x04:
  2520. ,function (parentObj) {
  2521. parentObj.FCarry = ((parentObj.registersHL & 0x8000) == 0x8000);
  2522. parentObj.registersHL = ((parentObj.registersHL << 1) & 0xFE00) | ((parentObj.FCarry) ? 0x100 : 0) | (parentObj.registersHL & 0xFF);
  2523. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2524. parentObj.FZero = (parentObj.registersHL <= 0xFF);
  2525. }
  2526. //#0x05:
  2527. ,function (parentObj) {
  2528. parentObj.FCarry = ((parentObj.registersHL & 0x80) == 0x80);
  2529. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2530. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2531. parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0x00);
  2532. }
  2533. //#0x06:
  2534. ,function (parentObj) {
  2535. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  2536. parentObj.FCarry = ((temp_var & 0x80) == 0x80);
  2537. temp_var = ((temp_var << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2538. parentObj.memoryWrite(parentObj.registersHL, temp_var);
  2539. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2540. parentObj.FZero = (temp_var == 0x00);
  2541. }
  2542. //#0x07:
  2543. ,function (parentObj) {
  2544. parentObj.FCarry = ((parentObj.registerA & 0x80) == 0x80);
  2545. parentObj.registerA = ((parentObj.registerA << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2546. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2547. parentObj.FZero = (parentObj.registerA == 0x00);
  2548. }
  2549. //#0x08:
  2550. ,function (parentObj) {
  2551. parentObj.FCarry = ((parentObj.registerB & 0x01) == 0x01);
  2552. parentObj.registerB = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerB >> 1);
  2553. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2554. parentObj.FZero = (parentObj.registerB == 0);
  2555. }
  2556. //#0x09:
  2557. ,function (parentObj) {
  2558. parentObj.FCarry = ((parentObj.registerC & 0x01) == 0x01);
  2559. parentObj.registerC = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerC >> 1);
  2560. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2561. parentObj.FZero = (parentObj.registerC == 0);
  2562. }
  2563. //#0x0A:
  2564. ,function (parentObj) {
  2565. parentObj.FCarry = ((parentObj.registerD & 0x01) == 0x01);
  2566. parentObj.registerD = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerD >> 1);
  2567. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2568. parentObj.FZero = (parentObj.registerD == 0);
  2569. }
  2570. //#0x0B:
  2571. ,function (parentObj) {
  2572. parentObj.FCarry = ((parentObj.registerE & 0x01) == 0x01);
  2573. parentObj.registerE = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerE >> 1);
  2574. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2575. parentObj.FZero = (parentObj.registerE == 0);
  2576. }
  2577. //#0x0C:
  2578. ,function (parentObj) {
  2579. parentObj.FCarry = ((parentObj.registersHL & 0x0100) == 0x0100);
  2580. parentObj.registersHL = ((parentObj.FCarry) ? 0x8000 : 0) | ((parentObj.registersHL >> 1) & 0xFF00) | (parentObj.registersHL & 0xFF);
  2581. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2582. parentObj.FZero = (parentObj.registersHL <= 0xFF);
  2583. }
  2584. //#0x0D:
  2585. ,function (parentObj) {
  2586. parentObj.FCarry = ((parentObj.registersHL & 0x01) == 0x01);
  2587. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.FCarry) ? 0x80 : 0) | ((parentObj.registersHL & 0xFF) >> 1);
  2588. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2589. parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0x00);
  2590. }
  2591. //#0x0E:
  2592. ,function (parentObj) {
  2593. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  2594. parentObj.FCarry = ((temp_var & 0x01) == 0x01);
  2595. temp_var = ((parentObj.FCarry) ? 0x80 : 0) | (temp_var >> 1);
  2596. parentObj.memoryWrite(parentObj.registersHL, temp_var);
  2597. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2598. parentObj.FZero = (temp_var == 0x00);
  2599. }
  2600. //#0x0F:
  2601. ,function (parentObj) {
  2602. parentObj.FCarry = ((parentObj.registerA & 0x01) == 0x01);
  2603. parentObj.registerA = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerA >> 1);
  2604. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2605. parentObj.FZero = (parentObj.registerA == 0x00);
  2606. }
  2607. //#0x10:
  2608. ,function (parentObj) {
  2609. var newFCarry = ((parentObj.registerB & 0x80) == 0x80);
  2610. parentObj.registerB = ((parentObj.registerB << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2611. parentObj.FCarry = newFCarry;
  2612. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2613. parentObj.FZero = (parentObj.registerB == 0);
  2614. }
  2615. //#0x11:
  2616. ,function (parentObj) {
  2617. var newFCarry = ((parentObj.registerC & 0x80) == 0x80);
  2618. parentObj.registerC = ((parentObj.registerC << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2619. parentObj.FCarry = newFCarry;
  2620. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2621. parentObj.FZero = (parentObj.registerC == 0);
  2622. }
  2623. //#0x12:
  2624. ,function (parentObj) {
  2625. var newFCarry = ((parentObj.registerD & 0x80) == 0x80);
  2626. parentObj.registerD = ((parentObj.registerD << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2627. parentObj.FCarry = newFCarry;
  2628. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2629. parentObj.FZero = (parentObj.registerD == 0);
  2630. }
  2631. //#0x13:
  2632. ,function (parentObj) {
  2633. var newFCarry = ((parentObj.registerE & 0x80) == 0x80);
  2634. parentObj.registerE = ((parentObj.registerE << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2635. parentObj.FCarry = newFCarry;
  2636. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2637. parentObj.FZero = (parentObj.registerE == 0);
  2638. }
  2639. //#0x14:
  2640. ,function (parentObj) {
  2641. var newFCarry = ((parentObj.registersHL & 0x8000) == 0x8000);
  2642. parentObj.registersHL = ((parentObj.registersHL << 1) & 0xFE00) | ((parentObj.FCarry) ? 0x100 : 0) | (parentObj.registersHL & 0xFF);
  2643. parentObj.FCarry = newFCarry;
  2644. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2645. parentObj.FZero = (parentObj.registersHL <= 0xFF);
  2646. }
  2647. //#0x15:
  2648. ,function (parentObj) {
  2649. var newFCarry = ((parentObj.registersHL & 0x80) == 0x80);
  2650. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2651. parentObj.FCarry = newFCarry;
  2652. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2653. parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0x00);
  2654. }
  2655. //#0x16:
  2656. ,function (parentObj) {
  2657. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  2658. var newFCarry = ((temp_var & 0x80) == 0x80);
  2659. temp_var = ((temp_var << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2660. parentObj.FCarry = newFCarry;
  2661. parentObj.memoryWrite(parentObj.registersHL, temp_var);
  2662. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2663. parentObj.FZero = (temp_var == 0x00);
  2664. }
  2665. //#0x17:
  2666. ,function (parentObj) {
  2667. var newFCarry = ((parentObj.registerA & 0x80) == 0x80);
  2668. parentObj.registerA = ((parentObj.registerA << 1) & 0xFF) | ((parentObj.FCarry) ? 1 : 0);
  2669. parentObj.FCarry = newFCarry;
  2670. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2671. parentObj.FZero = (parentObj.registerA == 0x00);
  2672. }
  2673. //#0x18:
  2674. ,function (parentObj) {
  2675. var newFCarry = ((parentObj.registerB & 0x01) == 0x01);
  2676. parentObj.registerB = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerB >> 1);
  2677. parentObj.FCarry = newFCarry;
  2678. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2679. parentObj.FZero = (parentObj.registerB == 0);
  2680. }
  2681. //#0x19:
  2682. ,function (parentObj) {
  2683. var newFCarry = ((parentObj.registerC & 0x01) == 0x01);
  2684. parentObj.registerC = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerC >> 1);
  2685. parentObj.FCarry = newFCarry;
  2686. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2687. parentObj.FZero = (parentObj.registerC == 0);
  2688. }
  2689. //#0x1A:
  2690. ,function (parentObj) {
  2691. var newFCarry = ((parentObj.registerD & 0x01) == 0x01);
  2692. parentObj.registerD = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerD >> 1);
  2693. parentObj.FCarry = newFCarry;
  2694. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2695. parentObj.FZero = (parentObj.registerD == 0);
  2696. }
  2697. //#0x1B:
  2698. ,function (parentObj) {
  2699. var newFCarry = ((parentObj.registerE & 0x01) == 0x01);
  2700. parentObj.registerE = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerE >> 1);
  2701. parentObj.FCarry = newFCarry;
  2702. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2703. parentObj.FZero = (parentObj.registerE == 0);
  2704. }
  2705. //#0x1C:
  2706. ,function (parentObj) {
  2707. var newFCarry = ((parentObj.registersHL & 0x0100) == 0x0100);
  2708. parentObj.registersHL = ((parentObj.FCarry) ? 0x8000 : 0) | ((parentObj.registersHL >> 1) & 0xFF00) | (parentObj.registersHL & 0xFF);
  2709. parentObj.FCarry = newFCarry;
  2710. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2711. parentObj.FZero = (parentObj.registersHL <= 0xFF);
  2712. }
  2713. //#0x1D:
  2714. ,function (parentObj) {
  2715. var newFCarry = ((parentObj.registersHL & 0x01) == 0x01);
  2716. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.FCarry) ? 0x80 : 0) | ((parentObj.registersHL & 0xFF) >> 1);
  2717. parentObj.FCarry = newFCarry;
  2718. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2719. parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0x00);
  2720. }
  2721. //#0x1E:
  2722. ,function (parentObj) {
  2723. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  2724. var newFCarry = ((temp_var & 0x01) == 0x01);
  2725. temp_var = ((parentObj.FCarry) ? 0x80 : 0) | (temp_var >> 1);
  2726. parentObj.FCarry = newFCarry;
  2727. parentObj.memoryWrite(parentObj.registersHL, temp_var);
  2728. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2729. parentObj.FZero = (temp_var == 0x00);
  2730. }
  2731. //#0x1F:
  2732. ,function (parentObj) {
  2733. var newFCarry = ((parentObj.registerA & 0x01) == 0x01);
  2734. parentObj.registerA = ((parentObj.FCarry) ? 0x80 : 0) | (parentObj.registerA >> 1);
  2735. parentObj.FCarry = newFCarry;
  2736. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2737. parentObj.FZero = (parentObj.registerA == 0x00);
  2738. }
  2739. //#0x20:
  2740. ,function (parentObj) {
  2741. parentObj.FCarry = ((parentObj.registerB & 0x80) == 0x80);
  2742. parentObj.registerB = (parentObj.registerB << 1) & 0xFF;
  2743. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2744. parentObj.FZero = (parentObj.registerB == 0);
  2745. }
  2746. //#0x21:
  2747. ,function (parentObj) {
  2748. parentObj.FCarry = ((parentObj.registerC & 0x80) == 0x80);
  2749. parentObj.registerC = (parentObj.registerC << 1) & 0xFF;
  2750. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2751. parentObj.FZero = (parentObj.registerC == 0);
  2752. }
  2753. //#0x22:
  2754. ,function (parentObj) {
  2755. parentObj.FCarry = ((parentObj.registerD & 0x80) == 0x80);
  2756. parentObj.registerD = (parentObj.registerD << 1) & 0xFF;
  2757. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2758. parentObj.FZero = (parentObj.registerD == 0);
  2759. }
  2760. //#0x23:
  2761. ,function (parentObj) {
  2762. parentObj.FCarry = ((parentObj.registerE & 0x80) == 0x80);
  2763. parentObj.registerE = (parentObj.registerE << 1) & 0xFF;
  2764. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2765. parentObj.FZero = (parentObj.registerE == 0);
  2766. }
  2767. //#0x24:
  2768. ,function (parentObj) {
  2769. parentObj.FCarry = ((parentObj.registersHL & 0x8000) == 0x8000);
  2770. parentObj.registersHL = ((parentObj.registersHL << 1) & 0xFE00) | (parentObj.registersHL & 0xFF);
  2771. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2772. parentObj.FZero = (parentObj.registersHL <= 0xFF);
  2773. }
  2774. //#0x25:
  2775. ,function (parentObj) {
  2776. parentObj.FCarry = ((parentObj.registersHL & 0x0080) == 0x0080);
  2777. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL << 1) & 0xFF);
  2778. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2779. parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0x00);
  2780. }
  2781. //#0x26:
  2782. ,function (parentObj) {
  2783. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  2784. parentObj.FCarry = ((temp_var & 0x80) == 0x80);
  2785. temp_var = (temp_var << 1) & 0xFF;
  2786. parentObj.memoryWrite(parentObj.registersHL, temp_var);
  2787. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2788. parentObj.FZero = (temp_var == 0x00);
  2789. }
  2790. //#0x27:
  2791. ,function (parentObj) {
  2792. parentObj.FCarry = ((parentObj.registerA & 0x80) == 0x80);
  2793. parentObj.registerA = (parentObj.registerA << 1) & 0xFF;
  2794. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2795. parentObj.FZero = (parentObj.registerA == 0x00);
  2796. }
  2797. //#0x28:
  2798. ,function (parentObj) {
  2799. parentObj.FCarry = ((parentObj.registerB & 0x01) == 0x01);
  2800. parentObj.registerB = (parentObj.registerB & 0x80) | (parentObj.registerB >> 1);
  2801. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2802. parentObj.FZero = (parentObj.registerB == 0);
  2803. }
  2804. //#0x29:
  2805. ,function (parentObj) {
  2806. parentObj.FCarry = ((parentObj.registerC & 0x01) == 0x01);
  2807. parentObj.registerC = (parentObj.registerC & 0x80) | (parentObj.registerC >> 1);
  2808. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2809. parentObj.FZero = (parentObj.registerC == 0);
  2810. }
  2811. //#0x2A:
  2812. ,function (parentObj) {
  2813. parentObj.FCarry = ((parentObj.registerD & 0x01) == 0x01);
  2814. parentObj.registerD = (parentObj.registerD & 0x80) | (parentObj.registerD >> 1);
  2815. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2816. parentObj.FZero = (parentObj.registerD == 0);
  2817. }
  2818. //#0x2B:
  2819. ,function (parentObj) {
  2820. parentObj.FCarry = ((parentObj.registerE & 0x01) == 0x01);
  2821. parentObj.registerE = (parentObj.registerE & 0x80) | (parentObj.registerE >> 1);
  2822. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2823. parentObj.FZero = (parentObj.registerE == 0);
  2824. }
  2825. //#0x2C:
  2826. ,function (parentObj) {
  2827. parentObj.FCarry = ((parentObj.registersHL & 0x0100) == 0x0100);
  2828. parentObj.registersHL = ((parentObj.registersHL >> 1) & 0xFF00) | (parentObj.registersHL & 0x80FF);
  2829. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2830. parentObj.FZero = (parentObj.registersHL <= 0xFF);
  2831. }
  2832. //#0x2D:
  2833. ,function (parentObj) {
  2834. parentObj.FCarry = ((parentObj.registersHL & 0x0001) == 0x0001);
  2835. parentObj.registersHL = (parentObj.registersHL & 0xFF80) | ((parentObj.registersHL & 0xFF) >> 1);
  2836. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2837. parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0x00);
  2838. }
  2839. //#0x2E:
  2840. ,function (parentObj) {
  2841. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  2842. parentObj.FCarry = ((temp_var & 0x01) == 0x01);
  2843. temp_var = (temp_var & 0x80) | (temp_var >> 1);
  2844. parentObj.memoryWrite(parentObj.registersHL, temp_var);
  2845. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2846. parentObj.FZero = (temp_var == 0x00);
  2847. }
  2848. //#0x2F:
  2849. ,function (parentObj) {
  2850. parentObj.FCarry = ((parentObj.registerA & 0x01) == 0x01);
  2851. parentObj.registerA = (parentObj.registerA & 0x80) | (parentObj.registerA >> 1);
  2852. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2853. parentObj.FZero = (parentObj.registerA == 0x00);
  2854. }
  2855. //#0x30:
  2856. ,function (parentObj) {
  2857. parentObj.registerB = ((parentObj.registerB & 0xF) << 4) | (parentObj.registerB >> 4);
  2858. parentObj.FZero = (parentObj.registerB == 0);
  2859. parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
  2860. }
  2861. //#0x31:
  2862. ,function (parentObj) {
  2863. parentObj.registerC = ((parentObj.registerC & 0xF) << 4) | (parentObj.registerC >> 4);
  2864. parentObj.FZero = (parentObj.registerC == 0);
  2865. parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
  2866. }
  2867. //#0x32:
  2868. ,function (parentObj) {
  2869. parentObj.registerD = ((parentObj.registerD & 0xF) << 4) | (parentObj.registerD >> 4);
  2870. parentObj.FZero = (parentObj.registerD == 0);
  2871. parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
  2872. }
  2873. //#0x33:
  2874. ,function (parentObj) {
  2875. parentObj.registerE = ((parentObj.registerE & 0xF) << 4) | (parentObj.registerE >> 4);
  2876. parentObj.FZero = (parentObj.registerE == 0);
  2877. parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
  2878. }
  2879. //#0x34:
  2880. ,function (parentObj) {
  2881. parentObj.registersHL = ((parentObj.registersHL & 0xF00) << 4) | ((parentObj.registersHL & 0xF000) >> 4) | (parentObj.registersHL & 0xFF);
  2882. parentObj.FZero = (parentObj.registersHL <= 0xFF);
  2883. parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
  2884. }
  2885. //#0x35:
  2886. ,function (parentObj) {
  2887. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL & 0xF) << 4) | ((parentObj.registersHL & 0xF0) >> 4);
  2888. parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0);
  2889. parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
  2890. }
  2891. //#0x36:
  2892. ,function (parentObj) {
  2893. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  2894. temp_var = ((temp_var & 0xF) << 4) | (temp_var >> 4);
  2895. parentObj.memoryWrite(parentObj.registersHL, temp_var);
  2896. parentObj.FZero = (temp_var == 0);
  2897. parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
  2898. }
  2899. //#0x37:
  2900. ,function (parentObj) {
  2901. parentObj.registerA = ((parentObj.registerA & 0xF) << 4) | (parentObj.registerA >> 4);
  2902. parentObj.FZero = (parentObj.registerA == 0);
  2903. parentObj.FCarry = parentObj.FHalfCarry = parentObj.FSubtract = false;
  2904. }
  2905. //#0x38:
  2906. ,function (parentObj) {
  2907. parentObj.FCarry = ((parentObj.registerB & 0x01) == 0x01);
  2908. parentObj.registerB >>= 1;
  2909. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2910. parentObj.FZero = (parentObj.registerB == 0);
  2911. }
  2912. //#0x39:
  2913. ,function (parentObj) {
  2914. parentObj.FCarry = ((parentObj.registerC & 0x01) == 0x01);
  2915. parentObj.registerC >>= 1;
  2916. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2917. parentObj.FZero = (parentObj.registerC == 0);
  2918. }
  2919. //#0x3A:
  2920. ,function (parentObj) {
  2921. parentObj.FCarry = ((parentObj.registerD & 0x01) == 0x01);
  2922. parentObj.registerD >>= 1;
  2923. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2924. parentObj.FZero = (parentObj.registerD == 0);
  2925. }
  2926. //#0x3B:
  2927. ,function (parentObj) {
  2928. parentObj.FCarry = ((parentObj.registerE & 0x01) == 0x01);
  2929. parentObj.registerE >>= 1;
  2930. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2931. parentObj.FZero = (parentObj.registerE == 0);
  2932. }
  2933. //#0x3C:
  2934. ,function (parentObj) {
  2935. parentObj.FCarry = ((parentObj.registersHL & 0x0100) == 0x0100);
  2936. parentObj.registersHL = ((parentObj.registersHL >> 1) & 0xFF00) | (parentObj.registersHL & 0xFF);
  2937. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2938. parentObj.FZero = (parentObj.registersHL <= 0xFF);
  2939. }
  2940. //#0x3D:
  2941. ,function (parentObj) {
  2942. parentObj.FCarry = ((parentObj.registersHL & 0x0001) == 0x0001);
  2943. parentObj.registersHL = (parentObj.registersHL & 0xFF00) | ((parentObj.registersHL & 0xFF) >> 1);
  2944. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2945. parentObj.FZero = ((parentObj.registersHL & 0xFF) == 0x00);
  2946. }
  2947. //#0x3E:
  2948. ,function (parentObj) {
  2949. var temp_var = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
  2950. parentObj.FCarry = ((temp_var & 0x01) == 0x01);
  2951. parentObj.memoryWrite(parentObj.registersHL, temp_var >>= 1);
  2952. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2953. parentObj.FZero = (temp_var == 0x00);
  2954. }
  2955. //#0x3F:
  2956. ,function (parentObj) {
  2957. parentObj.FCarry = ((parentObj.registerA & 0x01) == 0x01);
  2958. parentObj.registerA >>= 1;
  2959. parentObj.FHalfCarry = parentObj.FSubtract = false;
  2960. parentObj.FZero = (parentObj.registerA == 0x00);
  2961. }
  2962. //#0x40:
  2963. ,function (parentObj) {
  2964. parentObj.FHalfCarry = true;
  2965. parentObj.FSubtract = false;
  2966. parentObj.FZero = ((parentObj.registerB & 0x01) == 0);
  2967. }
  2968. //#0x41:
  2969. ,function (parentObj) {
  2970. parentObj.FHalfCarry = true;
  2971. parentObj.FSubtract = false;
  2972. parentObj.FZero = ((parentObj.registerC & 0x01) == 0);
  2973. }
  2974. //#0x42:
  2975. ,function (parentObj) {
  2976. parentObj.FHalfCarry = true;
  2977. parentObj.FSubtract = false;
  2978. parentObj.FZero = ((parentObj.registerD & 0x01) == 0);
  2979. }
  2980. //#0x43:
  2981. ,function (parentObj) {
  2982. parentObj.FHalfCarry = true;
  2983. parentObj.FSubtract = false;
  2984. parentObj.FZero = ((parentObj.registerE & 0x01) == 0);
  2985. }
  2986. //#0x44:
  2987. ,function (parentObj) {
  2988. parentObj.FHalfCarry = true;
  2989. parentObj.FSubtract = false;
  2990. parentObj.FZero = ((parentObj.registersHL & 0x0100) == 0);
  2991. }
  2992. //#0x45:
  2993. ,function (parentObj) {
  2994. parentObj.FHalfCarry = true;
  2995. parentObj.FSubtract = false;
  2996. parentObj.FZero = ((parentObj.registersHL & 0x0001) == 0);
  2997. }
  2998. //#0x46:
  2999. ,function (parentObj) {
  3000. parentObj.FHalfCarry = true;
  3001. parentObj.FSubtract = false;
  3002. parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x01) == 0);
  3003. }
  3004. //#0x47:
  3005. ,function (parentObj) {
  3006. parentObj.FHalfCarry = true;
  3007. parentObj.FSubtract = false;
  3008. parentObj.FZero = ((parentObj.registerA & 0x01) == 0);
  3009. }
  3010. //#0x48:
  3011. ,function (parentObj) {
  3012. parentObj.FHalfCarry = true;
  3013. parentObj.FSubtract = false;
  3014. parentObj.FZero = ((parentObj.registerB & 0x02) == 0);
  3015. }
  3016. //#0x49:
  3017. ,function (parentObj) {
  3018. parentObj.FHalfCarry = true;
  3019. parentObj.FSubtract = false;
  3020. parentObj.FZero = ((parentObj.registerC & 0x02) == 0);
  3021. }
  3022. //#0x4A:
  3023. ,function (parentObj) {
  3024. parentObj.FHalfCarry = true;
  3025. parentObj.FSubtract = false;
  3026. parentObj.FZero = ((parentObj.registerD & 0x02) == 0);
  3027. }
  3028. //#0x4B:
  3029. ,function (parentObj) {
  3030. parentObj.FHalfCarry = true;
  3031. parentObj.FSubtract = false;
  3032. parentObj.FZero = ((parentObj.registerE & 0x02) == 0);
  3033. }
  3034. //#0x4C:
  3035. ,function (parentObj) {
  3036. parentObj.FHalfCarry = true;
  3037. parentObj.FSubtract = false;
  3038. parentObj.FZero = ((parentObj.registersHL & 0x0200) == 0);
  3039. }
  3040. //#0x4D:
  3041. ,function (parentObj) {
  3042. parentObj.FHalfCarry = true;
  3043. parentObj.FSubtract = false;
  3044. parentObj.FZero = ((parentObj.registersHL & 0x0002) == 0);
  3045. }
  3046. //#0x4E:
  3047. ,function (parentObj) {
  3048. parentObj.FHalfCarry = true;
  3049. parentObj.FSubtract = false;
  3050. parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x02) == 0);
  3051. }
  3052. //#0x4F:
  3053. ,function (parentObj) {
  3054. parentObj.FHalfCarry = true;
  3055. parentObj.FSubtract = false;
  3056. parentObj.FZero = ((parentObj.registerA & 0x02) == 0);
  3057. }
  3058. //#0x50:
  3059. ,function (parentObj) {
  3060. parentObj.FHalfCarry = true;
  3061. parentObj.FSubtract = false;
  3062. parentObj.FZero = ((parentObj.registerB & 0x04) == 0);
  3063. }
  3064. //#0x51:
  3065. ,function (parentObj) {
  3066. parentObj.FHalfCarry = true;
  3067. parentObj.FSubtract = false;
  3068. parentObj.FZero = ((parentObj.registerC & 0x04) == 0);
  3069. }
  3070. //#0x52:
  3071. ,function (parentObj) {
  3072. parentObj.FHalfCarry = true;
  3073. parentObj.FSubtract = false;
  3074. parentObj.FZero = ((parentObj.registerD & 0x04) == 0);
  3075. }
  3076. //#0x53:
  3077. ,function (parentObj) {
  3078. parentObj.FHalfCarry = true;
  3079. parentObj.FSubtract = false;
  3080. parentObj.FZero = ((parentObj.registerE & 0x04) == 0);
  3081. }
  3082. //#0x54:
  3083. ,function (parentObj) {
  3084. parentObj.FHalfCarry = true;
  3085. parentObj.FSubtract = false;
  3086. parentObj.FZero = ((parentObj.registersHL & 0x0400) == 0);
  3087. }
  3088. //#0x55:
  3089. ,function (parentObj) {
  3090. parentObj.FHalfCarry = true;
  3091. parentObj.FSubtract = false;
  3092. parentObj.FZero = ((parentObj.registersHL & 0x0004) == 0);
  3093. }
  3094. //#0x56:
  3095. ,function (parentObj) {
  3096. parentObj.FHalfCarry = true;
  3097. parentObj.FSubtract = false;
  3098. parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x04) == 0);
  3099. }
  3100. //#0x57:
  3101. ,function (parentObj) {
  3102. parentObj.FHalfCarry = true;
  3103. parentObj.FSubtract = false;
  3104. parentObj.FZero = ((parentObj.registerA & 0x04) == 0);
  3105. }
  3106. //#0x58:
  3107. ,function (parentObj) {
  3108. parentObj.FHalfCarry = true;
  3109. parentObj.FSubtract = false;
  3110. parentObj.FZero = ((parentObj.registerB & 0x08) == 0);
  3111. }
  3112. //#0x59:
  3113. ,function (parentObj) {
  3114. parentObj.FHalfCarry = true;
  3115. parentObj.FSubtract = false;
  3116. parentObj.FZero = ((parentObj.registerC & 0x08) == 0);
  3117. }
  3118. //#0x5A:
  3119. ,function (parentObj) {
  3120. parentObj.FHalfCarry = true;
  3121. parentObj.FSubtract = false;
  3122. parentObj.FZero = ((parentObj.registerD & 0x08) == 0);
  3123. }
  3124. //#0x5B:
  3125. ,function (parentObj) {
  3126. parentObj.FHalfCarry = true;
  3127. parentObj.FSubtract = false;
  3128. parentObj.FZero = ((parentObj.registerE & 0x08) == 0);
  3129. }
  3130. //#0x5C:
  3131. ,function (parentObj) {
  3132. parentObj.FHalfCarry = true;
  3133. parentObj.FSubtract = false;
  3134. parentObj.FZero = ((parentObj.registersHL & 0x0800) == 0);
  3135. }
  3136. //#0x5D:
  3137. ,function (parentObj) {
  3138. parentObj.FHalfCarry = true;
  3139. parentObj.FSubtract = false;
  3140. parentObj.FZero = ((parentObj.registersHL & 0x0008) == 0);
  3141. }
  3142. //#0x5E:
  3143. ,function (parentObj) {
  3144. parentObj.FHalfCarry = true;
  3145. parentObj.FSubtract = false;
  3146. parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x08) == 0);
  3147. }
  3148. //#0x5F:
  3149. ,function (parentObj) {
  3150. parentObj.FHalfCarry = true;
  3151. parentObj.FSubtract = false;
  3152. parentObj.FZero = ((parentObj.registerA & 0x08) == 0);
  3153. }
  3154. //#0x60:
  3155. ,function (parentObj) {
  3156. parentObj.FHalfCarry = true;
  3157. parentObj.FSubtract = false;
  3158. parentObj.FZero = ((parentObj.registerB & 0x10) == 0);
  3159. }
  3160. //#0x61:
  3161. ,function (parentObj) {
  3162. parentObj.FHalfCarry = true;
  3163. parentObj.FSubtract = false;
  3164. parentObj.FZero = ((parentObj.registerC & 0x10) == 0);
  3165. }
  3166. //#0x62:
  3167. ,function (parentObj) {
  3168. parentObj.FHalfCarry = true;
  3169. parentObj.FSubtract = false;
  3170. parentObj.FZero = ((parentObj.registerD & 0x10) == 0);
  3171. }
  3172. //#0x63:
  3173. ,function (parentObj) {
  3174. parentObj.FHalfCarry = true;
  3175. parentObj.FSubtract = false;
  3176. parentObj.FZero = ((parentObj.registerE & 0x10) == 0);
  3177. }
  3178. //#0x64:
  3179. ,function (parentObj) {
  3180. parentObj.FHalfCarry = true;
  3181. parentObj.FSubtract = false;
  3182. parentObj.FZero = ((parentObj.registersHL & 0x1000) == 0);
  3183. }
  3184. //#0x65:
  3185. ,function (parentObj) {
  3186. parentObj.FHalfCarry = true;
  3187. parentObj.FSubtract = false;
  3188. parentObj.FZero = ((parentObj.registersHL & 0x0010) == 0);
  3189. }
  3190. //#0x66:
  3191. ,function (parentObj) {
  3192. parentObj.FHalfCarry = true;
  3193. parentObj.FSubtract = false;
  3194. parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x10) == 0);
  3195. }
  3196. //#0x67:
  3197. ,function (parentObj) {
  3198. parentObj.FHalfCarry = true;
  3199. parentObj.FSubtract = false;
  3200. parentObj.FZero = ((parentObj.registerA & 0x10) == 0);
  3201. }
  3202. //#0x68:
  3203. ,function (parentObj) {
  3204. parentObj.FHalfCarry = true;
  3205. parentObj.FSubtract = false;
  3206. parentObj.FZero = ((parentObj.registerB & 0x20) == 0);
  3207. }
  3208. //#0x69:
  3209. ,function (parentObj) {
  3210. parentObj.FHalfCarry = true;
  3211. parentObj.FSubtract = false;
  3212. parentObj.FZero = ((parentObj.registerC & 0x20) == 0);
  3213. }
  3214. //#0x6A:
  3215. ,function (parentObj) {
  3216. parentObj.FHalfCarry = true;
  3217. parentObj.FSubtract = false;
  3218. parentObj.FZero = ((parentObj.registerD & 0x20) == 0);
  3219. }
  3220. //#0x6B:
  3221. ,function (parentObj) {
  3222. parentObj.FHalfCarry = true;
  3223. parentObj.FSubtract = false;
  3224. parentObj.FZero = ((parentObj.registerE & 0x20) == 0);
  3225. }
  3226. //#0x6C:
  3227. ,function (parentObj) {
  3228. parentObj.FHalfCarry = true;
  3229. parentObj.FSubtract = false;
  3230. parentObj.FZero = ((parentObj.registersHL & 0x2000) == 0);
  3231. }
  3232. //#0x6D:
  3233. ,function (parentObj) {
  3234. parentObj.FHalfCarry = true;
  3235. parentObj.FSubtract = false;
  3236. parentObj.FZero = ((parentObj.registersHL & 0x0020) == 0);
  3237. }
  3238. //#0x6E:
  3239. ,function (parentObj) {
  3240. parentObj.FHalfCarry = true;
  3241. parentObj.FSubtract = false;
  3242. parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x20) == 0);
  3243. }
  3244. //#0x6F:
  3245. ,function (parentObj) {
  3246. parentObj.FHalfCarry = true;
  3247. parentObj.FSubtract = false;
  3248. parentObj.FZero = ((parentObj.registerA & 0x20) == 0);
  3249. }
  3250. //#0x70:
  3251. ,function (parentObj) {
  3252. parentObj.FHalfCarry = true;
  3253. parentObj.FSubtract = false;
  3254. parentObj.FZero = ((parentObj.registerB & 0x40) == 0);
  3255. }
  3256. //#0x71:
  3257. ,function (parentObj) {
  3258. parentObj.FHalfCarry = true;
  3259. parentObj.FSubtract = false;
  3260. parentObj.FZero = ((parentObj.registerC & 0x40) == 0);
  3261. }
  3262. //#0x72:
  3263. ,function (parentObj) {
  3264. parentObj.FHalfCarry = true;
  3265. parentObj.FSubtract = false;
  3266. parentObj.FZero = ((parentObj.registerD & 0x40) == 0);
  3267. }
  3268. //#0x73:
  3269. ,function (parentObj) {
  3270. parentObj.FHalfCarry = true;
  3271. parentObj.FSubtract = false;
  3272. parentObj.FZero = ((parentObj.registerE & 0x40) == 0);
  3273. }
  3274. //#0x74:
  3275. ,function (parentObj) {
  3276. parentObj.FHalfCarry = true;
  3277. parentObj.FSubtract = false;
  3278. parentObj.FZero = ((parentObj.registersHL & 0x4000) == 0);
  3279. }
  3280. //#0x75:
  3281. ,function (parentObj) {
  3282. parentObj.FHalfCarry = true;
  3283. parentObj.FSubtract = false;
  3284. parentObj.FZero = ((parentObj.registersHL & 0x0040) == 0);
  3285. }
  3286. //#0x76:
  3287. ,function (parentObj) {
  3288. parentObj.FHalfCarry = true;
  3289. parentObj.FSubtract = false;
  3290. parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x40) == 0);
  3291. }
  3292. //#0x77:
  3293. ,function (parentObj) {
  3294. parentObj.FHalfCarry = true;
  3295. parentObj.FSubtract = false;
  3296. parentObj.FZero = ((parentObj.registerA & 0x40) == 0);
  3297. }
  3298. //#0x78:
  3299. ,function (parentObj) {
  3300. parentObj.FHalfCarry = true;
  3301. parentObj.FSubtract = false;
  3302. parentObj.FZero = ((parentObj.registerB & 0x80) == 0);
  3303. }
  3304. //#0x79:
  3305. ,function (parentObj) {
  3306. parentObj.FHalfCarry = true;
  3307. parentObj.FSubtract = false;
  3308. parentObj.FZero = ((parentObj.registerC & 0x80) == 0);
  3309. }
  3310. //#0x7A:
  3311. ,function (parentObj) {
  3312. parentObj.FHalfCarry = true;
  3313. parentObj.FSubtract = false;
  3314. parentObj.FZero = ((parentObj.registerD & 0x80) == 0);
  3315. }
  3316. //#0x7B:
  3317. ,function (parentObj) {
  3318. parentObj.FHalfCarry = true;
  3319. parentObj.FSubtract = false;
  3320. parentObj.FZero = ((parentObj.registerE & 0x80) == 0);
  3321. }
  3322. //#0x7C:
  3323. ,function (parentObj) {
  3324. parentObj.FHalfCarry = true;
  3325. parentObj.FSubtract = false;
  3326. parentObj.FZero = ((parentObj.registersHL & 0x8000) == 0);
  3327. }
  3328. //#0x7D:
  3329. ,function (parentObj) {
  3330. parentObj.FHalfCarry = true;
  3331. parentObj.FSubtract = false;
  3332. parentObj.FZero = ((parentObj.registersHL & 0x0080) == 0);
  3333. }
  3334. //#0x7E:
  3335. ,function (parentObj) {
  3336. parentObj.FHalfCarry = true;
  3337. parentObj.FSubtract = false;
  3338. parentObj.FZero = ((parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x80) == 0);
  3339. }
  3340. //#0x7F:
  3341. ,function (parentObj) {
  3342. parentObj.FHalfCarry = true;
  3343. parentObj.FSubtract = false;
  3344. parentObj.FZero = ((parentObj.registerA & 0x80) == 0);
  3345. }
  3346. //#0x80:
  3347. ,function (parentObj) {
  3348. parentObj.registerB &= 0xFE;
  3349. }
  3350. //#0x81:
  3351. ,function (parentObj) {
  3352. parentObj.registerC &= 0xFE;
  3353. }
  3354. //#0x82:
  3355. ,function (parentObj) {
  3356. parentObj.registerD &= 0xFE;
  3357. }
  3358. //#0x83:
  3359. ,function (parentObj) {
  3360. parentObj.registerE &= 0xFE;
  3361. }
  3362. //#0x84:
  3363. ,function (parentObj) {
  3364. parentObj.registersHL &= 0xFEFF;
  3365. }
  3366. //#0x85:
  3367. ,function (parentObj) {
  3368. parentObj.registersHL &= 0xFFFE;
  3369. }
  3370. //#0x86:
  3371. ,function (parentObj) {
  3372. parentObj.memoryWrite(parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xFE);
  3373. }
  3374. //#0x87:
  3375. ,function (parentObj) {
  3376. parentObj.registerA &= 0xFE;
  3377. }
  3378. //#0x88:
  3379. ,function (parentObj) {
  3380. parentObj.registerB &= 0xFD;
  3381. }
  3382. //#0x89:
  3383. ,function (parentObj) {
  3384. parentObj.registerC &= 0xFD;
  3385. }
  3386. //#0x8A:
  3387. ,function (parentObj) {
  3388. parentObj.registerD &= 0xFD;
  3389. }
  3390. //#0x8B:
  3391. ,function (parentObj) {
  3392. parentObj.registerE &= 0xFD;
  3393. }
  3394. //#0x8C:
  3395. ,function (parentObj) {
  3396. parentObj.registersHL &= 0xFDFF;
  3397. }
  3398. //#0x8D:
  3399. ,function (parentObj) {
  3400. parentObj.registersHL &= 0xFFFD;
  3401. }
  3402. //#0x8E:
  3403. ,function (parentObj) {
  3404. parentObj.memoryWrite(parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xFD);
  3405. }
  3406. //#0x8F:
  3407. ,function (parentObj) {
  3408. parentObj.registerA &= 0xFD;
  3409. }
  3410. //#0xA0:
  3411. ,function (parentObj) {
  3412. parentObj.registerB &= 0xFB;
  3413. }
  3414. //#0xA1:
  3415. ,function (parentObj) {
  3416. parentObj.registerC &= 0xFB;
  3417. }
  3418. //#0xA2:
  3419. ,function (parentObj) {
  3420. parentObj.registerD &= 0xFB;
  3421. }
  3422. //#0xA3:
  3423. ,function (parentObj) {
  3424. parentObj.registerE &= 0xFB;
  3425. }
  3426. //#0xA4:
  3427. ,function (parentObj) {
  3428. parentObj.registersHL &= 0xFBFF;
  3429. }
  3430. //#0xA5:
  3431. ,function (parentObj) {
  3432. parentObj.registersHL &= 0xFFFB;
  3433. }
  3434. //#0xA6:
  3435. ,function (parentObj) {
  3436. parentObj.memoryWrite(parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xFB);
  3437. }
  3438. //#0xA7:
  3439. ,function (parentObj) {
  3440. parentObj.registerA &= 0xFB;
  3441. }
  3442. //#0xA8:
  3443. ,function (parentObj) {
  3444. parentObj.registerB &= 0xF7;
  3445. }
  3446. //#0xA9:
  3447. ,function (parentObj) {
  3448. parentObj.registerC &= 0xF7;
  3449. }
  3450. //#0xAA:
  3451. ,function (parentObj) {
  3452. parentObj.registerD &= 0xF7;
  3453. }
  3454. //#0xAB:
  3455. ,function (parentObj) {
  3456. parentObj.registerE &= 0xF7;
  3457. }
  3458. //#0xAC:
  3459. ,function (parentObj) {
  3460. parentObj.registersHL &= 0xF7FF;
  3461. }
  3462. //#0xAD:
  3463. ,function (parentObj) {
  3464. parentObj.registersHL &= 0xFFF7;
  3465. }
  3466. //#0xAE:
  3467. ,function (parentObj) {
  3468. parentObj.memoryWrite(parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xF7);
  3469. }
  3470. //#0xAF:
  3471. ,function (parentObj) {
  3472. parentObj.registerA &= 0xF7;
  3473. }
  3474. //#0xB0:
  3475. ,function (parentObj) {
  3476. parentObj.registerB &= 0xEF;
  3477. }
  3478. //#0xB1:
  3479. ,function (parentObj) {
  3480. parentObj.registerC &= 0xEF;
  3481. }
  3482. //#0xB2:
  3483. ,function (parentObj) {
  3484. parentObj.registerD &= 0xEF;
  3485. }
  3486. //#0xB3:
  3487. ,function (parentObj) {
  3488. parentObj.registerE &= 0xEF;
  3489. }
  3490. //#0xB4:
  3491. ,function (parentObj) {
  3492. parentObj.registersHL &= 0xEFFF;
  3493. }
  3494. //#0xB5:
  3495. ,function (parentObj) {
  3496. parentObj.registersHL &= 0xFFEF;
  3497. }
  3498. //#0xB6:
  3499. ,function (parentObj) {
  3500. parentObj.memoryWrite(parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xEF);
  3501. }
  3502. //#0xB7:
  3503. ,function (parentObj) {
  3504. parentObj.registerA &= 0xEF;
  3505. }
  3506. //#0xB8:
  3507. ,function (parentObj) {
  3508. parentObj.registerB &= 0xDF;
  3509. }
  3510. //#0xB9:
  3511. ,function (parentObj) {
  3512. parentObj.registerC &= 0xDF;
  3513. }
  3514. //#0xBA:
  3515. ,function (parentObj) {
  3516. parentObj.registerD &= 0xDF;
  3517. }
  3518. //#0xBB:
  3519. ,function (parentObj) {
  3520. parentObj.registerE &= 0xDF;
  3521. }
  3522. //#0xBC:
  3523. ,function (parentObj) {
  3524. parentObj.registersHL &= 0xDFFF;
  3525. }
  3526. //#0xBD:
  3527. ,function (parentObj) {
  3528. parentObj.registersHL &= 0xFFDF;
  3529. }
  3530. //#0xBE:
  3531. ,function (parentObj) {
  3532. parentObj.memoryWrite(parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xDF);
  3533. }
  3534. //#0xBF:
  3535. ,function (parentObj) {
  3536. parentObj.registerA &= 0xDF;
  3537. }
  3538. //#0xC0:
  3539. ,function (parentObj) {
  3540. parentObj.registerB &= 0xBF;
  3541. }
  3542. //#0xC1:
  3543. ,function (parentObj) {
  3544. parentObj.registerC &= 0xBF;
  3545. }
  3546. //#0xC2:
  3547. ,function (parentObj) {
  3548. parentObj.registerD &= 0xBF;
  3549. }
  3550. //#0xC3:
  3551. ,function (parentObj) {
  3552. parentObj.registerE &= 0xBF;
  3553. }
  3554. //#0x:
  3555. ,function (parentObj) {
  3556. parentObj.registersHL &= 0xBFFF;
  3557. }
  3558. //#0x:
  3559. ,function (parentObj) {
  3560. parentObj.registersHL &= 0xFFBF;
  3561. }
  3562. //#0x:
  3563. ,function (parentObj) {
  3564. parentObj.memoryWrite(parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0xBF);
  3565. }
  3566. //#0x:
  3567. ,function (parentObj) {
  3568. parentObj.registerA &= 0xBF;
  3569. }
  3570. //#0x:
  3571. ,function (parentObj) {
  3572. parentObj.registerB &= 0x7F;
  3573. }
  3574. //#0x:
  3575. ,function (parentObj) {
  3576. parentObj.registerC &= 0x7F;
  3577. }
  3578. //#0x:
  3579. ,function (parentObj) {
  3580. parentObj.registerD &= 0x7F;
  3581. }
  3582. //#0x:
  3583. ,function (parentObj) {
  3584. parentObj.registerE &= 0x7F;
  3585. }
  3586. //#0x:
  3587. ,function (parentObj) {
  3588. parentObj.registersHL &= 0x7FFF;
  3589. }
  3590. //#0x:
  3591. ,function (parentObj) {
  3592. parentObj.registersHL &= 0xFF7F;
  3593. }
  3594. //#0x:
  3595. ,function (parentObj) {
  3596. parentObj.memoryWrite(parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & 0x7F);
  3597. }
  3598. //#0x:
  3599. ,function (parentObj) {
  3600. parentObj.registerA &= 0x7F;
  3601. }
  3602. //#0x:
  3603. ,function (parentObj) {
  3604. parentObj.registerB |= 0x01;
  3605. }
  3606. //#0x:
  3607. ,function (parentObj) {
  3608. parentObj.registerC |= 0x01;
  3609. }
  3610. //#0x:
  3611. ,function (parentObj) {
  3612. parentObj.registerD |= 0x01;
  3613. }
  3614. //#0x:
  3615. ,function (parentObj) {
  3616. parentObj.registerE |= 0x01;
  3617. }
  3618. //#0x:
  3619. ,function (parentObj) {
  3620. parentObj.registersHL |= 0x0100;
  3621. }
  3622. //#0x:
  3623. ,function (parentObj) {
  3624. parentObj.registersHL |= 0x01;
  3625. }
  3626. //#0x:
  3627. ,function (parentObj) {
  3628. parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x01);
  3629. }
  3630. //#0x:
  3631. ,function (parentObj) {
  3632. parentObj.registerA |= 0x01;
  3633. }
  3634. //#0x:
  3635. ,function (parentObj) {
  3636. parentObj.registerB |= 0x02;
  3637. }
  3638. //#0x:
  3639. ,function (parentObj) {
  3640. parentObj.registerC |= 0x02;
  3641. }
  3642. //#0x:
  3643. ,function (parentObj) {
  3644. parentObj.registerD |= 0x02;
  3645. }
  3646. //#0x:
  3647. ,function (parentObj) {
  3648. parentObj.registerE |= 0x02;
  3649. }
  3650. //#0x:
  3651. ,function (parentObj) {
  3652. parentObj.registersHL |= 0x0200;
  3653. }
  3654. //#0x:
  3655. ,function (parentObj) {
  3656. parentObj.registersHL |= 0x02;
  3657. }
  3658. //#0x:
  3659. ,function (parentObj) {
  3660. parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x02);
  3661. }
  3662. //#0x:
  3663. ,function (parentObj) {
  3664. parentObj.registerA |= 0x02;
  3665. }
  3666. //#0x:
  3667. ,function (parentObj) {
  3668. parentObj.registerB |= 0x04;
  3669. }
  3670. //#0x:
  3671. ,function (parentObj) {
  3672. parentObj.registerC |= 0x04;
  3673. }
  3674. //#0x:
  3675. ,function (parentObj) {
  3676. parentObj.registerD |= 0x04;
  3677. }
  3678. //#0x:
  3679. ,function (parentObj) {
  3680. parentObj.registerE |= 0x04;
  3681. }
  3682. //#0x:
  3683. ,function (parentObj) {
  3684. parentObj.registersHL |= 0x0400;
  3685. }
  3686. //#0x:
  3687. ,function (parentObj) {
  3688. parentObj.registersHL |= 0x04;
  3689. }
  3690. //#0x:
  3691. ,function (parentObj) {
  3692. parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x04);
  3693. }
  3694. //#0x:
  3695. ,function (parentObj) {
  3696. parentObj.registerA |= 0x04;
  3697. }
  3698. //#0x:
  3699. ,function (parentObj) {
  3700. parentObj.registerB |= 0x08;
  3701. }
  3702. //#0x:
  3703. ,function (parentObj) {
  3704. parentObj.registerC |= 0x08;
  3705. }
  3706. //#0x:
  3707. ,function (parentObj) {
  3708. parentObj.registerD |= 0x08;
  3709. }
  3710. //#0x:
  3711. ,function (parentObj) {
  3712. parentObj.registerE |= 0x08;
  3713. }
  3714. //#0x:
  3715. ,function (parentObj) {
  3716. parentObj.registersHL |= 0x0800;
  3717. }
  3718. //#0x:
  3719. ,function (parentObj) {
  3720. parentObj.registersHL |= 0x08;
  3721. }
  3722. //#0x:
  3723. ,function (parentObj) {
  3724. parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x08);
  3725. }
  3726. //#0x:
  3727. ,function (parentObj) {
  3728. parentObj.registerA |= 0x08;
  3729. }
  3730. //#0x:
  3731. ,function (parentObj) {
  3732. parentObj.registerB |= 0x10;
  3733. }
  3734. //#0x:
  3735. ,function (parentObj) {
  3736. parentObj.registerC |= 0x10;
  3737. }
  3738. //#0x:
  3739. ,function (parentObj) {
  3740. parentObj.registerD |= 0x10;
  3741. }
  3742. //#0x:
  3743. ,function (parentObj) {
  3744. parentObj.registerE |= 0x10;
  3745. }
  3746. //#0x:
  3747. ,function (parentObj) {
  3748. parentObj.registersHL |= 0x1000;
  3749. }
  3750. //#0x:
  3751. ,function (parentObj) {
  3752. parentObj.registersHL |= 0x10;
  3753. }
  3754. //#0x:
  3755. ,function (parentObj) {
  3756. parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x10);
  3757. }
  3758. //#0x:
  3759. ,function (parentObj) {
  3760. parentObj.registerA |= 0x10;
  3761. }
  3762. //#0x:
  3763. ,function (parentObj) {
  3764. parentObj.registerB |= 0x20;
  3765. }
  3766. //#0x:
  3767. ,function (parentObj) {
  3768. parentObj.registerC |= 0x20;
  3769. }
  3770. //#0x:
  3771. ,function (parentObj) {
  3772. parentObj.registerD |= 0x20;
  3773. }
  3774. //#0x:
  3775. ,function (parentObj) {
  3776. parentObj.registerE |= 0x20;
  3777. }
  3778. //#0x:
  3779. ,function (parentObj) {
  3780. parentObj.registersHL |= 0x2000;
  3781. }
  3782. //#0x:
  3783. ,function (parentObj) {
  3784. parentObj.registersHL |= 0x20;
  3785. }
  3786. //#0x:
  3787. ,function (parentObj) {
  3788. parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x20);
  3789. }
  3790. //#0x:
  3791. ,function (parentObj) {
  3792. parentObj.registerA |= 0x20;
  3793. }
  3794. //#0x:
  3795. ,function (parentObj) {
  3796. parentObj.registerB |= 0x40;
  3797. }
  3798. //#0x:
  3799. ,function (parentObj) {
  3800. parentObj.registerC |= 0x40;
  3801. }
  3802. //#0x:
  3803. ,function (parentObj) {
  3804. parentObj.registerD |= 0x40;
  3805. }
  3806. //#0x:
  3807. ,function (parentObj) {
  3808. parentObj.registerE |= 0x40;
  3809. }
  3810. //#0x:
  3811. ,function (parentObj) {
  3812. parentObj.registersHL |= 0x4000;
  3813. }
  3814. //#0x:
  3815. ,function (parentObj) {
  3816. parentObj.registersHL |= 0x40;
  3817. }
  3818. //#0x:
  3819. ,function (parentObj) {
  3820. parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x40);
  3821. }
  3822. //#0x:
  3823. ,function (parentObj) {
  3824. parentObj.registerA |= 0x40;
  3825. }
  3826. //#0xF8:
  3827. ,function (parentObj) {
  3828. parentObj.registerB |= 0x80;
  3829. }
  3830. //#0xF9:
  3831. ,function (parentObj) {
  3832. parentObj.registerC |= 0x80;
  3833. }
  3834. //#0xFA:
  3835. ,function (parentObj) {
  3836. parentObj.registerD |= 0x80;
  3837. }
  3838. //#0xFB:
  3839. ,function (parentObj) {
  3840. parentObj.registerE |= 0x80;
  3841. }
  3842. //#0xFC:
  3843. ,function (parentObj) {
  3844. parentObj.registersHL |= 0x8000;
  3845. }
  3846. //#0xFD:
  3847. ,function (parentObj) {
  3848. parentObj.registersHL |= 0x80;
  3849. }
  3850. //#0xFE:
  3851. ,function (parentObj) {
  3852. parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | 0x80);
  3853. }
  3854. //#0xFF:
  3855. ,function (parentObj) {
  3856. parentObj.registerA |= 0x80;
  3857. }
  3858. );
  3859. GameBoyCore.prototype.TICKTable = new Array( //Number of machine cycles for each instruction:
  3860. /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F*/
  3861. 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1, //0
  3862. 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, //1
  3863. 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, //2
  3864. 2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1, //3
  3865.  
  3866. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, //4
  3867. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, //5
  3868. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, //6
  3869. 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, //7
  3870.  
  3871. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, //8
  3872. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, //9
  3873. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, //A
  3874. 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, //B
  3875.  
  3876. 2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4, //C
  3877. 2, 3, 3, 1, 3, 4, 2, 4, 2, 4, 3, 1, 3, 1, 2, 4, //D
  3878. 3, 3, 2, 1, 1, 4, 2, 4, 4, 1, 4, 1, 1, 1, 2, 4, //E
  3879. 3, 3, 2, 1, 1, 4, 2, 4, 3, 2, 4, 1, 0, 1, 2, 4 //F
  3880. );
  3881. GameBoyCore.prototype.SecondaryTICKTable = new Array( //Number of machine cycles for each 0xCBXX instruction:
  3882. /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F*/
  3883. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //0
  3884. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //1
  3885. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //2
  3886. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //3
  3887.  
  3888. 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, //4
  3889. 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, //5
  3890. 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, //6
  3891. 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, //7
  3892.  
  3893. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //8
  3894. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //9
  3895. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //A
  3896. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //B
  3897.  
  3898. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //C
  3899. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //D
  3900. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, //E
  3901. 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2 //F
  3902. );
  3903. GameBoyCore.prototype.saveSRAMState = function () {
  3904. if (!this.cBATT || this.MBCRam.length == 0) {
  3905. //No battery backup...
  3906. return [];
  3907. }
  3908. else {
  3909. //Return the MBC RAM for backup...
  3910. return this.fromTypedArray(this.MBCRam);
  3911. }
  3912. }
  3913. GameBoyCore.prototype.saveRTCState = function () {
  3914. if (!this.cTIMER) {
  3915. //No battery backup...
  3916. return [];
  3917. }
  3918. else {
  3919. //Return the MBC RAM for backup...
  3920. return [
  3921. this.lastIteration,
  3922. this.RTCisLatched,
  3923. this.latchedSeconds,
  3924. this.latchedMinutes,
  3925. this.latchedHours,
  3926. this.latchedLDays,
  3927. this.latchedHDays,
  3928. this.RTCSeconds,
  3929. this.RTCMinutes,
  3930. this.RTCHours,
  3931. this.RTCDays,
  3932. this.RTCDayOverFlow,
  3933. this.RTCHALT
  3934. ];
  3935. }
  3936. }
  3937. GameBoyCore.prototype.saveState = function () {
  3938. return [
  3939. this.fromTypedArray(this.ROM),
  3940. this.inBootstrap,
  3941. this.registerA,
  3942. this.FZero,
  3943. this.FSubtract,
  3944. this.FHalfCarry,
  3945. this.FCarry,
  3946. this.registerB,
  3947. this.registerC,
  3948. this.registerD,
  3949. this.registerE,
  3950. this.registersHL,
  3951. this.stackPointer,
  3952. this.programCounter,
  3953. this.halt,
  3954. this.IME,
  3955. this.hdmaRunning,
  3956. this.CPUTicks,
  3957. this.multiplier,
  3958. this.fromTypedArray(this.memory),
  3959. this.fromTypedArray(this.MBCRam),
  3960. this.fromTypedArray(this.VRAM),
  3961. this.currVRAMBank,
  3962. this.tileBankOffset,
  3963. this.fromTypedArray(this.GBCMemory),
  3964. this.MBC1Mode,
  3965. this.MBCRAMBanksEnabled,
  3966. this.currMBCRAMBank,
  3967. this.currMBCRAMBankPosition,
  3968. this.cGBC,
  3969. this.gbcRamBank,
  3970. this.gbcRamBankPosition,
  3971. this.ROMBank1offs,
  3972. this.currentROMBank,
  3973. this.cartridgeType,
  3974. this.name,
  3975. this.gameCode,
  3976. this.modeSTAT,
  3977. this.LYCMatchTriggerSTAT,
  3978. this.mode2TriggerSTAT,
  3979. this.mode1TriggerSTAT,
  3980. this.mode0TriggerSTAT,
  3981. this.LCDisOn,
  3982. this.gfxWindowCHRBankPosition,
  3983. this.gfxWindowDisplay,
  3984. this.gfxSpriteShow,
  3985. this.gfxSpriteDouble,
  3986. this.gfxBackgroundCHRBankPosition,
  3987. this.gfxBackgroundBankOffset,
  3988. this.TIMAEnabled,
  3989. this.DIVTicks,
  3990. this.LCDTicks,
  3991. this.timerTicks,
  3992. this.TACClocker,
  3993. this.untilEnable,
  3994. this.lastIteration,
  3995. this.cMBC1,
  3996. this.cMBC2,
  3997. this.cMBC3,
  3998. this.cMBC5,
  3999. this.cSRAM,
  4000. this.cMMMO1,
  4001. this.cRUMBLE,
  4002. this.cCamera,
  4003. this.cTAMA5,
  4004. this.cHuC3,
  4005. this.cHuC1,
  4006. this.drewBlank,
  4007. this.tileData.slice(0),
  4008. this.fromTypedArray(this.frameBuffer),
  4009. this.tileCount,
  4010. this.colorCount,
  4011. this.gbPalette,
  4012. this.gbcRawPalette,
  4013. this.gbcPalette,
  4014. this.cachedPaletteConversion,
  4015. this.transparentCutoff,
  4016. this.bgEnabled,
  4017. this.BGPriorityEnabled,
  4018. this.fromTypedArray(this.tileReadState),
  4019. this.windowSourceLine,
  4020. this.channel1adjustedFrequencyPrep,
  4021. this.channel1lastSampleLookup,
  4022. this.channel1adjustedDuty,
  4023. this.channel1totalLength,
  4024. this.channel1envelopeVolume,
  4025. this.channel1currentVolume,
  4026. this.channel1envelopeType,
  4027. this.channel1envelopeSweeps,
  4028. this.channel1consecutive,
  4029. this.channel1frequency,
  4030. this.channel1volumeEnvTime,
  4031. this.channel1volumeEnvTimeLast,
  4032. this.channel1lastTotalLength,
  4033. this.channel1timeSweep,
  4034. this.channel1lastTimeSweep,
  4035. this.channel1numSweep,
  4036. this.channel1frequencySweepDivider,
  4037. this.channel1decreaseSweep,
  4038. this.channel2adjustedFrequencyPrep,
  4039. this.channel2lastSampleLookup,
  4040. this.channel2adjustedDuty,
  4041. this.channel2totalLength,
  4042. this.channel2envelopeVolume,
  4043. this.channel2currentVolume,
  4044. this.channel2envelopeType,
  4045. this.channel2envelopeSweeps,
  4046. this.channel2consecutive,
  4047. this.channel2frequency,
  4048. this.channel2volumeEnvTime,
  4049. this.channel2volumeEnvTimeLast,
  4050. this.channel2lastTotalLength,
  4051. this.channel3canPlay,
  4052. this.channel3totalLength,
  4053. this.channel3lastTotalLength,
  4054. this.channel3patternType,
  4055. this.channel3frequency,
  4056. this.channel3consecutive,
  4057. this.channel3PCM,
  4058. this.channel3adjustedFrequencyPrep,
  4059. this.channel4adjustedFrequencyPrep,
  4060. this.channel4lastSampleLookup,
  4061. this.channel4totalLength,
  4062. this.channel4envelopeVolume,
  4063. this.channel4currentVolume,
  4064. this.channel4envelopeType,
  4065. this.channel4envelopeSweeps,
  4066. this.channel4consecutive,
  4067. this.channel4volumeEnvTime,
  4068. this.channel4volumeEnvTimeLast,
  4069. this.channel4lastTotalLength,
  4070. this.soundMasterEnabled,
  4071. this.VinLeftChannelEnabled,
  4072. this.VinRightChannelEnabled,
  4073. this.VinLeftChannelMasterVolume,
  4074. this.VinRightChannelMasterVolume,
  4075. this.leftChannel,
  4076. this.rightChannel,
  4077. this.actualScanLine,
  4078. this.RTCisLatched,
  4079. this.latchedSeconds,
  4080. this.latchedMinutes,
  4081. this.latchedHours,
  4082. this.latchedLDays,
  4083. this.latchedHDays,
  4084. this.RTCSeconds,
  4085. this.RTCMinutes,
  4086. this.RTCHours,
  4087. this.RTCDays,
  4088. this.RTCDayOverFlow,
  4089. this.RTCHALT,
  4090. this.gbColorizedPalette,
  4091. this.usedBootROM,
  4092. this.skipPCIncrement,
  4093. this.STATTracker,
  4094. this.gbcRamBankPositionECHO,
  4095. this.numRAMBanks
  4096. ];
  4097. }
  4098. GameBoyCore.prototype.returnFromState = function (returnedFrom) {
  4099. var index = 0;
  4100. var state = returnedFrom.slice(0);
  4101. this.ROM = this.toTypedArray(state[index++], 1);
  4102. this.inBootstrap = state[index++];
  4103. this.registerA = state[index++];
  4104. this.FZero = state[index++];
  4105. this.FSubtract = state[index++];
  4106. this.FHalfCarry = state[index++];
  4107. this.FCarry = state[index++];
  4108. this.registerB = state[index++];
  4109. this.registerC = state[index++];
  4110. this.registerD = state[index++];
  4111. this.registerE = state[index++];
  4112. this.registersHL = state[index++];
  4113. this.stackPointer = state[index++];
  4114. this.programCounter = state[index++];
  4115. this.halt = state[index++];
  4116. this.IME = state[index++];
  4117. this.hdmaRunning = state[index++];
  4118. this.CPUTicks = state[index++];
  4119. this.multiplier = state[index++];
  4120. this.memory = this.toTypedArray(state[index++], 1);
  4121. this.MBCRam = this.toTypedArray(state[index++], 1);
  4122. this.VRAM = this.toTypedArray(state[index++], 1);
  4123. this.currVRAMBank = state[index++];
  4124. this.tileBankOffset = state[index++];
  4125. this.GBCMemory = this.toTypedArray(state[index++], 1);
  4126. this.MBC1Mode = state[index++];
  4127. this.MBCRAMBanksEnabled = state[index++];
  4128. this.currMBCRAMBank = state[index++];
  4129. this.currMBCRAMBankPosition = state[index++];
  4130. this.cGBC = state[index++];
  4131. this.gbcRamBank = state[index++];
  4132. this.gbcRamBankPosition = state[index++];
  4133. this.ROMBank1offs = state[index++];
  4134. this.currentROMBank = state[index++];
  4135. this.cartridgeType = state[index++];
  4136. this.name = state[index++];
  4137. this.gameCode = state[index++];
  4138. this.modeSTAT = state[index++];
  4139. this.LYCMatchTriggerSTAT = state[index++];
  4140. this.mode2TriggerSTAT = state[index++];
  4141. this.mode1TriggerSTAT = state[index++];
  4142. this.mode0TriggerSTAT = state[index++];
  4143. this.LCDisOn = state[index++];
  4144. this.gfxWindowCHRBankPosition = state[index++];
  4145. this.gfxWindowDisplay = state[index++];
  4146. this.gfxSpriteShow = state[index++];
  4147. this.gfxSpriteDouble = state[index++];
  4148. this.gfxBackgroundCHRBankPosition = state[index++];
  4149. this.gfxBackgroundBankOffset = state[index++];
  4150. this.TIMAEnabled = state[index++];
  4151. this.DIVTicks = state[index++];
  4152. this.LCDTicks = state[index++];
  4153. this.timerTicks = state[index++];
  4154. this.TACClocker = state[index++];
  4155. this.untilEnable = state[index++];
  4156. this.lastIteration = state[index++];
  4157. this.cMBC1 = state[index++];
  4158. this.cMBC2 = state[index++];
  4159. this.cMBC3 = state[index++];
  4160. this.cMBC5 = state[index++];
  4161. this.cSRAM = state[index++];
  4162. this.cMMMO1 = state[index++];
  4163. this.cRUMBLE = state[index++];
  4164. this.cCamera = state[index++];
  4165. this.cTAMA5 = state[index++];
  4166. this.cHuC3 = state[index++];
  4167. this.cHuC1 = state[index++];
  4168. this.drewBlank = state[index++];
  4169. this.tileData = state[index++];
  4170. this.frameBuffer = this.toTypedArray(state[index++], 2);
  4171. this.tileCount = state[index++];
  4172. this.colorCount = state[index++];
  4173. this.gbPalette = state[index++];
  4174. this.gbcRawPalette = state[index++];
  4175. this.gbcPalette = state[index++];
  4176. this.cachedPaletteConversion = state[index++];
  4177. this.transparentCutoff = state[index++];
  4178. this.bgEnabled = state[index++];
  4179. this.BGPriorityEnabled = state[index++];
  4180. this.tileReadState = this.toTypedArray(state[index++], 1);
  4181. this.windowSourceLine = state[index++];
  4182. this.channel1adjustedFrequencyPrep = state[index++];
  4183. this.channel1lastSampleLookup = state[index++];
  4184. this.channel1adjustedDuty = state[index++];
  4185. this.channel1totalLength = state[index++];
  4186. this.channel1envelopeVolume = state[index++];
  4187. this.channel1currentVolume = state[index++];
  4188. this.channel1envelopeType = state[index++];
  4189. this.channel1envelopeSweeps = state[index++];
  4190. this.channel1consecutive = state[index++];
  4191. this.channel1frequency = state[index++];
  4192. this.channel1volumeEnvTime = state[index++];
  4193. this.channel1volumeEnvTimeLast = state[index++];
  4194. this.channel1lastTotalLength = state[index++];
  4195. this.channel1timeSweep = state[index++];
  4196. this.channel1lastTimeSweep = state[index++];
  4197. this.channel1numSweep = state[index++];
  4198. this.channel1frequencySweepDivider = state[index++];
  4199. this.channel1decreaseSweep = state[index++];
  4200. this.channel2adjustedFrequencyPrep = state[index++];
  4201. this.channel2lastSampleLookup = state[index++];
  4202. this.channel2adjustedDuty = state[index++];
  4203. this.channel2totalLength = state[index++];
  4204. this.channel2envelopeVolume = state[index++];
  4205. this.channel2currentVolume = state[index++];
  4206. this.channel2envelopeType = state[index++];
  4207. this.channel2envelopeSweeps = state[index++];
  4208. this.channel2consecutive = state[index++];
  4209. this.channel2frequency = state[index++];
  4210. this.channel2volumeEnvTime = state[index++];
  4211. this.channel2volumeEnvTimeLast = state[index++];
  4212. this.channel2lastTotalLength = state[index++];
  4213. this.channel3canPlay = state[index++];
  4214. this.channel3totalLength = state[index++];
  4215. this.channel3lastTotalLength = state[index++];
  4216. this.channel3patternType = state[index++];
  4217. this.channel3frequency = state[index++];
  4218. this.channel3consecutive = state[index++];
  4219. this.channel3PCM = state[index++];
  4220. this.channel3adjustedFrequencyPrep = state[index++];
  4221. this.channel4adjustedFrequencyPrep = state[index++];
  4222. this.channel4lastSampleLookup = state[index++];
  4223. this.channel4totalLength = state[index++];
  4224. this.channel4envelopeVolume = state[index++];
  4225. this.channel4currentVolume = state[index++];
  4226. this.channel4envelopeType = state[index++];
  4227. this.channel4envelopeSweeps = state[index++];
  4228. this.channel4consecutive = state[index++];
  4229. this.channel4volumeEnvTime = state[index++];
  4230. this.channel4volumeEnvTimeLast = state[index++];
  4231. this.channel4lastTotalLength = state[index++];
  4232. this.soundMasterEnabled = state[index++];
  4233. this.VinLeftChannelEnabled = state[index++];
  4234. this.VinRightChannelEnabled = state[index++];
  4235. this.VinLeftChannelMasterVolume = state[index++];
  4236. this.VinRightChannelMasterVolume = state[index++];
  4237. this.leftChannel = state[index++];
  4238. this.rightChannel = state[index++];
  4239. this.actualScanLine = state[index++];
  4240. this.RTCisLatched = state[index++];
  4241. this.latchedSeconds = state[index++];
  4242. this.latchedMinutes = state[index++];
  4243. this.latchedHours = state[index++];
  4244. this.latchedLDays = state[index++];
  4245. this.latchedHDays = state[index++];
  4246. this.RTCSeconds = state[index++];
  4247. this.RTCMinutes = state[index++];
  4248. this.RTCHours = state[index++];
  4249. this.RTCDays = state[index++];
  4250. this.RTCDayOverFlow = state[index++];
  4251. this.RTCHALT = state[index++];
  4252. this.gbColorizedPalette = state[index++];
  4253. this.usedBootROM = state[index++];
  4254. this.skipPCIncrement = state[index++];
  4255. this.STATTracker = state[index++];
  4256. this.gbcRamBankPositionECHO = state[index++];
  4257. this.numRAMBanks = state[index];
  4258. this.tileCountInvalidator = this.tileCount * 4;
  4259. this.fromSaveState = true;
  4260. this.checkPaletteType();
  4261. this.convertAuxilliary();
  4262. this.initializeLCDController();
  4263. this.memoryReadJumpCompile();
  4264. this.memoryWriteJumpCompile();
  4265. this.initLCD();
  4266. this.initSound();
  4267. this.drawToCanvas();
  4268. }
  4269. GameBoyCore.prototype.returnFromRTCState = function () {
  4270. if (typeof this.openRTC == "function" && this.cTIMER) {
  4271. var rtcData = this.openRTC(this.name);
  4272. var index = 0;
  4273. this.lastIteration = rtcData[index++];
  4274. this.RTCisLatched = rtcData[index++];
  4275. this.latchedSeconds = rtcData[index++];
  4276. this.latchedMinutes = rtcData[index++];
  4277. this.latchedHours = rtcData[index++];
  4278. this.latchedLDays = rtcData[index++];
  4279. this.latchedHDays = rtcData[index++];
  4280. this.RTCSeconds = rtcData[index++];
  4281. this.RTCMinutes = rtcData[index++];
  4282. this.RTCHours = rtcData[index++];
  4283. this.RTCDays = rtcData[index++];
  4284. this.RTCDayOverFlow = rtcData[index++];
  4285. this.RTCHALT = rtcData[index];
  4286. }
  4287. }
  4288. GameBoyCore.prototype.start = function () {
  4289. settings[4] = 0; //Reset the frame skip setting.
  4290. this.initializeLCDController(); //Compile the LCD controller functions.
  4291. this.initMemory(); //Write the startup memory.
  4292. this.ROMLoad(); //Load the ROM into memory and get cartridge information from it.
  4293. this.initLCD(); //Initialize the graphics.
  4294. this.initSound(); //Sound object initialization.
  4295. this.run(); //Start the emulation.
  4296. }
  4297. GameBoyCore.prototype.convertAuxilliary = function () {
  4298. try {
  4299. this.DAATable = new Uint16Array(this.DAATable);
  4300. this.TICKTable = new Uint8Array(this.TICKTable);
  4301. this.SecondaryTICKTable = new Uint8Array(this.SecondaryTICKTable);
  4302. }
  4303. catch (error) {
  4304. cout("Could not convert the auxilliary arrays to typed arrays (Error \"" + error.message + "\").", 1);
  4305. }
  4306. }
  4307. GameBoyCore.prototype.initMemory = function () {
  4308. //Initialize the RAM:
  4309. this.memory = this.getTypedArray(0x10000, 0, "uint8");
  4310. this.frameBuffer = this.getTypedArray(23040, 0xF8F8F8, "uint32");
  4311. this.gbcOBJRawPalette = this.getTypedArray(0x40, 0, "uint32");
  4312. this.gbcBGRawPalette = this.getTypedArray(0x40, 0, "uint32");
  4313. this.gbOBJPalette = this.getTypedArray(8, 0, "uint32");
  4314. this.gbBGPalette = this.getTypedArray(4, 0, "uint32");
  4315. this.gbcOBJPalette = this.getTypedArray(0x20, 0, "uint32");
  4316. this.gbcBGPalette = this.getTypedArray(0x20, 0, "uint32");
  4317. this.gbBGColorizedPalette = this.getTypedArray(4, 0, "uint32");
  4318. this.gbOBJColorizedPalette = this.getTypedArray(8, 0, "uint32");
  4319. this.cachedBGPaletteConversion = this.getTypedArray(4, 0, "uint32");
  4320. this.cachedOBJPaletteConversion = this.getTypedArray(8, 0, "uint32");
  4321. this.spriteLineStart = this.getTypedArray(23040, 0, "uint8");
  4322. this.BGCHRBank1Pointer = this.getTypedArray(0x800, 0, "uint16");
  4323. this.BGCHRBank2Pointer = this.getTypedArray(0x800, 0, "uint16");
  4324. this.BGCHRCurrentBank = this.BGCHRBank1Pointer;
  4325. this.tileCache = this.ArrayPad(0x300, this.ArrayPad(8, this.getTypedArray(0x8, "uint8")));
  4326. this.tileOBJCache = this.ArrayPad(0x200, this.ArrayPad(8, this.getTypedArray(0x8, "uint8")));
  4327. this.convertAuxilliary();
  4328. }
  4329. GameBoyCore.prototype.initSkipBootstrap = function () {
  4330. //Start as an unset device:
  4331. cout("Starting without the GBC boot ROM.", 0);
  4332. this.programCounter = 0x100;
  4333. this.stackPointer = 0xFFFE;
  4334. this.IME = true;
  4335. this.DIVTicks = 14;
  4336. this.registerA = (this.cGBC) ? 0x11 : 0x1;
  4337. this.registerB = 0;
  4338. this.registerC = 0x13;
  4339. this.registerD = 0;
  4340. this.registerE = 0xD8;
  4341. this.FZero = true;
  4342. this.FSubtract = false;
  4343. this.FHalfCarry = true;
  4344. this.FCarry = true;
  4345. this.registersHL = 0x014D;
  4346. this.VinLeftChannelMasterVolume = 1;
  4347. this.VinRightChannelMasterVolume = 1;
  4348. this.leftChannel = this.ArrayPad(4, true);
  4349. this.rightChannel = this.ArrayPad(4, true);
  4350. this.LCDCONTROL = this.LINECONTROL;
  4351. this.LCDisOn = true;
  4352. this.modeSTAT = 0;
  4353. this.STATTracker = 0;
  4354. this.LCDTicks = 15;
  4355. this.actualScanLine = 0;
  4356. this.gfxWindowCHRBankPosition = 0;
  4357. this.gfxWindowDisplay = false;
  4358. this.gfxBackgroundBankOffset = 0x80;
  4359. this.gfxBackgroundCHRBankPosition = 0;
  4360. this.gfxSpriteDouble = false;
  4361. this.gfxSpriteShow = false;
  4362. this.BGPriorityEnabled = true;
  4363. //Fill in the boot ROM set register values
  4364. //Default values to the GB boot ROM values, then fill in the GBC boot ROM values after ROM loading
  4365. var index = 0xFF;
  4366. while (index >= 0) {
  4367. if (index >= 0x30 && index < 0x40) {
  4368. this.memoryWrite(0xFF00 | index, this.ffxxDump[index]);
  4369. }
  4370. else {
  4371. switch (index) {
  4372. case 0x00:
  4373. case 0x01:
  4374. case 0x02:
  4375. case 0x07:
  4376. case 0x0F:
  4377. case 0xFF:
  4378. this.memoryWrite(0xFF00 | index, this.ffxxDump[index]);
  4379. break;
  4380. default:
  4381. this.memory[0xFF00 | index] = this.ffxxDump[index];
  4382. }
  4383. }
  4384. index--;
  4385. }
  4386. if (this.cGBC) {
  4387. this.memory[0xFF6C] = 0xFE;
  4388. this.memory[0xFF74] = 0xFE;
  4389. }
  4390. else {
  4391. this.memory[0xFF48] = 0xFF;
  4392. this.memory[0xFF49] = 0xFF;
  4393. this.memory[0xFF6C] = 0xFF;
  4394. this.memory[0xFF74] = 0xFF;
  4395. }
  4396. }
  4397. GameBoyCore.prototype.initBootstrap = function () {
  4398. //Start as an unset device:
  4399. cout("Starting the GBC boot ROM.", 0);
  4400. this.programCounter = 0;
  4401. this.stackPointer = 0;
  4402. this.IME = false;
  4403. this.LCDTicks = 0;
  4404. this.DIVTicks = 0;
  4405. this.registerA = 0;
  4406. this.registerB = 0;
  4407. this.registerC = 0;
  4408. this.registerD = 0;
  4409. this.registerE = 0;
  4410. this.FZero = this.FSubtract = this.FHalfCarry = this.FCarry = false;
  4411. this.registersHL = 0;
  4412. this.leftChannel = this.ArrayPad(4, false);
  4413. this.rightChannel = this.ArrayPad(4, false);
  4414. this.channel2frequency = this.channel1frequency = 0;
  4415. this.channel2volumeEnvTime = this.channel1volumeEnvTime = 0;
  4416. this.channel4consecutive = this.channel2consecutive = this.channel1consecutive = false;
  4417. this.VinLeftChannelMasterVolume = 1;
  4418. this.VinRightChannelMasterVolume = 1;
  4419. this.memory[0xFF00] = 0xF; //Set the joypad state.
  4420. }
  4421. GameBoyCore.prototype.ROMLoad = function () {
  4422. //Load the first two ROM banks (0x0000 - 0x7FFF) into regular gameboy memory:
  4423. this.ROM = this.getTypedArray(this.ROMImage.length, 0, "uint8");
  4424. this.usedBootROM = settings[16];
  4425. for (var romIndex = 0; romIndex < this.ROMImage.length; romIndex++) {
  4426. this.ROM[romIndex] = (this.ROMImage.charCodeAt(romIndex) & 0xFF);
  4427. if (romIndex < 0x8000) {
  4428. if (!this.usedBootROM || romIndex >= 0x900 || (romIndex >= 0x100 && romIndex < 0x200)) {
  4429. this.memory[romIndex] = this.ROM[romIndex]; //Load in the game ROM.
  4430. }
  4431. else {
  4432. this.memory[romIndex] = this.GBCBOOTROM[romIndex]; //Load in the GameBoy Color BOOT ROM.
  4433. }
  4434. }
  4435. }
  4436. // ROM name
  4437. for (var index = 0x134; index < 0x13F; index++) {
  4438. if (this.ROMImage.charCodeAt(index) > 0) {
  4439. this.name += this.ROMImage[index];
  4440. }
  4441. }
  4442. // ROM game code (for newer games)
  4443. for (var index = 0x13F; index < 0x143; index++) {
  4444. if (this.ROMImage.charCodeAt(index) > 0) {
  4445. this.gameCode += this.ROMImage[index];
  4446. }
  4447. }
  4448. cout("Game Title: " + this.name + "[" + this.gameCode + "][" + this.ROMImage[0x143] + "]", 0);
  4449. cout("Game Code: " + this.gameCode, 0);
  4450. // Cartridge type
  4451. this.cartridgeType = this.ROM[0x147];
  4452. cout("Cartridge type #" + this.cartridgeType, 0);
  4453. //Map out ROM cartridge sub-types.
  4454. var MBCType = "";
  4455. switch (this.cartridgeType) {
  4456. case 0x00:
  4457. //ROM w/o bank switching
  4458. if (!settings[9]) {
  4459. MBCType = "ROM";
  4460. break;
  4461. }
  4462. case 0x01:
  4463. this.cMBC1 = true;
  4464. MBCType = "MBC1";
  4465. break;
  4466. case 0x02:
  4467. this.cMBC1 = true;
  4468. this.cSRAM = true;
  4469. MBCType = "MBC1 + SRAM";
  4470. break;
  4471. case 0x03:
  4472. this.cMBC1 = true;
  4473. this.cSRAM = true;
  4474. this.cBATT = true;
  4475. MBCType = "MBC1 + SRAM + BATT";
  4476. break;
  4477. case 0x05:
  4478. this.cMBC2 = true;
  4479. MBCType = "MBC2";
  4480. break;
  4481. case 0x06:
  4482. this.cMBC2 = true;
  4483. this.cBATT = true;
  4484. MBCType = "MBC2 + BATT";
  4485. break;
  4486. case 0x08:
  4487. this.cSRAM = true;
  4488. MBCType = "ROM + SRAM";
  4489. break;
  4490. case 0x09:
  4491. this.cSRAM = true;
  4492. this.cBATT = true;
  4493. MBCType = "ROM + SRAM + BATT";
  4494. break;
  4495. case 0x0B:
  4496. this.cMMMO1 = true;
  4497. MBCType = "MMMO1";
  4498. break;
  4499. case 0x0C:
  4500. this.cMMMO1 = true;
  4501. this.cSRAM = true;
  4502. MBCType = "MMMO1 + SRAM";
  4503. break;
  4504. case 0x0D:
  4505. this.cMMMO1 = true;
  4506. this.cSRAM = true;
  4507. this.cBATT = true;
  4508. MBCType = "MMMO1 + SRAM + BATT";
  4509. break;
  4510. case 0x0F:
  4511. this.cMBC3 = true;
  4512. this.cTIMER = true;
  4513. this.cBATT = true;
  4514. MBCType = "MBC3 + TIMER + BATT";
  4515. break;
  4516. case 0x10:
  4517. this.cMBC3 = true;
  4518. this.cTIMER = true;
  4519. this.cBATT = true;
  4520. this.cSRAM = true;
  4521. MBCType = "MBC3 + TIMER + BATT + SRAM";
  4522. break;
  4523. case 0x11:
  4524. this.cMBC3 = true;
  4525. MBCType = "MBC3";
  4526. break;
  4527. case 0x12:
  4528. this.cMBC3 = true;
  4529. this.cSRAM = true;
  4530. MBCType = "MBC3 + SRAM";
  4531. break;
  4532. case 0x13:
  4533. this.cMBC3 = true;
  4534. this.cSRAM = true;
  4535. this.cBATT = true;
  4536. MBCType = "MBC3 + SRAM + BATT";
  4537. break;
  4538. case 0x19:
  4539. this.cMBC5 = true;
  4540. MBCType = "MBC5";
  4541. break;
  4542. case 0x1A:
  4543. this.cMBC5 = true;
  4544. this.cSRAM = true;
  4545. MBCType = "MBC5 + SRAM";
  4546. break;
  4547. case 0x1B:
  4548. this.cMBC5 = true;
  4549. this.cSRAM = true;
  4550. this.cBATT = true;
  4551. MBCType = "MBC5 + SRAM + BATT";
  4552. break;
  4553. case 0x1C:
  4554. this.cRUMBLE = true;
  4555. MBCType = "RUMBLE";
  4556. break;
  4557. case 0x1D:
  4558. this.cRUMBLE = true;
  4559. this.cSRAM = true;
  4560. MBCType = "RUMBLE + SRAM";
  4561. break;
  4562. case 0x1E:
  4563. this.cRUMBLE = true;
  4564. this.cSRAM = true;
  4565. this.cBATT = true;
  4566. MBCType = "RUMBLE + SRAM + BATT";
  4567. break;
  4568. case 0x1F:
  4569. this.cCamera = true;
  4570. MBCType = "GameBoy Camera";
  4571. break;
  4572. case 0xFD:
  4573. this.cTAMA5 = true;
  4574. MBCType = "TAMA5";
  4575. break;
  4576. case 0xFE:
  4577. this.cHuC3 = true;
  4578. MBCType = "HuC3";
  4579. break;
  4580. case 0xFF:
  4581. this.cHuC1 = true;
  4582. MBCType = "HuC1";
  4583. break;
  4584. default:
  4585. MBCType = "Unknown";
  4586. cout("Cartridge type is unknown.", 2);
  4587. pause();
  4588. }
  4589. cout("Cartridge Type: " + MBCType + ".", 0);
  4590. // ROM and RAM banks
  4591. this.numROMBanks = this.ROMBanks[this.ROM[0x148]];
  4592. cout(this.numROMBanks + " ROM banks.", 0);
  4593. switch (this.RAMBanks[this.ROM[0x149]]) {
  4594. case 0:
  4595. cout("No RAM banking requested for allocation or MBC is of type 2.", 0);
  4596. break;
  4597. case 2:
  4598. cout("1 RAM bank requested for allocation.", 0);
  4599. break;
  4600. case 3:
  4601. cout("4 RAM banks requested for allocation.", 0);
  4602. break;
  4603. case 4:
  4604. cout("16 RAM banks requested for allocation.", 0);
  4605. break;
  4606. default:
  4607. cout("RAM bank amount requested is unknown, will use maximum allowed by specified MBC type.", 0);
  4608. }
  4609. //Check the GB/GBC mode byte:
  4610. if (!this.usedBootROM) {
  4611. switch (this.ROM[0x143]) {
  4612. case 0x00: //Only GB mode
  4613. this.cGBC = false;
  4614. cout("Only GB mode detected.", 0);
  4615. break;
  4616. case 0x80: //Both GB + GBC modes
  4617. this.cGBC = !settings[2];
  4618. cout("GB and GBC mode detected.", 0);
  4619. break;
  4620. case 0xC0: //Only GBC mode
  4621. this.cGBC = true;
  4622. cout("Only GBC mode detected.", 0);
  4623. break;
  4624. default:
  4625. this.cGBC = false;
  4626. cout("Unknown GameBoy game type code #" + this.ROM[0x143] + ", defaulting to GB mode (Old games don't have a type code).", 1);
  4627. }
  4628. this.inBootstrap = false;
  4629. this.setupRAM(); //CPU/(V)RAM initialization.
  4630. this.initSkipBootstrap();
  4631. }
  4632. else {
  4633. this.cGBC = true; //Allow the GBC boot ROM to run in GBC mode...
  4634. this.setupRAM(); //CPU/(V)RAM initialization.
  4635. this.initBootstrap();
  4636. }
  4637. this.checkPaletteType();
  4638. //License Code Lookup:
  4639. var cOldLicense = this.ROM[0x14B];
  4640. var cNewLicense = (this.ROM[0x144] & 0xFF00) | (this.ROM[0x145] & 0xFF);
  4641. if (cOldLicense != 0x33) {
  4642. //Old Style License Header
  4643. cout("Old style license code: " + cOldLicense, 0);
  4644. }
  4645. else {
  4646. //New Style License Header
  4647. cout("New style license code: " + cNewLicense, 0);
  4648. }
  4649. }
  4650. GameBoyCore.prototype.disableBootROM = function () {
  4651. //Remove any traces of the boot ROM from ROM memory.
  4652. for (var index = 0; index < 0x900; index++) {
  4653. if (index < 0x100 || index >= 0x200) { //Skip the already loaded in ROM header.
  4654. this.memory[index] = this.ROM[index]; //Replace the GameBoy Color boot ROM with the game ROM.
  4655. }
  4656. }
  4657. this.checkPaletteType();
  4658. if (!this.cGBC) {
  4659. //Clean up the post-boot (GB mode only) state:
  4660. cout("Stepping down from GBC mode.", 0);
  4661. this.getGBCColor();
  4662. this.VRAM = this.GBCMemory = null; //Deleting these causes Google's V8 engine and Safari's JSC to deoptimize heavily.
  4663. //Possible Extra: shorten some gfx arrays to the length that we need (Remove the unused indices)
  4664. }
  4665. this.memoryReadJumpCompile();
  4666. this.memoryWriteJumpCompile();
  4667. }
  4668. GameBoyCore.prototype.initializeTiming = function () {
  4669. //Emulator Timing:
  4670. this.CPUCyclesPerIteration = (41943 / 40) * settings[20];
  4671. //Audio Timing:
  4672. this.preChewedAudioComputationMultiplier = 0x20000 / settings[14];
  4673. this.preChewedWAVEAudioComputationMultiplier = 0x200000 / settings[14];
  4674. this.whiteNoiseFrequencyPreMultiplier = 4194300 / settings[14] / 8;
  4675. this.volumeEnvelopePreMultiplier = settings[14] / 0x40;
  4676. this.channel1TimeSweepPreMultiplier = settings[14] / 0x80;
  4677. this.audioTotalLengthMultiplier = settings[14] / 0x100;
  4678. }
  4679. GameBoyCore.prototype.setupRAM = function () {
  4680. //Setup the auxilliary/switchable RAM to their maximum possible size (Bad headers can lie).
  4681. if (this.cMBC2) {
  4682. this.numRAMBanks = 1 / 16;
  4683. }
  4684. else if (this.cMBC1 || this.cRUMBLE || this.cMBC3 || this.cHuC3) {
  4685. this.numRAMBanks = 4;
  4686. }
  4687. else if (this.cMBC5) {
  4688. this.numRAMBanks = 16;
  4689. }
  4690. else if (this.cSRAM) {
  4691. this.numRAMBanks = 1;
  4692. }
  4693. if (this.numRAMBanks > 0) {
  4694. if (!this.MBCRAMUtilized()) {
  4695. //For ROM and unknown MBC cartridges using the external RAM:
  4696. this.MBCRAMBanksEnabled = true;
  4697. }
  4698. //Switched RAM Used
  4699. var MBCRam = (typeof this.openMBC == "function") ? this.openMBC(this.name) : [];
  4700. if (MBCRam.length > 0) {
  4701. //Flash the SRAM into memory:
  4702. this.MBCRam = this.toTypedArray(MBCRam, 1);
  4703. }
  4704. else {
  4705. this.MBCRam = this.getTypedArray(this.numRAMBanks * 0x2000, 0, "uint8");
  4706. }
  4707. }
  4708. cout("Actual bytes of MBC RAM allocated: " + (this.numRAMBanks * 0x2000), 0);
  4709. this.returnFromRTCState();
  4710. //Setup the RAM for GBC mode.
  4711. if (this.cGBC) {
  4712. this.VRAM = this.getTypedArray(0x2000, 0, "uint8");
  4713. this.GBCMemory = this.getTypedArray(0x7000, 0, "uint8");
  4714. }
  4715. this.memoryReadJumpCompile();
  4716. this.memoryWriteJumpCompile();
  4717. }
  4718. GameBoyCore.prototype.MBCRAMUtilized = function () {
  4719. return this.cMBC1 || this.cMBC2 || this.cMBC3 || this.cMBC5 || this.cRUMBLE;
  4720. }
  4721. GameBoyCore.prototype.initLCD = function () {
  4722. this.scaledFrameBuffer = this.getTypedArray(this.pixelCount, 0, "int32"); //Used for software side scaling...
  4723. this.transparentCutoff = (this.cGBC) ? 32 : 4;
  4724. try {
  4725. window.mozRequestAnimationFrame();
  4726. this.asyncDrawSupportDetected = 1;
  4727. }
  4728. catch (error) {
  4729. try {
  4730. window.webkitRequestAnimationFrame(vSyncGFX);
  4731. this.asyncDrawSupportDetected = 2;
  4732. }
  4733. catch (error) {
  4734. this.asyncDrawSupportDetected = 0;
  4735. cout("window.mozRequestAnimationFrame was not found.", 1);
  4736. }
  4737. }
  4738. try {
  4739. if (settings[5]) {
  4740. //Nasty since we are throwing on purpose to force a try/catch fallback
  4741. throw(new Error("Canvas 2D API path disabled."));
  4742. }
  4743. if (settings[11]) {
  4744. WebGL2D.enable(this.canvas);
  4745. this.drawContext = this.canvas.getContext("webgl-2d");
  4746. }
  4747. else {
  4748. this.drawContext = this.canvas.getContext("2d");
  4749. }
  4750. //Get a CanvasPixelArray buffer:
  4751. try {
  4752. this.canvasBuffer = this.drawContext.createImageData(this.width, this.height);
  4753. }
  4754. catch (error) {
  4755. cout("Falling back to the getImageData initialization (Error \"" + error.message + "\").", 1);
  4756. this.canvasBuffer = this.drawContext.getImageData(0, 0, this.width, this.height);
  4757. }
  4758. var index = this.pixelCount;
  4759. var index2 = this.rgbCount;
  4760. while (index > 0) {
  4761. this.frameBuffer[--index] = 0x00FFFFFF;
  4762. this.canvasBuffer.data[index2 -= 4] = 0xFF;
  4763. this.canvasBuffer.data[index2 + 1] = 0xFF;
  4764. this.canvasBuffer.data[index2 + 2] = 0xFF;
  4765. this.canvasBuffer.data[index2 + 3] = 0xFF;
  4766. }
  4767. this.drawContext.putImageData(this.canvasBuffer, 0, 0); //Throws any browser that won't support this later on.
  4768. this.canvasAlt.style.visibility = "hidden"; //Make sure, if restarted, that the fallback images aren't going cover the canvas.
  4769. this.canvas.style.visibility = "visible";
  4770. this.canvasFallbackHappened = false;
  4771. }
  4772. catch (error) {
  4773. //Falling back to an experimental data URI BMP file canvas alternative:
  4774. cout("Falling back to BMP imaging as a canvas alternative: " + error.message, 1);
  4775. this.width = 160;
  4776. this.height = 144;
  4777. this.canvasFallbackHappened = true;
  4778. this.drawContext = new BMPCanvas(this.canvasAlt, 160, 144, settings[6][0], settings[6][1]);
  4779. this.canvasBuffer = new Object();
  4780. var index = 23040;
  4781. while (index > 0) {
  4782. this.frameBuffer[--index] = 0x00FFFFFF;
  4783. }
  4784. this.canvasBuffer.data = this.ArrayPad(92160, 0xFF);
  4785. this.drawContext.putImageData(this.canvasBuffer, 0, 0);
  4786. //Make visible only after the images have been initialized.
  4787. this.canvasAlt.style.visibility = "visible";
  4788. this.canvas.style.visibility = "hidden"; //Speedier layout in some browsers.
  4789. }
  4790. }
  4791. GameBoyCore.prototype.JoyPadEvent = function (key, down) {
  4792. if (down) {
  4793. this.JoyPad &= 0xFF ^ (1 << key);
  4794. /*if (!this.cGBC) {
  4795. this.memory[0xFF0F] |= 0x10; //A real GBC doesn't set this!
  4796. }*/
  4797. }
  4798. else {
  4799. this.JoyPad |= (1 << key);
  4800. }
  4801. 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));
  4802. }
  4803. GameBoyCore.prototype.initSound = function () {
  4804. this.soundChannelsAllocated = (!settings[1]) ? 2 : 1;
  4805. if (settings[0]) {
  4806. try {
  4807. //mozAudio - Synchronous Audio API
  4808. this.audioHandle = new Audio();
  4809. this.audioHandle.mozSetup(this.soundChannelsAllocated, settings[14]);
  4810. this.samplesAlreadyWritten = this.audioHandle.mozWriteAudio(this.getTypedArray(settings[23], -1, "float32"));
  4811. cout("Mozilla Audio API Initialized:", 0);
  4812. this.audioType = 0;
  4813. }
  4814. catch (error) {
  4815. if (launchedContext) {
  4816. cout("WebKit Audio API Initialized:", 0);
  4817. resetWebAudioBuffer();
  4818. this.audioType = 1;
  4819. }
  4820. else {
  4821. try {
  4822. this.audioHandle = new AudioThread(this.soundChannelsAllocated, settings[14], settings[15], false);
  4823. cout("WAV PCM Audio Wrapper Initialized:", 0);
  4824. this.audioType = 2;
  4825. this.outTrackerLimit = 20;
  4826.  
  4827. }
  4828. catch (error) {
  4829. settings[0] = false;
  4830. this.audioType = -1;
  4831. cout("Audio system cannot run: " + error.message, 2);
  4832. }
  4833. }
  4834. }
  4835. if (settings[0]) {
  4836. cout("...Audio Channels: " + this.soundChannelsAllocated, 0);
  4837. cout("...Sample Rate: " + settings[14], 0);
  4838. this.initAudioBuffer();
  4839. }
  4840. }
  4841. }
  4842. GameBoyCore.prototype.initAudioBuffer = function () {
  4843. this.audioIndex = 0;
  4844. this.sampleSize = Math.floor(settings[14] / 1000 * settings[20]);
  4845. cout("...Samples Per VBlank (Per Channel): " + this.sampleSize, 0);
  4846. this.samplesOut = this.sampleSize / this.CPUCyclesPerIteration;
  4847. cout("...Samples Per machine cycle (Per Channel): " + this.samplesOut, 0);
  4848. this.numSamplesTotal = this.sampleSize * this.soundChannelsAllocated;
  4849. this.audioSamples = this.getTypedArray(this.numSamplesTotal, 0, "float32");
  4850. this.audioBackup = this.getTypedArray(this.numSamplesTotal, 0, "float32");
  4851. //Noise Sample Table:
  4852. this.noiseSampleTable = this.getTypedArray(0x80000, 0, "float32");
  4853. var randomFactor = 0;
  4854. for (var index = 0; index < 0x8000; index++) {
  4855. randomFactor = Math.random() / 2; //Get the pseudo-random value.
  4856. //Now multiply the pseudo-random value against all possible volume amounts and cache the result:
  4857. this.noiseSampleTable[0x08000 | index] = randomFactor * 0x1 / 0xF;
  4858. this.noiseSampleTable[0x10000 | index] = randomFactor * 0x2 / 0xF;
  4859. this.noiseSampleTable[0x18000 | index] = randomFactor * 0x3 / 0xF;
  4860. this.noiseSampleTable[0x20000 | index] = randomFactor * 0x4 / 0xF;
  4861. this.noiseSampleTable[0x28000 | index] = randomFactor * 0x5 / 0xF;
  4862. this.noiseSampleTable[0x30000 | index] = randomFactor * 0x6 / 0xF;
  4863. this.noiseSampleTable[0x38000 | index] = randomFactor * 0x7 / 0xF;
  4864. this.noiseSampleTable[0x40000 | index] = randomFactor * 0x8 / 0xF;
  4865. this.noiseSampleTable[0x48000 | index] = randomFactor * 0x9 / 0xF;
  4866. this.noiseSampleTable[0x50000 | index] = randomFactor * 0xA / 0xF;
  4867. this.noiseSampleTable[0x58000 | index] = randomFactor * 0xB / 0xF;
  4868. this.noiseSampleTable[0x60000 | index] = randomFactor * 0xC / 0xF;
  4869. this.noiseSampleTable[0x68000 | index] = randomFactor * 0xD / 0xF;
  4870. this.noiseSampleTable[0x70000 | index] = randomFactor * 0xE / 0xF;
  4871. this.noiseSampleTable[0x78000 | index] = randomFactor;
  4872. }
  4873. }
  4874. GameBoyCore.prototype.playAudio = function () {
  4875. if (settings[0]) {
  4876. if (!this.audioOverflow && this.audioIndex < this.numSamplesTotal) {
  4877. //Make sure we don't under-run the sample generation (Round off the CPU-timed audio generation):
  4878. this.generateAudio((this.numSamplesTotal - this.audioIndex) / this.soundChannelsAllocated);
  4879. }
  4880. var buffer = (this.audioOverflow != this.usingBackupAsMain) ? this.audioBackup : this.audioSamples;
  4881. if (this.audioType == 0) {
  4882. //mozAudio
  4883. var sampleOffset = this.audioHandle.mozCurrentSampleOffset();
  4884. if (sampleOffset < 0) {
  4885. //WTF Error Instance:
  4886. this.samplesAlreadyWritten += this.audioHandle.mozWriteAudio(buffer);
  4887. cout("mozCurrentSampleOffset gave an impossible number.", 1);
  4888. return;
  4889. }
  4890. else {
  4891. var samplesRequested = Math.min(settings[23] - this.samplesAlreadyWritten + sampleOffset, this.numSamplesTotal - this.soundChannelsAllocated);
  4892. this.samplesAlreadyWritten += this.audioHandle.mozWriteAudio(buffer);
  4893. if (samplesRequested > 0) {
  4894. //We need more audio samples since we went below our set low limit:
  4895. var neededSamples = samplesRequested - this.audioIndex;
  4896. if (neededSamples > 0) {
  4897. //Use any existing samples and then create some:
  4898. if (this.audioIndex > 0) {
  4899. this.samplesAlreadyWritten += this.audioHandle.mozWriteAudio(this.audioBufferSlice(this.audioIndex));
  4900. this.audioIndex = 0;
  4901. }
  4902. this.generateAudioSafe(neededSamples / this.soundChannelsAllocated);
  4903. this.samplesAlreadyWritten += this.audioHandle.mozWriteAudio(this.audioBufferSlice(this.audioIndex));
  4904. this.audioIndex = 0;
  4905. }
  4906. else if (neededSamples == 0) {
  4907. //Use the overflow buffer's existing samples:
  4908. this.samplesAlreadyWritten += this.audioHandle.mozWriteAudio(this.currentBuffer);
  4909. this.audioIndex = 0;
  4910. }
  4911. else {
  4912. //Use the overflow buffer's existing samples:
  4913. this.samplesAlreadyWritten += this.audioHandle.mozWriteAudio(this.audioBufferSlice(samplesRequested));
  4914. neededSamples = this.audioIndex - samplesRequested;
  4915. while (--neededSamples >= 0) {
  4916. //Move over the remaining samples to their new positions:
  4917. this.currentBuffer[neededSamples] = this.currentBuffer[samplesRequested + neededSamples];
  4918. }
  4919. this.audioIndex -= samplesRequested;
  4920. }
  4921. }
  4922. }
  4923. }
  4924. else if (this.audioType == 1) {
  4925. //WebKit Audio:
  4926. for (var bufferCounter = 0; bufferCounter < this.numSamplesTotal; bufferCounter++) {
  4927. audioContextSampleBuffer[bufferEnd++] = buffer[bufferCounter];
  4928. if (bufferEnd == startPosition) {
  4929. startPosition += this.soundChannelsAllocated;
  4930. if (settings[24] <= startPosition) {
  4931. startPosition -= settings[24];
  4932. }
  4933. }
  4934. else if (bufferEnd == settings[24]) {
  4935. bufferEnd = 0;
  4936. }
  4937. }
  4938. var samplesRequested = Math.min(settings[23] - ((startPosition > bufferEnd) ? (settings[24] - startPosition + bufferEnd) : (bufferEnd - startPosition)), this.numSamplesTotal - this.soundChannelsAllocated);
  4939. if (samplesRequested > 0) {
  4940. //We need more audio samples since we went below our set low limit:
  4941. var neededSamples = samplesRequested - this.audioIndex;
  4942. if (neededSamples > 0) {
  4943. //Use any existing samples and then create some:
  4944. for (var bufferCounter = 0; bufferCounter < this.audioIndex; bufferCounter++) {
  4945. audioContextSampleBuffer[bufferEnd++] = this.currentBuffer[bufferCounter];
  4946. if (bufferEnd == startPosition) {
  4947. startPosition += this.soundChannelsAllocated;
  4948. if (settings[24] <= startPosition) {
  4949. startPosition -= settings[24];
  4950. }
  4951. }
  4952. else if (bufferEnd == settings[24]) {
  4953. bufferEnd = 0;
  4954. }
  4955. }
  4956. this.audioIndex = 0;
  4957. this.generateAudioSafe(neededSamples / this.soundChannelsAllocated);
  4958. for (var bufferCounter = 0; bufferCounter < this.audioIndex; bufferCounter++) {
  4959. audioContextSampleBuffer[bufferEnd++] = this.currentBuffer[bufferCounter];
  4960. if (bufferEnd == startPosition) {
  4961. startPosition += this.soundChannelsAllocated;
  4962. if (settings[24] <= startPosition) {
  4963. startPosition -= settings[24];
  4964. }
  4965. }
  4966. else if (bufferEnd == settings[24]) {
  4967. bufferEnd = 0;
  4968. }
  4969. }
  4970. this.audioIndex = 0;
  4971. }
  4972. else {
  4973. //Use the overflow buffer's existing samples:
  4974. for (var bufferCounter = 0; bufferCounter < samplesRequested; bufferCounter++) {
  4975. audioContextSampleBuffer[bufferEnd++] = this.currentBuffer[bufferCounter];
  4976. if (bufferEnd == startPosition) {
  4977. startPosition += this.soundChannelsAllocated;
  4978. if (settings[24] <= startPosition) {
  4979. startPosition -= settings[24];
  4980. }
  4981. }
  4982. else if (bufferEnd == settings[24]) {
  4983. bufferEnd = 0;
  4984. }
  4985. }
  4986. neededSamples = this.audioIndex - samplesRequested;
  4987. while (--neededSamples >= 0) {
  4988. //Move over the remaining samples to their new positions:
  4989. this.currentBuffer[neededSamples] = this.currentBuffer[samplesRequested + neededSamples];
  4990. }
  4991. this.audioIndex -= samplesRequested;
  4992. }
  4993. }
  4994. }
  4995. else if (this.audioType == 2) {
  4996. //WAV PCM via Data URI
  4997. this.audioHandle = (this.outTracker++ > 0) ? this.audioHandle : new AudioThread(this.soundChannelsAllocated, settings[14], settings[15], false);
  4998. this.audioHandle.appendBatch(buffer);
  4999. }
  5000. }
  5001. }
  5002. GameBoyCore.prototype.audioUpdate = function () {
  5003. if (settings[0]) {
  5004. if (this.audioType == 2 && this.outTracker > this.outTrackerLimit) {
  5005. try {
  5006. this.audioHandle.outputAudio();
  5007. this.outTracker = 0;
  5008. }
  5009. catch (error) {
  5010. settings[0] = false;
  5011. cout("Audio system cannot run: " + error.message, 2);
  5012. }
  5013. }
  5014. this.audioOverflow = false;
  5015. }
  5016. }
  5017. GameBoyCore.prototype.initializeAudioStartState = function () {
  5018. this.channel1adjustedFrequencyPrep = 0;
  5019. this.channel1lastSampleLookup = 0;
  5020. this.channel1adjustedDuty = 0.5;
  5021. this.channel1totalLength = 0;
  5022. this.channel1envelopeVolume = 0;
  5023. this.channel1currentVolume = 0;
  5024. this.channel1envelopeType = false;
  5025. this.channel1envelopeSweeps = 0;
  5026. this.channel1consecutive = true;
  5027. this.channel1frequency = 0;
  5028. this.channel1volumeEnvTime = 0;
  5029. this.channel1volumeEnvTimeLast = 0;
  5030. this.channel1lastTotalLength = 0;
  5031. this.channel1timeSweep = 0;
  5032. this.channel1lastTimeSweep = 0;
  5033. this.channel1numSweep = 0;
  5034. this.channel1frequencySweepDivider = 0;
  5035. this.channel1decreaseSweep = false;
  5036. this.channel2adjustedFrequencyPrep = 0;
  5037. this.channel2lastSampleLookup = 0;
  5038. this.channel2adjustedDuty = 0.5;
  5039. this.channel2totalLength = 0;
  5040. this.channel2envelopeVolume = 0;
  5041. this.channel2currentVolume = 0;
  5042. this.channel2envelopeType = false;
  5043. this.channel2envelopeSweeps = 0;
  5044. this.channel2consecutive = true;
  5045. this.channel2frequency = 0;
  5046. this.channel2volumeEnvTime = 0;
  5047. this.channel2volumeEnvTimeLast = 0;
  5048. this.channel2lastTotalLength = 0;
  5049. this.channel3canPlay = false;
  5050. this.channel3totalLength = 0;
  5051. this.channel3lastTotalLength = 0;
  5052. this.channel3patternType = -20;
  5053. this.channel3frequency = 0;
  5054. this.channel3consecutive = true;
  5055. this.channel3PCM = this.getTypedArray(0x60, 0, "float32");
  5056. this.channel3adjustedFrequencyPrep = 0x20000 / settings[14];
  5057. this.channel4adjustedFrequencyPrep = 0;
  5058. this.channel4lastSampleLookup = 0; //Keeps track of the audio timing.
  5059. this.channel4totalLength = 0;
  5060. this.channel4envelopeVolume = 0;
  5061. this.channel4currentVolume = 0;
  5062. this.channel4envelopeType = false;
  5063. this.channel4envelopeSweeps = 0;
  5064. this.channel4consecutive = true;
  5065. this.channel4volumeEnvTime = 0;
  5066. this.channel4volumeEnvTimeLast = 0;
  5067. this.channel4lastTotalLength = 0;
  5068. this.noiseTableLength = 0x8000;
  5069. }
  5070. //Below are the audio generation functions timed against the CPU:
  5071. GameBoyCore.prototype.generateAudio = function (numSamples) {
  5072. if (settings[0]) {
  5073. if (this.soundMasterEnabled) {
  5074. if (settings[1]) { //Split Mono & Stereo into two, to avoid this if statement every iteration of the loop.
  5075. while (--numSamples >= 0) {
  5076. //MONO
  5077. this.channel1Compute();
  5078. this.channel2Compute();
  5079. this.channel3Compute();
  5080. this.channel4Compute();
  5081. this.currentBuffer[this.audioIndex++] = this.currentSampleRight * this.VinRightChannelMasterVolume - 1;
  5082. if (this.audioIndex == this.numSamplesTotal) {
  5083. this.audioIndex = 0;
  5084. if (this.usingBackupAsMain) {
  5085. this.currentBuffer = this.audioSamples;
  5086. this.usingBackupAsMain = false;
  5087. }
  5088. else {
  5089. this.currentBuffer = this.audioBackup;
  5090. this.usingBackupAsMain = true;
  5091. }
  5092. this.audioOverflow = true;
  5093. }
  5094. }
  5095. }
  5096. else {
  5097. while (--numSamples >= 0) {
  5098. //STEREO
  5099. this.channel1Compute();
  5100. this.channel2Compute();
  5101. this.channel3Compute();
  5102. this.channel4Compute();
  5103. this.currentBuffer[this.audioIndex++] = this.currentSampleLeft * this.VinLeftChannelMasterVolume - 1;
  5104. this.currentBuffer[this.audioIndex++] = this.currentSampleRight * this.VinRightChannelMasterVolume - 1;
  5105. if (this.audioIndex == this.numSamplesTotal) {
  5106. this.audioIndex = 0;
  5107. if (this.usingBackupAsMain) {
  5108. this.currentBuffer = this.audioSamples;
  5109. this.usingBackupAsMain = false;
  5110. }
  5111. else {
  5112. this.currentBuffer = this.audioBackup;
  5113. this.usingBackupAsMain = true;
  5114. }
  5115. this.audioOverflow = true;
  5116. }
  5117. }
  5118. }
  5119. }
  5120. else {
  5121. //SILENT OUTPUT:
  5122. if (settings[1]) {
  5123. while (--numSamples >= 0) {
  5124. //MONO
  5125. this.currentBuffer[this.audioIndex++] = -1;
  5126. if (this.audioIndex == this.numSamplesTotal) {
  5127. this.audioIndex = 0;
  5128. if (this.usingBackupAsMain) {
  5129. this.currentBuffer = this.audioSamples;
  5130. this.usingBackupAsMain = false;
  5131. }
  5132. else {
  5133. this.currentBuffer = this.audioBackup;
  5134. this.usingBackupAsMain = true;
  5135. }
  5136. this.audioOverflow = true;
  5137. }
  5138. }
  5139. }
  5140. else {
  5141. while (--numSamples >= 0) {
  5142. //STEREO
  5143. this.currentBuffer[this.audioIndex++] = this.currentBuffer[this.audioIndex++] = -1;
  5144. if (this.audioIndex == this.numSamplesTotal) {
  5145. this.audioIndex = 0;
  5146. if (this.usingBackupAsMain) {
  5147. this.currentBuffer = this.audioSamples;
  5148. this.usingBackupAsMain = false;
  5149. }
  5150. else {
  5151. this.currentBuffer = this.audioBackup;
  5152. this.usingBackupAsMain = true;
  5153. }
  5154. this.audioOverflow = true;
  5155. }
  5156. }
  5157. }
  5158. }
  5159. }
  5160. }
  5161. GameBoyCore.prototype.audioJIT = function () {
  5162. //Audio Sample Generation Timing:
  5163. var amount = this.audioTicks * this.samplesOut;
  5164. var actual = amount | 0;
  5165. this.rollover += amount - actual;
  5166. if (this.rollover >= 1) {
  5167. this.rollover--;
  5168. actual++;
  5169. }
  5170. this.generateAudio(actual);
  5171. this.audioTicks = 0;
  5172. }
  5173. GameBoyCore.prototype.channel1Compute = function () {
  5174. if ((this.channel1consecutive || this.channel1totalLength > 0) && this.channel1frequency <= 0x7FF) {
  5175. if (this.channel1lastSampleLookup <= this.channel1adjustedDuty) {
  5176. this.currentSampleLeft = (this.leftChannel[0]) ? this.channel1currentVolume : 0;
  5177. this.currentSampleRight = (this.rightChannel[0]) ? this.channel1currentVolume : 0;
  5178. }
  5179. else {
  5180. this.currentSampleLeft = this.currentSampleRight = 0;
  5181. }
  5182. if (this.channel1numSweep > 0) {
  5183. if (--this.channel1timeSweep == 0) {
  5184. this.channel1numSweep--;
  5185. if (this.channel1decreaseSweep) {
  5186. this.channel1frequency -= this.channel1frequency / this.channel1frequencySweepDivider;
  5187. }
  5188. else {
  5189. this.channel1frequency += this.channel1frequency / this.channel1frequencySweepDivider;
  5190. if (this.channel1frequency > 0x7FF) {
  5191. this.memory[0xFF26] &= 0xFE; //Channel #1 On Flag Off
  5192. }
  5193. }
  5194. this.channel1timeSweep = this.channel1lastTimeSweep;
  5195. //Pre-calculate the frequency computation outside the waveform generator for speed:
  5196. this.channel1adjustedFrequencyPrep = this.preChewedAudioComputationMultiplier / (0x800 - this.channel1frequency);
  5197. }
  5198. }
  5199. if (this.channel1envelopeSweeps > 0) {
  5200. if (this.channel1volumeEnvTime > 0) {
  5201. this.channel1volumeEnvTime--;
  5202. }
  5203. else {
  5204. if (!this.channel1envelopeType) {
  5205. if (this.channel1envelopeVolume > 0) {
  5206. this.channel1currentVolume = --this.channel1envelopeVolume / 0x1E;
  5207. this.channel1volumeEnvTime = this.channel1volumeEnvTimeLast;
  5208. }
  5209. }
  5210. else if (this.channel1envelopeVolume < 0xF) {
  5211. this.channel1currentVolume = ++this.channel1envelopeVolume / 0x1E;
  5212. this.channel1volumeEnvTime = this.channel1volumeEnvTimeLast;
  5213. }
  5214. }
  5215. }
  5216. if (this.channel1totalLength > 0) {
  5217. this.channel1totalLength--;
  5218. if (this.channel1totalLength <= 0) {
  5219. this.memory[0xFF26] &= 0xFE; //Channel #1 On Flag Off
  5220. }
  5221. }
  5222. this.channel1lastSampleLookup += this.channel1adjustedFrequencyPrep;
  5223. while (this.channel1lastSampleLookup >= 1) {
  5224. this.channel1lastSampleLookup -= 1;
  5225. }
  5226. }
  5227. else {
  5228. this.currentSampleLeft = this.currentSampleRight = 0;
  5229. }
  5230. }
  5231. GameBoyCore.prototype.channel2Compute = function () {
  5232. if (this.channel2consecutive || this.channel2totalLength > 0) {
  5233. if (this.channel2lastSampleLookup <= this.channel2adjustedDuty) {
  5234. if (this.leftChannel[1]) {
  5235. this.currentSampleLeft += this.channel2currentVolume;
  5236. }
  5237. if (this.rightChannel[1]) {
  5238. this.currentSampleRight += this.channel2currentVolume;
  5239. }
  5240. }
  5241. if (this.channel2envelopeSweeps > 0) {
  5242. if (this.channel2volumeEnvTime > 0) {
  5243. this.channel2volumeEnvTime--;
  5244. }
  5245. else {
  5246. if (!this.channel2envelopeType) {
  5247. if (this.channel2envelopeVolume > 0) {
  5248. this.channel2currentVolume = --this.channel2envelopeVolume / 0x1E;
  5249. this.channel2volumeEnvTime = this.channel2volumeEnvTimeLast;
  5250. }
  5251. }
  5252. else if (this.channel2envelopeVolume < 0xF) {
  5253. this.channel2currentVolume = ++this.channel2envelopeVolume / 0x1E;
  5254. this.channel2volumeEnvTime = this.channel2volumeEnvTimeLast;
  5255. }
  5256. }
  5257. }
  5258. if (this.channel2totalLength > 0) {
  5259. this.channel2totalLength--;
  5260. if (this.channel2totalLength <= 0) {
  5261. this.memory[0xFF26] &= 0xFD; //Channel #2 On Flag Off
  5262. }
  5263. }
  5264. this.channel2lastSampleLookup += this.channel2adjustedFrequencyPrep;
  5265. while (this.channel2lastSampleLookup >= 1) {
  5266. this.channel2lastSampleLookup -= 1;
  5267. }
  5268. }
  5269. }
  5270. GameBoyCore.prototype.channel3Compute = function () {
  5271. if (this.channel3canPlay && (this.channel3consecutive || this.channel3totalLength > 0)) {
  5272. if (this.channel3patternType > -20) {
  5273. var PCMSample = this.channel3PCM[this.channel3Tracker | this.channel3patternType];
  5274. if (this.leftChannel[2]) {
  5275. this.currentSampleLeft += PCMSample;
  5276. }
  5277. if (this.rightChannel[2]) {
  5278. this.currentSampleRight += PCMSample;
  5279. }
  5280. }
  5281. this.channel3Tracker += this.channel3adjustedFrequencyPrep;
  5282. if (this.channel3Tracker >= 0x20) {
  5283. this.channel3Tracker -= 0x20;
  5284. }
  5285. if (this.channel3totalLength > 0) {
  5286. this.channel3totalLength--;
  5287. if (this.channel3totalLength <= 0) {
  5288. this.memory[0xFF26] &= 0xFB; //Channel #3 On Flag Off
  5289. }
  5290. }
  5291. }
  5292. }
  5293. GameBoyCore.prototype.channel4Compute = function () {
  5294. if (this.channel4consecutive || this.channel4totalLength > 0) {
  5295. var duty = this.noiseSampleTable[this.channel4currentVolume | this.channel4lastSampleLookup];
  5296. if (this.leftChannel[3]) {
  5297. this.currentSampleLeft += duty;
  5298. }
  5299. if (this.rightChannel[3]) {
  5300. this.currentSampleRight += duty;
  5301. }
  5302. if (this.channel4envelopeSweeps > 0) {
  5303. if (this.channel4volumeEnvTime > 0) {
  5304. this.channel4volumeEnvTime--;
  5305. }
  5306. else {
  5307. if (!this.channel4envelopeType) {
  5308. if (this.channel4envelopeVolume > 0) {
  5309. this.channel4currentVolume = --this.channel4envelopeVolume << 15;
  5310. this.channel4volumeEnvTime = this.channel4volumeEnvTimeLast;
  5311. }
  5312. }
  5313. else if (this.channel4envelopeVolume < 0xF) {
  5314. this.channel4currentVolume = ++this.channel4envelopeVolume << 15;
  5315. this.channel4volumeEnvTime = this.channel4volumeEnvTimeLast;
  5316. }
  5317. }
  5318. }
  5319. if (this.channel4totalLength > 0) {
  5320. this.channel4totalLength--;
  5321. if (this.channel4totalLength <= 0) {
  5322. this.memory[0xFF26] &= 0xF7; //Channel #4 On Flag Off
  5323. }
  5324. }
  5325. this.channel4lastSampleLookup += this.channel4adjustedFrequencyPrep;
  5326. if (this.channel4lastSampleLookup >= this.noiseTableLength) {
  5327. this.channel4lastSampleLookup -= this.noiseTableLength;
  5328. }
  5329. }
  5330. }
  5331. //Below are the buffer-underrun protection audio refill functions:
  5332. GameBoyCore.prototype.generateAudioSafe = function (numSamples) {
  5333. if (settings[0]) {
  5334. if (this.soundMasterEnabled) {
  5335. if (settings[1]) { //Split Mono & Stereo into two, to avoid this if statement every iteration of the loop.
  5336. while (--numSamples >= 0) {
  5337. //MONO
  5338. this.audioChannelsComputeSafe();
  5339. this.currentBuffer[this.audioIndex++] = this.currentSampleRight * this.VinRightChannelMasterVolume - 1;
  5340. if (this.audioIndex == this.numSamplesTotal) {
  5341. this.audioIndex = 0;
  5342. if (this.usingBackupAsMain) {
  5343. this.currentBuffer = this.audioSamples;
  5344. this.usingBackupAsMain = false;
  5345. }
  5346. else {
  5347. this.currentBuffer = this.audioBackup;
  5348. this.usingBackupAsMain = true;
  5349. }
  5350. this.audioOverflow = true;
  5351. }
  5352. }
  5353. }
  5354. else {
  5355. while (--numSamples >= 0) {
  5356. //STEREO
  5357. this.audioChannelsComputeSafe();
  5358. this.currentBuffer[this.audioIndex++] = this.currentSampleLeft * this.VinLeftChannelMasterVolume - 1;
  5359. this.currentBuffer[this.audioIndex++] = this.currentSampleRight * this.VinRightChannelMasterVolume - 1;
  5360. if (this.audioIndex == this.numSamplesTotal) {
  5361. this.audioIndex = 0;
  5362. if (this.usingBackupAsMain) {
  5363. this.currentBuffer = this.audioSamples;
  5364. this.usingBackupAsMain = false;
  5365. }
  5366. else {
  5367. this.currentBuffer = this.audioBackup;
  5368. this.usingBackupAsMain = true;
  5369. }
  5370. this.audioOverflow = true;
  5371. }
  5372. }
  5373. }
  5374. }
  5375. else {
  5376. //SILENT OUTPUT:
  5377. if (settings[1]) {
  5378. while (--numSamples >= 0) {
  5379. //MONO
  5380. this.currentBuffer[this.audioIndex++] = -1;
  5381. if (this.audioIndex == this.numSamplesTotal) {
  5382. this.audioIndex = 0;
  5383. if (this.usingBackupAsMain) {
  5384. this.currentBuffer = this.audioSamples;
  5385. this.usingBackupAsMain = false;
  5386. }
  5387. else {
  5388. this.currentBuffer = this.audioBackup;
  5389. this.usingBackupAsMain = true;
  5390. }
  5391. this.audioOverflow = true;
  5392. }
  5393. }
  5394. }
  5395. else {
  5396. while (--numSamples >= 0) {
  5397. //STEREO
  5398. this.currentBuffer[this.audioIndex++] = this.currentBuffer[this.audioIndex++] = -1;
  5399. if (this.audioIndex == this.numSamplesTotal) {
  5400. this.audioIndex = 0;
  5401. if (this.usingBackupAsMain) {
  5402. this.currentBuffer = this.audioSamples;
  5403. this.usingBackupAsMain = false;
  5404. }
  5405. else {
  5406. this.currentBuffer = this.audioBackup;
  5407. this.usingBackupAsMain = true;
  5408. }
  5409. this.audioOverflow = true;
  5410. }
  5411. }
  5412. }
  5413. }
  5414. }
  5415. }
  5416. GameBoyCore.prototype.audioChannelsComputeSafe = function () {
  5417. //channel 1:
  5418. if ((this.channel1consecutive || this.channel1totalLength > 0) && this.channel1frequency <= 0x7FF) {
  5419. if (this.channel1lastSampleLookup <= this.channel1adjustedDuty) {
  5420. this.currentSampleLeft = (this.leftChannel[0]) ? this.channel1currentVolume : 0;
  5421. this.currentSampleRight = (this.rightChannel[0]) ? this.channel1currentVolume : 0;
  5422. }
  5423. else {
  5424. this.currentSampleLeft = this.currentSampleRight = 0;
  5425. }
  5426. this.channel1lastSampleLookup += this.channel1adjustedFrequencyPrep;
  5427. while (this.channel1lastSampleLookup >= 1) {
  5428. this.channel1lastSampleLookup -= 1;
  5429. }
  5430. }
  5431. else {
  5432. this.currentSampleLeft = this.currentSampleRight = 0;
  5433. }
  5434. //Channel 2:
  5435. if (this.channel2consecutive || this.channel2totalLength > 0) {
  5436. if (this.channel2lastSampleLookup <= this.channel2adjustedDuty) {
  5437. if (this.leftChannel[1]) {
  5438. this.currentSampleLeft += this.channel2currentVolume;
  5439. }
  5440. if (this.rightChannel[1]) {
  5441. this.currentSampleRight += this.channel2currentVolume;
  5442. }
  5443. }
  5444. this.channel2lastSampleLookup += this.channel2adjustedFrequencyPrep;
  5445. while (this.channel2lastSampleLookup >= 1) {
  5446. this.channel2lastSampleLookup -= 1;
  5447. }
  5448. }
  5449. //Channel 3:
  5450. if (this.channel3canPlay && (this.channel3consecutive || this.channel3totalLength > 0)) {
  5451. if (this.channel3patternType > -20) {
  5452. var PCMSample = this.channel3PCM[this.channel3Tracker | this.channel3patternType];
  5453. if (this.leftChannel[2]) {
  5454. this.currentSampleLeft += PCMSample;
  5455. }
  5456. if (this.rightChannel[2]) {
  5457. this.currentSampleRight += PCMSample;
  5458. }
  5459. }
  5460. this.channel3Tracker += this.channel3adjustedFrequencyPrep;
  5461. if (this.channel3Tracker >= 0x20) {
  5462. this.channel3Tracker -= 0x20;
  5463. }
  5464. }
  5465. //Channel 4:
  5466. if (this.channel4consecutive || this.channel4totalLength > 0) {
  5467. var duty = this.noiseSampleTable[this.channel4currentVolume | this.channel4lastSampleLookup];
  5468. if (this.leftChannel[3]) {
  5469. this.currentSampleLeft += duty;
  5470. }
  5471. if (this.rightChannel[3]) {
  5472. this.currentSampleRight += duty;
  5473. }
  5474. this.channel4lastSampleLookup += this.channel4adjustedFrequencyPrep;
  5475. if (this.channel4lastSampleLookup >= this.noiseTableLength) {
  5476. this.channel4lastSampleLookup -= this.noiseTableLength;
  5477. }
  5478. }
  5479. }
  5480. GameBoyCore.prototype.run = function () {
  5481. //The preprocessing before the actual iteration loop:
  5482. try {
  5483. if ((this.stopEmulator & 2) == 0) {
  5484. if ((this.stopEmulator & 1) == 1) {
  5485. this.stopEmulator = 0;
  5486. this.clockUpdate(); //Frame skip and RTC code.
  5487. this.audioUpdate(); //Lookup the rollover buffer and output WAVE PCM samples if sound is on and have fallen back to it.
  5488. if (!this.halt) { //If no HALT... Execute normally
  5489. this.executeIteration();
  5490. }
  5491. else { //If we bailed out of a halt because the iteration ran down its timing.
  5492. this.CPUTicks = 1;
  5493. this.OPCODE[0x76](this);
  5494. //Execute Interrupt:
  5495. this.runInterrupt();
  5496. //Timing:
  5497. this.updateCore();
  5498. this.executeIteration();
  5499. }
  5500. }
  5501. else { //We can only get here if there was an internal error, but the loop was restarted.
  5502. cout("Iterator restarted a faulted core.", 2);
  5503. pause();
  5504. }
  5505. }
  5506. }
  5507. catch (error) {
  5508. if (error.message != "HALT_OVERRUN") {
  5509. cout("GameBoy runtime error: " + error.message + "; line: " + error.lineNumber, 2);
  5510. }
  5511. }
  5512. }
  5513. GameBoyCore.prototype.executeIteration = function () {
  5514. //Iterate the interpreter loop:
  5515. var op = 0;
  5516. while (this.stopEmulator == 0) {
  5517. //Fetch the current opcode.
  5518. op = this.memoryReader[this.programCounter](this, this.programCounter);
  5519. if (!this.skipPCIncrement) {
  5520. //Increment the program counter to the next instruction:
  5521. this.programCounter = (this.programCounter + 1) & 0xFFFF;
  5522. }
  5523. this.skipPCIncrement = false;
  5524. //Get how many CPU cycles the current op code counts for:
  5525. this.CPUTicks = this.TICKTable[op];
  5526. //Execute the OP code instruction:
  5527. this.OPCODE[op](this);
  5528. //Interrupt Arming:
  5529. switch (this.untilEnable) {
  5530. case 1:
  5531. this.IME = true;
  5532. case 2:
  5533. this.untilEnable--;
  5534. }
  5535. //Execute Interrupt:
  5536. if (this.IME) {
  5537. this.runInterrupt();
  5538. }
  5539. //Timing:
  5540. this.updateCore();
  5541. }
  5542. }
  5543. GameBoyCore.prototype.runInterrupt = function () {
  5544. var bitShift = 0;
  5545. var testbit = 1;
  5546. var interrupts = this.memory[0xFFFF] & this.memory[0xFF0F];
  5547. while (bitShift < 5) {
  5548. //Check to see if an interrupt is enabled AND requested.
  5549. if ((testbit & interrupts) == testbit) {
  5550. this.IME = false; //Reset the interrupt enabling.
  5551. this.memory[0xFF0F] -= testbit; //Reset the interrupt request.
  5552. //Set the stack pointer to the current program counter value:
  5553. this.stackPointer = (this.stackPointer - 1) & 0xFFFF;
  5554. this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter >> 8);
  5555. this.stackPointer = (this.stackPointer - 1) & 0xFFFF;
  5556. this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter & 0xFF);
  5557. //Set the program counter to the interrupt's address:
  5558. this.programCounter = 0x40 | (bitShift << 3);
  5559. //Interrupts have a certain clock cycle length:
  5560. this.CPUTicks += 5; //People say it's around 5.
  5561. break; //We only want the highest priority interrupt.
  5562. }
  5563. testbit = 1 << ++bitShift;
  5564. }
  5565. }
  5566. GameBoyCore.prototype.scanLineMode2 = function () { //OAM Search Period
  5567. if (this.modeSTAT != 2) {
  5568. if (this.mode2TriggerSTAT) {
  5569. this.memory[0xFF0F] |= 0x2;
  5570. }
  5571. this.STATTracker = 1;
  5572. this.modeSTAT = 2;
  5573. }
  5574. }
  5575. GameBoyCore.prototype.scanLineMode3 = function () { //Scan Line Drawing Period
  5576. if (this.modeSTAT != 3) {
  5577. if (this.mode2TriggerSTAT && this.STATTracker == 0) {
  5578. this.memory[0xFF0F] |= 0x2;
  5579. }
  5580. this.STATTracker = 1;
  5581. this.modeSTAT = 3;
  5582. }
  5583. }
  5584. GameBoyCore.prototype.scanLineMode0 = function () { //Horizontal Blanking Period
  5585. if (this.modeSTAT != 0) {
  5586. if (this.STATTracker < 4) {
  5587. this.notifyScanline();
  5588. this.STATTracker |= 4
  5589. }
  5590. if (this.LCDTicks >= this.spriteCount) {
  5591. if (this.hdmaRunning && !this.halt) {
  5592. this.performHdma();
  5593. }
  5594. if (this.mode0TriggerSTAT || (this.mode2TriggerSTAT && this.STATTracker == 4)) {
  5595. this.memory[0xFF0F] |= 0x2;
  5596. }
  5597. this.STATTracker = 2;
  5598. this.modeSTAT = 0;
  5599. }
  5600. }
  5601. }
  5602. GameBoyCore.prototype.matchLYC = function () { //LYC Register Compare
  5603. if (this.memory[0xFF44] == this.memory[0xFF45]) {
  5604. this.memory[0xFF41] |= 0x04;
  5605. if (this.LYCMatchTriggerSTAT) {
  5606. this.memory[0xFF0F] |= 0x2;
  5607. }
  5608. }
  5609. else {
  5610. this.memory[0xFF41] &= 0xFB;
  5611. }
  5612. }
  5613. GameBoyCore.prototype.updateCore = function () {
  5614. //CPU Timers:
  5615. this.DIVTicks += this.CPUTicks; //DIV Timing
  5616. if (this.TIMAEnabled) { //TIMA Timing
  5617. this.timerTicks += this.CPUTicks;
  5618. while (this.timerTicks >= this.TACClocker) {
  5619. this.timerTicks -= this.TACClocker;
  5620. if (this.memory[0xFF05] == 0xFF) {
  5621. this.memory[0xFF05] = this.memory[0xFF06];
  5622. this.memory[0xFF0F] |= 0x4;
  5623. }
  5624. else {
  5625. this.memory[0xFF05]++;
  5626. }
  5627. }
  5628. }
  5629. //single-speed relative timing for A/V emulation:
  5630. var timedTicks = this.CPUTicks / this.multiplier;
  5631. this.LCDTicks += timedTicks; //LCD Timing
  5632. this.audioTicks += timedTicks; //Audio Timing
  5633. this.emulatorTicks += timedTicks; //Emulator Timing
  5634. this.LCDCONTROL[this.actualScanLine](this); //Scan Line and STAT Mode Control
  5635. //End of iteration routine:
  5636. if (this.emulatorTicks >= this.CPUCyclesPerIteration) {
  5637. this.audioJIT();
  5638. this.playAudio(); //Output all the samples built up.
  5639. if (this.asyncDrawSupportDetected == 1) {
  5640. //Async Event Handler for requesting frame time (Firefox 4):
  5641. window.mozRequestAnimationFrame();
  5642. }
  5643. else if (this.asyncDrawSupportDetected == 2) {
  5644. //Async Event Handler for requesting frame time (Chrome 11):
  5645. window.webkitRequestAnimationFrame(vSyncGFX);
  5646. }
  5647. else if (this.drewBlank == 0) { //LCD off takes at least 2 frames.
  5648. this.drawToCanvas(); //Display frame
  5649. }
  5650. //Update DIV Alignment (Integer overflow safety):
  5651. this.memory[0xFF04] = (this.memory[0xFF04] + (this.DIVTicks >> 6)) & 0xFF;
  5652. this.DIVTicks &= 0x3F;
  5653. //Update emulator flags:
  5654. this.stopEmulator |= 1; //End current loop.
  5655. this.emulatorTicks -= this.CPUCyclesPerIteration;
  5656. }
  5657. }
  5658. GameBoyCore.prototype.initializeLCDController = function () {
  5659. //Display on hanlding:
  5660. var line = 0;
  5661. while (line < 154) {
  5662. if (line < 143) {
  5663. //We're on a normal scan line:
  5664. this.LINECONTROL[line] = function (parentObj) {
  5665. if (parentObj.LCDTicks < 20) {
  5666. parentObj.scanLineMode2();
  5667. }
  5668. else if (parentObj.LCDTicks < 63) {
  5669. parentObj.scanLineMode3();
  5670. }
  5671. else if (parentObj.LCDTicks < 114) {
  5672. parentObj.scanLineMode0();
  5673. }
  5674. else {
  5675. //We're on a new scan line:
  5676. parentObj.LCDTicks -= 114;
  5677. if (parentObj.STATTracker != 2) {
  5678. if (parentObj.STATTracker < 4) {
  5679. parentObj.notifyScanline();
  5680. }
  5681. if (parentObj.hdmaRunning && !parentObj.halt) {
  5682. parentObj.performHdma();
  5683. }
  5684. if (parentObj.mode0TriggerSTAT) {
  5685. parentObj.memory[0xFF0F] |= 0x2;
  5686. }
  5687. }
  5688. parentObj.actualScanLine = ++parentObj.memory[0xFF44];
  5689. parentObj.matchLYC();
  5690. parentObj.STATTracker = 0;
  5691. parentObj.scanLineMode2();
  5692. if (parentObj.LCDTicks >= 114) {
  5693. //We need to skip 1 or more scan lines:
  5694. parentObj.notifyScanline();
  5695. parentObj.LCDCONTROL[parentObj.actualScanLine](parentObj); //Scan Line and STAT Mode Control
  5696. }
  5697. }
  5698. }
  5699. }
  5700. else if (line == 143) {
  5701. //We're on the last visible scan line of the LCD screen:
  5702. this.LINECONTROL[143] = function (parentObj) {
  5703. if (parentObj.LCDTicks < 20) {
  5704. parentObj.scanLineMode2();
  5705. }
  5706. else if (parentObj.LCDTicks < 63) {
  5707. parentObj.scanLineMode3();
  5708. }
  5709. else if (parentObj.LCDTicks < 114) {
  5710. parentObj.scanLineMode0();
  5711. }
  5712. else {
  5713. //Starting V-Blank:
  5714. //Just finished the last visible scan line:
  5715. parentObj.LCDTicks -= 114;
  5716. if (parentObj.mode1TriggerSTAT) {
  5717. parentObj.memory[0xFF0F] |= 0x2;
  5718. }
  5719. if (parentObj.STATTracker != 2) {
  5720. if (parentObj.STATTracker < 4) {
  5721. parentObj.notifyScanline();
  5722. }
  5723. if (parentObj.hdmaRunning && !parentObj.halt) {
  5724. parentObj.performHdma();
  5725. }
  5726. if (parentObj.mode0TriggerSTAT) {
  5727. parentObj.memory[0xFF0F] |= 0x2;
  5728. }
  5729. }
  5730. parentObj.actualScanLine = ++parentObj.memory[0xFF44];
  5731. parentObj.matchLYC();
  5732. parentObj.STATTracker = 0;
  5733. parentObj.modeSTAT = 1;
  5734. parentObj.memory[0xFF0F] |= 0x1;
  5735. if (parentObj.drewBlank > 0) { //LCD off takes at least 2 frames.
  5736. parentObj.drewBlank--;
  5737. }
  5738. if (parentObj.LCDTicks >= 114) {
  5739. //We need to skip 1 or more scan lines:
  5740. parentObj.LCDCONTROL[parentObj.actualScanLine](parentObj); //Scan Line and STAT Mode Control
  5741. }
  5742. }
  5743. }
  5744. }
  5745. else if (line < 153) {
  5746. //In VBlank
  5747. this.LINECONTROL[line] = function (parentObj) {
  5748. if (parentObj.LCDTicks >= 114) {
  5749. //We're on a new scan line:
  5750. parentObj.LCDTicks -= 114;
  5751. parentObj.actualScanLine = ++parentObj.memory[0xFF44];
  5752. parentObj.matchLYC();
  5753. if (parentObj.LCDTicks >= 114) {
  5754. //We need to skip 1 or more scan lines:
  5755. parentObj.LCDCONTROL[parentObj.actualScanLine](parentObj); //Scan Line and STAT Mode Control
  5756. }
  5757. }
  5758. }
  5759. }
  5760. else {
  5761. //VBlank Ending (We're on the last actual scan line)
  5762. this.LINECONTROL[153] = function (parentObj) {
  5763. if (parentObj.memory[0xFF44] == 153 && parentObj.LCDTicks >= 2) { //TODO: Double-check to see if 2 is right.
  5764. parentObj.memory[0xFF44] = 0; //LY register resets to 0 early.
  5765. parentObj.matchLYC();
  5766. }
  5767. if (parentObj.LCDTicks >= 114) {
  5768. //We reset back to the beginning:
  5769. parentObj.LCDTicks -= 114;
  5770. parentObj.actualScanLine = 0;
  5771. parentObj.scanLineMode2();
  5772. if (parentObj.LCDTicks >= 114) {
  5773. //We need to skip 1 or more scan lines:
  5774. parentObj.LCDCONTROL[parentObj.actualScanLine](parentObj); //Scan Line and STAT Mode Control
  5775. }
  5776. }
  5777. }
  5778. }
  5779. line++;
  5780. }
  5781. this.LCDCONTROL = (this.LCDisOn) ? this.LINECONTROL : this.DISPLAYOFFCONTROL;
  5782. }
  5783. GameBoyCore.prototype.DisplayShowOff = function () {
  5784. if (this.drewBlank == 0) {
  5785. //Draw a blank screen:
  5786. var index = this.rgbCount;
  5787. while (index > 0) {
  5788. this.canvasBuffer.data[--index] = 0xFF;
  5789. }
  5790. this.drawContext.putImageData(this.canvasBuffer, 0, 0);
  5791. this.drewBlank = 2;
  5792. }
  5793. }
  5794. GameBoyCore.prototype.performHdma = function () {
  5795. this.CPUTicks += 1 + (8 * this.multiplier);
  5796. var dmaSrc = (this.memory[0xFF51] << 8) | this.memory[0xFF52];
  5797. var dmaDstRelative = (this.memory[0xFF53] << 8) | this.memory[0xFF54];
  5798. var dmaDstFinal = dmaDstRelative + 0x10;
  5799. var tileRelative = this.tileData.length - this.tileCount;
  5800. if (this.currVRAMBank == 1) {
  5801. while (dmaDstRelative < dmaDstFinal) {
  5802. if (dmaDstRelative < 0x1800) { // Bkg Tile data area
  5803. var tileIndex = (dmaDstRelative >> 4) | 384;
  5804. if (this.tileReadState[tileIndex] == 1) {
  5805. var r = tileRelative + tileIndex;
  5806. do {
  5807. this.tileData[r] = null;
  5808. r -= this.tileCount;
  5809. } while (r >= 0);
  5810. this.tileReadState[tileIndex] = 0;
  5811. }
  5812. }
  5813. this.VRAM[dmaDstRelative++] = this.memoryReader[dmaSrc](this, dmaSrc++);
  5814. }
  5815. }
  5816. else {
  5817. while (dmaDstRelative < dmaDstFinal) {
  5818. if (dmaDstRelative < 0x1800) { // Bkg Tile data area
  5819. var tileIndex = dmaDstRelative >> 4;
  5820. if (this.tileReadState[tileIndex] == 1) {
  5821. var r = tileRelative + tileIndex;
  5822. do {
  5823. this.tileData[r] = null;
  5824. r -= this.tileCount;
  5825. } while (r >= 0);
  5826. this.tileReadState[tileIndex] = 0;
  5827. }
  5828. }
  5829. this.memory[0x8000 | dmaDstRelative++] = this.memoryReader[dmaSrc](this, dmaSrc++);
  5830. }
  5831. }
  5832. this.memory[0xFF51] = ((dmaSrc & 0xFF00) >> 8);
  5833. this.memory[0xFF52] = (dmaSrc & 0x00F0);
  5834. this.memory[0xFF53] = ((dmaDstFinal & 0x1F00) >> 8);
  5835. this.memory[0xFF54] = (dmaDstFinal & 0x00F0);
  5836. if (this.memory[0xFF55] == 0) {
  5837. this.hdmaRunning = false;
  5838. this.memory[0xFF55] = 0xFF; //Transfer completed ("Hidden last step," since some ROMs don't imply this, but most do).
  5839. }
  5840. else {
  5841. this.memory[0xFF55]--;
  5842. }
  5843. }
  5844. GameBoyCore.prototype.clockUpdate = function () {
  5845. //We're tying in the same timer for RTC and frame skipping, since we can and this reduces load.
  5846. if (settings[7] || this.cTIMER) {
  5847. var dateObj = new Date();
  5848. var newTime = dateObj.getTime();
  5849. var timeElapsed = newTime - this.lastIteration; //Get the numnber of milliseconds since this last executed.
  5850. this.lastIteration = newTime;
  5851. if (this.cTIMER && !this.RTCHALT) {
  5852. //Update the MBC3 RTC:
  5853. this.RTCSeconds += timeElapsed / 1000;
  5854. while (this.RTCSeconds >= 60) { //System can stutter, so the seconds difference can get large, thus the "while".
  5855. this.RTCSeconds -= 60;
  5856. this.RTCMinutes++;
  5857. if (this.RTCMinutes >= 60) {
  5858. this.RTCMinutes -= 60;
  5859. this.RTCHours++;
  5860. if (this.RTCHours >= 24) {
  5861. this.RTCHours -= 24
  5862. this.RTCDays++;
  5863. if (this.RTCDays >= 512) {
  5864. this.RTCDays -= 512;
  5865. this.RTCDayOverFlow = true;
  5866. }
  5867. }
  5868. }
  5869. }
  5870. }
  5871. if (settings[7]) {
  5872. //Auto Frame Skip:
  5873. if (timeElapsed > settings[20]) {
  5874. //Did not finish in time...
  5875. if (settings[4] < settings[8]) {
  5876. settings[4]++;
  5877. }
  5878. }
  5879. else if (settings[4] > 0) {
  5880. //We finished on time, decrease frame skipping (throttle to somewhere just below full speed)...
  5881. settings[4]--;
  5882. }
  5883. }
  5884. }
  5885. }
  5886. GameBoyCore.prototype.drawToCanvas = function () {
  5887. //Draw the frame buffer to the canvas:
  5888. if (settings[4] == 0 || this.frameCount > 0) {
  5889. //Copy and convert the framebuffer data to the CanvasPixelArray format.
  5890. var canvasData = this.canvasBuffer.data;
  5891. var frameBuffer = (settings[21] && this.pixelCount > 0 && this.width != 160 && this.height != 144) ? this.resizeFrameBuffer() : this.frameBuffer;
  5892. var bufferIndex = this.pixelCount;
  5893. var canvasIndex = this.rgbCount;
  5894. while (canvasIndex > 3) {
  5895. canvasData[canvasIndex -= 4] = (frameBuffer[--bufferIndex] >> 16) & 0xFF; //Red
  5896. canvasData[canvasIndex + 1] = (frameBuffer[bufferIndex] >> 8) & 0xFF; //Green
  5897. canvasData[canvasIndex + 2] = frameBuffer[bufferIndex] & 0xFF; //Blue
  5898. }
  5899. //Draw out the CanvasPixelArray data:
  5900. this.drawContext.putImageData(this.canvasBuffer, 0, 0);
  5901. if (settings[4] > 0) {
  5902. //Increment the frameskip counter:
  5903. this.frameCount -= settings[4];
  5904. }
  5905. }
  5906. else {
  5907. //Reset the frameskip counter:
  5908. this.frameCount += settings[12];
  5909. }
  5910. }
  5911. GameBoyCore.prototype.resizeFrameBuffer = function () {
  5912. //Attempt to resize the canvas in software instead of in CSS:
  5913. var column = 0;
  5914. var rowOffset = 0;
  5915. for (var row = 0; row < this.height; row++) {
  5916. rowOffset = ((row * this.heightRatio) | 0) * 160;
  5917. for (column = 0; column < this.width; column++) {
  5918. this.scaledFrameBuffer[(row * this.width) + column] = this.frameBuffer[rowOffset + ((column * this.widthRatio) | 0)];
  5919. }
  5920. }
  5921. return this.scaledFrameBuffer;
  5922. }
  5923. GameBoyCore.prototype.invalidateAll = function (pal) {
  5924. var stop = (pal + 1) * this.tileCountInvalidator;
  5925. for (var r = pal * this.tileCountInvalidator; r < stop; r++) {
  5926. this.tileData[r] = null;
  5927. }
  5928. }
  5929. GameBoyCore.prototype.setGBCPalettePre = function (index_, data) {
  5930. if (this.gbcRawPalette[index_] == data) {
  5931. return;
  5932. }
  5933. this.gbcRawPalette[index_] = data;
  5934. if (index_ >= 0x40 && (index_ & 0x6) == 0) {
  5935. // stay transparent
  5936. return;
  5937. }
  5938. var value = (this.gbcRawPalette[index_ | 1] << 8) | this.gbcRawPalette[index_ & -2];
  5939. this.gbcPalette[index_ >> 1] = 0x80000000 | ((value & 0x1F) << 19) | ((value & 0x3E0) << 6) | ((value & 0x7C00) >> 7);
  5940. this.invalidateAll(index_ >> 3);
  5941. }
  5942. GameBoyCore.prototype.getGBCColor = function () {
  5943. //GBC Colorization of DMG ROMs:
  5944. for (var counter = 0; counter < 12; counter++) {
  5945. var adjustedIndex = 2 * counter;
  5946. if (counter > 3) {
  5947. adjustedIndex += 0x38;
  5948. }
  5949. var value = (this.gbcRawPalette[adjustedIndex | 1] << 8) | this.gbcRawPalette[adjustedIndex];
  5950. this.cachedPaletteConversion[counter] = 0x80000000 | ((value & 0x1F) << 19) | ((value & 0x3E0) << 6) | ((value & 0x7C00) >> 7);
  5951. }
  5952. }
  5953. GameBoyCore.prototype.setGBCPalette = function (index_, data) {
  5954. this.setGBCPalettePre(index_, data);
  5955. if ((index_ & 0x6) == 0) {
  5956. this.gbcPalette[index_ >> 1] &= 0x00FFFFFF;
  5957. }
  5958. }
  5959. GameBoyCore.prototype.decodePalette = function (startIndex, data) {
  5960. this.gbPalette[startIndex] = this.colors[data & 0x03] & 0x00FFFFFF; // color 0: transparent
  5961. this.gbPalette[startIndex | 1] = this.colors[(data >> 2) & 0x03];
  5962. this.gbPalette[startIndex | 2] = this.colors[(data >> 4) & 0x03];
  5963. this.gbPalette[startIndex | 3] = this.colors[data >> 6];
  5964. if (this.usedBootROM) { //Do palette conversions if we did the GBC bootup:
  5965. //GB colorization:
  5966. this.gbColorizedPalette[startIndex] = this.cachedPaletteConversion[startIndex | (data & 0x03)] & 0x00FFFFFF;
  5967. this.gbColorizedPalette[startIndex | 1] = this.cachedPaletteConversion[startIndex | ((data >> 2) & 0x03)];
  5968. this.gbColorizedPalette[startIndex | 2] = this.cachedPaletteConversion[startIndex | ((data >> 4) & 0x03)];
  5969. this.gbColorizedPalette[startIndex | 3] = this.cachedPaletteConversion[startIndex | (data >> 6)];
  5970. }
  5971. }
  5972. GameBoyCore.prototype.notifyScanline = function () {
  5973. if (this.actualScanLine == 0) {
  5974. this.windowSourceLine = 0;
  5975. }
  5976. // determine the left edge of the window (160 if window is inactive)
  5977. var windowLeft = (this.gfxWindowDisplay && this.memory[0xFF4A] <= this.actualScanLine) ? Math.min(160, this.memory[0xFF4B] - 7) : 160;
  5978. // step 1: background+window
  5979. var skippedAnything = this.drawBackgroundForLine(this.actualScanLine, windowLeft, 0);
  5980. // At this point, the high (alpha) byte in the frameBuffer is 0xff for colors 1,2,3 and
  5981. // 0x00 for color 0. Foreground sprites draw on all colors, background sprites draw on
  5982. // top of color 0 only.
  5983. // step 2: sprites
  5984. this.drawSpritesForLine(this.actualScanLine);
  5985. // step 3: prio tiles+window
  5986. if (skippedAnything) {
  5987. this.drawBackgroundForLine(this.actualScanLine, windowLeft, 0x80);
  5988. }
  5989. if (windowLeft < 160) {
  5990. this.windowSourceLine++;
  5991. }
  5992. }
  5993. GameBoyCore.prototype.drawBackgroundForLine = function (line, windowLeft, priority) {
  5994. var skippedTile = false;
  5995. var tileNum = 0, tileXCoord = 0, tileAttrib = 0;
  5996. var sourceY = line + this.memory[0xFF42];
  5997. var sourceImageLine = sourceY & 0x7;
  5998. var tileX = this.memory[0xFF43] >> 3;
  5999. var memStart = ((this.gfxBackgroundCHRBankPosition) ? 0x1C00 : 0x1800) + ((sourceY & 0xF8) << 2);
  6000. var screenX = -(this.memory[0xFF43] & 7);
  6001. for (; screenX < windowLeft; tileX++, screenX += 8) {
  6002. tileXCoord = (tileX & 0x1F);
  6003. var baseaddr = this.memory[0x8000 | memStart | tileXCoord];
  6004. tileNum = (this.gfxBackgroundBankOffset || baseaddr > 0x7F) ? baseaddr : (baseaddr + 0x100);
  6005. tileAttrib = 0;
  6006. if (this.cGBC) {
  6007. var mapAttrib = this.VRAM[memStart | tileXCoord];
  6008. if ((mapAttrib & 0x80) != priority) {
  6009. skippedTile = true;
  6010. continue;
  6011. }
  6012. tileAttrib = ((mapAttrib & 0x07) << 2) | ((mapAttrib >> 5) & 0x03);
  6013. tileNum += 384 * ((mapAttrib >> 3) & 0x01); // tile vram bank
  6014. }
  6015. this.drawPartCopy(tileNum, screenX, line, sourceImageLine, tileAttrib);
  6016. }
  6017. if (windowLeft < 160) {
  6018. // window!
  6019. var windowStartAddress = (this.gfxWindowCHRBankPosition) ? 0x1C00 : 0x1800;
  6020. var tileAddress = windowStartAddress | ((this.windowSourceLine >> 3) << 5);
  6021. var windowSourceTileLine = this.windowSourceLine & 0x7;
  6022. for (screenX = windowLeft; screenX < 160; tileAddress++, screenX += 8) {
  6023. var baseaddr = this.memory[0x8000 | tileAddress];
  6024. tileNum = (this.gfxBackgroundBankOffset || baseaddr > 0x7F) ? baseaddr : (baseaddr + 0x100);
  6025. tileAttrib = 0;
  6026. if (this.cGBC) {
  6027. var mapAttrib = this.VRAM[tileAddress];
  6028. if ((mapAttrib & 0x80) != priority) {
  6029. skippedTile = true;
  6030. continue;
  6031. }
  6032. tileAttrib = ((mapAttrib & 0x07) << 2) | ((mapAttrib >> 5) & 0x03); // mirroring
  6033. tileNum += 384 * ((mapAttrib >> 3) & 0x01); // tile vram bank
  6034. }
  6035. this.drawPartCopy(tileNum, screenX, line, windowSourceTileLine, tileAttrib);
  6036. }
  6037. }
  6038. return skippedTile;
  6039. }
  6040. GameBoyCore.prototype.drawPartCopy = function (tileIndex, x, y, sourceLine, attribs) {
  6041. var image = this.tileData[tileIndex + this.tileCount * attribs] || this.updateImage(tileIndex, attribs);
  6042. var dst = x + y * 160;
  6043. var src = sourceLine * 8;
  6044. var dstEnd = (x > 152) ? ((y + 1) * 160) : (dst + 8);
  6045. if (x < 0) { // adjust left
  6046. dst -= x;
  6047. src -= x;
  6048. }
  6049. while (dst < dstEnd) {
  6050. this.frameBuffer[dst++] = image[src++];
  6051. }
  6052. }
  6053. GameBoyCore.prototype.updateImage = function (tileIndex, attribs) {
  6054. var index_ = tileIndex + this.tileCount * attribs;
  6055. var otherBank = (tileIndex >= 384);
  6056. var offset = otherBank ? ((tileIndex - 384) << 4) : (tileIndex << 4);
  6057. var paletteStart = attribs & 0xFC;
  6058. var transparent = (attribs >= this.transparentCutoff);
  6059. var pixix = 0;
  6060. var pixixdx = 1;
  6061. var pixixdy = 0;
  6062. var tempPix = this.getTypedArray(64, 0, "int32");
  6063. if ((attribs & 2) != 0) {
  6064. pixixdy = -16;
  6065. pixix = 56;
  6066. }
  6067. if ((attribs & 1) == 0) {
  6068. pixixdx = -1;
  6069. pixix += 7;
  6070. pixixdy += 16;
  6071. }
  6072. for (var y = 8; --y >= 0;) {
  6073. var num = this.weaveLookup[this.VRAMReadGFX(offset++, otherBank)] + (this.weaveLookup[this.VRAMReadGFX(offset++, otherBank)] << 1);
  6074. if (num != 0) {
  6075. transparent = false;
  6076. }
  6077. for (var x = 8; --x >= 0;) {
  6078. tempPix[pixix] = this.palette[paletteStart | (num & 3)] & -1;
  6079. pixix += pixixdx;
  6080. num >>= 2;
  6081. }
  6082. pixix += pixixdy;
  6083. }
  6084. this.tileData[index_] = (transparent) ? true : tempPix;
  6085. this.tileReadState[tileIndex] = 1;
  6086. return this.tileData[index_];
  6087. }
  6088. GameBoyCore.prototype.drawSpritesForLine = function (line) {
  6089. if (!this.gfxSpriteShow) {
  6090. return;
  6091. }
  6092. var minSpriteY = line - ((this.gfxSpriteDouble) ? 15 : 7);
  6093. // either only do priorityFlag == 0 (all foreground),
  6094. // or first 0x80 (background) and then 0 (foreground)
  6095. this.spriteCount = 63;
  6096. for (var priorityFlag = (this.BGPriorityEnabled ? 0x80 : 0); priorityFlag >= 0; priorityFlag -= 0x80) {
  6097. var oamIx = 159;
  6098. while (oamIx >= 0) {
  6099. var attributes = this.memory[0xFE00 | oamIx--];
  6100. if ((attributes & 0x80) == priorityFlag || !this.BGPriorityEnabled) {
  6101. var tileNum = this.memory[0xFE00 | oamIx--];
  6102. var spriteX = this.memory[0xFE00 | oamIx--] - 8;
  6103. var spriteY = this.memory[0xFE00 | oamIx--] - 16;
  6104. var offset = line - spriteY;
  6105. if (spriteX >= 160 || spriteY < minSpriteY || offset < 0) {
  6106. continue;
  6107. }
  6108. this.spriteCount += 1.5;
  6109. if (this.gfxSpriteDouble) {
  6110. tileNum = tileNum & 0xFE;
  6111. }
  6112. var spriteAttrib = (attributes & 0x7F) >> 5; // flipx: from bit 0x20 to 0x01, flipy: from bit 0x40 to 0x02
  6113. if (this.cGBC) {
  6114. spriteAttrib += 0x20 + ((attributes & 0x07) << 2); // palette
  6115. tileNum += 0x30 * (attributes & 0x08); // tile vram bank
  6116. }
  6117. else {
  6118. // attributes 0x10: 0x00 = OBJ1 palette, 0x10 = OBJ2 palette
  6119. // spriteAttrib: 0x04: OBJ1 palette, 0x08: OBJ2 palette
  6120. spriteAttrib += 0x4 + ((attributes & 0x10) >> 2);
  6121. }
  6122. if (priorityFlag == 0x80) {
  6123. // background
  6124. if (this.gfxSpriteDouble) {
  6125. if ((spriteAttrib & 2) != 0) {
  6126. this.drawPartBgSprite((tileNum | 1) - (offset >> 3), spriteX, line, offset & 7, spriteAttrib);
  6127. }
  6128. else {
  6129. this.drawPartBgSprite((tileNum & -2) + (offset >> 3), spriteX, line, offset & 7, spriteAttrib);
  6130. }
  6131. }
  6132. else {
  6133. this.drawPartBgSprite(tileNum, spriteX, line, offset, spriteAttrib);
  6134. }
  6135. }
  6136. else {
  6137. // foreground
  6138. if (this.gfxSpriteDouble) {
  6139. if ((spriteAttrib & 2) != 0) {
  6140. this.drawPartFgSprite((tileNum | 1) - (offset >> 3), spriteX, line, offset & 7, spriteAttrib);
  6141. }
  6142. else {
  6143. this.drawPartFgSprite((tileNum & -2) + (offset >> 3), spriteX, line, offset & 7, spriteAttrib);
  6144. }
  6145. }
  6146. else {
  6147. this.drawPartFgSprite(tileNum, spriteX, line, offset, spriteAttrib);
  6148. }
  6149. }
  6150. }
  6151. else {
  6152. oamIx -= 3;
  6153. }
  6154. }
  6155. }
  6156. }
  6157. GameBoyCore.prototype.drawPartFgSprite = function (tileIndex, x, y, sourceLine, attribs) {
  6158. var im = this.tileData[tileIndex + this.tileCount * attribs] || this.updateImage(tileIndex, attribs);
  6159. if (im === true) {
  6160. return;
  6161. }
  6162. var dst = x + y * 160;
  6163. var src = sourceLine * 8;
  6164. var dstEnd = (x > 152) ? ((y + 1) * 160) : (dst + 8);
  6165. if (x < 0) { // adjust left
  6166. dst -= x;
  6167. src -= x;
  6168. }
  6169. while (dst < dstEnd) {
  6170. if (im[src] < 0) {
  6171. this.frameBuffer[dst] = im[src];
  6172. }
  6173. dst++;
  6174. src++;
  6175. }
  6176. }
  6177. GameBoyCore.prototype.drawPartBgSprite = function (tileIndex, x, y, sourceLine, attribs) {
  6178. var im = this.tileData[tileIndex + this.tileCount * attribs] || this.updateImage(tileIndex, attribs);
  6179. if (im === true) {
  6180. return;
  6181. }
  6182. var dst = x + y * 160;
  6183. var src = sourceLine * 8;
  6184. var dstEnd = (x > 152) ? ((y + 1) * 160) : (dst + 8);
  6185. if (x < 0) { // adjust left
  6186. dst -= x;
  6187. src -= x;
  6188. }
  6189. while (dst < dstEnd) {
  6190. if (im[src] < 0 && this.frameBuffer[dst] >= 0) {
  6191. this.frameBuffer[dst] = im[src];
  6192. }
  6193. dst++;
  6194. src++;
  6195. }
  6196. }
  6197. //New GFX Engine:
  6198. GameBoyCore.prototype.drawScanline = function () {
  6199. if (this.bgEnabled) {
  6200. this.BGLayerRender();
  6201. this.WindowLayerRender();
  6202. this.SpriteLayerRender();
  6203. }
  6204. else {
  6205. var pixelLine = (this.actualScanLine + 1) * 160;
  6206. for (pixelPosition = this.actualScanLine * 160; pixelPosition < pixelLine; pixelPosition++) {
  6207. this.framebuffer[pixelPosition++] = 0xF8F8F8;
  6208. }
  6209. }
  6210. }
  6211. GameBoyCore.prototype.checkPaletteType = function () {
  6212. //Reference the correct palette ahead of time...
  6213. this.BGPalette = (this.cGBC) ? this.gbcBGPalette : ((this.usedBootROM && settings[17]) ? this.gbBGColorizedPalette : this.gbBGPalette);
  6214. this.OBJPalette = (this.cGBC) ? this.gbcOBJPalette : ((this.usedBootROM && settings[17]) ? this.gbOBJColorizedPalette : this.gbOBJPalette);
  6215. }
  6216. GameBoyCore.prototype.getGBCColor = function () {
  6217. //GBC Colorization of DMG ROMs:
  6218. //BG
  6219. for (var counter = 0; counter < 4; counter++) {
  6220. var adjustedIndex = 2 * counter;
  6221. var value = (this.gbcBGRawPalette[adjustedIndex | 1] << 8) | this.gbcBGRawPalette[adjustedIndex];
  6222. this.cachedBGPaletteConversion[counter] = ((value & 0x1F) << 19) | ((value & 0x3E0) << 6) | ((value & 0x7C00) >> 7);
  6223. }
  6224. //OBJ
  6225. for (var counter = 0; counter < 8; counter++) {
  6226. var adjustedIndex = 2 * counter;
  6227. if (counter > 3) {
  6228. adjustedIndex += 0x38;
  6229. }
  6230. var value = (this.gbcOBJRawPalette[adjustedIndex | 1] << 8) | this.gbcOBJRawPalette[adjustedIndex];
  6231. this.cachedOBJPaletteConversion[counter] = ((value & 0x1F) << 19) | ((value & 0x3E0) << 6) | ((value & 0x7C00) >> 7);
  6232. }
  6233. }
  6234. GameBoyCore.prototype.setGBBGPalette = function (data) {
  6235. this.gbBGPalette[0] = this.colors[data & 0x03] | 0x2000000;
  6236. this.gbBGPalette[1] = this.colors[(data >> 2) & 0x03];
  6237. this.gbBGPalette[2] = this.colors[(data >> 4) & 0x03];
  6238. this.gbBGPalette[3] = this.colors[data >> 6];
  6239. if (this.usedBootROM) { //Do palette conversions if we did the GBC bootup:
  6240. //GB colorization:
  6241. this.gbBGColorizedPalette[0] = this.cachedBGPaletteConversion[data & 0x03] | 0x2000000;
  6242. this.gbBGColorizedPalette[1] = this.cachedBGPaletteConversion[(data >> 2) & 0x03];
  6243. this.gbBGColorizedPalette[2] = this.cachedBGPaletteConversion[(data >> 4) & 0x03];
  6244. this.gbBGColorizedPalette[3] = this.cachedBGPaletteConversion[data >> 6];
  6245. }
  6246. }
  6247. GameBoyCore.prototype.setGBOBJPalette = function (index, data) {
  6248. this.gbOBJPalette[index | 0] = this.colors[data & 0x03] | 0x2000000;
  6249. this.gbOBJPalette[index | 1] = this.colors[(data >> 2) & 0x03];
  6250. this.gbOBJPalette[index | 2] = this.colors[(data >> 4) & 0x03];
  6251. this.gbOBJPalette[index | 3] = this.colors[data >> 6];
  6252. if (this.usedBootROM) { //Do palette conversions if we did the GBC bootup:
  6253. //GB colorization:
  6254. this.gbOBJColorizedPalette[index] = this.cachedOBJPaletteConversion[index | (data & 0x03)] | 0x2000000;
  6255. this.gbOBJColorizedPalette[index | 1] = this.cachedOBJPaletteConversion[index | ((data >> 2) & 0x03)];
  6256. this.gbOBJColorizedPalette[index | 2] = this.cachedOBJPaletteConversion[index | ((data >> 4) & 0x03)];
  6257. this.gbOBJColorizedPalette[index | 3] = this.cachedOBJPaletteConversion[index | (data >> 6)];
  6258. }
  6259. }
  6260. GameBoyCore.prototype.setGBCBGPalette = function (index, data) {
  6261. if (this.gbcBGRawPalette[index] != data) {
  6262. //Update the color palette for BG tiles since it changed:
  6263. this.gbcBGRawPalette[index] = data;
  6264. var value = (this.gbcBGRawPalette[dataNumber | 1] << 8) | this.gbcBGRawPalette[index & -2];
  6265. if ((index & 0x06) == 0) {
  6266. //Palette 0 (Special tile Priority stuff)
  6267. this.BGPalette[index >> 1] = 0x2000000 | ((value & 0x1F) << 19) | ((value & 0x3E0) << 6) | ((value & 0x7C00) >> 7);
  6268. }
  6269. else {
  6270. //Regular Palettes (No special crap)
  6271. this.BGPalette[index >> 1] = ((value & 0x1F) << 19) | ((value & 0x3E0) << 6) | ((value & 0x7C00) >> 7);
  6272. }
  6273. }
  6274. }
  6275. GameBoyCore.prototype.setGBCOBJPalette = function (index, data) {
  6276. if (this.gbcOBJRawPalette[index] != data) {
  6277. //Update the color palette for OBJ tiles since it changed:
  6278. this.gbcOBJRawPalette[index] = data;
  6279. var value = (this.gbcOBJRawPalette[dataNumber | 1] << 8) | this.gbcOBJRawPalette[index & -2];
  6280. if ((index & 0x06) > 0) {
  6281. //Regular Palettes (No special crap)
  6282. this.OBJPalette[index >> 1] = ((value & 0x1F) << 19) | ((value & 0x3E0) << 6) | ((value & 0x7C00) >> 7);
  6283. }
  6284. }
  6285. }
  6286. GameBoyCore.prototype.BGLayerRender = function () {
  6287. var scrollYAdjusted = (this.memory[0xFF42] + this.actualScanLine) & 0xFF; //The line of the BG we're at.
  6288. var tileYLine = scrollYAdjusted % 8; //The row in the cached tiles we're fetching from.
  6289. var tileYDown = (scrollYAdjusted - tileYLine) << 3; //The row of cached tiles we're fetching from.
  6290. var scrollXAdjusted = this.memory[0xFF43]; //The scroll amount of the BG.
  6291. var pixelPosition = this.actualScanLine * 160; //Current pixel we're working on.
  6292. var pixelPositionEnd = pixelPosition + 160; //Make sure we do at most 160 pixels a scanline.
  6293. var tileNumber = 0;
  6294. var chrCode = 0;
  6295. for (var tileScroll = scrollXAdjusted / 8; scrollXAdjusted < 0x100; scrollXAdjusted++, tileScroll += 0.125, pixelPosition++) {
  6296. tileNumber = tileYDown + tileScroll;
  6297. chrCode = this.BGCHRCurrentBank[this.gfxBackgroundCHRBankPosition | tileNumber];
  6298. characterBank = ((charcode & 0x8) == 0x8) ? (0x180 + this.gfxBackgroundBankOffset) : this.gfxBackgroundBankOffset;
  6299. this.framebuffer[pixelPosition] = (((chrCode & 0x80) << 17) & this.BGPriorityEnabled) | this.BGPalette[((chrCode & 0x7) << 2) | this.tileCache[characterBank + ((this.gfxBackgroundBankOffset + tileNumber) & 0xFF)][tileYLine][(scrollXAdjusted % 8)]];
  6300. }
  6301. for (tileScroll = scrollXAdjusted = 0; pixelPosition < pixelPositionEnd; scrollXAdjusted++, tileScroll += 0.125, pixelPosition++) {
  6302. tileNumber = tileYDown + tileScroll;
  6303. chrCode = this.BGCHRCurrentBank[this.gfxBackgroundCHRBankPosition | tileNumber];
  6304. characterBank = ((charcode & 0x8) == 0x8) ? (0x180 + this.gfxBackgroundBankOffset) : this.gfxBackgroundBankOffset;
  6305. this.framebuffer[pixelPosition] = (((chrCode & 0x80) << 17) & this.BGPriorityEnabled) | this.BGPalette[((chrCode & 0x7) << 2) | this.tileCache[characterBank + ((this.gfxBackgroundBankOffset + tileNumber) & 0xFF)][tileYLine][(scrollXAdjusted % 8)]];
  6306. }
  6307. }
  6308. GameBoyCore.prototype.WindowLayerRender = function () {
  6309. if (this.gfxWindowDisplay) { //Is the window enabled?
  6310. var scrollYAdjusted = this.memory[0xFF4A]; //The line of the BG we're at.
  6311. var tileYLine = (this.actualScanLine - scrollYAdjusted) % 8; //The row in the cached tiles we're fetching from.
  6312. var tileYDown = (this.actualScanLine - tileYLine) << 3; //The row of cached tiles we're fetching from.
  6313. var scrollXAdjusted = this.memory[0xFF4B] - 7; //The scroll amount of the BG.
  6314. var pixelPosition = (this.actualScanLine * 160) + scrollXAdjusted;//Current pixel we're working on.
  6315. var pixelPositionEnd = pixelPosition + 160; //Make sure we do at most 160 pixels a scanline.
  6316. var tileNumber = 0;
  6317. var chrCode = 0;
  6318. for (var tileScroll = 0; pixelPosition < pixelPositionEnd, scrollXAdjusted < 160, scrollYAdjusted < 144; scrollXAdjusted++, tileScroll += 0.125, pixelPosition++) {
  6319. tileNumber = tileYDown + tileScroll;
  6320. chrCode = this.BGCHRCurrentBank[this.gfxWindowCHRBankPosition | tileNumber];
  6321. characterBank = ((charcode & 0x8) == 0x8) ? (0x180 + this.gfxBackgroundBankOffset) : this.gfxBackgroundBankOffset;
  6322. this.framebuffer[pixelPosition] = (((chrCode & 0x80) << 17) & this.BGPriorityEnabled) | this.BGPalette[((chrCode & 0x7) << 2) | this.tileCache[characterBank + ((this.gfxBackgroundBankOffset + tileNumber) & 0xFF)][tileYLine][(scrollXAdjusted % 8)]];
  6323. }
  6324. }
  6325. }
  6326. GameBoyCore.prototype.SpriteLayerRender = function () {
  6327. if (this.gfxSpriteShow) { //Is the window enabled?
  6328. var chrCode = 0;
  6329. var spriteIndex = 0;
  6330. var xcoord = 0;
  6331. for (var pixelPosition = 0; pixelPosition < 23040; pixelPosition++) {
  6332. if (this.framebuffer[pixelPosition] >= 0x2000000) {
  6333. xcoord = pixelPosition % 160;
  6334. //We encounted palette-zero, so we always overwrite it:
  6335. spriteIndex = this.spriteLineStart[pixelPosition] * 4;
  6336. if (spriteIndex > -1) {
  6337. this.framebuffer[pixelPosition] = this.OBJPalette[((this.memory[0xFE03 | spriteIndex] & 0x7) << 2) | this.tileOBJCache[this.memory[0xFE02 | spriteIndex]][((pixelPosition - xcoord) / 160) - this.memory[0xFE00 | spriteIndex] + 10][xcoord - this.memory[0xFE01 | spriteIndex] + 8]];
  6338. }
  6339. }
  6340. else if (this.framebuffer[pixelPosition] < 0x1000000) {
  6341. xcoord = pixelPosition % 160;
  6342. spriteIndex = this.spriteLineStart[pixelPosition] * 4;
  6343. if (spriteIndex > -1) {
  6344. chrCode = this.memory[0xFE03 | spriteIndex];
  6345. if (chrCode < 0x80) { //Check to see if sprites give priority to the BG tile.
  6346. this.framebuffer[pixelPosition] = this.OBJPalette[((chrCode & 0x7) << 2) | this.tileOBJCache[this.memory[0xFE02 | spriteIndex]][((pixelPosition - xcoord) / 160) - this.memory[0xFE00 | spriteIndex] + 10][xcoord - this.memory[0xFE01 | spriteIndex] + 8]];
  6347. }
  6348. }
  6349. }
  6350. }
  6351. }
  6352. }
  6353. //Memory Reading:
  6354. GameBoyCore.prototype.memoryRead = function (address) {
  6355. //Act as a wrapper for reading the returns from the compiled jumps to memory.
  6356. return this.memoryReader[address](this, address); //This seems to be faster than the usual if/else.
  6357. }
  6358. GameBoyCore.prototype.memoryReadJumpCompile = function () {
  6359. //Faster in some browsers, since we are doing less conditionals overall by implementing them in advance.
  6360. for (var index = 0x0000; index <= 0xFFFF; index++) {
  6361. if (index < 0x4000) {
  6362. this.memoryReader[index] = this.memoryReadNormal;
  6363. }
  6364. else if (index < 0x8000) {
  6365. this.memoryReader[index] = this.memoryReadROM;
  6366. }
  6367. else if (index >= 0x8000 && index < 0xA000) {
  6368. this.memoryReader[index] = (this.cGBC) ? this.VRAMReadCGBCPU : this.VRAMReadDMGCPU;
  6369. }
  6370. else if (index >= 0xA000 && index < 0xC000) {
  6371. if ((this.numRAMBanks == 1 / 16 && index < 0xA200) || this.numRAMBanks >= 1) {
  6372. if (!this.cMBC3) {
  6373. this.memoryReader[index] = this.memoryReadMBC;
  6374. }
  6375. else {
  6376. //MBC3 RTC + RAM:
  6377. this.memoryReader[index] = this.memoryReadMBC3;
  6378. }
  6379. }
  6380. else {
  6381. this.memoryReader[index] = this.memoryReadBAD;
  6382. }
  6383. }
  6384. else if (index >= 0xC000 && index < 0xE000) {
  6385. if (!this.cGBC || index < 0xD000) {
  6386. this.memoryReader[index] = this.memoryReadNormal;
  6387. }
  6388. else {
  6389. this.memoryReader[index] = this.memoryReadGBCMemory;
  6390. }
  6391. }
  6392. else if (index >= 0xE000 && index < 0xFE00) {
  6393. if (!this.cGBC || index < 0xF000) {
  6394. this.memoryReader[index] = this.memoryReadECHONormal;
  6395. }
  6396. else {
  6397. this.memoryReader[index] = this.memoryReadECHOGBCMemory;
  6398. }
  6399. }
  6400. else if (index < 0xFEA0) {
  6401. this.memoryReader[index] = this.memoryReadOAM;
  6402. }
  6403. else if (this.cGBC && index >= 0xFEA0 && index < 0xFF00) {
  6404. this.memoryReader[index] = this.memoryReadNormal;
  6405. }
  6406. else if (index >= 0xFF00) {
  6407. switch (index) {
  6408. case 0xFF00:
  6409. //JOYPAD:
  6410. this.memoryReader[0xFF00] = function (parentObj, address) {
  6411. return 0xC0 | parentObj.memory[0xFF00]; //Top nibble returns as set.
  6412. }
  6413. break;
  6414. case 0xFF01:
  6415. //SC
  6416. this.memoryReader[0xFF01] = function (parentObj, address) {
  6417. return ((parentObj.memory[0xFF02] & 0x1) == 0x1) ? 0xFF : parentObj.memory[0xFF01];
  6418. }
  6419. break;
  6420. case 0xFF02:
  6421. //SB
  6422. if (this.cGBC) {
  6423. this.memoryReader[0xFF02] = function (parentObj, address) {
  6424. return 0x7C | parentObj.memory[0xFF02];
  6425. }
  6426. }
  6427. else {
  6428. this.memoryReader[0xFF02] = function (parentObj, address) {
  6429. return 0x7E | parentObj.memory[0xFF02];
  6430. }
  6431. }
  6432. break;
  6433. case 0xFF04:
  6434. //DIV
  6435. this.memoryReader[0xFF04] = function (parentObj, address) {
  6436. parentObj.memory[0xFF04] = (parentObj.memory[0xFF04] + (parentObj.DIVTicks >> 6)) & 0xFF;
  6437. parentObj.DIVTicks &= 0x3F;
  6438. return parentObj.memory[0xFF04];
  6439.  
  6440. }
  6441. break;
  6442. case 0xFF07:
  6443. this.memoryReader[0xFF07] = function (parentObj, address) {
  6444. return 0xF8 | parentObj.memory[0xFF07];
  6445. }
  6446. break;
  6447. case 0xFF0F:
  6448. //IF
  6449. this.memoryReader[0xFF0F] = function (parentObj, address) {
  6450. return 0xE0 | parentObj.memory[0xFF0F];
  6451. }
  6452. break;
  6453. case 0xFF10:
  6454. this.memoryReader[0xFF10] = function (parentObj, address) {
  6455. return 0x80 | parentObj.memory[0xFF10];
  6456. }
  6457. break;
  6458. case 0xFF11:
  6459. this.memoryReader[0xFF11] = function (parentObj, address) {
  6460. return 0x3F | parentObj.memory[0xFF11];
  6461. }
  6462. break;
  6463. case 0xFF13:
  6464. this.memoryReader[0xFF13] = this.memoryReadBAD;
  6465. break;
  6466. case 0xFF14:
  6467. this.memoryReader[0xFF14] = function (parentObj, address) {
  6468. return 0xBF | parentObj.memory[0xFF14];
  6469. }
  6470. break;
  6471. case 0xFF16:
  6472. this.memoryReader[0xFF16] = function (parentObj, address) {
  6473. return 0x3F | parentObj.memory[0xFF16];
  6474. }
  6475. break;
  6476. case 0xFF18:
  6477. this.memoryReader[0xFF18] = this.memoryReadBAD;
  6478. break;
  6479. case 0xFF19:
  6480. this.memoryReader[0xFF19] = function (parentObj, address) {
  6481. return 0xBF | parentObj.memory[0xFF19];
  6482. }
  6483. break;
  6484. case 0xFF1A:
  6485. this.memoryReader[0xFF1A] = function (parentObj, address) {
  6486. return 0x7F | parentObj.memory[0xFF1A];
  6487. }
  6488. break;
  6489. case 0xFF1B:
  6490. this.memoryReader[0xFF1B] = this.memoryReadBAD;
  6491. break;
  6492. case 0xFF1C:
  6493. this.memoryReader[0xFF1C] = function (parentObj, address) {
  6494. return 0x9F | parentObj.memory[0xFF1C];
  6495. }
  6496. break;
  6497. case 0xFF1D:
  6498. this.memoryReader[0xFF1D] = function (parentObj, address) {
  6499. return 0xFF;
  6500. }
  6501. break;
  6502. case 0xFF1E:
  6503. this.memoryReader[0xFF1E] = function (parentObj, address) {
  6504. return 0xBF | parentObj.memory[0xFF1E];
  6505. }
  6506. break;
  6507. case 0xFF1F:
  6508. case 0xFF20:
  6509. this.memoryReader[index] = this.memoryReadBAD;
  6510. break;
  6511. case 0xFF23:
  6512. this.memoryReader[0xFF23] = function (parentObj, address) {
  6513. return 0xBF | parentObj.memory[0xFF23];
  6514. }
  6515. break;
  6516. case 0xFF26:
  6517. this.memoryReader[0xFF26] = function (parentObj, address) {
  6518. parentObj.audioJIT();
  6519. return 0x70 | parentObj.memory[0xFF26];
  6520. }
  6521. break;
  6522. case 0xFF27:
  6523. case 0xFF28:
  6524. case 0xFF29:
  6525. case 0xFF2A:
  6526. case 0xFF2B:
  6527. case 0xFF2C:
  6528. case 0xFF2D:
  6529. case 0xFF2E:
  6530. case 0xFF2F:
  6531. this.memoryReader[index] = this.memoryReadBAD;
  6532. break;
  6533. case 0xFF30:
  6534. case 0xFF31:
  6535. case 0xFF32:
  6536. case 0xFF33:
  6537. case 0xFF34:
  6538. case 0xFF35:
  6539. case 0xFF36:
  6540. case 0xFF37:
  6541. case 0xFF38:
  6542. case 0xFF39:
  6543. case 0xFF3A:
  6544. case 0xFF3B:
  6545. case 0xFF3C:
  6546. case 0xFF3D:
  6547. case 0xFF3E:
  6548. case 0xFF3F:
  6549. this.memoryReader[index] = function (parentObj, address) {
  6550. return (parentObj.channel3canPlay) ? parentObj.memory[0xFF00 | (parentObj.channel3Tracker / 2)] : parentObj.memory[address];
  6551. }
  6552. break;
  6553. case 0xFF41:
  6554. this.memoryReader[0xFF41] = function (parentObj, address) {
  6555. return 0x80 | parentObj.memory[0xFF41] | parentObj.modeSTAT;
  6556. }
  6557. break;
  6558. case 0xFF44:
  6559. this.memoryReader[0xFF44] = function (parentObj, address) {
  6560. return ((parentObj.LCDisOn) ? parentObj.memory[0xFF44] : 0);
  6561. }
  6562. break;
  6563. case 0xFF4F:
  6564. this.memoryReader[0xFF4F] = function (parentObj, address) {
  6565. return parentObj.currVRAMBank;
  6566. }
  6567. break;
  6568. case 0xFF56:
  6569. if (this.cGBC) {
  6570. this.memoryReader[0xFF56] = function (parentObj, address) {
  6571. //Return IR "not connected" status:
  6572. return 0x3C | ((parentObj.memory[0xFF56] >= 0xC0) ? (0x2 | (parentObj.memory[0xFF56] & 0xC1)) : (parentObj.memory[0xFF56] & 0xC3));
  6573. }
  6574. }
  6575. else {
  6576. this.memoryReader[0xFF56] = this.memoryReadNormal;
  6577. }
  6578. break;
  6579. case 0xFF6C:
  6580. if (this.cGBC) {
  6581. this.memoryReader[0xFF6C] = function (parentObj, address) {
  6582. return 0xFE | parentObj.memory[0xFF6C];
  6583. }
  6584. }
  6585. else {
  6586. this.memoryReader[index] = this.memoryReadBAD;
  6587. }
  6588. break;
  6589. case 0xFF70:
  6590. if (this.cGBC) {
  6591. //SVBK
  6592. this.memoryReader[0xFF70] = function (parentObj, address, data) {
  6593. return 0x40 | parentObj.memory[0xFF70];
  6594. }
  6595. }
  6596. else {
  6597. this.memoryReader[0xFF70] = this.memoryReadBAD;
  6598. }
  6599. break;
  6600. case 0xFF75:
  6601. this.memoryReader[0xFF75] = function (parentObj, address) {
  6602. return 0x8F | parentObj.memory[0xFF75];
  6603. }
  6604. break;
  6605. case 0xFF76:
  6606. case 0xFF77:
  6607. this.memoryReader[index] = function (parentObj, address) {
  6608. return 0;
  6609. }
  6610. break;
  6611. default:
  6612. this.memoryReader[index] = this.memoryReadNormal;
  6613. }
  6614. }
  6615. else {
  6616. this.memoryReader[index] = this.memoryReadBAD;
  6617. }
  6618. }
  6619. }
  6620. GameBoyCore.prototype.memoryReadNormal = function (parentObj, address) {
  6621. return parentObj.memory[address];
  6622. }
  6623. GameBoyCore.prototype.memoryReadROM = function (parentObj, address) {
  6624. return parentObj.ROM[parentObj.currentROMBank + address];
  6625. }
  6626. GameBoyCore.prototype.memoryReadMBC = function (parentObj, address) {
  6627. //Switchable RAM
  6628. if (parentObj.MBCRAMBanksEnabled || settings[10]) {
  6629. return parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition];
  6630. }
  6631. //cout("Reading from disabled RAM.", 1);
  6632. return 0xFF;
  6633. }
  6634. GameBoyCore.prototype.memoryReadMBC3 = function (parentObj, address) {
  6635. //Switchable RAM
  6636. if (parentObj.MBCRAMBanksEnabled || settings[10]) {
  6637. switch (parentObj.currMBCRAMBank) {
  6638. case 0x00:
  6639. case 0x01:
  6640. case 0x02:
  6641. case 0x03:
  6642. return parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition];
  6643. break;
  6644. case 0x08:
  6645. return parentObj.latchedSeconds;
  6646. break;
  6647. case 0x09:
  6648. return parentObj.latchedMinutes;
  6649. break;
  6650. case 0x0A:
  6651. return parentObj.latchedHours;
  6652. break;
  6653. case 0x0B:
  6654. return parentObj.latchedLDays;
  6655. break;
  6656. case 0x0C:
  6657. return (((parentObj.RTCDayOverFlow) ? 0x80 : 0) + ((parentObj.RTCHALT) ? 0x40 : 0)) + parentObj.latchedHDays;
  6658. }
  6659. }
  6660. //cout("Reading from invalid or disabled RAM.", 1);
  6661. return 0xFF;
  6662. }
  6663. GameBoyCore.prototype.memoryReadGBCMemory = function (parentObj, address) {
  6664. return parentObj.GBCMemory[address + parentObj.gbcRamBankPosition];
  6665. }
  6666. GameBoyCore.prototype.memoryReadOAM = function (parentObj, address) {
  6667. return (parentObj.modeSTAT > 1) ? 0xFF : parentObj.memory[address];
  6668. }
  6669. GameBoyCore.prototype.memoryReadECHOGBCMemory = function (parentObj, address) {
  6670. return parentObj.GBCMemory[address + parentObj.gbcRamBankPositionECHO];
  6671. }
  6672. GameBoyCore.prototype.memoryReadECHONormal = function (parentObj, address) {
  6673. return parentObj.memory[address - 0x2000];
  6674. }
  6675. GameBoyCore.prototype.memoryReadBAD = function (parentObj, address) {
  6676. return 0xFF;
  6677. }
  6678. GameBoyCore.prototype.VRAMReadCGBCPU = function (parentObj, address) {
  6679. //CPU Side Reading The VRAM (Optimized for GameBoy Color)
  6680. return (parentObj.modeSTAT > 2) ? 0xFF : ((parentObj.currVRAMBank == 0) ? parentObj.memory[address] : parentObj.VRAM[address - 0x8000]);
  6681. }
  6682. GameBoyCore.prototype.VRAMReadDMGCPU = function (parentObj, address) {
  6683. //CPU Side Reading The VRAM (Optimized for classic GameBoy)
  6684. return (parentObj.modeSTAT > 2) ? 0xFF : parentObj.memory[address];
  6685. }
  6686. GameBoyCore.prototype.VRAMReadGFX = function (address, gbcBank) {
  6687. //Graphics Side Reading The VRAM
  6688. return ((!gbcBank) ? this.memory[0x8000 | address] : this.VRAM[address]);
  6689. }
  6690. GameBoyCore.prototype.setCurrentMBC1ROMBank = function () {
  6691. //Read the cartridge ROM data from RAM memory:
  6692. switch (this.ROMBank1offs) {
  6693. case 0x00:
  6694. case 0x20:
  6695. case 0x40:
  6696. case 0x60:
  6697. //Bank calls for 0x00, 0x20, 0x40, and 0x60 are really for 0x01, 0x21, 0x41, and 0x61.
  6698. this.currentROMBank = this.ROMBank1offs << 14;
  6699. break;
  6700. default:
  6701. this.currentROMBank = (this.ROMBank1offs - 1) << 14;
  6702. }
  6703. while (this.currentROMBank + 0x4000 >= this.ROM.length) {
  6704. this.currentROMBank -= this.ROM.length;
  6705. }
  6706. }
  6707. GameBoyCore.prototype.setCurrentMBC2AND3ROMBank = function () {
  6708. //Read the cartridge ROM data from RAM memory:
  6709. //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):
  6710. this.currentROMBank = Math.max(this.ROMBank1offs - 1, 0) << 14;
  6711. while (this.currentROMBank + 0x4000 >= this.ROM.length) {
  6712. this.currentROMBank -= this.ROM.length;
  6713. }
  6714. }
  6715. GameBoyCore.prototype.setCurrentMBC5ROMBank = function () {
  6716. //Read the cartridge ROM data from RAM memory:
  6717. this.currentROMBank = (this.ROMBank1offs - 1) << 14;
  6718. while (this.currentROMBank + 0x4000 >= this.ROM.length) {
  6719. this.currentROMBank -= this.ROM.length;
  6720. }
  6721. }
  6722. //Memory Writing:
  6723. GameBoyCore.prototype.memoryWrite = function (address, data) {
  6724. //Act as a wrapper for writing by compiled jumps to specific memory writing functions.
  6725. this.memoryWriter[address](this, address, data);
  6726. }
  6727. GameBoyCore.prototype.memoryWriteJumpCompile = function () {
  6728. //Faster in some browsers, since we are doing less conditionals overall by implementing them in advance.
  6729. for (var index = 0x0000; index <= 0xFFFF; index++) {
  6730. if (index < 0x8000) {
  6731. if (this.cMBC1) {
  6732. if (index < 0x2000) {
  6733. this.memoryWriter[index] = this.MBCWriteEnable;
  6734. }
  6735. else if (index < 0x4000) {
  6736. this.memoryWriter[index] = this.MBC1WriteROMBank;
  6737. }
  6738. else if (index < 0x6000) {
  6739. this.memoryWriter[index] = this.MBC1WriteRAMBank;
  6740. }
  6741. else {
  6742. this.memoryWriter[index] = this.MBC1WriteType;
  6743. }
  6744. }
  6745. else if (this.cMBC2) {
  6746. if (index < 0x1000) {
  6747. this.memoryWriter[index] = this.MBCWriteEnable;
  6748. }
  6749. else if (index >= 0x2100 && index < 0x2200) {
  6750. this.memoryWriter[index] = this.MBC2WriteROMBank;
  6751. }
  6752. else {
  6753. this.memoryWriter[index] = this.cartIgnoreWrite;
  6754. }
  6755. }
  6756. else if (this.cMBC3) {
  6757. if (index < 0x2000) {
  6758. this.memoryWriter[index] = this.MBCWriteEnable;
  6759. }
  6760. else if (index < 0x4000) {
  6761. this.memoryWriter[index] = this.MBC3WriteROMBank;
  6762. }
  6763. else if (index < 0x6000) {
  6764. this.memoryWriter[index] = this.MBC3WriteRAMBank;
  6765. }
  6766. else {
  6767. this.memoryWriter[index] = this.MBC3WriteRTCLatch;
  6768. }
  6769. }
  6770. else if (this.cMBC5 || this.cRUMBLE) {
  6771. if (index < 0x2000) {
  6772. this.memoryWriter[index] = this.MBCWriteEnable;
  6773. }
  6774. else if (index < 0x3000) {
  6775. this.memoryWriter[index] = this.MBC5WriteROMBankLow;
  6776. }
  6777. else if (index < 0x4000) {
  6778. this.memoryWriter[index] = this.MBC5WriteROMBankHigh;
  6779. }
  6780. else if (index < 0x6000) {
  6781. this.memoryWriter[index] = (this.cRUMBLE) ? this.RUMBLEWriteRAMBank : this.MBC5WriteRAMBank;
  6782. }
  6783. else {
  6784. this.memoryWriter[index] = this.cartIgnoreWrite;
  6785. }
  6786. }
  6787. else if (this.cHuC3) {
  6788. if (index < 0x2000) {
  6789. this.memoryWriter[index] = this.MBCWriteEnable;
  6790. }
  6791. else if (index < 0x4000) {
  6792. this.memoryWriter[index] = this.MBC3WriteROMBank;
  6793. }
  6794. else if (index < 0x6000) {
  6795. this.memoryWriter[index] = this.HuC3WriteRAMBank;
  6796. }
  6797. else {
  6798. this.memoryWriter[index] = this.cartIgnoreWrite;
  6799. }
  6800. }
  6801. else {
  6802. this.memoryWriter[index] = this.cartIgnoreWrite;
  6803. }
  6804. }
  6805. else if (index < 0xA000) {
  6806. this.memoryWriter[index] = this.VRAMWrite;
  6807. }
  6808. else if (index < 0xC000) {
  6809. if ((this.numRAMBanks == 1 / 16 && index < 0xA200) || this.numRAMBanks >= 1) {
  6810. if (!this.cMBC3) {
  6811. this.memoryWriter[index] = this.memoryWriteMBCRAM;
  6812. }
  6813. else {
  6814. //MBC3 RTC + RAM:
  6815. this.memoryWriter[index] = this.memoryWriteMBC3RAM;
  6816. }
  6817. }
  6818. else {
  6819. this.memoryWriter[index] = this.cartIgnoreWrite;
  6820. }
  6821. }
  6822. else if (index < 0xE000) {
  6823. if (this.cGBC && index >= 0xD000) {
  6824. this.memoryWriter[index] = this.memoryWriteGBCRAM;
  6825. }
  6826. else {
  6827. this.memoryWriter[index] = this.memoryWriteNormal;
  6828. }
  6829. }
  6830. else if (index < 0xFE00) {
  6831. if (this.cGBC && index >= 0xF000) {
  6832. this.memoryWriter[index] = this.memoryWriteECHOGBCRAM;
  6833. }
  6834. else {
  6835. this.memoryWriter[index] = this.memoryWriteECHONormal;
  6836. }
  6837. }
  6838. else if (index <= 0xFEA0) {
  6839. this.memoryWriter[index] = this.memoryWriteOAMRAM;
  6840. }
  6841. else if (index < 0xFF00) {
  6842. if (this.cGBC) { //Only GBC has access to this RAM.
  6843. this.memoryWriter[index] = this.memoryWriteNormal;
  6844. }
  6845. else {
  6846. this.memoryWriter[index] = this.cartIgnoreWrite;
  6847. }
  6848. }
  6849. else {
  6850. //Start the I/O initialization by filling in the slots as normal memory:
  6851. this.memoryWriter[index] = this.memoryWriteNormal;
  6852. }
  6853. }
  6854. this.registerWriteJumpCompile(); //Compile the I/O write functions separately...
  6855. }
  6856. GameBoyCore.prototype.MBCWriteEnable = function (parentObj, address, data) {
  6857. //MBC RAM Bank Enable/Disable:
  6858. parentObj.MBCRAMBanksEnabled = ((data & 0x0F) == 0x0A); //If lower nibble is 0x0A, then enable, otherwise disable.
  6859. }
  6860. GameBoyCore.prototype.MBC1WriteROMBank = function (parentObj, address, data) {
  6861. //MBC1 ROM bank switching:
  6862. parentObj.ROMBank1offs = (parentObj.ROMBank1offs & 0x60) | (data & 0x1F);
  6863. parentObj.setCurrentMBC1ROMBank();
  6864. }
  6865. GameBoyCore.prototype.MBC1WriteRAMBank = function (parentObj, address, data) {
  6866. //MBC1 RAM bank switching
  6867. if (parentObj.MBC1Mode) {
  6868. //4/32 Mode
  6869. parentObj.currMBCRAMBank = data & 0x3;
  6870. parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
  6871. }
  6872. else {
  6873. //16/8 Mode
  6874. parentObj.ROMBank1offs = ((data & 0x03) << 5) | (parentObj.ROMBank1offs & 0x1F);
  6875. parentObj.setCurrentMBC1ROMBank();
  6876. }
  6877. }
  6878. GameBoyCore.prototype.MBC1WriteType = function (parentObj, address, data) {
  6879. //MBC1 mode setting:
  6880. parentObj.MBC1Mode = ((data & 0x1) == 0x1);
  6881. }
  6882. GameBoyCore.prototype.MBC2WriteROMBank = function (parentObj, address, data) {
  6883. //MBC2 ROM bank switching:
  6884. parentObj.ROMBank1offs = data & 0x0F;
  6885. parentObj.setCurrentMBC2AND3ROMBank();
  6886. }
  6887. GameBoyCore.prototype.MBC3WriteROMBank = function (parentObj, address, data) {
  6888. //MBC3 ROM bank switching:
  6889. parentObj.ROMBank1offs = data & 0x7F;
  6890. parentObj.setCurrentMBC2AND3ROMBank();
  6891. }
  6892. GameBoyCore.prototype.MBC3WriteRAMBank = function (parentObj, address, data) {
  6893. parentObj.currMBCRAMBank = data;
  6894. if (data < 4) {
  6895. //MBC3 RAM bank switching
  6896. parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
  6897. }
  6898. }
  6899. GameBoyCore.prototype.MBC3WriteRTCLatch = function (parentObj, address, data) {
  6900. if (data == 0) {
  6901. parentObj.RTCisLatched = false;
  6902. }
  6903. else if (!parentObj.RTCisLatched) {
  6904. //Copy over the current RTC time for reading.
  6905. parentObj.RTCisLatched = true;
  6906. parentObj.latchedSeconds = parentObj.RTCSeconds | 0;
  6907. parentObj.latchedMinutes = parentObj.RTCMinutes;
  6908. parentObj.latchedHours = parentObj.RTCHours;
  6909. parentObj.latchedLDays = (parentObj.RTCDays & 0xFF);
  6910. parentObj.latchedHDays = parentObj.RTCDays >> 8;
  6911. }
  6912. }
  6913. GameBoyCore.prototype.MBC5WriteROMBankLow = function (parentObj, address, data) {
  6914. //MBC5 ROM bank switching:
  6915. parentObj.ROMBank1offs = (parentObj.ROMBank1offs & 0x100) | data;
  6916. parentObj.setCurrentMBC5ROMBank();
  6917. }
  6918. GameBoyCore.prototype.MBC5WriteROMBankHigh = function (parentObj, address, data) {
  6919. //MBC5 ROM bank switching (by least significant bit):
  6920. parentObj.ROMBank1offs = ((data & 0x01) << 8) | (parentObj.ROMBank1offs & 0xFF);
  6921. parentObj.setCurrentMBC5ROMBank();
  6922. }
  6923. GameBoyCore.prototype.MBC5WriteRAMBank = function (parentObj, address, data) {
  6924. //MBC5 RAM bank switching
  6925. parentObj.currMBCRAMBank = data & 0xF;
  6926. parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
  6927. }
  6928. GameBoyCore.prototype.RUMBLEWriteRAMBank = function (parentObj, address, data) {
  6929. //MBC5 RAM bank switching
  6930. //Like MBC5, but bit 3 of the lower nibble is used for rumbling and bit 2 is ignored.
  6931. parentObj.currMBCRAMBank = data & 0x3;
  6932. parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
  6933. }
  6934. GameBoyCore.prototype.HuC3WriteRAMBank = function (parentObj, address, data) {
  6935. //HuC3 RAM bank switching
  6936. parentObj.currMBCRAMBank = data & 0x03;
  6937. parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << 13) - 0xA000;
  6938. }
  6939. GameBoyCore.prototype.cartIgnoreWrite = function (parentObj, address, data) {
  6940. //We might have encountered illegal RAM writing or such, so just do nothing...
  6941. }
  6942. GameBoyCore.prototype.memoryWriteNormal = function (parentObj, address, data) {
  6943. parentObj.memory[address] = data;
  6944. }
  6945. GameBoyCore.prototype.memoryWriteMBCRAM = function (parentObj, address, data) {
  6946. if (parentObj.MBCRAMBanksEnabled || settings[10]) {
  6947. parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition] = data;
  6948. }
  6949. }
  6950. GameBoyCore.prototype.memoryWriteMBC3RAM = function (parentObj, address, data) {
  6951. if (parentObj.MBCRAMBanksEnabled || settings[10]) {
  6952. switch (parentObj.currMBCRAMBank) {
  6953. case 0x00:
  6954. case 0x01:
  6955. case 0x02:
  6956. case 0x03:
  6957. parentObj.MBCRam[address + parentObj.currMBCRAMBankPosition] = data;
  6958. break;
  6959. case 0x08:
  6960. if (data < 60) {
  6961. parentObj.RTCSeconds = data;
  6962. }
  6963. else {
  6964. cout("(Bank #" + parentObj.currMBCRAMBank + ") RTC write out of range: " + data, 1);
  6965. }
  6966. break;
  6967. case 0x09:
  6968. if (data < 60) {
  6969. parentObj.RTCMinutes = data;
  6970. }
  6971. else {
  6972. cout("(Bank #" + parentObj.currMBCRAMBank + ") RTC write out of range: " + data, 1);
  6973. }
  6974. break;
  6975. case 0x0A:
  6976. if (data < 24) {
  6977. parentObj.RTCHours = data;
  6978. }
  6979. else {
  6980. cout("(Bank #" + parentObj.currMBCRAMBank + ") RTC write out of range: " + data, 1);
  6981. }
  6982. break;
  6983. case 0x0B:
  6984. parentObj.RTCDays = (data & 0xFF) | (parentObj.RTCDays & 0x100);
  6985. break;
  6986. case 0x0C:
  6987. parentObj.RTCDayOverFlow = (data & 0x80) == 0x80;
  6988. parentObj.RTCHalt = (data & 0x40) == 0x40;
  6989. parentObj.RTCDays = ((data & 0x1) << 8) | (parentObj.RTCDays & 0xFF);
  6990. break;
  6991. default:
  6992. cout("Invalid MBC3 bank address selected: " + parentObj.currMBCRAMBank, 0);
  6993. }
  6994. }
  6995. }
  6996. GameBoyCore.prototype.memoryWriteGBCRAM = function (parentObj, address, data) {
  6997. parentObj.GBCMemory[address + parentObj.gbcRamBankPosition] = data;
  6998. }
  6999. GameBoyCore.prototype.memoryWriteOAMRAM = function (parentObj, address, data) {
  7000. if (parentObj.modeSTAT < 2) { //OAM RAM cannot be written to in mode 2 & 3
  7001. parentObj.memory[address] = data;
  7002. }
  7003. }
  7004. GameBoyCore.prototype.memoryWriteECHOGBCRAM = function (parentObj, address, data) {
  7005. parentObj.GBCMemory[address + parentObj.gbcRamBankPositionECHO] = data;
  7006. }
  7007. GameBoyCore.prototype.memoryWriteECHONormal = function (parentObj, address, data) {
  7008. parentObj.memory[address - 0x2000] = data;
  7009. }
  7010. GameBoyCore.prototype.VRAMWrite = function (parentObj, address, data) {
  7011. if (parentObj.modeSTAT < 3) { //VRAM cannot be written to during mode 3
  7012. if (address < 0x9800) { // Bkg Tile data area
  7013. var tileIndex = ((address & 0x1FFF) >> 4) | parentObj.tileBankOffset;
  7014. if (parentObj.tileReadState[tileIndex] == 1) {
  7015. var r = parentObj.tileData.length - parentObj.tileCount + tileIndex;
  7016. do {
  7017. parentObj.tileData[r] = null;
  7018. r -= parentObj.tileCount;
  7019. } while (r >= 0);
  7020. parentObj.tileReadState[tileIndex] = 0;
  7021. }
  7022. }
  7023. if (parentObj.currVRAMBank == 0) {
  7024. parentObj.memory[address] = data;
  7025. }
  7026. else {
  7027. parentObj.VRAM[address & 0x1FFF] = data;
  7028. }
  7029. }
  7030. }
  7031. GameBoyCore.prototype.registerWriteJumpCompile = function () {
  7032. //I/O Registers (GB + GBC):
  7033. //JoyPad
  7034. this.memoryWriter[0xFF00] = function (parentObj, address, data) {
  7035. parentObj.memory[0xFF00] = (data & 0x30) | ((((data & 0x20) == 0) ? (parentObj.JoyPad >> 4) : 0xF) & (((data & 0x10) == 0) ? (parentObj.JoyPad & 0xF) : 0xF));
  7036. }
  7037. //SB (Serial Transfer Data)
  7038. this.memoryWriter[0xFF01] = function (parentObj, address, data) {
  7039. parentObj.memory[0xFF01] = data;
  7040. }
  7041. //SC (Serial Transfer Control Register)
  7042. this.memoryWriter[0xFF02] = function (parentObj, address, data) {
  7043. if (((data & 0x1) == 0x1)) {
  7044. //Internal clock:
  7045. parentObj.memory[0xFF02] = (data & 0x7F);
  7046. parentObj.memory[0xFF0F] |= 0x8; //Get this time delayed...
  7047. }
  7048. else {
  7049. //External clock:
  7050. parentObj.memory[0xFF02] = data;
  7051. //No connected serial device, so don't trigger interrupt...
  7052. }
  7053. }
  7054. //DIV
  7055. this.memoryWriter[0xFF04] = function (parentObj, address, data) {
  7056. parentObj.DIVTicks &= 0x3F; //Update DIV for realignment.
  7057. parentObj.memory[0xFF04] = 0;
  7058. }
  7059. //TIMA
  7060. this.memoryWriter[0xFF05] = function (parentObj, address, data) {
  7061. parentObj.memory[0xFF05] = data;
  7062. }
  7063. //TMA
  7064. this.memoryWriter[0xFF06] = function (parentObj, address, data) {
  7065. parentObj.memory[0xFF06] = data;
  7066. }
  7067. //TAC
  7068. this.memoryWriter[0xFF07] = function (parentObj, address, data) {
  7069. parentObj.memory[0xFF07] = data & 0x07;
  7070. parentObj.TIMAEnabled = (data & 0x04) == 0x04;
  7071. parentObj.TACClocker = Math.pow(4, ((data & 0x3) != 0) ? (data & 0x3) : 4); //TODO: Find a way to not make a conditional in here...
  7072. }
  7073. //IF (Interrupt Request)
  7074. this.memoryWriter[0xFF0F] = function (parentObj, address, data) {
  7075. parentObj.memory[0xFF0F] = data;
  7076. }
  7077. this.memoryWriter[0xFF10] = function (parentObj, address, data) {
  7078. parentObj.audioJIT();
  7079. parentObj.channel1lastTimeSweep = parentObj.channel1timeSweep = (((data & 0x70) >> 4) * parentObj.channel1TimeSweepPreMultiplier) | 0;
  7080. parentObj.channel1numSweep = data & 0x07;
  7081. parentObj.channel1frequencySweepDivider = 1 << parentObj.channel1numSweep;
  7082. parentObj.channel1decreaseSweep = ((data & 0x08) == 0x08);
  7083. parentObj.memory[0xFF10] = data;
  7084. }
  7085. this.memoryWriter[0xFF11] = function (parentObj, address, data) {
  7086. parentObj.audioJIT();
  7087. parentObj.channel1adjustedDuty = parentObj.dutyLookup[data >> 6];
  7088. parentObj.channel1lastTotalLength = parentObj.channel1totalLength = (0x40 - (data & 0x3F)) * parentObj.audioTotalLengthMultiplier;
  7089. parentObj.memory[0xFF11] = data & 0xC0;
  7090. }
  7091. this.memoryWriter[0xFF12] = function (parentObj, address, data) {
  7092. parentObj.audioJIT();
  7093. parentObj.channel1envelopeVolume = data >> 4;
  7094. parentObj.channel1currentVolume = parentObj.channel1envelopeVolume / 0x1E;
  7095. parentObj.channel1envelopeType = ((data & 0x08) == 0x08);
  7096. parentObj.channel1envelopeSweeps = data & 0x7;
  7097. parentObj.channel1volumeEnvTime = parentObj.channel1volumeEnvTimeLast = parentObj.channel1envelopeSweeps * parentObj.volumeEnvelopePreMultiplier;
  7098. parentObj.memory[0xFF12] = data;
  7099. }
  7100. this.memoryWriter[0xFF13] = function (parentObj, address, data) {
  7101. parentObj.audioJIT();
  7102. parentObj.channel1frequency = (parentObj.channel1frequency & 0x700) | data;
  7103. //Pre-calculate the frequency computation outside the waveform generator for speed:
  7104. parentObj.channel1adjustedFrequencyPrep = parentObj.preChewedAudioComputationMultiplier / (0x800 - parentObj.channel1frequency);
  7105. parentObj.memory[0xFF13] = data;
  7106. }
  7107. this.memoryWriter[0xFF14] = function (parentObj, address, data) {
  7108. parentObj.audioJIT();
  7109. if ((data & 0x80) == 0x80) {
  7110. parentObj.channel1envelopeVolume = parentObj.memory[0xFF12] >> 4;
  7111. parentObj.channel1currentVolume = parentObj.channel1envelopeVolume / 0x1E;
  7112. parentObj.channel1volumeEnvTime = parentObj.channel1volumeEnvTimeLast;
  7113. parentObj.channel1totalLength = parentObj.channel1lastTotalLength;
  7114. parentObj.channel1timeSweep = parentObj.channel1lastTimeSweep;
  7115. parentObj.channel1numSweep = parentObj.memory[0xFF10] & 0x07;
  7116. parentObj.channel1frequencySweepDivider = 1 << parentObj.channel1numSweep;
  7117. if ((data & 0x40) == 0x40) {
  7118. parentObj.memory[0xFF26] |= 0x1;
  7119. }
  7120. }
  7121. parentObj.channel1consecutive = ((data & 0x40) == 0x0);
  7122. parentObj.channel1frequency = ((data & 0x7) << 8) | (parentObj.channel1frequency & 0xFF);
  7123. //Pre-calculate the frequency computation outside the waveform generator for speed:
  7124. parentObj.channel1adjustedFrequencyPrep = parentObj.preChewedAudioComputationMultiplier / (0x800 - parentObj.channel1frequency);
  7125. parentObj.memory[0xFF14] = data & 0x40;
  7126. }
  7127. this.memoryWriter[0xFF16] = function (parentObj, address, data) {
  7128. parentObj.audioJIT();
  7129. parentObj.channel2adjustedDuty = parentObj.dutyLookup[data >> 6];
  7130. parentObj.channel2lastTotalLength = parentObj.channel2totalLength = (0x40 - (data & 0x3F)) * parentObj.audioTotalLengthMultiplier;
  7131. parentObj.memory[0xFF16] = data & 0xC0;
  7132. }
  7133. this.memoryWriter[0xFF17] = function (parentObj, address, data) {
  7134. parentObj.audioJIT();
  7135. parentObj.channel2envelopeVolume = data >> 4;
  7136. parentObj.channel2currentVolume = parentObj.channel2envelopeVolume / 0x1E;
  7137. parentObj.channel2envelopeType = ((data & 0x08) == 0x08);
  7138. parentObj.channel2envelopeSweeps = data & 0x7;
  7139. parentObj.channel2volumeEnvTime = parentObj.channel2volumeEnvTimeLast = parentObj.channel2envelopeSweeps * parentObj.volumeEnvelopePreMultiplier;
  7140. parentObj.memory[0xFF17] = data;
  7141. }
  7142. this.memoryWriter[0xFF18] = function (parentObj, address, data) {
  7143. parentObj.audioJIT();
  7144. parentObj.channel2frequency = (parentObj.channel2frequency & 0x700) | data;
  7145. //Pre-calculate the frequency computation outside the waveform generator for speed:
  7146. parentObj.channel2adjustedFrequencyPrep = parentObj.preChewedAudioComputationMultiplier / (0x800 - parentObj.channel2frequency);
  7147. parentObj.memory[0xFF18] = data;
  7148. }
  7149. this.memoryWriter[0xFF19] = function (parentObj, address, data) {
  7150. parentObj.audioJIT();
  7151. if ((data & 0x80) == 0x80) {
  7152. parentObj.channel2envelopeVolume = parentObj.memory[0xFF17] >> 4;
  7153. parentObj.channel2currentVolume = parentObj.channel2envelopeVolume / 0x1E;
  7154. parentObj.channel2volumeEnvTime = parentObj.channel2volumeEnvTimeLast;
  7155. parentObj.channel2totalLength = parentObj.channel2lastTotalLength;
  7156. if ((data & 0x40) == 0x40) {
  7157. parentObj.memory[0xFF26] |= 0x2;
  7158. }
  7159. }
  7160. parentObj.channel2consecutive = ((data & 0x40) == 0x0);
  7161. parentObj.channel2frequency = ((data & 0x7) << 8) | (parentObj.channel2frequency & 0xFF);
  7162. //Pre-calculate the frequency computation outside the waveform generator for speed:
  7163. parentObj.channel2adjustedFrequencyPrep = parentObj.preChewedAudioComputationMultiplier / (0x800 - parentObj.channel2frequency);
  7164. parentObj.memory[0xFF19] = data & 0x40;
  7165. }
  7166. this.memoryWriter[0xFF1A] = function (parentObj, address, data) {
  7167. parentObj.audioJIT();
  7168. if (!parentObj.channel3canPlay && data >= 0x80) {
  7169. parentObj.channel3Tracker = 0;
  7170. }
  7171. parentObj.channel3canPlay = (data >= 0x80);
  7172. if (parentObj.channel3canPlay && (parentObj.memory[0xFF1A] & 0x80) == 0x80) {
  7173. parentObj.channel3totalLength = parentObj.channel3lastTotalLength;
  7174. if (!parentObj.channel3consecutive) {
  7175. parentObj.memory[0xFF26] |= 0x4;
  7176. }
  7177. }
  7178. parentObj.memory[0xFF1A] = data & 0x80;
  7179. }
  7180. this.memoryWriter[0xFF1B] = function (parentObj, address, data) {
  7181. parentObj.audioJIT();
  7182. parentObj.channel3lastTotalLength = parentObj.channel3totalLength = (0x100 - data) * parentObj.audioTotalLengthMultiplier;
  7183. parentObj.memory[0xFF1B] = data;
  7184. }
  7185. this.memoryWriter[0xFF1C] = function (parentObj, address, data) {
  7186. parentObj.audioJIT();
  7187. parentObj.memory[0xFF1C] = data & 0x60;
  7188. parentObj.channel3patternType = parentObj.memory[0xFF1C] - 0x20;
  7189. }
  7190. this.memoryWriter[0xFF1D] = function (parentObj, address, data) {
  7191. parentObj.audioJIT();
  7192. parentObj.channel3frequency = (parentObj.channel3frequency & 0x700) | data;
  7193. parentObj.channel3adjustedFrequencyPrep = parentObj.preChewedWAVEAudioComputationMultiplier / (0x800 - parentObj.channel3frequency);
  7194. parentObj.memory[0xFF1D] = data;
  7195. }
  7196. this.memoryWriter[0xFF1E] = function (parentObj, address, data) {
  7197. parentObj.audioJIT();
  7198. if ((data & 0x80) == 0x80) {
  7199. parentObj.channel3totalLength = parentObj.channel3lastTotalLength;
  7200. parentObj.channel3Tracker = 0;
  7201. if ((data & 0x40) == 0x40) {
  7202. parentObj.memory[0xFF26] |= 0x4;
  7203. }
  7204. }
  7205. parentObj.channel3consecutive = ((data & 0x40) == 0x0);
  7206. parentObj.channel3frequency = ((data & 0x7) << 8) | (parentObj.channel3frequency & 0xFF);
  7207. parentObj.channel3adjustedFrequencyPrep = parentObj.preChewedWAVEAudioComputationMultiplier / (0x800 - parentObj.channel3frequency);
  7208. parentObj.memory[0xFF1E] = data & 0x40;
  7209. }
  7210. this.memoryWriter[0xFF20] = function (parentObj, address, data) {
  7211. parentObj.audioJIT();
  7212. parentObj.channel4lastTotalLength = parentObj.channel4totalLength = (0x40 - (data & 0x3F)) * parentObj.audioTotalLengthMultiplier;
  7213. parentObj.memory[0xFF20] = data | 0xC0;
  7214. }
  7215. this.memoryWriter[0xFF21] = function (parentObj, address, data) {
  7216. parentObj.audioJIT();
  7217. parentObj.channel4envelopeVolume = data >> 4;
  7218. parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << 15;
  7219. parentObj.channel4envelopeType = ((data & 0x08) == 0x08);
  7220. parentObj.channel4envelopeSweeps = data & 0x7;
  7221. parentObj.channel4volumeEnvTime = parentObj.channel4volumeEnvTimeLast = parentObj.channel4envelopeSweeps * parentObj.volumeEnvelopePreMultiplier;
  7222. parentObj.memory[0xFF21] = data;
  7223. }
  7224. this.memoryWriter[0xFF22] = function (parentObj, address, data) {
  7225. parentObj.audioJIT();
  7226. parentObj.channel4adjustedFrequencyPrep = parentObj.whiteNoiseFrequencyPreMultiplier / Math.max(data & 0x7, 0.5) / Math.pow(2, (data >> 4) + 1);
  7227. var bitWidth = (data & 0x8);
  7228. if ((bitWidth == 0x8 && parentObj.noiseTableLength == 0x8000) || (bitWidth == 0 && parentObj.noiseTableLength == 0x80)) {
  7229. parentObj.channel4lastSampleLookup = 0;
  7230. parentObj.noiseTableLength = (bitWidth == 0x8) ? 0x80 : 0x8000;
  7231. }
  7232. parentObj.memory[0xFF22] = data;
  7233. }
  7234. this.memoryWriter[0xFF23] = function (parentObj, address, data) {
  7235. parentObj.audioJIT();
  7236. parentObj.memory[0xFF23] = data;
  7237. parentObj.channel4consecutive = ((data & 0x40) == 0x0);
  7238. if ((data & 0x80) == 0x80) {
  7239. parentObj.channel4lastSampleLookup = 0;
  7240. parentObj.channel4envelopeVolume = parentObj.memory[0xFF21] >> 4;
  7241. parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << 15;
  7242. parentObj.channel4volumeEnvTime = parentObj.channel4volumeEnvTimeLast;
  7243. parentObj.channel4totalLength = parentObj.channel4lastTotalLength;
  7244. if ((data & 0x40) == 0x40) {
  7245. parentObj.memory[0xFF26] |= 0x8;
  7246. }
  7247. }
  7248. }
  7249. this.memoryWriter[0xFF24] = function (parentObj, address, data) {
  7250. if (parentObj.memory[0xFF24] != data) {
  7251. parentObj.audioJIT();
  7252. parentObj.memory[0xFF24] = data;
  7253. parentObj.VinLeftChannelEnabled = ((data & 0x80) == 0x80);
  7254. parentObj.VinRightChannelEnabled = ((data & 0x8) == 0x8);
  7255. parentObj.VinLeftChannelMasterVolume = (((data >> 4) & 0x07) + 1) / 8;
  7256. parentObj.VinRightChannelMasterVolume = ((data & 0x07) + 1) / 8;
  7257. }
  7258. }
  7259. this.memoryWriter[0xFF25] = function (parentObj, address, data) {
  7260. if (parentObj.memory[0xFF25] != data) {
  7261. parentObj.audioJIT();
  7262. parentObj.memory[0xFF25] = data;
  7263. parentObj.rightChannel = [(data & 0x01) == 0x01, (data & 0x02) == 0x02, (data & 0x04) == 0x04, (data & 0x08) == 0x08];
  7264. parentObj.leftChannel = [(data & 0x10) == 0x10, (data & 0x20) == 0x20, (data & 0x40) == 0x40, (data & 0x80) == 0x80];
  7265. }
  7266. }
  7267. this.memoryWriter[0xFF26] = function (parentObj, address, data) {
  7268. parentObj.audioJIT();
  7269. var soundEnabled = (data & 0x80);
  7270. parentObj.memory[0xFF26] = soundEnabled | (parentObj.memory[0xFF26] & 0xF);
  7271. /*if (!parentObj.soundMasterEnabled && (soundEnabled == 0x80)) {
  7272. parentObj.memory[0xFF26] = 0;
  7273. parentObj.initializeAudioStartState();
  7274. for (address = 0xFF30; address < 0xFF40; address++) {
  7275. parentObj.memory[address] = 0;
  7276. }
  7277. }*/
  7278. parentObj.soundMasterEnabled = (soundEnabled == 0x80);
  7279. }
  7280. //0xFF27 to 0xFF2F don't do anything...
  7281. this.memoryWriter[0xFF27] = this.cartIgnoreWrite;
  7282. this.memoryWriter[0xFF28] = this.cartIgnoreWrite;
  7283. this.memoryWriter[0xFF29] = this.cartIgnoreWrite;
  7284. this.memoryWriter[0xFF2A] = this.cartIgnoreWrite;
  7285. this.memoryWriter[0xFF2B] = this.cartIgnoreWrite;
  7286. this.memoryWriter[0xFF2C] = this.cartIgnoreWrite;
  7287. this.memoryWriter[0xFF2D] = this.cartIgnoreWrite;
  7288. this.memoryWriter[0xFF2E] = this.cartIgnoreWrite;
  7289. this.memoryWriter[0xFF2F] = this.cartIgnoreWrite;
  7290. //WAVE PCM RAM:
  7291. this.memoryWriter[0xFF30] = function (parentObj, address, data) {
  7292. if (parentObj.memory[0xFF30] != data) {
  7293. parentObj.audioJIT();
  7294. parentObj.memory[0xFF30] = data;
  7295. parentObj.channel3PCM[0x00] = (data >> 4) / 0x1E;
  7296. parentObj.channel3PCM[0x20] = (data >> 5) / 0x1E;
  7297. parentObj.channel3PCM[0x40] = (data >> 6) / 0x1E;
  7298. parentObj.channel3PCM[0x01] = (data & 0xF) / 0x1E;
  7299. parentObj.channel3PCM[0x21] = (data & 0xE) / 0x3C;
  7300. parentObj.channel3PCM[0x41] = (data & 0xC) / 0x78;
  7301. }
  7302. }
  7303. this.memoryWriter[0xFF31] = function (parentObj, address, data) {
  7304. if (parentObj.memory[0xFF31] != data) {
  7305. parentObj.audioJIT();
  7306. parentObj.memory[0xFF31] = data;
  7307. parentObj.channel3PCM[0x02] = (data >> 4) / 0x1E;
  7308. parentObj.channel3PCM[0x22] = (data >> 5) / 0x1E;
  7309. parentObj.channel3PCM[0x42] = (data >> 6) / 0x1E;
  7310. parentObj.channel3PCM[0x03] = (data & 0xF) / 0x1E;
  7311. parentObj.channel3PCM[0x23] = (data & 0xE) / 0x3C;
  7312. parentObj.channel3PCM[0x43] = (data & 0xC) / 0x78;
  7313. }
  7314. }
  7315. this.memoryWriter[0xFF32] = function (parentObj, address, data) {
  7316. if (parentObj.memory[0xFF32] != data) {
  7317. parentObj.audioJIT();
  7318. parentObj.memory[0xFF32] = data;
  7319. parentObj.channel3PCM[0x04] = (data >> 4) / 0x1E;
  7320. parentObj.channel3PCM[0x24] = (data >> 5) / 0x1E;
  7321. parentObj.channel3PCM[0x44] = (data >> 6) / 0x1E;
  7322. parentObj.channel3PCM[0x05] = (data & 0xF) / 0x1E;
  7323. parentObj.channel3PCM[0x25] = (data & 0xE) / 0x3C;
  7324. parentObj.channel3PCM[0x45] = (data & 0xC) / 0x78;
  7325. }
  7326. }
  7327. this.memoryWriter[0xFF33] = function (parentObj, address, data) {
  7328. if (parentObj.memory[0xFF33] != data) {
  7329. parentObj.audioJIT();
  7330. parentObj.memory[0xFF33] = data;
  7331. parentObj.channel3PCM[0x06] = (data >> 4) / 0x1E;
  7332. parentObj.channel3PCM[0x26] = (data >> 5) / 0x1E;
  7333. parentObj.channel3PCM[0x46] = (data >> 6) / 0x1E;
  7334. parentObj.channel3PCM[0x07] = (data & 0xF) / 0x1E;
  7335. parentObj.channel3PCM[0x27] = (data & 0xE) / 0x3C;
  7336. parentObj.channel3PCM[0x47] = (data & 0xC) / 0x78;
  7337. }
  7338. }
  7339. this.memoryWriter[0xFF34] = function (parentObj, address, data) {
  7340. if (parentObj.memory[0xFF34] != data) {
  7341. parentObj.audioJIT();
  7342. parentObj.memory[0xFF34] = data;
  7343. parentObj.channel3PCM[0x08] = (data >> 4) / 0x1E;
  7344. parentObj.channel3PCM[0x28] = (data >> 5) / 0x1E;
  7345. parentObj.channel3PCM[0x48] = (data >> 6) / 0x1E;
  7346. parentObj.channel3PCM[0x09] = (data & 0xF) / 0x1E;
  7347. parentObj.channel3PCM[0x29] = (data & 0xE) / 0x3C;
  7348. parentObj.channel3PCM[0x49] = (data & 0xC) / 0x78;
  7349. }
  7350. }
  7351. this.memoryWriter[0xFF35] = function (parentObj, address, data) {
  7352. if (parentObj.memory[0xFF35] != data) {
  7353. parentObj.audioJIT();
  7354. parentObj.memory[0xFF35] = data;
  7355. parentObj.channel3PCM[0x0A] = (data >> 4) / 0x1E;
  7356. parentObj.channel3PCM[0x2A] = (data >> 5) / 0x1E;
  7357. parentObj.channel3PCM[0x4A] = (data >> 6) / 0x1E;
  7358. parentObj.channel3PCM[0x0B] = (data & 0xF) / 0x1E;
  7359. parentObj.channel3PCM[0x2B] = (data & 0xE) / 0x3C;
  7360. parentObj.channel3PCM[0x4B] = (data & 0xC) / 0x78;
  7361. }
  7362. }
  7363. this.memoryWriter[0xFF36] = function (parentObj, address, data) {
  7364. if (parentObj.memory[0xFF36] != data) {
  7365. parentObj.audioJIT();
  7366. parentObj.memory[0xFF36] = data;
  7367. parentObj.channel3PCM[0x0C] = (data >> 4) / 0x1E;
  7368. parentObj.channel3PCM[0x2C] = (data >> 5) / 0x1E;
  7369. parentObj.channel3PCM[0x4C] = (data >> 6) / 0x1E;
  7370. parentObj.channel3PCM[0x0D] = (data & 0xF) / 0x1E;
  7371. parentObj.channel3PCM[0x2D] = (data & 0xE) / 0x3C;
  7372. parentObj.channel3PCM[0x4D] = (data & 0xC) / 0x78;
  7373. }
  7374. }
  7375. this.memoryWriter[0xFF37] = function (parentObj, address, data) {
  7376. if (parentObj.memory[0xFF37] != data) {
  7377. parentObj.audioJIT();
  7378. parentObj.memory[0xFF37] = data;
  7379. parentObj.channel3PCM[0x0E] = (data >> 4) / 0x1E;
  7380. parentObj.channel3PCM[0x2E] = (data >> 5) / 0x1E;
  7381. parentObj.channel3PCM[0x4E] = (data >> 6) / 0x1E;
  7382. parentObj.channel3PCM[0x0F] = (data & 0xF) / 0x1E;
  7383. parentObj.channel3PCM[0x2F] = (data & 0xE) / 0x3C;
  7384. parentObj.channel3PCM[0x4F] = (data & 0xC) / 0x78;
  7385. }
  7386. }
  7387. this.memoryWriter[0xFF38] = function (parentObj, address, data) {
  7388. if (parentObj.memory[0xFF38] != data) {
  7389. parentObj.audioJIT();
  7390. parentObj.memory[0xFF38] = data;
  7391. parentObj.channel3PCM[0x10] = (data >> 4) / 0x1E;
  7392. parentObj.channel3PCM[0x30] = (data >> 5) / 0x1E;
  7393. parentObj.channel3PCM[0x50] = (data >> 6) / 0x1E;
  7394. parentObj.channel3PCM[0x11] = (data & 0xF) / 0x1E;
  7395. parentObj.channel3PCM[0x31] = (data & 0xE) / 0x3C;
  7396. parentObj.channel3PCM[0x51] = (data & 0xC) / 0x78;
  7397. }
  7398. }
  7399. this.memoryWriter[0xFF39] = function (parentObj, address, data) {
  7400. if (parentObj.memory[0xFF39] != data) {
  7401. parentObj.audioJIT();
  7402. parentObj.memory[0xFF39] = data;
  7403. parentObj.channel3PCM[0x12] = (data >> 4) / 0x1E;
  7404. parentObj.channel3PCM[0x32] = (data >> 5) / 0x1E;
  7405. parentObj.channel3PCM[0x52] = (data >> 6) / 0x1E;
  7406. parentObj.channel3PCM[0x13] = (data & 0xF) / 0x1E;
  7407. parentObj.channel3PCM[0x33] = (data & 0xE) / 0x3C;
  7408. parentObj.channel3PCM[0x53] = (data & 0xC) / 0x78;
  7409. }
  7410. }
  7411. this.memoryWriter[0xFF3A] = function (parentObj, address, data) {
  7412. if (parentObj.memory[0xFF3A] != data) {
  7413. parentObj.audioJIT();
  7414. parentObj.memory[0xFF3A] = data;
  7415. parentObj.channel3PCM[0x14] = (data >> 4) / 0x1E;
  7416. parentObj.channel3PCM[0x34] = (data >> 5) / 0x1E;
  7417. parentObj.channel3PCM[0x54] = (data >> 6) / 0x1E;
  7418. parentObj.channel3PCM[0x15] = (data & 0xF) / 0x1E;
  7419. parentObj.channel3PCM[0x35] = (data & 0xE) / 0x3C;
  7420. parentObj.channel3PCM[0x55] = (data & 0xC) / 0x78;
  7421. }
  7422. }
  7423. this.memoryWriter[0xFF3B] = function (parentObj, address, data) {
  7424. if (parentObj.memory[0xFF3B] != data) {
  7425. parentObj.audioJIT();
  7426. parentObj.memory[0xFF3B] = data;
  7427. parentObj.channel3PCM[0x16] = (data >> 4) / 0x1E;
  7428. parentObj.channel3PCM[0x36] = (data >> 5) / 0x1E;
  7429. parentObj.channel3PCM[0x56] = (data >> 6) / 0x1E;
  7430. parentObj.channel3PCM[0x17] = (data & 0xF) / 0x1E;
  7431. parentObj.channel3PCM[0x37] = (data & 0xE) / 0x3C;
  7432. parentObj.channel3PCM[0x57] = (data & 0xC) / 0x78;
  7433. }
  7434. }
  7435. this.memoryWriter[0xFF3C] = function (parentObj, address, data) {
  7436. if (parentObj.memory[0xFF3C] != data) {
  7437. parentObj.audioJIT();
  7438. parentObj.memory[0xFF3C] = data;
  7439. parentObj.channel3PCM[0x18] = (data >> 4) / 0x1E;
  7440. parentObj.channel3PCM[0x38] = (data >> 5) / 0x1E;
  7441. parentObj.channel3PCM[0x58] = (data >> 6) / 0x1E;
  7442. parentObj.channel3PCM[0x19] = (data & 0xF) / 0x1E;
  7443. parentObj.channel3PCM[0x39] = (data & 0xE) / 0x3C;
  7444. parentObj.channel3PCM[0x59] = (data & 0xC) / 0x78;
  7445. }
  7446. }
  7447. this.memoryWriter[0xFF3D] = function (parentObj, address, data) {
  7448. if (parentObj.memory[0xFF3D] != data) {
  7449. parentObj.audioJIT();
  7450. parentObj.memory[0xFF3D] = data;
  7451. parentObj.channel3PCM[0x1A] = (data >> 4) / 0x1E;
  7452. parentObj.channel3PCM[0x3A] = (data >> 5) / 0x1E;
  7453. parentObj.channel3PCM[0x5A] = (data >> 6) / 0x1E;
  7454. parentObj.channel3PCM[0x1B] = (data & 0xF) / 0x1E;
  7455. parentObj.channel3PCM[0x3B] = (data & 0xE) / 0x3C;
  7456. parentObj.channel3PCM[0x5B] = (data & 0xC) / 0x78;
  7457. }
  7458. }
  7459. this.memoryWriter[0xFF3E] = function (parentObj, address, data) {
  7460. if (parentObj.memory[0xFF3E] != data) {
  7461. parentObj.audioJIT();
  7462. parentObj.memory[0xFF3E] = data;
  7463. parentObj.channel3PCM[0x1C] = (data >> 4) / 0x1E;
  7464. parentObj.channel3PCM[0x3C] = (data >> 5) / 0x1E;
  7465. parentObj.channel3PCM[0x5C] = (data >> 6) / 0x1E;
  7466. parentObj.channel3PCM[0x1D] = (data & 0xF) / 0x1E;
  7467. parentObj.channel3PCM[0x3D] = (data & 0xE) / 0x3C;
  7468. parentObj.channel3PCM[0x5D] = (data & 0xC) / 0x78;
  7469. }
  7470. }
  7471. this.memoryWriter[0xFF3F] = function (parentObj, address, data) {
  7472. if (parentObj.memory[0xFF3F] != data) {
  7473. parentObj.audioJIT();
  7474. parentObj.memory[0xFF3F] = data;
  7475. parentObj.channel3PCM[0x1E] = (data >> 4) / 0x1E;
  7476. parentObj.channel3PCM[0x3E] = (data >> 5) / 0x1E;
  7477. parentObj.channel3PCM[0x5E] = (data >> 6) / 0x1E;
  7478. parentObj.channel3PCM[0x1F] = (data & 0xF) / 0x1E;
  7479. parentObj.channel3PCM[0x3F] = (data & 0xE) / 0x3C;
  7480. parentObj.channel3PCM[0x5F] = (data & 0xC) / 0x78;
  7481. }
  7482. }
  7483. this.memoryWriter[0xFF44] = function (parentObj, address, data) {
  7484. //Read Only:
  7485. if (parentObj.LCDisOn) {
  7486. //Gambatte says to do this:
  7487. parentObj.LCDTicks = parentObj.STATTracker = parentObj.actualScanLine = parentObj.memory[0xFF44] = 0;
  7488. }
  7489. }
  7490. this.memoryWriter[0xFF45] = function (parentObj, address, data) {
  7491. parentObj.memory[0xFF45] = data;
  7492. if (parentObj.LCDisOn) {
  7493. parentObj.matchLYC(); //Get the compare of the first scan line.
  7494. }
  7495. }
  7496. this.memoryWriter[0xFF72] = function (parentObj, address, data) {
  7497. parentObj.memory[0xFF72] = data;
  7498. }
  7499. this.memoryWriter[0xFF73] = function (parentObj, address, data) {
  7500. parentObj.memory[0xFF73] = data;
  7501. }
  7502. this.memoryWriter[0xFF75] = function (parentObj, address, data) {
  7503. parentObj.memory[0xFF75] = data;
  7504. }
  7505. this.memoryWriter[0xFF76] = this.cartIgnoreWrite;
  7506. this.memoryWriter[0xFF77] = this.cartIgnoreWrite;
  7507. //IE (Interrupt Enable)
  7508. this.memoryWriter[0xFFFF] = function (parentObj, address, data) {
  7509. parentObj.memory[0xFFFF] = data;
  7510. }
  7511. if (this.cGBC) {
  7512. //GameBoy Color Specific I/O:
  7513. this.memoryWriter[0xFF40] = function (parentObj, address, data) {
  7514. var temp_var = (data & 0x80) == 0x80;
  7515. if (temp_var != parentObj.LCDisOn) {
  7516. //When the display mode changes...
  7517. parentObj.LCDisOn = temp_var;
  7518. parentObj.memory[0xFF41] &= 0xF8;
  7519. parentObj.modeSTAT = parentObj.STATTracker = parentObj.LCDTicks = parentObj.actualScanLine = parentObj.memory[0xFF44] = 0;
  7520. if (parentObj.LCDisOn) {
  7521. parentObj.matchLYC(); //Get the compare of the first scan line.
  7522. parentObj.LCDCONTROL = parentObj.LINECONTROL;
  7523. }
  7524. else {
  7525. parentObj.LCDCONTROL = parentObj.DISPLAYOFFCONTROL;
  7526. parentObj.DisplayShowOff();
  7527. }
  7528. parentObj.memory[0xFF0F] &= 0xFD;
  7529. }
  7530. parentObj.gfxWindowCHRBankPosition = ((data & 0x40) == 0x40) ? 0x400 : 0;
  7531. parentObj.gfxWindowDisplay = (data & 0x20) == 0x20;
  7532. parentObj.gfxBackgroundBankOffset = ((data & 0x10) == 0x10) ? 0 : 0x80;
  7533. parentObj.gfxBackgroundCHRBankPosition = ((data & 0x08) == 0x08) ? 0x400 : 0;
  7534. parentObj.gfxSpriteDouble = (data & 0x04) == 0x04;
  7535. parentObj.gfxSpriteShow = (data & 0x02) == 0x02;
  7536. parentObj.BGPriorityEnabled = ((data & 0x01) == 0x01) ? 0x1000000 : 0;
  7537. parentObj.memory[0xFF40] = data;
  7538. }
  7539. this.memoryWriter[0xFF41] = function (parentObj, address, data) {
  7540. parentObj.LYCMatchTriggerSTAT = ((data & 0x40) == 0x40);
  7541. parentObj.mode2TriggerSTAT = ((data & 0x20) == 0x20);
  7542. parentObj.mode1TriggerSTAT = ((data & 0x10) == 0x10);
  7543. parentObj.mode0TriggerSTAT = ((data & 0x08) == 0x08);
  7544. parentObj.memory[0xFF41] = (data & 0xF8);
  7545. }
  7546. this.memoryWriter[0xFF46] = function (parentObj, address, data) {
  7547. parentObj.memory[0xFF46] = data;
  7548. data <<= 8;
  7549. address = 0xFE00;
  7550. while (address < 0xFEA0) {
  7551. parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
  7552. }
  7553. parentObj.recompileOAM();
  7554. }
  7555. //KEY1
  7556. this.memoryWriter[0xFF4D] = function (parentObj, address, data) {
  7557. parentObj.memory[0xFF4D] = (data & 0x7F) | (parentObj.memory[0xFF4D] & 0x80);
  7558. }
  7559. this.memoryWriter[0xFF4F] = function (parentObj, address, data) {
  7560. parentObj.currVRAMBank = data & 0x01;
  7561. if (parentObj.currVRAMBank > 0) {
  7562. parentObj.tileBankOffset = 0x180;
  7563. parentObj.BGCHRCurrentBank = parentObj.BGCHRBank2Pointer;
  7564. }
  7565. else {
  7566. parentObj.tileBankOffset = 0;
  7567. parentObj.BGCHRCurrentBank = parentObj.BGCHRBank1Pointer;
  7568. }
  7569. //Only writable by GBC.
  7570. }
  7571. this.memoryWriter[0xFF51] = function (parentObj, address, data) {
  7572. if (!parentObj.hdmaRunning) {
  7573. parentObj.memory[0xFF51] = data;
  7574. }
  7575. }
  7576. this.memoryWriter[0xFF52] = function (parentObj, address, data) {
  7577. if (!parentObj.hdmaRunning) {
  7578. parentObj.memory[0xFF52] = data & 0xF0;
  7579. }
  7580. }
  7581. this.memoryWriter[0xFF53] = function (parentObj, address, data) {
  7582. if (!parentObj.hdmaRunning) {
  7583. parentObj.memory[0xFF53] = data & 0x1F;
  7584. }
  7585. }
  7586. this.memoryWriter[0xFF54] = function (parentObj, address, data) {
  7587. if (!parentObj.hdmaRunning) {
  7588. parentObj.memory[0xFF54] = data & 0xF0;
  7589. }
  7590. }
  7591. this.memoryWriter[0xFF55] = function (parentObj, address, data) {
  7592. if (!parentObj.hdmaRunning) {
  7593. if ((data & 0x80) == 0) {
  7594. //DMA
  7595. parentObj.CPUTicks += 1 + ((8 * ((data & 0x7F) + 1)) * parentObj.multiplier);
  7596. var dmaSrc = (parentObj.memory[0xFF51] << 8) | parentObj.memory[0xFF52];
  7597. var dmaDst = 0x8000 | (parentObj.memory[0xFF53] << 8) | parentObj.memory[0xFF54];
  7598. var endAmount = (((data & 0x7F) << 4) + 0x10);
  7599. for (var loopAmount = 0; loopAmount < endAmount; loopAmount++) {
  7600. parentObj.memoryWriter[dmaDst](parentObj, dmaDst++, parentObj.memoryReader[dmaSrc](parentObj, dmaSrc++));
  7601. }
  7602. parentObj.memory[0xFF51] = ((dmaSrc & 0xFF00) >> 8);
  7603. parentObj.memory[0xFF52] = (dmaSrc & 0x00F0);
  7604. parentObj.memory[0xFF53] = ((dmaDst & 0x1F00) >> 8);
  7605. parentObj.memory[0xFF54] = (dmaDst & 0x00F0);
  7606. parentObj.memory[0xFF55] = 0xFF; //Transfer completed.
  7607. }
  7608. else {
  7609. //H-Blank DMA
  7610. if (data > 0x80) {
  7611. parentObj.hdmaRunning = true;
  7612. parentObj.memory[0xFF55] = data & 0x7F;
  7613. }
  7614. else {
  7615. parentObj.memory[0xFF55] = 0xFF;
  7616. }
  7617. }
  7618. }
  7619. else if ((data & 0x80) == 0) {
  7620. //Stop H-Blank DMA
  7621. parentObj.hdmaRunning = false;
  7622. parentObj.memory[0xFF55] |= 0x80;
  7623. }
  7624. }
  7625. this.memoryWriter[0xFF68] = function (parentObj, address, data) {
  7626. parentObj.memory[0xFF69] = parentObj.gbcBGRawPalette[data & 0x3F];
  7627. parentObj.memory[0xFF68] = data;
  7628. }
  7629. this.memoryWriter[0xFF69] = function (parentObj, address, data) {
  7630. parentObj.setGBCBGPalette(parentObj.memory[0xFF68] & 0x3F, data);
  7631. if (parentObj.memory[0xFF68] > 0x7F) { // high bit = autoincrement
  7632. var next = ((parentObj.memory[0xFF68] + 1) & 0x3F);
  7633. parentObj.memory[0xFF68] = (next | 0x80);
  7634. parentObj.memory[0xFF69] = parentObj.gbcBGRawPalette[next];
  7635. }
  7636. else {
  7637. parentObj.memory[0xFF69] = data;
  7638. }
  7639. }
  7640. this.memoryWriter[0xFF6A] = function (parentObj, address, data) {
  7641. parentObj.memory[0xFF6B] = parentObj.gbcOBJRawPalette[data & 0x3F];
  7642. parentObj.memory[0xFF6A] = data;
  7643. }
  7644. this.memoryWriter[0xFF6B] = function (parentObj, address, data) {
  7645. parentObj.setGBCOBJPalette(parentObj.memory[0xFF6A] & 0x3F, data);
  7646. if (parentObj.memory[0xFF6A] > 0x7F) { // high bit = autoincrement
  7647. var next = ((parentObj.memory[0xFF6A] + 1) & 0x3F);
  7648. parentObj.memory[0xFF6A] = (next | 0x80);
  7649. parentObj.memory[0xFF6B] = parentObj.gbcOBJRawPalette[next];
  7650. }
  7651. else {
  7652. parentObj.memory[0xFF6B] = data;
  7653. }
  7654. }
  7655. //SVBK
  7656. this.memoryWriter[0xFF70] = function (parentObj, address, data) {
  7657. var addressCheck = (parentObj.memory[0xFF51] << 8) | parentObj.memory[0xFF52]; //Cannot change the RAM bank while WRAM is the source of a running HDMA.
  7658. if (!parentObj.hdmaRunning || addressCheck < 0xD000 || addressCheck >= 0xE000) {
  7659. parentObj.gbcRamBank = Math.max(data & 0x07, 1); //Bank range is from 1-7
  7660. parentObj.gbcRamBankPosition = ((parentObj.gbcRamBank - 1) << 12) - 0xD000;
  7661. parentObj.gbcRamBankPositionECHO = parentObj.gbcRamBankPosition - 0x2000;
  7662. }
  7663. parentObj.memory[0xFF70] = data; //Bit 6 cannot be written to.
  7664. }
  7665. this.memoryWriter[0xFF74] = function (parentObj, address, data) {
  7666. parentObj.memory[0xFF74] = data;
  7667. }
  7668. }
  7669. else {
  7670. //Fill in the GameBoy Color I/O registers as normal RAM for GameBoy compatibility:
  7671. this.memoryWriter[0xFF40] = function (parentObj, address, data) {
  7672. var temp_var = (data & 0x80) == 0x80;
  7673. if (temp_var != parentObj.LCDisOn) {
  7674. //When the display mode changes...
  7675. parentObj.LCDisOn = temp_var;
  7676. parentObj.memory[0xFF41] &= 0xF8;
  7677. parentObj.modeSTAT = parentObj.STATTracker = parentObj.LCDTicks = parentObj.actualScanLine = parentObj.memory[0xFF44] = 0;
  7678. if (parentObj.LCDisOn) {
  7679. parentObj.matchLYC(); //Get the compare of the first scan line.
  7680. parentObj.LCDCONTROL = parentObj.LINECONTROL;
  7681. }
  7682. else {
  7683. parentObj.LCDCONTROL = parentObj.DISPLAYOFFCONTROL;
  7684. parentObj.DisplayShowOff();
  7685. }
  7686. parentObj.memory[0xFF0F] &= 0xFD;
  7687. }
  7688. parentObj.gfxWindowCHRBankPosition = ((data & 0x40) == 0x40) ? 0x400 : 0;
  7689. parentObj.gfxWindowDisplay = (data & 0x20) == 0x20;
  7690. parentObj.gfxBackgroundBankOffset = ((data & 0x10) == 0x10) ? 0 : 0x80;
  7691. parentObj.gfxBackgroundCHRBankPosition = ((data & 0x08) == 0x08) ? 0x400 : 0;
  7692. parentObj.gfxSpriteDouble = (data & 0x04) == 0x04;
  7693. parentObj.gfxSpriteShow = (data & 0x02) == 0x02;
  7694. if ((data & 0x01) == 0) {
  7695. // this emulates the gbc-in-gb-mode, not the original gb-mode
  7696. parentObj.bgEnabled = false;
  7697. parentObj.gfxWindowDisplay = false;
  7698. }
  7699. else {
  7700. parentObj.bgEnabled = true;
  7701. }
  7702. parentObj.memory[0xFF40] = data;
  7703. }
  7704. this.memoryWriter[0xFF41] = function (parentObj, address, data) {
  7705. parentObj.LYCMatchTriggerSTAT = ((data & 0x40) == 0x40);
  7706. parentObj.mode2TriggerSTAT = ((data & 0x20) == 0x20);
  7707. parentObj.mode1TriggerSTAT = ((data & 0x10) == 0x10);
  7708. parentObj.mode0TriggerSTAT = ((data & 0x08) == 0x08);
  7709. parentObj.memory[0xFF41] = (data & 0xF8);
  7710. if (parentObj.LCDisOn && parentObj.modeSTAT < 2) {
  7711. parentObj.memory[0xFF0F] |= 0x2;
  7712. }
  7713. }
  7714. this.memoryWriter[0xFF46] = function (parentObj, address, data) {
  7715. parentObj.memory[0xFF46] = data;
  7716. if (data > 0x7F) { //DMG cannot DMA from the ROM banks.
  7717. data <<= 8;
  7718. address = 0xFE00;
  7719. while (address < 0xFEA0) {
  7720. parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
  7721. }
  7722. parentObj.recompileOAM();
  7723. }
  7724. }
  7725. this.memoryWriter[0xFF47] = function (parentObj, address, data) {
  7726. if (parentObj.memory[0xFF47] != data) {
  7727. parentObj.setGBBGPalette(0, data);
  7728. parentObj.memory[0xFF47] = data;
  7729. }
  7730. }
  7731. this.memoryWriter[0xFF48] = function (parentObj, address, data) {
  7732. if (parentObj.memory[0xFF48] != data) {
  7733. parentObj.setGBOBJPalette(0, data);
  7734. parentObj.memory[0xFF48] = data;
  7735. }
  7736. }
  7737. this.memoryWriter[0xFF49] = function (parentObj, address, data) {
  7738. if (parentObj.memory[0xFF49] != data) {
  7739. parentObj.setGBOBJPalette(4, data);
  7740. parentObj.memory[0xFF49] = data;
  7741. }
  7742. }
  7743. this.memoryWriter[0xFF4D] = function (parentObj, address, data) {
  7744. parentObj.memory[0xFF4D] = data;
  7745. }
  7746. this.memoryWriter[0xFF4F] = this.cartIgnoreWrite; //Not writable in DMG mode.
  7747. this.memoryWriter[0xFF55] = this.cartIgnoreWrite;
  7748. this.memoryWriter[0xFF68] = this.cartIgnoreWrite;
  7749. this.memoryWriter[0xFF69] = this.cartIgnoreWrite;
  7750. this.memoryWriter[0xFF6A] = this.cartIgnoreWrite;
  7751. this.memoryWriter[0xFF6B] = this.cartIgnoreWrite;
  7752. this.memoryWriter[0xFF6C] = this.cartIgnoreWrite;
  7753. this.memoryWriter[0xFF70] = this.cartIgnoreWrite;
  7754. this.memoryWriter[0xFF74] = this.cartIgnoreWrite;
  7755. }
  7756. //Boot I/O Registers:
  7757. if (this.inBootstrap) {
  7758. this.memoryWriter[0xFF50] = function (parentObj, address, data) {
  7759. cout("Boot ROM reads blocked: Bootstrap process has ended.", 0);
  7760. parentObj.inBootstrap = false;
  7761. parentObj.disableBootROM(); //Fill in the boot ROM ranges with ROM bank 0 ROM ranges
  7762. parentObj.memory[0xFF50] = data; //Bits are sustained in memory?
  7763. }
  7764. if (this.cGBC) {
  7765. this.memoryWriter[0xFF6C] = function (parentObj, address, data) {
  7766. if (parentObj.inBootstrap) {
  7767. parentObj.cGBC = ((data & 0x1) == 0);
  7768. cout("Booted to GBC Mode: " + parentObj.cGBC, 0);
  7769. }
  7770. parentObj.memory[0xFF6C] = data;
  7771. }
  7772. }
  7773. }
  7774. else {
  7775. //Lockout the ROMs from accessing the BOOT ROM control register:
  7776. this.memoryWriter[0xFF50] = this.cartIgnoreWrite;
  7777. }
  7778. }
  7779. //Helper Functions
  7780. GameBoyCore.prototype.usbtsb = function (ubyte) {
  7781. //Unsigned byte to signed byte:
  7782. return (ubyte & 0x7F) - (ubyte & 0x80);
  7783. }
  7784. GameBoyCore.prototype.toTypedArray = function (baseArray, memtype) {
  7785. try {
  7786. var length = baseArray.length;
  7787. switch (memtype) {
  7788. case 1:
  7789. var typedArrayTemp = new Uint8Array(length);
  7790. break;
  7791. case 2:
  7792. var typedArrayTemp = new Int32Array(length);
  7793. break;
  7794. default:
  7795. cout("Could not convert an array to a typed array: Invalid type parameter.", 1);
  7796. return baseArray;
  7797. }
  7798. for (var index = 0; index < length; index++) {
  7799. typedArrayTemp[index] = baseArray[index];
  7800. }
  7801. return typedArrayTemp;
  7802. }
  7803. catch (error) {
  7804. cout("Could not convert an array to a typed array: " + error.message, 1);
  7805. return baseArray;
  7806. }
  7807. }
  7808. GameBoyCore.prototype.fromTypedArray = function (baseArray) {
  7809. try {
  7810. var arrayTemp = new Array(baseArray.length);
  7811. for (var index = 0; index < baseArray.length; index++) {
  7812. arrayTemp[index] = baseArray[index];
  7813. }
  7814. return arrayTemp;
  7815. }
  7816. catch (error) {
  7817. return baseArray;
  7818. }
  7819. }
  7820. GameBoyCore.prototype.getTypedArray = function (length, defaultValue, numberType) {
  7821. try {
  7822. if (settings[22]) {
  7823. throw(new Error(""));
  7824. }
  7825. switch (numberType) {
  7826. case "uint8":
  7827. var arrayHandle = new Uint8Array(length);
  7828. break;
  7829. case "int8":
  7830. var arrayHandle = new Int8Array(length);
  7831. break;
  7832. case "uint16":
  7833. var arrayHandle = new Uint16Array(length);
  7834. break;
  7835. case "int16":
  7836. var arrayHandle = new Int16Array(length);
  7837. break;
  7838. case "uint32":
  7839. var arrayHandle = new Uint32Array(length);
  7840. break;
  7841. case "int32":
  7842. var arrayHandle = new Int32Array(length);
  7843. break;
  7844. case "float32":
  7845. var arrayHandle = new Float32Array(length);
  7846. }
  7847. if (defaultValue > 0) {
  7848. var index = 0;
  7849. while (index < length) {
  7850. arrayHandle[index++] = defaultValue;
  7851. }
  7852. }
  7853. }
  7854. catch (error) {
  7855. var arrayHandle = new Array(length);
  7856. var index = 0;
  7857. while (index < length) {
  7858. arrayHandle[index++] = defaultValue;
  7859. }
  7860. }
  7861. return arrayHandle;
  7862. }
  7863. GameBoyCore.prototype.audioBufferSlice = function (length) {
  7864. if (typeof this.currentBuffer.subarray == "function") {
  7865. //"I am disappoint" I had to change this one day later from subset:
  7866. return this.currentBuffer.subarray(0, length);
  7867. }
  7868. else {
  7869. return this.currentBuffer.slice(0, length);
  7870. }
  7871. }
  7872. GameBoyCore.prototype.ArrayPad = function (length, defaultValue) {
  7873. var arrayHandle = new Array(length);
  7874. var index = 0;
  7875. while (index < length) {
  7876. arrayHandle[index++] = defaultValue;
  7877. }
  7878. return arrayHandle;
  7879. }
Add Comment
Please, Sign In to add comment