1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-11-28 08:50:22 +00:00
8bitworkshop/jsnes/jsnes.min.js.map
2018-07-28 09:46:27 -04:00

1 line
481 KiB
Plaintext

{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///jsnes.min.js","webpack:///webpack/bootstrap be5c7600992719b4371b","webpack:///./src/utils.js","webpack:///./src/controller.js","webpack:///./src/tile.js","webpack:///./src/index.js","webpack:///./src/nes.js","webpack:///./src/cpu.js","webpack:///./src/ppu.js","webpack:///./src/papu.js","webpack:///./src/rom.js","webpack:///./src/mappers.js"],"names":["root","factory","exports","module","define","amd","self","this","modules","__webpack_require__","moduleId","installedModules","i","l","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","copyArrayElements","src","srcPos","dest","destPos","length","copyArray","slice","fromJSON","obj","state","JSON_PROPERTIES","toJSON","Controller","Array","BUTTON_A","BUTTON_B","BUTTON_SELECT","BUTTON_START","BUTTON_UP","BUTTON_DOWN","BUTTON_LEFT","BUTTON_RIGHT","buttonDown","key","buttonUp","Tile","pix","fbIndex","tIndex","x","y","w","h","incX","incY","palIndex","tpri","initialized","opaque","setBuffer","scanline","setScanline","sline","b1","b2","render","buffer","srcx1","srcy1","srcx2","srcy2","dx","dy","palAdd","palette","flipHorizontal","flipVertical","pri","priTable","isTransparent","NES","CPU","PPU","PAPU","ROM","opts","onFrame","onAudioSample","onStatusUpdate","onBatteryRamWrite","preferredFrameRate","emulateSound","sampleRate","frameTime","ui","writeFrame","updateStatus","cpu","ppu","papu","mmap","controllers","1","2","frame","bind","zapperMove","zapperFireDown","zapperFireUp","fpsFrameCount","romData","reset","lastFpsTime","startFrame","cycles","FRAMELOOP","cyclesToHalt","emulate","clockFrameCounter","curX","spr0HitX","f_spVisibility","spr0HitY","setStatusFlag","STATUS_SPRITE0HIT","requestEndFrame","nmiCounter","startVBlank","endScanline","controller","button","zapperX","zapperY","zapperFired","getFPS","now","Date","fps","reloadROM","loadROM","data","rom","load","createMapper","setMirroring","getMirroringType","setFramerate","rate","setSampleRate","utils","nes","mem","REG_ACC","REG_X","REG_Y","REG_SP","REG_PC","REG_PC_NEW","REG_STATUS","F_CARRY","F_DECIMAL","F_INTERRUPT","F_INTERRUPT_NEW","F_OVERFLOW","F_SIGN","F_ZERO","F_NOTUSED","F_NOTUSED_NEW","F_BRK","F_BRK_NEW","opdata","crash","irqRequested","irqType","IRQ_NORMAL","IRQ_NMI","IRQ_RESET","j","k","setStatus","OpData","temp","add","doIrq","doNonMaskableInterrupt","doResetInterrupt","opinf","cycleCount","cycleAdd","addrMode","opaddr","addr","load16bit","write","push","pull","stackWrap","stop","crashMessage","toString","val","requestIrq","type","value","pageCrossed","addr1","addr2","haltCycles","status","getStatus","st","setOp","INS_ADC","ADDR_IMM","ADDR_ZP","ADDR_ZPX","ADDR_ABS","ADDR_ABSX","ADDR_ABSY","ADDR_PREIDXIND","ADDR_POSTIDXIND","INS_AND","INS_ASL","ADDR_ACC","INS_BCC","ADDR_REL","INS_BCS","INS_BEQ","INS_BIT","INS_BMI","INS_BNE","INS_BPL","INS_BRK","ADDR_IMP","INS_BVC","INS_BVS","INS_CLC","INS_CLD","INS_CLI","INS_CLV","INS_CMP","INS_CPX","INS_CPY","INS_DEC","INS_DEX","INS_DEY","INS_EOR","INS_INC","INS_INX","INS_INY","INS_JMP","ADDR_INDABS","INS_JSR","INS_LDA","INS_LDX","ADDR_ZPY","INS_LDY","INS_LSR","INS_NOP","INS_ORA","INS_PHA","INS_PHP","INS_PLA","INS_PLP","INS_ROL","INS_ROR","INS_RTI","INS_RTS","INS_SBC","INS_SEC","INS_SED","INS_SEI","INS_STA","INS_STX","INS_STY","INS_TAX","INS_TAY","INS_TSX","INS_TXA","INS_TXS","INS_TYA","cycTable","instname","addrDesc","INS_DUMMY","inst","op","size","vramMem","spriteMem","vramAddress","vramTmpAddress","vramBufferedReadValue","firstWrite","sramAddress","currentMirroring","nmiOk","dummyCycleToggle","validTileData","scanlineAlreadyRendered","f_nmiOnVblank","f_spriteSize","f_bgPatternTable","f_spPatternTable","f_addrInc","f_nTblAddress","f_color","f_bgVisibility","f_spClipping","f_bgClipping","f_dispType","cntFV","cntV","cntH","cntVT","cntHT","regFV","regV","regH","regVT","regHT","regFH","regS","curNt","attrib","bgbuffer","pixrendered","scantile","lastRenderedScanline","sprX","sprY","sprTile","sprCol","vertFlip","horiFlip","bgPriority","hitSpr0","sprPalette","imgPalette","ptTile","ntable1","nameTable","vramMirrorTable","palTable","showSpr0Hit","clipToTvSize","STATUS_VRAMWRITE","STATUS_SLSPRITECOUNT","STATUS_VBLANK","NameTable","PaletteTable","loadNTSCPalette","updateControlReg1","updateControlReg2","mirroring","triggerRendering","defineMirrorRegion","HORIZONTAL_MIRRORING","VERTICAL_MIRRORING","SINGLESCREEN_MIRRORING","SINGLESCREEN_MIRRORING2","fromStart","toStart","renderFramePartially","endFrame","renderBgScanline","checkSprite0","clockIrqCounter","regsToAddress","cntsToAddress","bgColor","setEmphasis","updatePalettes","flag","readStatusRegister","tmp","writeSRAMAddress","address","sramLoad","sramWrite","spriteRamWriteUpdate","scrollWrite","writeVRAMAddress","latchAccess","vramLoad","mirroredLoad","cntsFromAddress","regsFromAddress","vramWrite","mirroredWrite","writeMem","sramDMA","baseAddress","incTileCounter","count","Error","startScan","scanCount","renderSpritesPartially","si","ei","destIndex","scan","baseTile","t","tpix","att","col","tscanoffset","targetBuffer","tile","getTileIndex","getAttrib","sx","startscan","scancount","bgPri","top","toffset","bufferIndex","tIndexAdd","patternWrite","nameTableWrite","attribTableWrite","getEntry","tileIndex","Math","floor","leftOver","index","writeAttrib","doNMI","isPixelWhite","width","height","tx","ty","basex","basey","sqy","sqx","curTable","emphTable","currentEmph","makeTables","loadPALPalette","r","g","b","rFactor","gFactor","bFactor","emph","getRed","getGreen","getBlue","getRgb","yiq","rgb","loadDefaultPalette","square1","ChannelSquare","square2","triangle","ChannelTriangle","noise","ChannelNoise","dmc","ChannelDM","frameIrqCounter","frameIrqCounterMax","initCounter","channelEnableValue","lengthLookup","dmcFreqLookup","noiseWavelengthLookup","square_table","tnd_table","frameIrqEnabled","frameIrqActive","frameClockNow","startedPlaying","recordOutput","initingHardware","masterFrameCounter","derivedFrameCounter","countSequence","sampleTimer","sampleTimerMax","sampleCount","triValue","smpSquare1","smpSquare2","smpTriangle","smpDmc","accCount","prevSampleL","prevSampleR","smpAccumL","smpAccumR","dacRange","dcValue","masterVolume","stereoPosLSquare1","stereoPosLSquare2","stereoPosLTriangle","stereoPosLNoise","stereoPosLDMC","stereoPosRSquare1","stereoPosRSquare2","stereoPosRTriangle","stereoPosRNoise","stereoPosRDMC","extraCycles","maxSample","minSample","panning","setPanning","initLengthLookup","initDmcFrequencyLookup","initNoiseWavelengthLookup","initDACtables","writeReg","updateChannelEnable","resetCounter","readReg","getLengthStatus","getIrqStatus","irqGenerated","frameCounterTick","setEnabled","nCycles","maxCycles","isEnabled","shiftCounter","dmaFrequency","clockDmc","progTimerMax","progTimerCount","linearCounter","lengthCounter","triangleCounter","sampleValue","squareCounter","updateSampleValue","acc_c","accValue","shiftReg","randomMode","randomBit","accSample","sample","sampleCondition","clockLengthCounter","clockSweep","clockEnvDecay","clockLinearCounter","sq_index","tnd_index","smpNoise","sampleValueL","sampleValueR","smpDiffL","smpDiffR","getLengthMax","getDmcFrequency","getNoiseWaveLength","pos","updateStereoPos","setMasterVolume","ival","max_sqr","max_tnd","MODE_NORMAL","MODE_LOOP","MODE_IRQ","hasSample","playMode","dmaCounter","deltaCounter","playStartAddress","playAddress","playLength","playLengthCounter","reg4012","reg4013","dacLsb","endOfSample","nextSample","envDecayDisable","envDecayLoopEnable","lengthCounterEnable","envReset","shiftNow","envDecayRate","envDecayCounter","envVolume","dutyLookup","impLookup","sqr1","sweepActive","sweepCarry","updateSweepPeriod","sweepCounter","sweepCounterMax","sweepMode","sweepShiftAmount","dutyMode","sweepResult","vol","addrAdd","lcHalt","lcControl","lcLoadValue","updateSampleCondition","clockProgrammableTimer","clockTriangleGenerator","Mappers","mapperName","FOURSCREEN_MIRRORING","SINGLESCREEN_MIRRORING3","SINGLESCREEN_MIRRORING4","CHRROM_MIRRORING","header","vrom","vromTile","romCount","vromCount","batteryRam","trainer","fourScreen","mapperType","valid","v","indexOf","charCodeAt","foundError","offset","getMapperName","mapperSupported","joy1StrobeState","joy2StrobeState","joypadLastWrite","regWrite","writelow","regLoad","joy1Read","joy2Read","ret","loadPRGROM","loadCHRROM","loadBatteryRam","loadRomBank","loadVromBank","ram","bank","load32kRomBank","load8kVromBank","bank4kStart","load1kVromBank","bank1k","bank4k","bankoffset","baseIndex","load2kVromBank","bank2k","load8kRomBank","bank8k","bank16k","apply","regBuffer","regBufferCounter","oneScreenMirroring","prgSwitchingArea","prgSwitchingSize","vromSwitchingSize","romSelectionReg0","romSelectionReg1","romBankSelect","arguments","getRegNumber","setReg","reg","baseBank","switchLowHighPrgRom","oldSetting","switch16to32","switch32to16","CMD_SEL_2_1K_VROM_0000","CMD_SEL_2_1K_VROM_0800","CMD_SEL_1K_VROM_1000","CMD_SEL_1K_VROM_1400","CMD_SEL_1K_VROM_1800","CMD_SEL_1K_VROM_1C00","CMD_SEL_ROM_PAGE1","CMD_SEL_ROM_PAGE2","command","prgAddressSelect","chrAddressSelect","pageNumber","irqCounter","irqLatchValue","irqEnable","prgAddressChanged","executeCommand","cmd","arg","prg_size","chr_size","sram_we_a","sram_we_b","graphic_mode","nametable_mode","nametable_type","fill_chr","fill_pal","SetBank_SRAM","SetBank_CPU","chr_mode","chr_page","SetBank_PPU","split_control","split_scroll","split_page","irq_line","ClearIRQ","irq_enable","mult_a","mult_b","exWrite","irq_status","prgbank1","prgbank2","console","log"],"mappings":"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","file":"jsnes.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"jsnes\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"jsnes\"] = factory();\n\telse\n\t\troot[\"jsnes\"] = factory();\n})(typeof self !== 'undefined' ? self : this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"jsnes\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"jsnes\"] = factory();\n\telse\n\t\troot[\"jsnes\"] = factory();\n})(typeof self !== 'undefined' ? self : this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 3);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports) {\n\nmodule.exports = {\n copyArrayElements: function(src, srcPos, dest, destPos, length) {\n for (var i = 0; i < length; ++i) {\n dest[destPos + i] = src[srcPos + i];\n }\n },\n\n copyArray: function(src) {\n return src.slice(0);\n },\n\n fromJSON: function(obj, state) {\n for (var i = 0; i < obj.JSON_PROPERTIES.length; i++) {\n obj[obj.JSON_PROPERTIES[i]] = state[obj.JSON_PROPERTIES[i]];\n }\n },\n\n toJSON: function(obj) {\n var state = {};\n for (var i = 0; i < obj.JSON_PROPERTIES.length; i++) {\n state[obj.JSON_PROPERTIES[i]] = obj[obj.JSON_PROPERTIES[i]];\n }\n return state;\n }\n};\n\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports) {\n\nvar Controller = function() {\n this.state = new Array(8);\n for (var i = 0; i < this.state.length; i++) {\n this.state[i] = 0x40;\n }\n};\n\nController.BUTTON_A = 0;\nController.BUTTON_B = 1;\nController.BUTTON_SELECT = 2;\nController.BUTTON_START = 3;\nController.BUTTON_UP = 4;\nController.BUTTON_DOWN = 5;\nController.BUTTON_LEFT = 6;\nController.BUTTON_RIGHT = 7;\n\nController.prototype = {\n buttonDown: function(key) {\n this.state[key] = 0x41;\n },\n\n buttonUp: function(key) {\n this.state[key] = 0x40;\n }\n};\n\nmodule.exports = Controller;\n\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports) {\n\nvar Tile = function() {\n // Tile data:\n this.pix = new Array(64);\n\n this.fbIndex = null;\n this.tIndex = null;\n this.x = null;\n this.y = null;\n this.w = null;\n this.h = null;\n this.incX = null;\n this.incY = null;\n this.palIndex = null;\n this.tpri = null;\n this.c = null;\n this.initialized = false;\n this.opaque = new Array(8);\n};\n\nTile.prototype = {\n setBuffer: function(scanline) {\n for (this.y = 0; this.y < 8; this.y++) {\n this.setScanline(this.y, scanline[this.y], scanline[this.y + 8]);\n }\n },\n\n setScanline: function(sline, b1, b2) {\n this.initialized = true;\n this.tIndex = sline << 3;\n for (this.x = 0; this.x < 8; this.x++) {\n this.pix[this.tIndex + this.x] =\n ((b1 >> (7 - this.x)) & 1) + (((b2 >> (7 - this.x)) & 1) << 1);\n if (this.pix[this.tIndex + this.x] === 0) {\n this.opaque[sline] = false;\n }\n }\n },\n\n render: function(\n buffer,\n srcx1,\n srcy1,\n srcx2,\n srcy2,\n dx,\n dy,\n palAdd,\n palette,\n flipHorizontal,\n flipVertical,\n pri,\n priTable\n ) {\n if (dx < -7 || dx >= 256 || dy < -7 || dy >= 240) {\n return;\n }\n\n this.w = srcx2 - srcx1;\n this.h = srcy2 - srcy1;\n\n if (dx < 0) {\n srcx1 -= dx;\n }\n if (dx + srcx2 >= 256) {\n srcx2 = 256 - dx;\n }\n\n if (dy < 0) {\n srcy1 -= dy;\n }\n if (dy + srcy2 >= 240) {\n srcy2 = 240 - dy;\n }\n\n if (!flipHorizontal && !flipVertical) {\n this.fbIndex = (dy << 8) + dx;\n this.tIndex = 0;\n for (this.y = 0; this.y < 8; this.y++) {\n for (this.x = 0; this.x < 8; this.x++) {\n if (\n this.x >= srcx1 &&\n this.x < srcx2 &&\n this.y >= srcy1 &&\n this.y < srcy2\n ) {\n this.palIndex = this.pix[this.tIndex];\n this.tpri = priTable[this.fbIndex];\n if (this.palIndex !== 0 && pri <= (this.tpri & 0xff)) {\n //console.log(\"Rendering upright tile to buffer\");\n buffer[this.fbIndex] = palette[this.palIndex + palAdd];\n this.tpri = (this.tpri & 0xf00) | pri;\n priTable[this.fbIndex] = this.tpri;\n }\n }\n this.fbIndex++;\n this.tIndex++;\n }\n this.fbIndex -= 8;\n this.fbIndex += 256;\n }\n } else if (flipHorizontal && !flipVertical) {\n this.fbIndex = (dy << 8) + dx;\n this.tIndex = 7;\n for (this.y = 0; this.y < 8; this.y++) {\n for (this.x = 0; this.x < 8; this.x++) {\n if (\n this.x >= srcx1 &&\n this.x < srcx2 &&\n this.y >= srcy1 &&\n this.y < srcy2\n ) {\n this.palIndex = this.pix[this.tIndex];\n this.tpri = priTable[this.fbIndex];\n if (this.palIndex !== 0 && pri <= (this.tpri & 0xff)) {\n buffer[this.fbIndex] = palette[this.palIndex + palAdd];\n this.tpri = (this.tpri & 0xf00) | pri;\n priTable[this.fbIndex] = this.tpri;\n }\n }\n this.fbIndex++;\n this.tIndex--;\n }\n this.fbIndex -= 8;\n this.fbIndex += 256;\n this.tIndex += 16;\n }\n } else if (flipVertical && !flipHorizontal) {\n this.fbIndex = (dy << 8) + dx;\n this.tIndex = 56;\n for (this.y = 0; this.y < 8; this.y++) {\n for (this.x = 0; this.x < 8; this.x++) {\n if (\n this.x >= srcx1 &&\n this.x < srcx2 &&\n this.y >= srcy1 &&\n this.y < srcy2\n ) {\n this.palIndex = this.pix[this.tIndex];\n this.tpri = priTable[this.fbIndex];\n if (this.palIndex !== 0 && pri <= (this.tpri & 0xff)) {\n buffer[this.fbIndex] = palette[this.palIndex + palAdd];\n this.tpri = (this.tpri & 0xf00) | pri;\n priTable[this.fbIndex] = this.tpri;\n }\n }\n this.fbIndex++;\n this.tIndex++;\n }\n this.fbIndex -= 8;\n this.fbIndex += 256;\n this.tIndex -= 16;\n }\n } else {\n this.fbIndex = (dy << 8) + dx;\n this.tIndex = 63;\n for (this.y = 0; this.y < 8; this.y++) {\n for (this.x = 0; this.x < 8; this.x++) {\n if (\n this.x >= srcx1 &&\n this.x < srcx2 &&\n this.y >= srcy1 &&\n this.y < srcy2\n ) {\n this.palIndex = this.pix[this.tIndex];\n this.tpri = priTable[this.fbIndex];\n if (this.palIndex !== 0 && pri <= (this.tpri & 0xff)) {\n buffer[this.fbIndex] = palette[this.palIndex + palAdd];\n this.tpri = (this.tpri & 0xf00) | pri;\n priTable[this.fbIndex] = this.tpri;\n }\n }\n this.fbIndex++;\n this.tIndex--;\n }\n this.fbIndex -= 8;\n this.fbIndex += 256;\n }\n }\n },\n\n isTransparent: function(x, y) {\n return this.pix[(y << 3) + x] === 0;\n },\n\n toJSON: function() {\n return {\n opaque: this.opaque,\n pix: this.pix\n };\n },\n\n fromJSON: function(s) {\n this.opaque = s.opaque;\n this.pix = s.pix;\n }\n};\n\nmodule.exports = Tile;\n\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports, __webpack_require__) {\n\nmodule.exports = {\n Controller: __webpack_require__(1),\n NES: __webpack_require__(4),\n};\n\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar CPU = __webpack_require__(5);\nvar Controller = __webpack_require__(1);\nvar PPU = __webpack_require__(6);\nvar PAPU = __webpack_require__(7);\nvar ROM = __webpack_require__(8);\n\nvar NES = function(opts) {\n this.opts = {\n onFrame: function() {},\n onAudioSample: null,\n onStatusUpdate: function() {},\n onBatteryRamWrite: function() {},\n\n // FIXME: not actually used except for in PAPU\n preferredFrameRate: 60,\n\n emulateSound: true,\n sampleRate: 44100 // Sound sample rate in hz\n };\n if (typeof opts !== \"undefined\") {\n var key;\n for (key in this.opts) {\n if (typeof opts[key] !== \"undefined\") {\n this.opts[key] = opts[key];\n }\n }\n }\n\n this.frameTime = 1000 / this.opts.preferredFrameRate;\n\n this.ui = {\n writeFrame: this.opts.onFrame,\n updateStatus: this.opts.onStatusUpdate\n };\n this.cpu = new CPU(this);\n this.ppu = new PPU(this);\n this.papu = new PAPU(this);\n this.mmap = null; // set in loadROM()\n this.controllers = {\n 1: new Controller(),\n 2: new Controller(),\n };\n\n this.ui.updateStatus(\"Ready to load a ROM.\");\n\n this.frame = this.frame.bind(this);\n this.buttonDown = this.buttonDown.bind(this);\n this.buttonUp = this.buttonUp.bind(this);\n this.zapperMove = this.zapperMove.bind(this);\n this.zapperFireDown = this.zapperFireDown.bind(this);\n this.zapperFireUp = this.zapperFireUp.bind(this);\n};\n\nNES.prototype = {\n fpsFrameCount: 0,\n romData: null,\n\n // Resets the system\n reset: function() {\n if (this.mmap !== null) {\n this.mmap.reset();\n }\n\n this.cpu.reset();\n this.ppu.reset();\n this.papu.reset();\n\n this.lastFpsTime = null;\n this.fpsFrameCount = 0;\n },\n\n frame: function() {\n this.ppu.startFrame();\n var cycles = 0;\n var emulateSound = this.opts.emulateSound;\n var cpu = this.cpu;\n var ppu = this.ppu;\n var papu = this.papu;\n FRAMELOOP: for (;;) {\n if (cpu.cyclesToHalt === 0) {\n // Execute a CPU instruction\n cycles = cpu.emulate();\n if (emulateSound) {\n papu.clockFrameCounter(cycles);\n }\n cycles *= 3;\n } else {\n if (cpu.cyclesToHalt > 8) {\n cycles = 24;\n if (emulateSound) {\n papu.clockFrameCounter(8);\n }\n cpu.cyclesToHalt -= 8;\n } else {\n cycles = cpu.cyclesToHalt * 3;\n if (emulateSound) {\n papu.clockFrameCounter(cpu.cyclesToHalt);\n }\n cpu.cyclesToHalt = 0;\n }\n }\n\n for (; cycles > 0; cycles--) {\n if (\n ppu.curX === ppu.spr0HitX &&\n ppu.f_spVisibility === 1 &&\n ppu.scanline - 21 === ppu.spr0HitY\n ) {\n // Set sprite 0 hit flag:\n ppu.setStatusFlag(ppu.STATUS_SPRITE0HIT, true);\n }\n\n if (ppu.requestEndFrame) {\n ppu.nmiCounter--;\n if (ppu.nmiCounter === 0) {\n ppu.requestEndFrame = false;\n ppu.startVBlank();\n break FRAMELOOP;\n }\n }\n\n ppu.curX++;\n if (ppu.curX === 341) {\n ppu.curX = 0;\n ppu.endScanline();\n }\n }\n }\n this.fpsFrameCount++;\n },\n\n buttonDown: function(controller, button) {\n this.controllers[controller].buttonDown(button);\n },\n\n buttonUp: function(controller, button) {\n this.controllers[controller].buttonUp(button);\n },\n\n zapperMove: function(x, y) {\n if (!this.mmap) return;\n this.mmap.zapperX = x;\n this.mmap.zapperY = y;\n },\n\n zapperFireDown: function() {\n if (!this.mmap) return;\n this.mmap.zapperFired = true;\n },\n\n zapperFireUp: function() {\n if (!this.mmap) return;\n this.mmap.zapperFired = false;\n },\n\n getFPS: function() {\n var now = +new Date();\n var fps = null;\n if (this.lastFpsTime) {\n fps = this.fpsFrameCount / ((now - this.lastFpsTime) / 1000);\n }\n this.fpsFrameCount = 0;\n this.lastFpsTime = now;\n return fps;\n },\n\n reloadROM: function() {\n if (this.romData !== null) {\n this.loadROM(this.romData);\n }\n },\n\n // Loads a ROM file into the CPU and PPU.\n // The ROM file is validated first.\n loadROM: function(data) {\n // Load ROM file:\n this.rom = new ROM(this);\n this.rom.load(data);\n\n this.reset();\n this.mmap = this.rom.createMapper();\n this.mmap.loadROM();\n this.ppu.setMirroring(this.rom.getMirroringType());\n this.romData = data;\n },\n\n setFramerate: function(rate) {\n this.opts.preferredFrameRate = rate;\n this.frameTime = 1000 / rate;\n this.papu.setSampleRate(this.opts.sampleRate, false);\n },\n\n toJSON: function() {\n return {\n romData: this.romData,\n cpu: this.cpu.toJSON(),\n mmap: this.mmap.toJSON(),\n ppu: this.ppu.toJSON()\n };\n },\n\n fromJSON: function(s) {\n this.loadROM(s.romData);\n this.cpu.fromJSON(s.cpu);\n this.mmap.fromJSON(s.mmap);\n this.ppu.fromJSON(s.ppu);\n }\n};\n\nmodule.exports = NES;\n\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar utils = __webpack_require__(0);\n\nvar CPU = function(nes) {\n this.nes = nes;\n\n // Keep Chrome happy\n this.mem = null;\n this.REG_ACC = null;\n this.REG_X = null;\n this.REG_Y = null;\n this.REG_SP = null;\n this.REG_PC = null;\n this.REG_PC_NEW = null;\n this.REG_STATUS = null;\n this.F_CARRY = null;\n this.F_DECIMAL = null;\n this.F_INTERRUPT = null;\n this.F_INTERRUPT_NEW = null;\n this.F_OVERFLOW = null;\n this.F_SIGN = null;\n this.F_ZERO = null;\n this.F_NOTUSED = null;\n this.F_NOTUSED_NEW = null;\n this.F_BRK = null;\n this.F_BRK_NEW = null;\n this.opdata = null;\n this.cyclesToHalt = null;\n this.crash = null;\n this.irqRequested = null;\n this.irqType = null;\n\n this.reset();\n};\n\nCPU.prototype = {\n // IRQ Types\n IRQ_NORMAL: 0,\n IRQ_NMI: 1,\n IRQ_RESET: 2,\n\n reset: function() {\n // Main memory\n this.mem = new Array(0x10000);\n\n for (var i = 0; i < 0x2000; i++) {\n this.mem[i] = 0xff;\n }\n for (var p = 0; p < 4; p++) {\n var j = p * 0x800;\n this.mem[j + 0x008] = 0xf7;\n this.mem[j + 0x009] = 0xef;\n this.mem[j + 0x00a] = 0xdf;\n this.mem[j + 0x00f] = 0xbf;\n }\n for (var k = 0x2001; k < this.mem.length; k++) {\n this.mem[k] = 0;\n }\n\n // CPU Registers:\n this.REG_ACC = 0;\n this.REG_X = 0;\n this.REG_Y = 0;\n // Reset Stack pointer:\n this.REG_SP = 0x01ff;\n // Reset Program counter:\n this.REG_PC = 0x8000 - 1;\n this.REG_PC_NEW = 0x8000 - 1;\n // Reset Status register:\n this.REG_STATUS = 0x28;\n\n this.setStatus(0x28);\n\n // Set flags:\n this.F_CARRY = 0;\n this.F_DECIMAL = 0;\n this.F_INTERRUPT = 1;\n this.F_INTERRUPT_NEW = 1;\n this.F_OVERFLOW = 0;\n this.F_SIGN = 0;\n this.F_ZERO = 1;\n\n this.F_NOTUSED = 1;\n this.F_NOTUSED_NEW = 1;\n this.F_BRK = 1;\n this.F_BRK_NEW = 1;\n\n this.opdata = new OpData().opdata;\n this.cyclesToHalt = 0;\n\n // Reset crash flag:\n this.crash = false;\n\n // Interrupt notification:\n this.irqRequested = false;\n this.irqType = null;\n },\n\n // Emulates a single CPU instruction, returns the number of cycles\n emulate: function() {\n var temp;\n var add;\n\n // Check interrupts:\n if (this.irqRequested) {\n temp =\n this.F_CARRY |\n ((this.F_ZERO === 0 ? 1 : 0) << 1) |\n (this.F_INTERRUPT << 2) |\n (this.F_DECIMAL << 3) |\n (this.F_BRK << 4) |\n (this.F_NOTUSED << 5) |\n (this.F_OVERFLOW << 6) |\n (this.F_SIGN << 7);\n\n this.REG_PC_NEW = this.REG_PC;\n this.F_INTERRUPT_NEW = this.F_INTERRUPT;\n switch (this.irqType) {\n case 0: {\n // Normal IRQ:\n if (this.F_INTERRUPT !== 0) {\n // console.log(\"Interrupt was masked.\");\n break;\n }\n this.doIrq(temp);\n // console.log(\"Did normal IRQ. I=\"+this.F_INTERRUPT);\n break;\n }\n case 1: {\n // NMI:\n this.doNonMaskableInterrupt(temp);\n break;\n }\n case 2: {\n // Reset:\n this.doResetInterrupt();\n break;\n }\n }\n\n this.REG_PC = this.REG_PC_NEW;\n this.F_INTERRUPT = this.F_INTERRUPT_NEW;\n this.F_BRK = this.F_BRK_NEW;\n this.irqRequested = false;\n }\n\n var opinf = this.opdata[this.nes.mmap.load(this.REG_PC + 1)];\n var cycleCount = opinf >> 24;\n var cycleAdd = 0;\n\n // Find address mode:\n var addrMode = (opinf >> 8) & 0xff;\n\n // Increment PC by number of op bytes:\n var opaddr = this.REG_PC;\n this.REG_PC += (opinf >> 16) & 0xff;\n\n var addr = 0;\n switch (addrMode) {\n case 0: {\n // Zero Page mode. Use the address given after the opcode,\n // but without high byte.\n addr = this.load(opaddr + 2);\n break;\n }\n case 1: {\n // Relative mode.\n addr = this.load(opaddr + 2);\n if (addr < 0x80) {\n addr += this.REG_PC;\n } else {\n addr += this.REG_PC - 256;\n }\n break;\n }\n case 2: {\n // Ignore. Address is implied in instruction.\n break;\n }\n case 3: {\n // Absolute mode. Use the two bytes following the opcode as\n // an address.\n addr = this.load16bit(opaddr + 2);\n break;\n }\n case 4: {\n // Accumulator mode. The address is in the accumulator\n // register.\n addr = this.REG_ACC;\n break;\n }\n case 5: {\n // Immediate mode. The value is given after the opcode.\n addr = this.REG_PC;\n break;\n }\n case 6: {\n // Zero Page Indexed mode, X as index. Use the address given\n // after the opcode, then add the\n // X register to it to get the final address.\n addr = (this.load(opaddr + 2) + this.REG_X) & 0xff;\n break;\n }\n case 7: {\n // Zero Page Indexed mode, Y as index. Use the address given\n // after the opcode, then add the\n // Y register to it to get the final address.\n addr = (this.load(opaddr + 2) + this.REG_Y) & 0xff;\n break;\n }\n case 8: {\n // Absolute Indexed Mode, X as index. Same as zero page\n // indexed, but with the high byte.\n addr = this.load16bit(opaddr + 2);\n if ((addr & 0xff00) !== ((addr + this.REG_X) & 0xff00)) {\n cycleAdd = 1;\n }\n addr += this.REG_X;\n break;\n }\n case 9: {\n // Absolute Indexed Mode, Y as index. Same as zero page\n // indexed, but with the high byte.\n addr = this.load16bit(opaddr + 2);\n if ((addr & 0xff00) !== ((addr + this.REG_Y) & 0xff00)) {\n cycleAdd = 1;\n }\n addr += this.REG_Y;\n break;\n }\n case 10: {\n // Pre-indexed Indirect mode. Find the 16-bit address\n // starting at the given location plus\n // the current X register. The value is the contents of that\n // address.\n addr = this.load(opaddr + 2);\n if ((addr & 0xff00) !== ((addr + this.REG_X) & 0xff00)) {\n cycleAdd = 1;\n }\n addr += this.REG_X;\n addr &= 0xff;\n addr = this.load16bit(addr);\n break;\n }\n case 11: {\n // Post-indexed Indirect mode. Find the 16-bit address\n // contained in the given location\n // (and the one following). Add to that address the contents\n // of the Y register. Fetch the value\n // stored at that adress.\n addr = this.load16bit(this.load(opaddr + 2));\n if ((addr & 0xff00) !== ((addr + this.REG_Y) & 0xff00)) {\n cycleAdd = 1;\n }\n addr += this.REG_Y;\n break;\n }\n case 12: {\n // Indirect Absolute mode. Find the 16-bit address contained\n // at the given location.\n addr = this.load16bit(opaddr + 2); // Find op\n if (addr < 0x1fff) {\n addr =\n this.mem[addr] +\n (this.mem[(addr & 0xff00) | (((addr & 0xff) + 1) & 0xff)] << 8); // Read from address given in op\n } else {\n addr =\n this.nes.mmap.load(addr) +\n (this.nes.mmap.load(\n (addr & 0xff00) | (((addr & 0xff) + 1) & 0xff)\n ) <<\n 8);\n }\n break;\n }\n }\n // Wrap around for addresses above 0xFFFF:\n addr &= 0xffff;\n\n // ----------------------------------------------------------------------------------------------------\n // Decode & execute instruction:\n // ----------------------------------------------------------------------------------------------------\n\n // This should be compiled to a jump table.\n switch (opinf & 0xff) {\n case 0: {\n // *******\n // * ADC *\n // *******\n\n // Add with carry.\n temp = this.REG_ACC + this.load(addr) + this.F_CARRY;\n\n if (\n ((this.REG_ACC ^ this.load(addr)) & 0x80) === 0 &&\n ((this.REG_ACC ^ temp) & 0x80) !== 0\n ) {\n this.F_OVERFLOW = 1;\n } else {\n this.F_OVERFLOW = 0;\n }\n this.F_CARRY = temp > 255 ? 1 : 0;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n this.REG_ACC = temp & 255;\n cycleCount += cycleAdd;\n break;\n }\n case 1: {\n // *******\n // * AND *\n // *******\n\n // AND memory with accumulator.\n this.REG_ACC = this.REG_ACC & this.load(addr);\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n //this.REG_ACC = temp;\n if (addrMode !== 11) cycleCount += cycleAdd; // PostIdxInd = 11\n break;\n }\n case 2: {\n // *******\n // * ASL *\n // *******\n\n // Shift left one bit\n if (addrMode === 4) {\n // ADDR_ACC = 4\n\n this.F_CARRY = (this.REG_ACC >> 7) & 1;\n this.REG_ACC = (this.REG_ACC << 1) & 255;\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n } else {\n temp = this.load(addr);\n this.F_CARRY = (temp >> 7) & 1;\n temp = (temp << 1) & 255;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n this.write(addr, temp);\n }\n break;\n }\n case 3: {\n // *******\n // * BCC *\n // *******\n\n // Branch on carry clear\n if (this.F_CARRY === 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 4: {\n // *******\n // * BCS *\n // *******\n\n // Branch on carry set\n if (this.F_CARRY === 1) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 5: {\n // *******\n // * BEQ *\n // *******\n\n // Branch on zero\n if (this.F_ZERO === 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 6: {\n // *******\n // * BIT *\n // *******\n\n temp = this.load(addr);\n this.F_SIGN = (temp >> 7) & 1;\n this.F_OVERFLOW = (temp >> 6) & 1;\n temp &= this.REG_ACC;\n this.F_ZERO = temp;\n break;\n }\n case 7: {\n // *******\n // * BMI *\n // *******\n\n // Branch on negative result\n if (this.F_SIGN === 1) {\n cycleCount++;\n this.REG_PC = addr;\n }\n break;\n }\n case 8: {\n // *******\n // * BNE *\n // *******\n\n // Branch on not zero\n if (this.F_ZERO !== 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 9: {\n // *******\n // * BPL *\n // *******\n\n // Branch on positive result\n if (this.F_SIGN === 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 10: {\n // *******\n // * BRK *\n // *******\n\n this.REG_PC += 2;\n this.push((this.REG_PC >> 8) & 255);\n this.push(this.REG_PC & 255);\n this.F_BRK = 1;\n\n this.push(\n this.F_CARRY |\n ((this.F_ZERO === 0 ? 1 : 0) << 1) |\n (this.F_INTERRUPT << 2) |\n (this.F_DECIMAL << 3) |\n (this.F_BRK << 4) |\n (this.F_NOTUSED << 5) |\n (this.F_OVERFLOW << 6) |\n (this.F_SIGN << 7)\n );\n\n this.F_INTERRUPT = 1;\n //this.REG_PC = load(0xFFFE) | (load(0xFFFF) << 8);\n this.REG_PC = this.load16bit(0xfffe);\n this.REG_PC--;\n break;\n }\n case 11: {\n // *******\n // * BVC *\n // *******\n\n // Branch on overflow clear\n if (this.F_OVERFLOW === 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 12: {\n // *******\n // * BVS *\n // *******\n\n // Branch on overflow set\n if (this.F_OVERFLOW === 1) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 13: {\n // *******\n // * CLC *\n // *******\n\n // Clear carry flag\n this.F_CARRY = 0;\n break;\n }\n case 14: {\n // *******\n // * CLD *\n // *******\n\n // Clear decimal flag\n this.F_DECIMAL = 0;\n break;\n }\n case 15: {\n // *******\n // * CLI *\n // *******\n\n // Clear interrupt flag\n this.F_INTERRUPT = 0;\n break;\n }\n case 16: {\n // *******\n // * CLV *\n // *******\n\n // Clear overflow flag\n this.F_OVERFLOW = 0;\n break;\n }\n case 17: {\n // *******\n // * CMP *\n // *******\n\n // Compare memory and accumulator:\n temp = this.REG_ACC - this.load(addr);\n this.F_CARRY = temp >= 0 ? 1 : 0;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n cycleCount += cycleAdd;\n break;\n }\n case 18: {\n // *******\n // * CPX *\n // *******\n\n // Compare memory and index X:\n temp = this.REG_X - this.load(addr);\n this.F_CARRY = temp >= 0 ? 1 : 0;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n break;\n }\n case 19: {\n // *******\n // * CPY *\n // *******\n\n // Compare memory and index Y:\n temp = this.REG_Y - this.load(addr);\n this.F_CARRY = temp >= 0 ? 1 : 0;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n break;\n }\n case 20: {\n // *******\n // * DEC *\n // *******\n\n // Decrement memory by one:\n temp = (this.load(addr) - 1) & 0xff;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n this.write(addr, temp);\n break;\n }\n case 21: {\n // *******\n // * DEX *\n // *******\n\n // Decrement index X by one:\n this.REG_X = (this.REG_X - 1) & 0xff;\n this.F_SIGN = (this.REG_X >> 7) & 1;\n this.F_ZERO = this.REG_X;\n break;\n }\n case 22: {\n // *******\n // * DEY *\n // *******\n\n // Decrement index Y by one:\n this.REG_Y = (this.REG_Y - 1) & 0xff;\n this.F_SIGN = (this.REG_Y >> 7) & 1;\n this.F_ZERO = this.REG_Y;\n break;\n }\n case 23: {\n // *******\n // * EOR *\n // *******\n\n // XOR Memory with accumulator, store in accumulator:\n this.REG_ACC = (this.load(addr) ^ this.REG_ACC) & 0xff;\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n cycleCount += cycleAdd;\n break;\n }\n case 24: {\n // *******\n // * INC *\n // *******\n\n // Increment memory by one:\n temp = (this.load(addr) + 1) & 0xff;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n this.write(addr, temp & 0xff);\n break;\n }\n case 25: {\n // *******\n // * INX *\n // *******\n\n // Increment index X by one:\n this.REG_X = (this.REG_X + 1) & 0xff;\n this.F_SIGN = (this.REG_X >> 7) & 1;\n this.F_ZERO = this.REG_X;\n break;\n }\n case 26: {\n // *******\n // * INY *\n // *******\n\n // Increment index Y by one:\n this.REG_Y++;\n this.REG_Y &= 0xff;\n this.F_SIGN = (this.REG_Y >> 7) & 1;\n this.F_ZERO = this.REG_Y;\n break;\n }\n case 27: {\n // *******\n // * JMP *\n // *******\n\n // Jump to new location:\n this.REG_PC = addr - 1;\n break;\n }\n case 28: {\n // *******\n // * JSR *\n // *******\n\n // Jump to new location, saving return address.\n // Push return address on stack:\n this.push((this.REG_PC >> 8) & 255);\n this.push(this.REG_PC & 255);\n this.REG_PC = addr - 1;\n break;\n }\n case 29: {\n // *******\n // * LDA *\n // *******\n\n // Load accumulator with memory:\n this.REG_ACC = this.load(addr);\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n cycleCount += cycleAdd;\n break;\n }\n case 30: {\n // *******\n // * LDX *\n // *******\n\n // Load index X with memory:\n this.REG_X = this.load(addr);\n this.F_SIGN = (this.REG_X >> 7) & 1;\n this.F_ZERO = this.REG_X;\n cycleCount += cycleAdd;\n break;\n }\n case 31: {\n // *******\n // * LDY *\n // *******\n\n // Load index Y with memory:\n this.REG_Y = this.load(addr);\n this.F_SIGN = (this.REG_Y >> 7) & 1;\n this.F_ZERO = this.REG_Y;\n cycleCount += cycleAdd;\n break;\n }\n case 32: {\n // *******\n // * LSR *\n // *******\n\n // Shift right one bit:\n if (addrMode === 4) {\n // ADDR_ACC\n\n temp = this.REG_ACC & 0xff;\n this.F_CARRY = temp & 1;\n temp >>= 1;\n this.REG_ACC = temp;\n } else {\n temp = this.load(addr) & 0xff;\n this.F_CARRY = temp & 1;\n temp >>= 1;\n this.write(addr, temp);\n }\n this.F_SIGN = 0;\n this.F_ZERO = temp;\n break;\n }\n case 33: {\n // *******\n // * NOP *\n // *******\n\n // No OPeration.\n // Ignore.\n break;\n }\n case 34: {\n // *******\n // * ORA *\n // *******\n\n // OR memory with accumulator, store in accumulator.\n temp = (this.load(addr) | this.REG_ACC) & 255;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n this.REG_ACC = temp;\n if (addrMode !== 11) cycleCount += cycleAdd; // PostIdxInd = 11\n break;\n }\n case 35: {\n // *******\n // * PHA *\n // *******\n\n // Push accumulator on stack\n this.push(this.REG_ACC);\n break;\n }\n case 36: {\n // *******\n // * PHP *\n // *******\n\n // Push processor status on stack\n this.F_BRK = 1;\n this.push(\n this.F_CARRY |\n ((this.F_ZERO === 0 ? 1 : 0) << 1) |\n (this.F_INTERRUPT << 2) |\n (this.F_DECIMAL << 3) |\n (this.F_BRK << 4) |\n (this.F_NOTUSED << 5) |\n (this.F_OVERFLOW << 6) |\n (this.F_SIGN << 7)\n );\n break;\n }\n case 37: {\n // *******\n // * PLA *\n // *******\n\n // Pull accumulator from stack\n this.REG_ACC = this.pull();\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n break;\n }\n case 38: {\n // *******\n // * PLP *\n // *******\n\n // Pull processor status from stack\n temp = this.pull();\n this.F_CARRY = temp & 1;\n this.F_ZERO = ((temp >> 1) & 1) === 1 ? 0 : 1;\n this.F_INTERRUPT = (temp >> 2) & 1;\n this.F_DECIMAL = (temp >> 3) & 1;\n this.F_BRK = (temp >> 4) & 1;\n this.F_NOTUSED = (temp >> 5) & 1;\n this.F_OVERFLOW = (temp >> 6) & 1;\n this.F_SIGN = (temp >> 7) & 1;\n\n this.F_NOTUSED = 1;\n break;\n }\n case 39: {\n // *******\n // * ROL *\n // *******\n\n // Rotate one bit left\n if (addrMode === 4) {\n // ADDR_ACC = 4\n\n temp = this.REG_ACC;\n add = this.F_CARRY;\n this.F_CARRY = (temp >> 7) & 1;\n temp = ((temp << 1) & 0xff) + add;\n this.REG_ACC = temp;\n } else {\n temp = this.load(addr);\n add = this.F_CARRY;\n this.F_CARRY = (temp >> 7) & 1;\n temp = ((temp << 1) & 0xff) + add;\n this.write(addr, temp);\n }\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n break;\n }\n case 40: {\n // *******\n // * ROR *\n // *******\n\n // Rotate one bit right\n if (addrMode === 4) {\n // ADDR_ACC = 4\n\n add = this.F_CARRY << 7;\n this.F_CARRY = this.REG_ACC & 1;\n temp = (this.REG_ACC >> 1) + add;\n this.REG_ACC = temp;\n } else {\n temp = this.load(addr);\n add = this.F_CARRY << 7;\n this.F_CARRY = temp & 1;\n temp = (temp >> 1) + add;\n this.write(addr, temp);\n }\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n break;\n }\n case 41: {\n // *******\n // * RTI *\n // *******\n\n // Return from interrupt. Pull status and PC from stack.\n\n temp = this.pull();\n this.F_CARRY = temp & 1;\n this.F_ZERO = ((temp >> 1) & 1) === 0 ? 1 : 0;\n this.F_INTERRUPT = (temp >> 2) & 1;\n this.F_DECIMAL = (temp >> 3) & 1;\n this.F_BRK = (temp >> 4) & 1;\n this.F_NOTUSED = (temp >> 5) & 1;\n this.F_OVERFLOW = (temp >> 6) & 1;\n this.F_SIGN = (temp >> 7) & 1;\n\n this.REG_PC = this.pull();\n this.REG_PC += this.pull() << 8;\n if (this.REG_PC === 0xffff) {\n return;\n }\n this.REG_PC--;\n this.F_NOTUSED = 1;\n break;\n }\n case 42: {\n // *******\n // * RTS *\n // *******\n\n // Return from subroutine. Pull PC from stack.\n\n this.REG_PC = this.pull();\n this.REG_PC += this.pull() << 8;\n\n if (this.REG_PC === 0xffff) {\n return; // return from NSF play routine:\n }\n break;\n }\n case 43: {\n // *******\n // * SBC *\n // *******\n\n temp = this.REG_ACC - this.load(addr) - (1 - this.F_CARRY);\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n if (\n ((this.REG_ACC ^ temp) & 0x80) !== 0 &&\n ((this.REG_ACC ^ this.load(addr)) & 0x80) !== 0\n ) {\n this.F_OVERFLOW = 1;\n } else {\n this.F_OVERFLOW = 0;\n }\n this.F_CARRY = temp < 0 ? 0 : 1;\n this.REG_ACC = temp & 0xff;\n if (addrMode !== 11) cycleCount += cycleAdd; // PostIdxInd = 11\n break;\n }\n case 44: {\n // *******\n // * SEC *\n // *******\n\n // Set carry flag\n this.F_CARRY = 1;\n break;\n }\n case 45: {\n // *******\n // * SED *\n // *******\n\n // Set decimal mode\n this.F_DECIMAL = 1;\n break;\n }\n case 46: {\n // *******\n // * SEI *\n // *******\n\n // Set interrupt disable status\n this.F_INTERRUPT = 1;\n break;\n }\n case 47: {\n // *******\n // * STA *\n // *******\n\n // Store accumulator in memory\n this.write(addr, this.REG_ACC);\n break;\n }\n case 48: {\n // *******\n // * STX *\n // *******\n\n // Store index X in memory\n this.write(addr, this.REG_X);\n break;\n }\n case 49: {\n // *******\n // * STY *\n // *******\n\n // Store index Y in memory:\n this.write(addr, this.REG_Y);\n break;\n }\n case 50: {\n // *******\n // * TAX *\n // *******\n\n // Transfer accumulator to index X:\n this.REG_X = this.REG_ACC;\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n break;\n }\n case 51: {\n // *******\n // * TAY *\n // *******\n\n // Transfer accumulator to index Y:\n this.REG_Y = this.REG_ACC;\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n break;\n }\n case 52: {\n // *******\n // * TSX *\n // *******\n\n // Transfer stack pointer to index X:\n this.REG_X = this.REG_SP - 0x0100;\n this.F_SIGN = (this.REG_SP >> 7) & 1;\n this.F_ZERO = this.REG_X;\n break;\n }\n case 53: {\n // *******\n // * TXA *\n // *******\n\n // Transfer index X to accumulator:\n this.REG_ACC = this.REG_X;\n this.F_SIGN = (this.REG_X >> 7) & 1;\n this.F_ZERO = this.REG_X;\n break;\n }\n case 54: {\n // *******\n // * TXS *\n // *******\n\n // Transfer index X to stack pointer:\n this.REG_SP = this.REG_X + 0x0100;\n this.stackWrap();\n break;\n }\n case 55: {\n // *******\n // * TYA *\n // *******\n\n // Transfer index Y to accumulator:\n this.REG_ACC = this.REG_Y;\n this.F_SIGN = (this.REG_Y >> 7) & 1;\n this.F_ZERO = this.REG_Y;\n break;\n }\n default: {\n // *******\n // * ??? *\n // *******\n\n this.nes.stop();\n this.nes.crashMessage =\n \"Game crashed, invalid opcode at address $\" + opaddr.toString(16);\n break;\n }\n } // end of switch\n\n return cycleCount;\n },\n\n load: function(addr) {\n if (addr < 0x2000) {\n return this.mem[addr & 0x7ff];\n } else {\n return this.nes.mmap.load(addr);\n }\n },\n\n load16bit: function(addr) {\n if (addr < 0x1fff) {\n return this.mem[addr & 0x7ff] | (this.mem[(addr + 1) & 0x7ff] << 8);\n } else {\n return this.nes.mmap.load(addr) | (this.nes.mmap.load(addr + 1) << 8);\n }\n },\n\n write: function(addr, val) {\n if (addr < 0x2000) {\n this.mem[addr & 0x7ff] = val;\n } else {\n this.nes.mmap.write(addr, val);\n }\n },\n\n requestIrq: function(type) {\n if (this.irqRequested) {\n if (type === this.IRQ_NORMAL) {\n return;\n }\n // console.log(\"too fast irqs. type=\"+type);\n }\n this.irqRequested = true;\n this.irqType = type;\n },\n\n push: function(value) {\n this.nes.mmap.write(this.REG_SP, value);\n this.REG_SP--;\n this.REG_SP = 0x0100 | (this.REG_SP & 0xff);\n },\n\n stackWrap: function() {\n this.REG_SP = 0x0100 | (this.REG_SP & 0xff);\n },\n\n pull: function() {\n this.REG_SP++;\n this.REG_SP = 0x0100 | (this.REG_SP & 0xff);\n return this.nes.mmap.load(this.REG_SP);\n },\n\n pageCrossed: function(addr1, addr2) {\n return (addr1 & 0xff00) !== (addr2 & 0xff00);\n },\n\n haltCycles: function(cycles) {\n this.cyclesToHalt += cycles;\n },\n\n doNonMaskableInterrupt: function(status) {\n if ((this.nes.mmap.load(0x2000) & 128) !== 0) {\n // Check whether VBlank Interrupts are enabled\n\n this.REG_PC_NEW++;\n this.push((this.REG_PC_NEW >> 8) & 0xff);\n this.push(this.REG_PC_NEW & 0xff);\n //this.F_INTERRUPT_NEW = 1;\n this.push(status);\n\n this.REG_PC_NEW =\n this.nes.mmap.load(0xfffa) | (this.nes.mmap.load(0xfffb) << 8);\n this.REG_PC_NEW--;\n }\n },\n\n doResetInterrupt: function() {\n this.REG_PC_NEW =\n this.nes.mmap.load(0xfffc) | (this.nes.mmap.load(0xfffd) << 8);\n this.REG_PC_NEW--;\n },\n\n doIrq: function(status) {\n this.REG_PC_NEW++;\n this.push((this.REG_PC_NEW >> 8) & 0xff);\n this.push(this.REG_PC_NEW & 0xff);\n this.push(status);\n this.F_INTERRUPT_NEW = 1;\n this.F_BRK_NEW = 0;\n\n this.REG_PC_NEW =\n this.nes.mmap.load(0xfffe) | (this.nes.mmap.load(0xffff) << 8);\n this.REG_PC_NEW--;\n },\n\n getStatus: function() {\n return (\n this.F_CARRY |\n (this.F_ZERO << 1) |\n (this.F_INTERRUPT << 2) |\n (this.F_DECIMAL << 3) |\n (this.F_BRK << 4) |\n (this.F_NOTUSED << 5) |\n (this.F_OVERFLOW << 6) |\n (this.F_SIGN << 7)\n );\n },\n\n setStatus: function(st) {\n this.F_CARRY = st & 1;\n this.F_ZERO = (st >> 1) & 1;\n this.F_INTERRUPT = (st >> 2) & 1;\n this.F_DECIMAL = (st >> 3) & 1;\n this.F_BRK = (st >> 4) & 1;\n this.F_NOTUSED = (st >> 5) & 1;\n this.F_OVERFLOW = (st >> 6) & 1;\n this.F_SIGN = (st >> 7) & 1;\n },\n\n JSON_PROPERTIES: [\n \"mem\",\n \"cyclesToHalt\",\n \"irqRequested\",\n \"irqType\",\n // Registers\n \"REG_ACC\",\n \"REG_X\",\n \"REG_Y\",\n \"REG_SP\",\n \"REG_PC\",\n \"REG_PC_NEW\",\n \"REG_STATUS\",\n // Status\n \"F_CARRY\",\n \"F_DECIMAL\",\n \"F_INTERRUPT\",\n \"F_INTERRUPT_NEW\",\n \"F_OVERFLOW\",\n \"F_SIGN\",\n \"F_ZERO\",\n \"F_NOTUSED\",\n \"F_NOTUSED_NEW\",\n \"F_BRK\",\n \"F_BRK_NEW\"\n ],\n\n toJSON: function() {\n return utils.toJSON(this);\n },\n\n fromJSON: function(s) {\n utils.fromJSON(this, s);\n }\n};\n\n// Generates and provides an array of details about instructions\nvar OpData = function() {\n this.opdata = new Array(256);\n\n // Set all to invalid instruction (to detect crashes):\n for (var i = 0; i < 256; i++) this.opdata[i] = 0xff;\n\n // Now fill in all valid opcodes:\n\n // ADC:\n this.setOp(this.INS_ADC, 0x69, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_ADC, 0x65, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_ADC, 0x75, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_ADC, 0x6d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_ADC, 0x7d, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_ADC, 0x79, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_ADC, 0x61, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_ADC, 0x71, this.ADDR_POSTIDXIND, 2, 5);\n\n // AND:\n this.setOp(this.INS_AND, 0x29, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_AND, 0x25, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_AND, 0x35, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_AND, 0x2d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_AND, 0x3d, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_AND, 0x39, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_AND, 0x21, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_AND, 0x31, this.ADDR_POSTIDXIND, 2, 5);\n\n // ASL:\n this.setOp(this.INS_ASL, 0x0a, this.ADDR_ACC, 1, 2);\n this.setOp(this.INS_ASL, 0x06, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_ASL, 0x16, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_ASL, 0x0e, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_ASL, 0x1e, this.ADDR_ABSX, 3, 7);\n\n // BCC:\n this.setOp(this.INS_BCC, 0x90, this.ADDR_REL, 2, 2);\n\n // BCS:\n this.setOp(this.INS_BCS, 0xb0, this.ADDR_REL, 2, 2);\n\n // BEQ:\n this.setOp(this.INS_BEQ, 0xf0, this.ADDR_REL, 2, 2);\n\n // BIT:\n this.setOp(this.INS_BIT, 0x24, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_BIT, 0x2c, this.ADDR_ABS, 3, 4);\n\n // BMI:\n this.setOp(this.INS_BMI, 0x30, this.ADDR_REL, 2, 2);\n\n // BNE:\n this.setOp(this.INS_BNE, 0xd0, this.ADDR_REL, 2, 2);\n\n // BPL:\n this.setOp(this.INS_BPL, 0x10, this.ADDR_REL, 2, 2);\n\n // BRK:\n this.setOp(this.INS_BRK, 0x00, this.ADDR_IMP, 1, 7);\n\n // BVC:\n this.setOp(this.INS_BVC, 0x50, this.ADDR_REL, 2, 2);\n\n // BVS:\n this.setOp(this.INS_BVS, 0x70, this.ADDR_REL, 2, 2);\n\n // CLC:\n this.setOp(this.INS_CLC, 0x18, this.ADDR_IMP, 1, 2);\n\n // CLD:\n this.setOp(this.INS_CLD, 0xd8, this.ADDR_IMP, 1, 2);\n\n // CLI:\n this.setOp(this.INS_CLI, 0x58, this.ADDR_IMP, 1, 2);\n\n // CLV:\n this.setOp(this.INS_CLV, 0xb8, this.ADDR_IMP, 1, 2);\n\n // CMP:\n this.setOp(this.INS_CMP, 0xc9, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_CMP, 0xc5, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_CMP, 0xd5, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_CMP, 0xcd, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_CMP, 0xdd, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_CMP, 0xd9, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_CMP, 0xc1, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_CMP, 0xd1, this.ADDR_POSTIDXIND, 2, 5);\n\n // CPX:\n this.setOp(this.INS_CPX, 0xe0, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_CPX, 0xe4, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_CPX, 0xec, this.ADDR_ABS, 3, 4);\n\n // CPY:\n this.setOp(this.INS_CPY, 0xc0, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_CPY, 0xc4, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_CPY, 0xcc, this.ADDR_ABS, 3, 4);\n\n // DEC:\n this.setOp(this.INS_DEC, 0xc6, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_DEC, 0xd6, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_DEC, 0xce, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_DEC, 0xde, this.ADDR_ABSX, 3, 7);\n\n // DEX:\n this.setOp(this.INS_DEX, 0xca, this.ADDR_IMP, 1, 2);\n\n // DEY:\n this.setOp(this.INS_DEY, 0x88, this.ADDR_IMP, 1, 2);\n\n // EOR:\n this.setOp(this.INS_EOR, 0x49, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_EOR, 0x45, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_EOR, 0x55, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_EOR, 0x4d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_EOR, 0x5d, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_EOR, 0x59, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_EOR, 0x41, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_EOR, 0x51, this.ADDR_POSTIDXIND, 2, 5);\n\n // INC:\n this.setOp(this.INS_INC, 0xe6, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_INC, 0xf6, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_INC, 0xee, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_INC, 0xfe, this.ADDR_ABSX, 3, 7);\n\n // INX:\n this.setOp(this.INS_INX, 0xe8, this.ADDR_IMP, 1, 2);\n\n // INY:\n this.setOp(this.INS_INY, 0xc8, this.ADDR_IMP, 1, 2);\n\n // JMP:\n this.setOp(this.INS_JMP, 0x4c, this.ADDR_ABS, 3, 3);\n this.setOp(this.INS_JMP, 0x6c, this.ADDR_INDABS, 3, 5);\n\n // JSR:\n this.setOp(this.INS_JSR, 0x20, this.ADDR_ABS, 3, 6);\n\n // LDA:\n this.setOp(this.INS_LDA, 0xa9, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_LDA, 0xa5, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_LDA, 0xb5, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_LDA, 0xad, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_LDA, 0xbd, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_LDA, 0xb9, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_LDA, 0xa1, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_LDA, 0xb1, this.ADDR_POSTIDXIND, 2, 5);\n\n // LDX:\n this.setOp(this.INS_LDX, 0xa2, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_LDX, 0xa6, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_LDX, 0xb6, this.ADDR_ZPY, 2, 4);\n this.setOp(this.INS_LDX, 0xae, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_LDX, 0xbe, this.ADDR_ABSY, 3, 4);\n\n // LDY:\n this.setOp(this.INS_LDY, 0xa0, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_LDY, 0xa4, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_LDY, 0xb4, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_LDY, 0xac, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_LDY, 0xbc, this.ADDR_ABSX, 3, 4);\n\n // LSR:\n this.setOp(this.INS_LSR, 0x4a, this.ADDR_ACC, 1, 2);\n this.setOp(this.INS_LSR, 0x46, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_LSR, 0x56, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_LSR, 0x4e, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_LSR, 0x5e, this.ADDR_ABSX, 3, 7);\n\n // NOP:\n this.setOp(this.INS_NOP, 0xea, this.ADDR_IMP, 1, 2);\n\n // ORA:\n this.setOp(this.INS_ORA, 0x09, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_ORA, 0x05, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_ORA, 0x15, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_ORA, 0x0d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_ORA, 0x1d, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_ORA, 0x19, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_ORA, 0x01, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_ORA, 0x11, this.ADDR_POSTIDXIND, 2, 5);\n\n // PHA:\n this.setOp(this.INS_PHA, 0x48, this.ADDR_IMP, 1, 3);\n\n // PHP:\n this.setOp(this.INS_PHP, 0x08, this.ADDR_IMP, 1, 3);\n\n // PLA:\n this.setOp(this.INS_PLA, 0x68, this.ADDR_IMP, 1, 4);\n\n // PLP:\n this.setOp(this.INS_PLP, 0x28, this.ADDR_IMP, 1, 4);\n\n // ROL:\n this.setOp(this.INS_ROL, 0x2a, this.ADDR_ACC, 1, 2);\n this.setOp(this.INS_ROL, 0x26, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_ROL, 0x36, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_ROL, 0x2e, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_ROL, 0x3e, this.ADDR_ABSX, 3, 7);\n\n // ROR:\n this.setOp(this.INS_ROR, 0x6a, this.ADDR_ACC, 1, 2);\n this.setOp(this.INS_ROR, 0x66, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_ROR, 0x76, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_ROR, 0x6e, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_ROR, 0x7e, this.ADDR_ABSX, 3, 7);\n\n // RTI:\n this.setOp(this.INS_RTI, 0x40, this.ADDR_IMP, 1, 6);\n\n // RTS:\n this.setOp(this.INS_RTS, 0x60, this.ADDR_IMP, 1, 6);\n\n // SBC:\n this.setOp(this.INS_SBC, 0xe9, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_SBC, 0xe5, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_SBC, 0xf5, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_SBC, 0xed, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_SBC, 0xfd, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_SBC, 0xf9, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_SBC, 0xe1, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_SBC, 0xf1, this.ADDR_POSTIDXIND, 2, 5);\n\n // SEC:\n this.setOp(this.INS_SEC, 0x38, this.ADDR_IMP, 1, 2);\n\n // SED:\n this.setOp(this.INS_SED, 0xf8, this.ADDR_IMP, 1, 2);\n\n // SEI:\n this.setOp(this.INS_SEI, 0x78, this.ADDR_IMP, 1, 2);\n\n // STA:\n this.setOp(this.INS_STA, 0x85, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_STA, 0x95, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_STA, 0x8d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_STA, 0x9d, this.ADDR_ABSX, 3, 5);\n this.setOp(this.INS_STA, 0x99, this.ADDR_ABSY, 3, 5);\n this.setOp(this.INS_STA, 0x81, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_STA, 0x91, this.ADDR_POSTIDXIND, 2, 6);\n\n // STX:\n this.setOp(this.INS_STX, 0x86, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_STX, 0x96, this.ADDR_ZPY, 2, 4);\n this.setOp(this.INS_STX, 0x8e, this.ADDR_ABS, 3, 4);\n\n // STY:\n this.setOp(this.INS_STY, 0x84, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_STY, 0x94, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_STY, 0x8c, this.ADDR_ABS, 3, 4);\n\n // TAX:\n this.setOp(this.INS_TAX, 0xaa, this.ADDR_IMP, 1, 2);\n\n // TAY:\n this.setOp(this.INS_TAY, 0xa8, this.ADDR_IMP, 1, 2);\n\n // TSX:\n this.setOp(this.INS_TSX, 0xba, this.ADDR_IMP, 1, 2);\n\n // TXA:\n this.setOp(this.INS_TXA, 0x8a, this.ADDR_IMP, 1, 2);\n\n // TXS:\n this.setOp(this.INS_TXS, 0x9a, this.ADDR_IMP, 1, 2);\n\n // TYA:\n this.setOp(this.INS_TYA, 0x98, this.ADDR_IMP, 1, 2);\n\n // prettier-ignore\n this.cycTable = new Array(\n /*0x00*/ 7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,\n /*0x10*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0x20*/ 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,\n /*0x30*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0x40*/ 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,\n /*0x50*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0x60*/ 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,\n /*0x70*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0x80*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,\n /*0x90*/ 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,\n /*0xA0*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,\n /*0xB0*/ 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,\n /*0xC0*/ 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,\n /*0xD0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0xE0*/ 2,6,3,8,3,3,5,5,2,2,2,2,4,4,6,6,\n /*0xF0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7\n );\n\n this.instname = new Array(56);\n\n // Instruction Names:\n this.instname[0] = \"ADC\";\n this.instname[1] = \"AND\";\n this.instname[2] = \"ASL\";\n this.instname[3] = \"BCC\";\n this.instname[4] = \"BCS\";\n this.instname[5] = \"BEQ\";\n this.instname[6] = \"BIT\";\n this.instname[7] = \"BMI\";\n this.instname[8] = \"BNE\";\n this.instname[9] = \"BPL\";\n this.instname[10] = \"BRK\";\n this.instname[11] = \"BVC\";\n this.instname[12] = \"BVS\";\n this.instname[13] = \"CLC\";\n this.instname[14] = \"CLD\";\n this.instname[15] = \"CLI\";\n this.instname[16] = \"CLV\";\n this.instname[17] = \"CMP\";\n this.instname[18] = \"CPX\";\n this.instname[19] = \"CPY\";\n this.instname[20] = \"DEC\";\n this.instname[21] = \"DEX\";\n this.instname[22] = \"DEY\";\n this.instname[23] = \"EOR\";\n this.instname[24] = \"INC\";\n this.instname[25] = \"INX\";\n this.instname[26] = \"INY\";\n this.instname[27] = \"JMP\";\n this.instname[28] = \"JSR\";\n this.instname[29] = \"LDA\";\n this.instname[30] = \"LDX\";\n this.instname[31] = \"LDY\";\n this.instname[32] = \"LSR\";\n this.instname[33] = \"NOP\";\n this.instname[34] = \"ORA\";\n this.instname[35] = \"PHA\";\n this.instname[36] = \"PHP\";\n this.instname[37] = \"PLA\";\n this.instname[38] = \"PLP\";\n this.instname[39] = \"ROL\";\n this.instname[40] = \"ROR\";\n this.instname[41] = \"RTI\";\n this.instname[42] = \"RTS\";\n this.instname[43] = \"SBC\";\n this.instname[44] = \"SEC\";\n this.instname[45] = \"SED\";\n this.instname[46] = \"SEI\";\n this.instname[47] = \"STA\";\n this.instname[48] = \"STX\";\n this.instname[49] = \"STY\";\n this.instname[50] = \"TAX\";\n this.instname[51] = \"TAY\";\n this.instname[52] = \"TSX\";\n this.instname[53] = \"TXA\";\n this.instname[54] = \"TXS\";\n this.instname[55] = \"TYA\";\n\n this.addrDesc = new Array(\n \"Zero Page \",\n \"Relative \",\n \"Implied \",\n \"Absolute \",\n \"Accumulator \",\n \"Immediate \",\n \"Zero Page,X \",\n \"Zero Page,Y \",\n \"Absolute,X \",\n \"Absolute,Y \",\n \"Preindexed Indirect \",\n \"Postindexed Indirect\",\n \"Indirect Absolute \"\n );\n};\n\nOpData.prototype = {\n INS_ADC: 0,\n INS_AND: 1,\n INS_ASL: 2,\n\n INS_BCC: 3,\n INS_BCS: 4,\n INS_BEQ: 5,\n INS_BIT: 6,\n INS_BMI: 7,\n INS_BNE: 8,\n INS_BPL: 9,\n INS_BRK: 10,\n INS_BVC: 11,\n INS_BVS: 12,\n\n INS_CLC: 13,\n INS_CLD: 14,\n INS_CLI: 15,\n INS_CLV: 16,\n INS_CMP: 17,\n INS_CPX: 18,\n INS_CPY: 19,\n\n INS_DEC: 20,\n INS_DEX: 21,\n INS_DEY: 22,\n\n INS_EOR: 23,\n\n INS_INC: 24,\n INS_INX: 25,\n INS_INY: 26,\n\n INS_JMP: 27,\n INS_JSR: 28,\n\n INS_LDA: 29,\n INS_LDX: 30,\n INS_LDY: 31,\n INS_LSR: 32,\n\n INS_NOP: 33,\n\n INS_ORA: 34,\n\n INS_PHA: 35,\n INS_PHP: 36,\n INS_PLA: 37,\n INS_PLP: 38,\n\n INS_ROL: 39,\n INS_ROR: 40,\n INS_RTI: 41,\n INS_RTS: 42,\n\n INS_SBC: 43,\n INS_SEC: 44,\n INS_SED: 45,\n INS_SEI: 46,\n INS_STA: 47,\n INS_STX: 48,\n INS_STY: 49,\n\n INS_TAX: 50,\n INS_TAY: 51,\n INS_TSX: 52,\n INS_TXA: 53,\n INS_TXS: 54,\n INS_TYA: 55,\n\n INS_DUMMY: 56, // dummy instruction used for 'halting' the processor some cycles\n\n // -------------------------------- //\n\n // Addressing modes:\n ADDR_ZP: 0,\n ADDR_REL: 1,\n ADDR_IMP: 2,\n ADDR_ABS: 3,\n ADDR_ACC: 4,\n ADDR_IMM: 5,\n ADDR_ZPX: 6,\n ADDR_ZPY: 7,\n ADDR_ABSX: 8,\n ADDR_ABSY: 9,\n ADDR_PREIDXIND: 10,\n ADDR_POSTIDXIND: 11,\n ADDR_INDABS: 12,\n\n setOp: function(inst, op, addr, size, cycles) {\n this.opdata[op] =\n (inst & 0xff) |\n ((addr & 0xff) << 8) |\n ((size & 0xff) << 16) |\n ((cycles & 0xff) << 24);\n }\n};\n\nmodule.exports = CPU;\n\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar Tile = __webpack_require__(2);\nvar utils = __webpack_require__(0);\n\nvar PPU = function(nes) {\n this.nes = nes;\n\n // Keep Chrome happy\n this.vramMem = null;\n this.spriteMem = null;\n this.vramAddress = null;\n this.vramTmpAddress = null;\n this.vramBufferedReadValue = null;\n this.firstWrite = null;\n this.sramAddress = null;\n this.currentMirroring = null;\n this.requestEndFrame = null;\n this.nmiOk = null;\n this.dummyCycleToggle = null;\n this.validTileData = null;\n this.nmiCounter = null;\n this.scanlineAlreadyRendered = null;\n this.f_nmiOnVblank = null;\n this.f_spriteSize = null;\n this.f_bgPatternTable = null;\n this.f_spPatternTable = null;\n this.f_addrInc = null;\n this.f_nTblAddress = null;\n this.f_color = null;\n this.f_spVisibility = null;\n this.f_bgVisibility = null;\n this.f_spClipping = null;\n this.f_bgClipping = null;\n this.f_dispType = null;\n this.cntFV = null;\n this.cntV = null;\n this.cntH = null;\n this.cntVT = null;\n this.cntHT = null;\n this.regFV = null;\n this.regV = null;\n this.regH = null;\n this.regVT = null;\n this.regHT = null;\n this.regFH = null;\n this.regS = null;\n this.curNt = null;\n this.attrib = null;\n this.buffer = null;\n this.bgbuffer = null;\n this.pixrendered = null;\n\n this.validTileData = null;\n this.scantile = null;\n this.scanline = null;\n this.lastRenderedScanline = null;\n this.curX = null;\n this.sprX = null;\n this.sprY = null;\n this.sprTile = null;\n this.sprCol = null;\n this.vertFlip = null;\n this.horiFlip = null;\n this.bgPriority = null;\n this.spr0HitX = null;\n this.spr0HitY = null;\n this.hitSpr0 = null;\n this.sprPalette = null;\n this.imgPalette = null;\n this.ptTile = null;\n this.ntable1 = null;\n this.currentMirroring = null;\n this.nameTable = null;\n this.vramMirrorTable = null;\n this.palTable = null;\n\n // Rendering Options:\n this.showSpr0Hit = false;\n this.clipToTvSize = true;\n\n this.reset();\n};\n\nPPU.prototype = {\n // Status flags:\n STATUS_VRAMWRITE: 4,\n STATUS_SLSPRITECOUNT: 5,\n STATUS_SPRITE0HIT: 6,\n STATUS_VBLANK: 7,\n\n reset: function() {\n var i;\n\n // Memory\n this.vramMem = new Array(0x8000);\n this.spriteMem = new Array(0x100);\n for (i = 0; i < this.vramMem.length; i++) {\n this.vramMem[i] = 0;\n }\n for (i = 0; i < this.spriteMem.length; i++) {\n this.spriteMem[i] = 0;\n }\n\n // VRAM I/O:\n this.vramAddress = null;\n this.vramTmpAddress = null;\n this.vramBufferedReadValue = 0;\n this.firstWrite = true; // VRAM/Scroll Hi/Lo latch\n\n // SPR-RAM I/O:\n this.sramAddress = 0; // 8-bit only.\n\n this.currentMirroring = -1;\n this.requestEndFrame = false;\n this.nmiOk = false;\n this.dummyCycleToggle = false;\n this.validTileData = false;\n this.nmiCounter = 0;\n this.scanlineAlreadyRendered = null;\n\n // Control Flags Register 1:\n this.f_nmiOnVblank = 0; // NMI on VBlank. 0=disable, 1=enable\n this.f_spriteSize = 0; // Sprite size. 0=8x8, 1=8x16\n this.f_bgPatternTable = 0; // Background Pattern Table address. 0=0x0000,1=0x1000\n this.f_spPatternTable = 0; // Sprite Pattern Table address. 0=0x0000,1=0x1000\n this.f_addrInc = 0; // PPU Address Increment. 0=1,1=32\n this.f_nTblAddress = 0; // Name Table Address. 0=0x2000,1=0x2400,2=0x2800,3=0x2C00\n\n // Control Flags Register 2:\n this.f_color = 0; // Background color. 0=black, 1=blue, 2=green, 4=red\n this.f_spVisibility = 0; // Sprite visibility. 0=not displayed,1=displayed\n this.f_bgVisibility = 0; // Background visibility. 0=Not Displayed,1=displayed\n this.f_spClipping = 0; // Sprite clipping. 0=Sprites invisible in left 8-pixel column,1=No clipping\n this.f_bgClipping = 0; // Background clipping. 0=BG invisible in left 8-pixel column, 1=No clipping\n this.f_dispType = 0; // Display type. 0=color, 1=monochrome\n\n // Counters:\n this.cntFV = 0;\n this.cntV = 0;\n this.cntH = 0;\n this.cntVT = 0;\n this.cntHT = 0;\n\n // Registers:\n this.regFV = 0;\n this.regV = 0;\n this.regH = 0;\n this.regVT = 0;\n this.regHT = 0;\n this.regFH = 0;\n this.regS = 0;\n\n // These are temporary variables used in rendering and sound procedures.\n // Their states outside of those procedures can be ignored.\n // TODO: the use of this is a bit weird, investigate\n this.curNt = null;\n\n // Variables used when rendering:\n this.attrib = new Array(32);\n this.buffer = new Array(256 * 240);\n this.bgbuffer = new Array(256 * 240);\n this.pixrendered = new Array(256 * 240);\n\n this.validTileData = null;\n\n this.scantile = new Array(32);\n\n // Initialize misc vars:\n this.scanline = 0;\n this.lastRenderedScanline = -1;\n this.curX = 0;\n\n // Sprite data:\n this.sprX = new Array(64); // X coordinate\n this.sprY = new Array(64); // Y coordinate\n this.sprTile = new Array(64); // Tile Index (into pattern table)\n this.sprCol = new Array(64); // Upper two bits of color\n this.vertFlip = new Array(64); // Vertical Flip\n this.horiFlip = new Array(64); // Horizontal Flip\n this.bgPriority = new Array(64); // Background priority\n this.spr0HitX = 0; // Sprite #0 hit X coordinate\n this.spr0HitY = 0; // Sprite #0 hit Y coordinate\n this.hitSpr0 = false;\n\n // Palette data:\n this.sprPalette = new Array(16);\n this.imgPalette = new Array(16);\n\n // Create pattern table tile buffers:\n this.ptTile = new Array(512);\n for (i = 0; i < 512; i++) {\n this.ptTile[i] = new Tile();\n }\n\n // Create nametable buffers:\n // Name table data:\n this.ntable1 = new Array(4);\n this.currentMirroring = -1;\n this.nameTable = new Array(4);\n for (i = 0; i < 4; i++) {\n this.nameTable[i] = new NameTable(32, 32, \"Nt\" + i);\n }\n\n // Initialize mirroring lookup table:\n this.vramMirrorTable = new Array(0x8000);\n for (i = 0; i < 0x8000; i++) {\n this.vramMirrorTable[i] = i;\n }\n\n this.palTable = new PaletteTable();\n this.palTable.loadNTSCPalette();\n //this.palTable.loadDefaultPalette();\n\n this.updateControlReg1(0);\n this.updateControlReg2(0);\n },\n\n // Sets Nametable mirroring.\n setMirroring: function(mirroring) {\n if (mirroring === this.currentMirroring) {\n return;\n }\n\n this.currentMirroring = mirroring;\n this.triggerRendering();\n\n // Remove mirroring:\n if (this.vramMirrorTable === null) {\n this.vramMirrorTable = new Array(0x8000);\n }\n for (var i = 0; i < 0x8000; i++) {\n this.vramMirrorTable[i] = i;\n }\n\n // Palette mirroring:\n this.defineMirrorRegion(0x3f20, 0x3f00, 0x20);\n this.defineMirrorRegion(0x3f40, 0x3f00, 0x20);\n this.defineMirrorRegion(0x3f80, 0x3f00, 0x20);\n this.defineMirrorRegion(0x3fc0, 0x3f00, 0x20);\n\n // Additional mirroring:\n this.defineMirrorRegion(0x3000, 0x2000, 0xf00);\n this.defineMirrorRegion(0x4000, 0x0000, 0x4000);\n\n if (mirroring === this.nes.rom.HORIZONTAL_MIRRORING) {\n // Horizontal mirroring.\n\n this.ntable1[0] = 0;\n this.ntable1[1] = 0;\n this.ntable1[2] = 1;\n this.ntable1[3] = 1;\n\n this.defineMirrorRegion(0x2400, 0x2000, 0x400);\n this.defineMirrorRegion(0x2c00, 0x2800, 0x400);\n } else if (mirroring === this.nes.rom.VERTICAL_MIRRORING) {\n // Vertical mirroring.\n\n this.ntable1[0] = 0;\n this.ntable1[1] = 1;\n this.ntable1[2] = 0;\n this.ntable1[3] = 1;\n\n this.defineMirrorRegion(0x2800, 0x2000, 0x400);\n this.defineMirrorRegion(0x2c00, 0x2400, 0x400);\n } else if (mirroring === this.nes.rom.SINGLESCREEN_MIRRORING) {\n // Single Screen mirroring\n\n this.ntable1[0] = 0;\n this.ntable1[1] = 0;\n this.ntable1[2] = 0;\n this.ntable1[3] = 0;\n\n this.defineMirrorRegion(0x2400, 0x2000, 0x400);\n this.defineMirrorRegion(0x2800, 0x2000, 0x400);\n this.defineMirrorRegion(0x2c00, 0x2000, 0x400);\n } else if (mirroring === this.nes.rom.SINGLESCREEN_MIRRORING2) {\n this.ntable1[0] = 1;\n this.ntable1[1] = 1;\n this.ntable1[2] = 1;\n this.ntable1[3] = 1;\n\n this.defineMirrorRegion(0x2400, 0x2400, 0x400);\n this.defineMirrorRegion(0x2800, 0x2400, 0x400);\n this.defineMirrorRegion(0x2c00, 0x2400, 0x400);\n } else {\n // Assume Four-screen mirroring.\n\n this.ntable1[0] = 0;\n this.ntable1[1] = 1;\n this.ntable1[2] = 2;\n this.ntable1[3] = 3;\n }\n },\n\n // Define a mirrored area in the address lookup table.\n // Assumes the regions don't overlap.\n // The 'to' region is the region that is physically in memory.\n defineMirrorRegion: function(fromStart, toStart, size) {\n for (var i = 0; i < size; i++) {\n this.vramMirrorTable[fromStart + i] = toStart + i;\n }\n },\n\n startVBlank: function() {\n // Do NMI:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_NMI);\n\n // Make sure everything is rendered:\n if (this.lastRenderedScanline < 239) {\n this.renderFramePartially(\n this.lastRenderedScanline + 1,\n 240 - this.lastRenderedScanline\n );\n }\n\n // End frame:\n this.endFrame();\n\n // Reset scanline counter:\n this.lastRenderedScanline = -1;\n },\n\n endScanline: function() {\n switch (this.scanline) {\n case 19:\n // Dummy scanline.\n // May be variable length:\n if (this.dummyCycleToggle) {\n // Remove dead cycle at end of scanline,\n // for next scanline:\n this.curX = 1;\n this.dummyCycleToggle = !this.dummyCycleToggle;\n }\n break;\n\n case 20:\n // Clear VBlank flag:\n this.setStatusFlag(this.STATUS_VBLANK, false);\n\n // Clear Sprite #0 hit flag:\n this.setStatusFlag(this.STATUS_SPRITE0HIT, false);\n this.hitSpr0 = false;\n this.spr0HitX = -1;\n this.spr0HitY = -1;\n\n if (this.f_bgVisibility === 1 || this.f_spVisibility === 1) {\n // Update counters:\n this.cntFV = this.regFV;\n this.cntV = this.regV;\n this.cntH = this.regH;\n this.cntVT = this.regVT;\n this.cntHT = this.regHT;\n\n if (this.f_bgVisibility === 1) {\n // Render dummy scanline:\n this.renderBgScanline(false, 0);\n }\n }\n\n if (this.f_bgVisibility === 1 && this.f_spVisibility === 1) {\n // Check sprite 0 hit for first scanline:\n this.checkSprite0(0);\n }\n\n if (this.f_bgVisibility === 1 || this.f_spVisibility === 1) {\n // Clock mapper IRQ Counter:\n this.nes.mmap.clockIrqCounter();\n }\n break;\n\n case 261:\n // Dead scanline, no rendering.\n // Set VINT:\n this.setStatusFlag(this.STATUS_VBLANK, true);\n this.requestEndFrame = true;\n this.nmiCounter = 9;\n\n // Wrap around:\n this.scanline = -1; // will be incremented to 0\n\n break;\n\n default:\n if (this.scanline >= 21 && this.scanline <= 260) {\n // Render normally:\n if (this.f_bgVisibility === 1) {\n if (!this.scanlineAlreadyRendered) {\n // update scroll:\n this.cntHT = this.regHT;\n this.cntH = this.regH;\n this.renderBgScanline(true, this.scanline + 1 - 21);\n }\n this.scanlineAlreadyRendered = false;\n\n // Check for sprite 0 (next scanline):\n if (!this.hitSpr0 && this.f_spVisibility === 1) {\n if (\n this.sprX[0] >= -7 &&\n this.sprX[0] < 256 &&\n this.sprY[0] + 1 <= this.scanline - 20 &&\n this.sprY[0] + 1 + (this.f_spriteSize === 0 ? 8 : 16) >=\n this.scanline - 20\n ) {\n if (this.checkSprite0(this.scanline - 20)) {\n this.hitSpr0 = true;\n }\n }\n }\n }\n\n if (this.f_bgVisibility === 1 || this.f_spVisibility === 1) {\n // Clock mapper IRQ Counter:\n this.nes.mmap.clockIrqCounter();\n }\n }\n }\n\n this.scanline++;\n this.regsToAddress();\n this.cntsToAddress();\n },\n\n startFrame: function() {\n // Set background color:\n var bgColor = 0;\n\n if (this.f_dispType === 0) {\n // Color display.\n // f_color determines color emphasis.\n // Use first entry of image palette as BG color.\n bgColor = this.imgPalette[0];\n } else {\n // Monochrome display.\n // f_color determines the bg color.\n switch (this.f_color) {\n case 0:\n // Black\n bgColor = 0x00000;\n break;\n case 1:\n // Green\n bgColor = 0x00ff00;\n break;\n case 2:\n // Blue\n bgColor = 0xff0000;\n break;\n case 3:\n // Invalid. Use black.\n bgColor = 0x000000;\n break;\n case 4:\n // Red\n bgColor = 0x0000ff;\n break;\n default:\n // Invalid. Use black.\n bgColor = 0x0;\n }\n }\n\n var buffer = this.buffer;\n var i;\n for (i = 0; i < 256 * 240; i++) {\n buffer[i] = bgColor;\n }\n var pixrendered = this.pixrendered;\n for (i = 0; i < pixrendered.length; i++) {\n pixrendered[i] = 65;\n }\n },\n\n endFrame: function() {\n var i, x, y;\n var buffer = this.buffer;\n\n // Draw spr#0 hit coordinates:\n if (this.showSpr0Hit) {\n // Spr 0 position:\n if (\n this.sprX[0] >= 0 &&\n this.sprX[0] < 256 &&\n this.sprY[0] >= 0 &&\n this.sprY[0] < 240\n ) {\n for (i = 0; i < 256; i++) {\n buffer[(this.sprY[0] << 8) + i] = 0xff5555;\n }\n for (i = 0; i < 240; i++) {\n buffer[(i << 8) + this.sprX[0]] = 0xff5555;\n }\n }\n // Hit position:\n if (\n this.spr0HitX >= 0 &&\n this.spr0HitX < 256 &&\n this.spr0HitY >= 0 &&\n this.spr0HitY < 240\n ) {\n for (i = 0; i < 256; i++) {\n buffer[(this.spr0HitY << 8) + i] = 0x55ff55;\n }\n for (i = 0; i < 240; i++) {\n buffer[(i << 8) + this.spr0HitX] = 0x55ff55;\n }\n }\n }\n\n // This is a bit lazy..\n // if either the sprites or the background should be clipped,\n // both are clipped after rendering is finished.\n if (\n this.clipToTvSize ||\n this.f_bgClipping === 0 ||\n this.f_spClipping === 0\n ) {\n // Clip left 8-pixels column:\n for (y = 0; y < 240; y++) {\n for (x = 0; x < 8; x++) {\n buffer[(y << 8) + x] = 0;\n }\n }\n }\n\n if (this.clipToTvSize) {\n // Clip right 8-pixels column too:\n for (y = 0; y < 240; y++) {\n for (x = 0; x < 8; x++) {\n buffer[(y << 8) + 255 - x] = 0;\n }\n }\n }\n\n // Clip top and bottom 8 pixels:\n if (this.clipToTvSize) {\n for (y = 0; y < 8; y++) {\n for (x = 0; x < 256; x++) {\n buffer[(y << 8) + x] = 0;\n buffer[((239 - y) << 8) + x] = 0;\n }\n }\n }\n\n this.nes.ui.writeFrame(buffer);\n },\n\n updateControlReg1: function(value) {\n this.triggerRendering();\n\n this.f_nmiOnVblank = (value >> 7) & 1;\n this.f_spriteSize = (value >> 5) & 1;\n this.f_bgPatternTable = (value >> 4) & 1;\n this.f_spPatternTable = (value >> 3) & 1;\n this.f_addrInc = (value >> 2) & 1;\n this.f_nTblAddress = value & 3;\n\n this.regV = (value >> 1) & 1;\n this.regH = value & 1;\n this.regS = (value >> 4) & 1;\n },\n\n updateControlReg2: function(value) {\n this.triggerRendering();\n\n this.f_color = (value >> 5) & 7;\n this.f_spVisibility = (value >> 4) & 1;\n this.f_bgVisibility = (value >> 3) & 1;\n this.f_spClipping = (value >> 2) & 1;\n this.f_bgClipping = (value >> 1) & 1;\n this.f_dispType = value & 1;\n\n if (this.f_dispType === 0) {\n this.palTable.setEmphasis(this.f_color);\n }\n this.updatePalettes();\n },\n\n setStatusFlag: function(flag, value) {\n var n = 1 << flag;\n this.nes.cpu.mem[0x2002] =\n (this.nes.cpu.mem[0x2002] & (255 - n)) | (value ? n : 0);\n },\n\n // CPU Register $2002:\n // Read the Status Register.\n readStatusRegister: function() {\n var tmp = this.nes.cpu.mem[0x2002];\n\n // Reset scroll & VRAM Address toggle:\n this.firstWrite = true;\n\n // Clear VBlank flag:\n this.setStatusFlag(this.STATUS_VBLANK, false);\n\n // Fetch status data:\n return tmp;\n },\n\n // CPU Register $2003:\n // Write the SPR-RAM address that is used for sramWrite (Register 0x2004 in CPU memory map)\n writeSRAMAddress: function(address) {\n this.sramAddress = address;\n },\n\n // CPU Register $2004 (R):\n // Read from SPR-RAM (Sprite RAM).\n // The address should be set first.\n sramLoad: function() {\n /*short tmp = sprMem.load(sramAddress);\n sramAddress++; // Increment address\n sramAddress%=0x100;\n return tmp;*/\n return this.spriteMem[this.sramAddress];\n },\n\n // CPU Register $2004 (W):\n // Write to SPR-RAM (Sprite RAM).\n // The address should be set first.\n sramWrite: function(value) {\n this.spriteMem[this.sramAddress] = value;\n this.spriteRamWriteUpdate(this.sramAddress, value);\n this.sramAddress++; // Increment address\n this.sramAddress %= 0x100;\n },\n\n // CPU Register $2005:\n // Write to scroll registers.\n // The first write is the vertical offset, the second is the\n // horizontal offset:\n scrollWrite: function(value) {\n this.triggerRendering();\n\n if (this.firstWrite) {\n // First write, horizontal scroll:\n this.regHT = (value >> 3) & 31;\n this.regFH = value & 7;\n } else {\n // Second write, vertical scroll:\n this.regFV = value & 7;\n this.regVT = (value >> 3) & 31;\n }\n this.firstWrite = !this.firstWrite;\n },\n\n // CPU Register $2006:\n // Sets the adress used when reading/writing from/to VRAM.\n // The first write sets the high byte, the second the low byte.\n writeVRAMAddress: function(address) {\n if (this.firstWrite) {\n this.regFV = (address >> 4) & 3;\n this.regV = (address >> 3) & 1;\n this.regH = (address >> 2) & 1;\n this.regVT = (this.regVT & 7) | ((address & 3) << 3);\n } else {\n this.triggerRendering();\n\n this.regVT = (this.regVT & 24) | ((address >> 5) & 7);\n this.regHT = address & 31;\n\n this.cntFV = this.regFV;\n this.cntV = this.regV;\n this.cntH = this.regH;\n this.cntVT = this.regVT;\n this.cntHT = this.regHT;\n\n this.checkSprite0(this.scanline - 20);\n }\n\n this.firstWrite = !this.firstWrite;\n\n // Invoke mapper latch:\n this.cntsToAddress();\n if (this.vramAddress < 0x2000) {\n this.nes.mmap.latchAccess(this.vramAddress);\n }\n },\n\n // CPU Register $2007(R):\n // Read from PPU memory. The address should be set first.\n vramLoad: function() {\n var tmp;\n\n this.cntsToAddress();\n this.regsToAddress();\n\n // If address is in range 0x0000-0x3EFF, return buffered values:\n if (this.vramAddress <= 0x3eff) {\n tmp = this.vramBufferedReadValue;\n\n // Update buffered value:\n if (this.vramAddress < 0x2000) {\n this.vramBufferedReadValue = this.vramMem[this.vramAddress];\n } else {\n this.vramBufferedReadValue = this.mirroredLoad(this.vramAddress);\n }\n\n // Mapper latch access:\n if (this.vramAddress < 0x2000) {\n this.nes.mmap.latchAccess(this.vramAddress);\n }\n\n // Increment by either 1 or 32, depending on d2 of Control Register 1:\n this.vramAddress += this.f_addrInc === 1 ? 32 : 1;\n\n this.cntsFromAddress();\n this.regsFromAddress();\n\n return tmp; // Return the previous buffered value.\n }\n\n // No buffering in this mem range. Read normally.\n tmp = this.mirroredLoad(this.vramAddress);\n\n // Increment by either 1 or 32, depending on d2 of Control Register 1:\n this.vramAddress += this.f_addrInc === 1 ? 32 : 1;\n\n this.cntsFromAddress();\n this.regsFromAddress();\n\n return tmp;\n },\n\n // CPU Register $2007(W):\n // Write to PPU memory. The address should be set first.\n vramWrite: function(value) {\n this.triggerRendering();\n this.cntsToAddress();\n this.regsToAddress();\n\n if (this.vramAddress >= 0x2000) {\n // Mirroring is used.\n this.mirroredWrite(this.vramAddress, value);\n } else {\n // Write normally.\n this.writeMem(this.vramAddress, value);\n\n // Invoke mapper latch:\n this.nes.mmap.latchAccess(this.vramAddress);\n }\n\n // Increment by either 1 or 32, depending on d2 of Control Register 1:\n this.vramAddress += this.f_addrInc === 1 ? 32 : 1;\n this.regsFromAddress();\n this.cntsFromAddress();\n },\n\n // CPU Register $4014:\n // Write 256 bytes of main memory\n // into Sprite RAM.\n sramDMA: function(value) {\n var baseAddress = value * 0x100;\n var data;\n for (var i = this.sramAddress; i < 256; i++) {\n data = this.nes.cpu.mem[baseAddress + i];\n this.spriteMem[i] = data;\n this.spriteRamWriteUpdate(i, data);\n }\n\n this.nes.cpu.haltCycles(513);\n },\n\n // Updates the scroll registers from a new VRAM address.\n regsFromAddress: function() {\n var address = (this.vramTmpAddress >> 8) & 0xff;\n this.regFV = (address >> 4) & 7;\n this.regV = (address >> 3) & 1;\n this.regH = (address >> 2) & 1;\n this.regVT = (this.regVT & 7) | ((address & 3) << 3);\n\n address = this.vramTmpAddress & 0xff;\n this.regVT = (this.regVT & 24) | ((address >> 5) & 7);\n this.regHT = address & 31;\n },\n\n // Updates the scroll registers from a new VRAM address.\n cntsFromAddress: function() {\n var address = (this.vramAddress >> 8) & 0xff;\n this.cntFV = (address >> 4) & 3;\n this.cntV = (address >> 3) & 1;\n this.cntH = (address >> 2) & 1;\n this.cntVT = (this.cntVT & 7) | ((address & 3) << 3);\n\n address = this.vramAddress & 0xff;\n this.cntVT = (this.cntVT & 24) | ((address >> 5) & 7);\n this.cntHT = address & 31;\n },\n\n regsToAddress: function() {\n var b1 = (this.regFV & 7) << 4;\n b1 |= (this.regV & 1) << 3;\n b1 |= (this.regH & 1) << 2;\n b1 |= (this.regVT >> 3) & 3;\n\n var b2 = (this.regVT & 7) << 5;\n b2 |= this.regHT & 31;\n\n this.vramTmpAddress = ((b1 << 8) | b2) & 0x7fff;\n },\n\n cntsToAddress: function() {\n var b1 = (this.cntFV & 7) << 4;\n b1 |= (this.cntV & 1) << 3;\n b1 |= (this.cntH & 1) << 2;\n b1 |= (this.cntVT >> 3) & 3;\n\n var b2 = (this.cntVT & 7) << 5;\n b2 |= this.cntHT & 31;\n\n this.vramAddress = ((b1 << 8) | b2) & 0x7fff;\n },\n\n incTileCounter: function(count) {\n for (var i = count; i !== 0; i--) {\n this.cntHT++;\n if (this.cntHT === 32) {\n this.cntHT = 0;\n this.cntVT++;\n if (this.cntVT >= 30) {\n this.cntH++;\n if (this.cntH === 2) {\n this.cntH = 0;\n this.cntV++;\n if (this.cntV === 2) {\n this.cntV = 0;\n this.cntFV++;\n this.cntFV &= 0x7;\n }\n }\n }\n }\n }\n },\n\n // Reads from memory, taking into account\n // mirroring/mapping of address ranges.\n mirroredLoad: function(address) {\n return this.vramMem[this.vramMirrorTable[address]];\n },\n\n // Writes to memory, taking into account\n // mirroring/mapping of address ranges.\n mirroredWrite: function(address, value) {\n if (address >= 0x3f00 && address < 0x3f20) {\n // Palette write mirroring.\n if (address === 0x3f00 || address === 0x3f10) {\n this.writeMem(0x3f00, value);\n this.writeMem(0x3f10, value);\n } else if (address === 0x3f04 || address === 0x3f14) {\n this.writeMem(0x3f04, value);\n this.writeMem(0x3f14, value);\n } else if (address === 0x3f08 || address === 0x3f18) {\n this.writeMem(0x3f08, value);\n this.writeMem(0x3f18, value);\n } else if (address === 0x3f0c || address === 0x3f1c) {\n this.writeMem(0x3f0c, value);\n this.writeMem(0x3f1c, value);\n } else {\n this.writeMem(address, value);\n }\n } else {\n // Use lookup table for mirrored address:\n if (address < this.vramMirrorTable.length) {\n this.writeMem(this.vramMirrorTable[address], value);\n } else {\n throw new Error(\"Invalid VRAM address: \" + address.toString(16));\n }\n }\n },\n\n triggerRendering: function() {\n if (this.scanline >= 21 && this.scanline <= 260) {\n // Render sprites, and combine:\n this.renderFramePartially(\n this.lastRenderedScanline + 1,\n this.scanline - 21 - this.lastRenderedScanline\n );\n\n // Set last rendered scanline:\n this.lastRenderedScanline = this.scanline - 21;\n }\n },\n\n renderFramePartially: function(startScan, scanCount) {\n if (this.f_spVisibility === 1) {\n this.renderSpritesPartially(startScan, scanCount, true);\n }\n\n if (this.f_bgVisibility === 1) {\n var si = startScan << 8;\n var ei = (startScan + scanCount) << 8;\n if (ei > 0xf000) {\n ei = 0xf000;\n }\n var buffer = this.buffer;\n var bgbuffer = this.bgbuffer;\n var pixrendered = this.pixrendered;\n for (var destIndex = si; destIndex < ei; destIndex++) {\n if (pixrendered[destIndex] > 0xff) {\n buffer[destIndex] = bgbuffer[destIndex];\n }\n }\n }\n\n if (this.f_spVisibility === 1) {\n this.renderSpritesPartially(startScan, scanCount, false);\n }\n\n this.validTileData = false;\n },\n\n renderBgScanline: function(bgbuffer, scan) {\n var baseTile = this.regS === 0 ? 0 : 256;\n var destIndex = (scan << 8) - this.regFH;\n\n this.curNt = this.ntable1[this.cntV + this.cntV + this.cntH];\n\n this.cntHT = this.regHT;\n this.cntH = this.regH;\n this.curNt = this.ntable1[this.cntV + this.cntV + this.cntH];\n\n if (scan < 240 && scan - this.cntFV >= 0) {\n var tscanoffset = this.cntFV << 3;\n var scantile = this.scantile;\n var attrib = this.attrib;\n var ptTile = this.ptTile;\n var nameTable = this.nameTable;\n var imgPalette = this.imgPalette;\n var pixrendered = this.pixrendered;\n var targetBuffer = bgbuffer ? this.bgbuffer : this.buffer;\n\n var t, tpix, att, col;\n\n for (var tile = 0; tile < 32; tile++) {\n if (scan >= 0) {\n // Fetch tile & attrib data:\n if (this.validTileData) {\n // Get data from array:\n t = scantile[tile];\n if (typeof t === \"undefined\") {\n continue;\n }\n tpix = t.pix;\n att = attrib[tile];\n } else {\n // Fetch data:\n t =\n ptTile[\n baseTile +\n nameTable[this.curNt].getTileIndex(this.cntHT, this.cntVT)\n ];\n if (typeof t === \"undefined\") {\n continue;\n }\n tpix = t.pix;\n att = nameTable[this.curNt].getAttrib(this.cntHT, this.cntVT);\n scantile[tile] = t;\n attrib[tile] = att;\n }\n\n // Render tile scanline:\n var sx = 0;\n var x = (tile << 3) - this.regFH;\n\n if (x > -8) {\n if (x < 0) {\n destIndex -= x;\n sx = -x;\n }\n if (t.opaque[this.cntFV]) {\n for (; sx < 8; sx++) {\n targetBuffer[destIndex] =\n imgPalette[tpix[tscanoffset + sx] + att];\n pixrendered[destIndex] |= 256;\n destIndex++;\n }\n } else {\n for (; sx < 8; sx++) {\n col = tpix[tscanoffset + sx];\n if (col !== 0) {\n targetBuffer[destIndex] = imgPalette[col + att];\n pixrendered[destIndex] |= 256;\n }\n destIndex++;\n }\n }\n }\n }\n\n // Increase Horizontal Tile Counter:\n if (++this.cntHT === 32) {\n this.cntHT = 0;\n this.cntH++;\n this.cntH %= 2;\n this.curNt = this.ntable1[(this.cntV << 1) + this.cntH];\n }\n }\n\n // Tile data for one row should now have been fetched,\n // so the data in the array is valid.\n this.validTileData = true;\n }\n\n // update vertical scroll:\n this.cntFV++;\n if (this.cntFV === 8) {\n this.cntFV = 0;\n this.cntVT++;\n if (this.cntVT === 30) {\n this.cntVT = 0;\n this.cntV++;\n this.cntV %= 2;\n this.curNt = this.ntable1[(this.cntV << 1) + this.cntH];\n } else if (this.cntVT === 32) {\n this.cntVT = 0;\n }\n\n // Invalidate fetched data:\n this.validTileData = false;\n }\n },\n\n renderSpritesPartially: function(startscan, scancount, bgPri) {\n if (this.f_spVisibility === 1) {\n for (var i = 0; i < 64; i++) {\n if (\n this.bgPriority[i] === bgPri &&\n this.sprX[i] >= 0 &&\n this.sprX[i] < 256 &&\n this.sprY[i] + 8 >= startscan &&\n this.sprY[i] < startscan + scancount\n ) {\n // Show sprite.\n if (this.f_spriteSize === 0) {\n // 8x8 sprites\n\n this.srcy1 = 0;\n this.srcy2 = 8;\n\n if (this.sprY[i] < startscan) {\n this.srcy1 = startscan - this.sprY[i] - 1;\n }\n\n if (this.sprY[i] + 8 > startscan + scancount) {\n this.srcy2 = startscan + scancount - this.sprY[i] + 1;\n }\n\n if (this.f_spPatternTable === 0) {\n this.ptTile[this.sprTile[i]].render(\n this.buffer,\n 0,\n this.srcy1,\n 8,\n this.srcy2,\n this.sprX[i],\n this.sprY[i] + 1,\n this.sprCol[i],\n this.sprPalette,\n this.horiFlip[i],\n this.vertFlip[i],\n i,\n this.pixrendered\n );\n } else {\n this.ptTile[this.sprTile[i] + 256].render(\n this.buffer,\n 0,\n this.srcy1,\n 8,\n this.srcy2,\n this.sprX[i],\n this.sprY[i] + 1,\n this.sprCol[i],\n this.sprPalette,\n this.horiFlip[i],\n this.vertFlip[i],\n i,\n this.pixrendered\n );\n }\n } else {\n // 8x16 sprites\n var top = this.sprTile[i];\n if ((top & 1) !== 0) {\n top = this.sprTile[i] - 1 + 256;\n }\n\n var srcy1 = 0;\n var srcy2 = 8;\n\n if (this.sprY[i] < startscan) {\n srcy1 = startscan - this.sprY[i] - 1;\n }\n\n if (this.sprY[i] + 8 > startscan + scancount) {\n srcy2 = startscan + scancount - this.sprY[i];\n }\n\n this.ptTile[top + (this.vertFlip[i] ? 1 : 0)].render(\n this.buffer,\n 0,\n srcy1,\n 8,\n srcy2,\n this.sprX[i],\n this.sprY[i] + 1,\n this.sprCol[i],\n this.sprPalette,\n this.horiFlip[i],\n this.vertFlip[i],\n i,\n this.pixrendered\n );\n\n srcy1 = 0;\n srcy2 = 8;\n\n if (this.sprY[i] + 8 < startscan) {\n srcy1 = startscan - (this.sprY[i] + 8 + 1);\n }\n\n if (this.sprY[i] + 16 > startscan + scancount) {\n srcy2 = startscan + scancount - (this.sprY[i] + 8);\n }\n\n this.ptTile[top + (this.vertFlip[i] ? 0 : 1)].render(\n this.buffer,\n 0,\n srcy1,\n 8,\n srcy2,\n this.sprX[i],\n this.sprY[i] + 1 + 8,\n this.sprCol[i],\n this.sprPalette,\n this.horiFlip[i],\n this.vertFlip[i],\n i,\n this.pixrendered\n );\n }\n }\n }\n }\n },\n\n checkSprite0: function(scan) {\n this.spr0HitX = -1;\n this.spr0HitY = -1;\n\n var toffset;\n var tIndexAdd = this.f_spPatternTable === 0 ? 0 : 256;\n var x, y, t, i;\n var bufferIndex;\n var col;\n var bgPri;\n\n x = this.sprX[0];\n y = this.sprY[0] + 1;\n\n if (this.f_spriteSize === 0) {\n // 8x8 sprites.\n\n // Check range:\n if (y <= scan && y + 8 > scan && x >= -7 && x < 256) {\n // Sprite is in range.\n // Draw scanline:\n t = this.ptTile[this.sprTile[0] + tIndexAdd];\n col = this.sprCol[0];\n bgPri = this.bgPriority[0];\n\n if (this.vertFlip[0]) {\n toffset = 7 - (scan - y);\n } else {\n toffset = scan - y;\n }\n toffset *= 8;\n\n bufferIndex = scan * 256 + x;\n if (this.horiFlip[0]) {\n for (i = 7; i >= 0; i--) {\n if (x >= 0 && x < 256) {\n if (\n bufferIndex >= 0 &&\n bufferIndex < 61440 &&\n this.pixrendered[bufferIndex] !== 0\n ) {\n if (t.pix[toffset + i] !== 0) {\n this.spr0HitX = bufferIndex % 256;\n this.spr0HitY = scan;\n return true;\n }\n }\n }\n x++;\n bufferIndex++;\n }\n } else {\n for (i = 0; i < 8; i++) {\n if (x >= 0 && x < 256) {\n if (\n bufferIndex >= 0 &&\n bufferIndex < 61440 &&\n this.pixrendered[bufferIndex] !== 0\n ) {\n if (t.pix[toffset + i] !== 0) {\n this.spr0HitX = bufferIndex % 256;\n this.spr0HitY = scan;\n return true;\n }\n }\n }\n x++;\n bufferIndex++;\n }\n }\n }\n } else {\n // 8x16 sprites:\n\n // Check range:\n if (y <= scan && y + 16 > scan && x >= -7 && x < 256) {\n // Sprite is in range.\n // Draw scanline:\n\n if (this.vertFlip[0]) {\n toffset = 15 - (scan - y);\n } else {\n toffset = scan - y;\n }\n\n if (toffset < 8) {\n // first half of sprite.\n t = this.ptTile[\n this.sprTile[0] +\n (this.vertFlip[0] ? 1 : 0) +\n ((this.sprTile[0] & 1) !== 0 ? 255 : 0)\n ];\n } else {\n // second half of sprite.\n t = this.ptTile[\n this.sprTile[0] +\n (this.vertFlip[0] ? 0 : 1) +\n ((this.sprTile[0] & 1) !== 0 ? 255 : 0)\n ];\n if (this.vertFlip[0]) {\n toffset = 15 - toffset;\n } else {\n toffset -= 8;\n }\n }\n toffset *= 8;\n col = this.sprCol[0];\n bgPri = this.bgPriority[0];\n\n bufferIndex = scan * 256 + x;\n if (this.horiFlip[0]) {\n for (i = 7; i >= 0; i--) {\n if (x >= 0 && x < 256) {\n if (\n bufferIndex >= 0 &&\n bufferIndex < 61440 &&\n this.pixrendered[bufferIndex] !== 0\n ) {\n if (t.pix[toffset + i] !== 0) {\n this.spr0HitX = bufferIndex % 256;\n this.spr0HitY = scan;\n return true;\n }\n }\n }\n x++;\n bufferIndex++;\n }\n } else {\n for (i = 0; i < 8; i++) {\n if (x >= 0 && x < 256) {\n if (\n bufferIndex >= 0 &&\n bufferIndex < 61440 &&\n this.pixrendered[bufferIndex] !== 0\n ) {\n if (t.pix[toffset + i] !== 0) {\n this.spr0HitX = bufferIndex % 256;\n this.spr0HitY = scan;\n return true;\n }\n }\n }\n x++;\n bufferIndex++;\n }\n }\n }\n }\n\n return false;\n },\n\n // This will write to PPU memory, and\n // update internally buffered data\n // appropriately.\n writeMem: function(address, value) {\n this.vramMem[address] = value;\n\n // Update internally buffered data:\n if (address < 0x2000) {\n this.vramMem[address] = value;\n this.patternWrite(address, value);\n } else if (address >= 0x2000 && address < 0x23c0) {\n this.nameTableWrite(this.ntable1[0], address - 0x2000, value);\n } else if (address >= 0x23c0 && address < 0x2400) {\n this.attribTableWrite(this.ntable1[0], address - 0x23c0, value);\n } else if (address >= 0x2400 && address < 0x27c0) {\n this.nameTableWrite(this.ntable1[1], address - 0x2400, value);\n } else if (address >= 0x27c0 && address < 0x2800) {\n this.attribTableWrite(this.ntable1[1], address - 0x27c0, value);\n } else if (address >= 0x2800 && address < 0x2bc0) {\n this.nameTableWrite(this.ntable1[2], address - 0x2800, value);\n } else if (address >= 0x2bc0 && address < 0x2c00) {\n this.attribTableWrite(this.ntable1[2], address - 0x2bc0, value);\n } else if (address >= 0x2c00 && address < 0x2fc0) {\n this.nameTableWrite(this.ntable1[3], address - 0x2c00, value);\n } else if (address >= 0x2fc0 && address < 0x3000) {\n this.attribTableWrite(this.ntable1[3], address - 0x2fc0, value);\n } else if (address >= 0x3f00 && address < 0x3f20) {\n this.updatePalettes();\n }\n },\n\n // Reads data from $3f00 to $f20\n // into the two buffered palettes.\n updatePalettes: function() {\n var i;\n\n for (i = 0; i < 16; i++) {\n if (this.f_dispType === 0) {\n this.imgPalette[i] = this.palTable.getEntry(\n this.vramMem[0x3f00 + i] & 63\n );\n } else {\n this.imgPalette[i] = this.palTable.getEntry(\n this.vramMem[0x3f00 + i] & 32\n );\n }\n }\n for (i = 0; i < 16; i++) {\n if (this.f_dispType === 0) {\n this.sprPalette[i] = this.palTable.getEntry(\n this.vramMem[0x3f10 + i] & 63\n );\n } else {\n this.sprPalette[i] = this.palTable.getEntry(\n this.vramMem[0x3f10 + i] & 32\n );\n }\n }\n },\n\n // Updates the internal pattern\n // table buffers with this new byte.\n // In vNES, there is a version of this with 4 arguments which isn't used.\n patternWrite: function(address, value) {\n var tileIndex = Math.floor(address / 16);\n var leftOver = address % 16;\n if (leftOver < 8) {\n this.ptTile[tileIndex].setScanline(\n leftOver,\n value,\n this.vramMem[address + 8]\n );\n } else {\n this.ptTile[tileIndex].setScanline(\n leftOver - 8,\n this.vramMem[address - 8],\n value\n );\n }\n },\n\n // Updates the internal name table buffers\n // with this new byte.\n nameTableWrite: function(index, address, value) {\n this.nameTable[index].tile[address] = value;\n\n // Update Sprite #0 hit:\n //updateSpr0Hit();\n this.checkSprite0(this.scanline - 20);\n },\n\n // Updates the internal pattern\n // table buffers with this new attribute\n // table byte.\n attribTableWrite: function(index, address, value) {\n this.nameTable[index].writeAttrib(address, value);\n },\n\n // Updates the internally buffered sprite\n // data with this new byte of info.\n spriteRamWriteUpdate: function(address, value) {\n var tIndex = Math.floor(address / 4);\n\n if (tIndex === 0) {\n //updateSpr0Hit();\n this.checkSprite0(this.scanline - 20);\n }\n\n if (address % 4 === 0) {\n // Y coordinate\n this.sprY[tIndex] = value;\n } else if (address % 4 === 1) {\n // Tile index\n this.sprTile[tIndex] = value;\n } else if (address % 4 === 2) {\n // Attributes\n this.vertFlip[tIndex] = (value & 0x80) !== 0;\n this.horiFlip[tIndex] = (value & 0x40) !== 0;\n this.bgPriority[tIndex] = (value & 0x20) !== 0;\n this.sprCol[tIndex] = (value & 3) << 2;\n } else if (address % 4 === 3) {\n // X coordinate\n this.sprX[tIndex] = value;\n }\n },\n\n doNMI: function() {\n // Set VBlank flag:\n this.setStatusFlag(this.STATUS_VBLANK, true);\n //nes.getCpu().doNonMaskableInterrupt();\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_NMI);\n },\n\n isPixelWhite: function(x, y) {\n this.triggerRendering();\n return this.nes.ppu.buffer[(y << 8) + x] === 0xffffff;\n },\n\n JSON_PROPERTIES: [\n // Memory\n \"vramMem\",\n \"spriteMem\",\n // Counters\n \"cntFV\",\n \"cntV\",\n \"cntH\",\n \"cntVT\",\n \"cntHT\",\n // Registers\n \"regFV\",\n \"regV\",\n \"regH\",\n \"regVT\",\n \"regHT\",\n \"regFH\",\n \"regS\",\n // VRAM addr\n \"vramAddress\",\n \"vramTmpAddress\",\n // Control/Status registers\n \"f_nmiOnVblank\",\n \"f_spriteSize\",\n \"f_bgPatternTable\",\n \"f_spPatternTable\",\n \"f_addrInc\",\n \"f_nTblAddress\",\n \"f_color\",\n \"f_spVisibility\",\n \"f_bgVisibility\",\n \"f_spClipping\",\n \"f_bgClipping\",\n \"f_dispType\",\n // VRAM I/O\n \"vramBufferedReadValue\",\n \"firstWrite\",\n // Mirroring\n \"currentMirroring\",\n \"vramMirrorTable\",\n \"ntable1\",\n // SPR-RAM I/O\n \"sramAddress\",\n // Sprites. Most sprite data is rebuilt from spriteMem\n \"hitSpr0\",\n // Palettes\n \"sprPalette\",\n \"imgPalette\",\n // Rendering progression\n \"curX\",\n \"scanline\",\n \"lastRenderedScanline\",\n \"curNt\",\n \"scantile\",\n // Used during rendering\n \"attrib\",\n \"buffer\",\n \"bgbuffer\",\n \"pixrendered\",\n // Misc\n \"requestEndFrame\",\n \"nmiOk\",\n \"dummyCycleToggle\",\n \"nmiCounter\",\n \"validTileData\",\n \"scanlineAlreadyRendered\"\n ],\n\n toJSON: function() {\n var i;\n var state = utils.toJSON(this);\n\n state.nameTable = [];\n for (i = 0; i < this.nameTable.length; i++) {\n state.nameTable[i] = this.nameTable[i].toJSON();\n }\n\n state.ptTile = [];\n for (i = 0; i < this.ptTile.length; i++) {\n state.ptTile[i] = this.ptTile[i].toJSON();\n }\n\n return state;\n },\n\n fromJSON: function(state) {\n var i;\n\n utils.fromJSON(this, state);\n\n for (i = 0; i < this.nameTable.length; i++) {\n this.nameTable[i].fromJSON(state.nameTable[i]);\n }\n\n for (i = 0; i < this.ptTile.length; i++) {\n this.ptTile[i].fromJSON(state.ptTile[i]);\n }\n\n // Sprite data:\n for (i = 0; i < this.spriteMem.length; i++) {\n this.spriteRamWriteUpdate(i, this.spriteMem[i]);\n }\n }\n};\n\nvar NameTable = function(width, height, name) {\n this.width = width;\n this.height = height;\n this.name = name;\n\n this.tile = new Array(width * height);\n this.attrib = new Array(width * height);\n for (var i = 0; i < width * height; i++) {\n this.tile[i] = 0;\n this.attrib[i] = 0;\n }\n};\n\nNameTable.prototype = {\n getTileIndex: function(x, y) {\n return this.tile[y * this.width + x];\n },\n\n getAttrib: function(x, y) {\n return this.attrib[y * this.width + x];\n },\n\n writeAttrib: function(index, value) {\n var basex = (index % 8) * 4;\n var basey = Math.floor(index / 8) * 4;\n var add;\n var tx, ty;\n var attindex;\n\n for (var sqy = 0; sqy < 2; sqy++) {\n for (var sqx = 0; sqx < 2; sqx++) {\n add = (value >> (2 * (sqy * 2 + sqx))) & 3;\n for (var y = 0; y < 2; y++) {\n for (var x = 0; x < 2; x++) {\n tx = basex + sqx * 2 + x;\n ty = basey + sqy * 2 + y;\n attindex = ty * this.width + tx;\n this.attrib[ty * this.width + tx] = (add << 2) & 12;\n }\n }\n }\n }\n },\n\n toJSON: function() {\n return {\n tile: this.tile,\n attrib: this.attrib\n };\n },\n\n fromJSON: function(s) {\n this.tile = s.tile;\n this.attrib = s.attrib;\n }\n};\n\nvar PaletteTable = function() {\n this.curTable = new Array(64);\n this.emphTable = new Array(8);\n this.currentEmph = -1;\n};\n\nPaletteTable.prototype = {\n reset: function() {\n this.setEmphasis(0);\n },\n\n loadNTSCPalette: function() {\n // prettier-ignore\n this.curTable = [0x525252, 0xB40000, 0xA00000, 0xB1003D, 0x740069, 0x00005B, 0x00005F, 0x001840, 0x002F10, 0x084A08, 0x006700, 0x124200, 0x6D2800, 0x000000, 0x000000, 0x000000, 0xC4D5E7, 0xFF4000, 0xDC0E22, 0xFF476B, 0xD7009F, 0x680AD7, 0x0019BC, 0x0054B1, 0x006A5B, 0x008C03, 0x00AB00, 0x2C8800, 0xA47200, 0x000000, 0x000000, 0x000000, 0xF8F8F8, 0xFFAB3C, 0xFF7981, 0xFF5BC5, 0xFF48F2, 0xDF49FF, 0x476DFF, 0x00B4F7, 0x00E0FF, 0x00E375, 0x03F42B, 0x78B82E, 0xE5E218, 0x787878, 0x000000, 0x000000, 0xFFFFFF, 0xFFF2BE, 0xF8B8B8, 0xF8B8D8, 0xFFB6FF, 0xFFC3FF, 0xC7D1FF, 0x9ADAFF, 0x88EDF8, 0x83FFDD, 0xB8F8B8, 0xF5F8AC, 0xFFFFB0, 0xF8D8F8, 0x000000, 0x000000];\n this.makeTables();\n this.setEmphasis(0);\n },\n\n loadPALPalette: function() {\n // prettier-ignore\n this.curTable = [0x525252, 0xB40000, 0xA00000, 0xB1003D, 0x740069, 0x00005B, 0x00005F, 0x001840, 0x002F10, 0x084A08, 0x006700, 0x124200, 0x6D2800, 0x000000, 0x000000, 0x000000, 0xC4D5E7, 0xFF4000, 0xDC0E22, 0xFF476B, 0xD7009F, 0x680AD7, 0x0019BC, 0x0054B1, 0x006A5B, 0x008C03, 0x00AB00, 0x2C8800, 0xA47200, 0x000000, 0x000000, 0x000000, 0xF8F8F8, 0xFFAB3C, 0xFF7981, 0xFF5BC5, 0xFF48F2, 0xDF49FF, 0x476DFF, 0x00B4F7, 0x00E0FF, 0x00E375, 0x03F42B, 0x78B82E, 0xE5E218, 0x787878, 0x000000, 0x000000, 0xFFFFFF, 0xFFF2BE, 0xF8B8B8, 0xF8B8D8, 0xFFB6FF, 0xFFC3FF, 0xC7D1FF, 0x9ADAFF, 0x88EDF8, 0x83FFDD, 0xB8F8B8, 0xF5F8AC, 0xFFFFB0, 0xF8D8F8, 0x000000, 0x000000];\n this.makeTables();\n this.setEmphasis(0);\n },\n\n makeTables: function() {\n var r, g, b, col, i, rFactor, gFactor, bFactor;\n\n // Calculate a table for each possible emphasis setting:\n for (var emph = 0; emph < 8; emph++) {\n // Determine color component factors:\n rFactor = 1.0;\n gFactor = 1.0;\n bFactor = 1.0;\n\n if ((emph & 1) !== 0) {\n rFactor = 0.75;\n bFactor = 0.75;\n }\n if ((emph & 2) !== 0) {\n rFactor = 0.75;\n gFactor = 0.75;\n }\n if ((emph & 4) !== 0) {\n gFactor = 0.75;\n bFactor = 0.75;\n }\n\n this.emphTable[emph] = new Array(64);\n\n // Calculate table:\n for (i = 0; i < 64; i++) {\n col = this.curTable[i];\n r = Math.floor(this.getRed(col) * rFactor);\n g = Math.floor(this.getGreen(col) * gFactor);\n b = Math.floor(this.getBlue(col) * bFactor);\n this.emphTable[emph][i] = this.getRgb(r, g, b);\n }\n }\n },\n\n setEmphasis: function(emph) {\n if (emph !== this.currentEmph) {\n this.currentEmph = emph;\n for (var i = 0; i < 64; i++) {\n this.curTable[i] = this.emphTable[emph][i];\n }\n }\n },\n\n getEntry: function(yiq) {\n return this.curTable[yiq];\n },\n\n getRed: function(rgb) {\n return (rgb >> 16) & 0xff;\n },\n\n getGreen: function(rgb) {\n return (rgb >> 8) & 0xff;\n },\n\n getBlue: function(rgb) {\n return rgb & 0xff;\n },\n\n getRgb: function(r, g, b) {\n return (r << 16) | (g << 8) | b;\n },\n\n loadDefaultPalette: function() {\n this.curTable[0] = this.getRgb(117, 117, 117);\n this.curTable[1] = this.getRgb(39, 27, 143);\n this.curTable[2] = this.getRgb(0, 0, 171);\n this.curTable[3] = this.getRgb(71, 0, 159);\n this.curTable[4] = this.getRgb(143, 0, 119);\n this.curTable[5] = this.getRgb(171, 0, 19);\n this.curTable[6] = this.getRgb(167, 0, 0);\n this.curTable[7] = this.getRgb(127, 11, 0);\n this.curTable[8] = this.getRgb(67, 47, 0);\n this.curTable[9] = this.getRgb(0, 71, 0);\n this.curTable[10] = this.getRgb(0, 81, 0);\n this.curTable[11] = this.getRgb(0, 63, 23);\n this.curTable[12] = this.getRgb(27, 63, 95);\n this.curTable[13] = this.getRgb(0, 0, 0);\n this.curTable[14] = this.getRgb(0, 0, 0);\n this.curTable[15] = this.getRgb(0, 0, 0);\n this.curTable[16] = this.getRgb(188, 188, 188);\n this.curTable[17] = this.getRgb(0, 115, 239);\n this.curTable[18] = this.getRgb(35, 59, 239);\n this.curTable[19] = this.getRgb(131, 0, 243);\n this.curTable[20] = this.getRgb(191, 0, 191);\n this.curTable[21] = this.getRgb(231, 0, 91);\n this.curTable[22] = this.getRgb(219, 43, 0);\n this.curTable[23] = this.getRgb(203, 79, 15);\n this.curTable[24] = this.getRgb(139, 115, 0);\n this.curTable[25] = this.getRgb(0, 151, 0);\n this.curTable[26] = this.getRgb(0, 171, 0);\n this.curTable[27] = this.getRgb(0, 147, 59);\n this.curTable[28] = this.getRgb(0, 131, 139);\n this.curTable[29] = this.getRgb(0, 0, 0);\n this.curTable[30] = this.getRgb(0, 0, 0);\n this.curTable[31] = this.getRgb(0, 0, 0);\n this.curTable[32] = this.getRgb(255, 255, 255);\n this.curTable[33] = this.getRgb(63, 191, 255);\n this.curTable[34] = this.getRgb(95, 151, 255);\n this.curTable[35] = this.getRgb(167, 139, 253);\n this.curTable[36] = this.getRgb(247, 123, 255);\n this.curTable[37] = this.getRgb(255, 119, 183);\n this.curTable[38] = this.getRgb(255, 119, 99);\n this.curTable[39] = this.getRgb(255, 155, 59);\n this.curTable[40] = this.getRgb(243, 191, 63);\n this.curTable[41] = this.getRgb(131, 211, 19);\n this.curTable[42] = this.getRgb(79, 223, 75);\n this.curTable[43] = this.getRgb(88, 248, 152);\n this.curTable[44] = this.getRgb(0, 235, 219);\n this.curTable[45] = this.getRgb(0, 0, 0);\n this.curTable[46] = this.getRgb(0, 0, 0);\n this.curTable[47] = this.getRgb(0, 0, 0);\n this.curTable[48] = this.getRgb(255, 255, 255);\n this.curTable[49] = this.getRgb(171, 231, 255);\n this.curTable[50] = this.getRgb(199, 215, 255);\n this.curTable[51] = this.getRgb(215, 203, 255);\n this.curTable[52] = this.getRgb(255, 199, 255);\n this.curTable[53] = this.getRgb(255, 199, 219);\n this.curTable[54] = this.getRgb(255, 191, 179);\n this.curTable[55] = this.getRgb(255, 219, 171);\n this.curTable[56] = this.getRgb(255, 231, 163);\n this.curTable[57] = this.getRgb(227, 255, 163);\n this.curTable[58] = this.getRgb(171, 243, 191);\n this.curTable[59] = this.getRgb(179, 255, 207);\n this.curTable[60] = this.getRgb(159, 255, 243);\n this.curTable[61] = this.getRgb(0, 0, 0);\n this.curTable[62] = this.getRgb(0, 0, 0);\n this.curTable[63] = this.getRgb(0, 0, 0);\n\n this.makeTables();\n this.setEmphasis(0);\n }\n};\n\nmodule.exports = PPU;\n\n\n/***/ }),\n/* 7 */\n/***/ (function(module, exports) {\n\nvar CPU_FREQ_NTSC = 1789772.5; //1789772.72727272d;\n// var CPU_FREQ_PAL = 1773447.4;\n\nvar PAPU = function(nes) {\n this.nes = nes;\n\n this.square1 = new ChannelSquare(this, true);\n this.square2 = new ChannelSquare(this, false);\n this.triangle = new ChannelTriangle(this);\n this.noise = new ChannelNoise(this);\n this.dmc = new ChannelDM(this);\n\n this.frameIrqCounter = null;\n this.frameIrqCounterMax = 4;\n this.initCounter = 2048;\n this.channelEnableValue = null;\n\n this.sampleRate = 44100;\n\n this.lengthLookup = null;\n this.dmcFreqLookup = null;\n this.noiseWavelengthLookup = null;\n this.square_table = null;\n this.tnd_table = null;\n\n this.frameIrqEnabled = false;\n this.frameIrqActive = null;\n this.frameClockNow = null;\n this.startedPlaying = false;\n this.recordOutput = false;\n this.initingHardware = false;\n\n this.masterFrameCounter = null;\n this.derivedFrameCounter = null;\n this.countSequence = null;\n this.sampleTimer = null;\n this.frameTime = null;\n this.sampleTimerMax = null;\n this.sampleCount = null;\n this.triValue = 0;\n\n this.smpSquare1 = null;\n this.smpSquare2 = null;\n this.smpTriangle = null;\n this.smpDmc = null;\n this.accCount = null;\n\n // DC removal vars:\n this.prevSampleL = 0;\n this.prevSampleR = 0;\n this.smpAccumL = 0;\n this.smpAccumR = 0;\n\n // DAC range:\n this.dacRange = 0;\n this.dcValue = 0;\n\n // Master volume:\n this.masterVolume = 256;\n\n // Stereo positioning:\n this.stereoPosLSquare1 = null;\n this.stereoPosLSquare2 = null;\n this.stereoPosLTriangle = null;\n this.stereoPosLNoise = null;\n this.stereoPosLDMC = null;\n this.stereoPosRSquare1 = null;\n this.stereoPosRSquare2 = null;\n this.stereoPosRTriangle = null;\n this.stereoPosRNoise = null;\n this.stereoPosRDMC = null;\n\n this.extraCycles = null;\n\n this.maxSample = null;\n this.minSample = null;\n\n // Panning:\n this.panning = [80, 170, 100, 150, 128];\n this.setPanning(this.panning);\n\n // Initialize lookup tables:\n this.initLengthLookup();\n this.initDmcFrequencyLookup();\n this.initNoiseWavelengthLookup();\n this.initDACtables();\n\n // Init sound registers:\n for (var i = 0; i < 0x14; i++) {\n if (i === 0x10) {\n this.writeReg(0x4010, 0x10);\n } else {\n this.writeReg(0x4000 + i, 0);\n }\n }\n\n this.reset();\n};\n\nPAPU.prototype = {\n reset: function() {\n this.sampleRate = this.nes.opts.sampleRate;\n this.sampleTimerMax = Math.floor(\n 1024.0 *\n CPU_FREQ_NTSC *\n this.nes.opts.preferredFrameRate /\n (this.sampleRate * 60.0)\n );\n\n this.frameTime = Math.floor(\n 14915.0 * this.nes.opts.preferredFrameRate / 60.0\n );\n\n this.sampleTimer = 0;\n\n this.updateChannelEnable(0);\n this.masterFrameCounter = 0;\n this.derivedFrameCounter = 0;\n this.countSequence = 0;\n this.sampleCount = 0;\n this.initCounter = 2048;\n this.frameIrqEnabled = false;\n this.initingHardware = false;\n\n this.resetCounter();\n\n this.square1.reset();\n this.square2.reset();\n this.triangle.reset();\n this.noise.reset();\n this.dmc.reset();\n\n this.accCount = 0;\n this.smpSquare1 = 0;\n this.smpSquare2 = 0;\n this.smpTriangle = 0;\n this.smpDmc = 0;\n\n this.frameIrqEnabled = false;\n this.frameIrqCounterMax = 4;\n\n this.channelEnableValue = 0xff;\n this.startedPlaying = false;\n this.prevSampleL = 0;\n this.prevSampleR = 0;\n this.smpAccumL = 0;\n this.smpAccumR = 0;\n\n this.maxSample = -500000;\n this.minSample = 500000;\n },\n\n readReg: function(address) {\n // Read 0x4015:\n var tmp = 0;\n tmp |= this.square1.getLengthStatus();\n tmp |= this.square2.getLengthStatus() << 1;\n tmp |= this.triangle.getLengthStatus() << 2;\n tmp |= this.noise.getLengthStatus() << 3;\n tmp |= this.dmc.getLengthStatus() << 4;\n tmp |= (this.frameIrqActive && this.frameIrqEnabled ? 1 : 0) << 6;\n tmp |= this.dmc.getIrqStatus() << 7;\n\n this.frameIrqActive = false;\n this.dmc.irqGenerated = false;\n\n return tmp & 0xffff;\n },\n\n writeReg: function(address, value) {\n if (address >= 0x4000 && address < 0x4004) {\n // Square Wave 1 Control\n this.square1.writeReg(address, value);\n // console.log(\"Square Write\");\n } else if (address >= 0x4004 && address < 0x4008) {\n // Square 2 Control\n this.square2.writeReg(address, value);\n } else if (address >= 0x4008 && address < 0x400c) {\n // Triangle Control\n this.triangle.writeReg(address, value);\n } else if (address >= 0x400c && address <= 0x400f) {\n // Noise Control\n this.noise.writeReg(address, value);\n } else if (address === 0x4010) {\n // DMC Play mode & DMA frequency\n this.dmc.writeReg(address, value);\n } else if (address === 0x4011) {\n // DMC Delta Counter\n this.dmc.writeReg(address, value);\n } else if (address === 0x4012) {\n // DMC Play code starting address\n this.dmc.writeReg(address, value);\n } else if (address === 0x4013) {\n // DMC Play code length\n this.dmc.writeReg(address, value);\n } else if (address === 0x4015) {\n // Channel enable\n this.updateChannelEnable(value);\n\n if (value !== 0 && this.initCounter > 0) {\n // Start hardware initialization\n this.initingHardware = true;\n }\n\n // DMC/IRQ Status\n this.dmc.writeReg(address, value);\n } else if (address === 0x4017) {\n // Frame counter control\n this.countSequence = (value >> 7) & 1;\n this.masterFrameCounter = 0;\n this.frameIrqActive = false;\n\n if (((value >> 6) & 0x1) === 0) {\n this.frameIrqEnabled = true;\n } else {\n this.frameIrqEnabled = false;\n }\n\n if (this.countSequence === 0) {\n // NTSC:\n this.frameIrqCounterMax = 4;\n this.derivedFrameCounter = 4;\n } else {\n // PAL:\n this.frameIrqCounterMax = 5;\n this.derivedFrameCounter = 0;\n this.frameCounterTick();\n }\n }\n },\n\n resetCounter: function() {\n if (this.countSequence === 0) {\n this.derivedFrameCounter = 4;\n } else {\n this.derivedFrameCounter = 0;\n }\n },\n\n // Updates channel enable status.\n // This is done on writes to the\n // channel enable register (0x4015),\n // and when the user enables/disables channels\n // in the GUI.\n updateChannelEnable: function(value) {\n this.channelEnableValue = value & 0xffff;\n this.square1.setEnabled((value & 1) !== 0);\n this.square2.setEnabled((value & 2) !== 0);\n this.triangle.setEnabled((value & 4) !== 0);\n this.noise.setEnabled((value & 8) !== 0);\n this.dmc.setEnabled((value & 16) !== 0);\n },\n\n // Clocks the frame counter. It should be clocked at\n // twice the cpu speed, so the cycles will be\n // divided by 2 for those counters that are\n // clocked at cpu speed.\n clockFrameCounter: function(nCycles) {\n if (this.initCounter > 0) {\n if (this.initingHardware) {\n this.initCounter -= nCycles;\n if (this.initCounter <= 0) {\n this.initingHardware = false;\n }\n return;\n }\n }\n\n // Don't process ticks beyond next sampling:\n nCycles += this.extraCycles;\n var maxCycles = this.sampleTimerMax - this.sampleTimer;\n if (nCycles << 10 > maxCycles) {\n this.extraCycles = ((nCycles << 10) - maxCycles) >> 10;\n nCycles -= this.extraCycles;\n } else {\n this.extraCycles = 0;\n }\n\n var dmc = this.dmc;\n var triangle = this.triangle;\n var square1 = this.square1;\n var square2 = this.square2;\n var noise = this.noise;\n\n // Clock DMC:\n if (dmc.isEnabled) {\n dmc.shiftCounter -= nCycles << 3;\n while (dmc.shiftCounter <= 0 && dmc.dmaFrequency > 0) {\n dmc.shiftCounter += dmc.dmaFrequency;\n dmc.clockDmc();\n }\n }\n\n // Clock Triangle channel Prog timer:\n if (triangle.progTimerMax > 0) {\n triangle.progTimerCount -= nCycles;\n while (triangle.progTimerCount <= 0) {\n triangle.progTimerCount += triangle.progTimerMax + 1;\n if (triangle.linearCounter > 0 && triangle.lengthCounter > 0) {\n triangle.triangleCounter++;\n triangle.triangleCounter &= 0x1f;\n\n if (triangle.isEnabled) {\n if (triangle.triangleCounter >= 0x10) {\n // Normal value.\n triangle.sampleValue = triangle.triangleCounter & 0xf;\n } else {\n // Inverted value.\n triangle.sampleValue = 0xf - (triangle.triangleCounter & 0xf);\n }\n triangle.sampleValue <<= 4;\n }\n }\n }\n }\n\n // Clock Square channel 1 Prog timer:\n square1.progTimerCount -= nCycles;\n if (square1.progTimerCount <= 0) {\n square1.progTimerCount += (square1.progTimerMax + 1) << 1;\n\n square1.squareCounter++;\n square1.squareCounter &= 0x7;\n square1.updateSampleValue();\n }\n\n // Clock Square channel 2 Prog timer:\n square2.progTimerCount -= nCycles;\n if (square2.progTimerCount <= 0) {\n square2.progTimerCount += (square2.progTimerMax + 1) << 1;\n\n square2.squareCounter++;\n square2.squareCounter &= 0x7;\n square2.updateSampleValue();\n }\n\n // Clock noise channel Prog timer:\n var acc_c = nCycles;\n if (noise.progTimerCount - acc_c > 0) {\n // Do all cycles at once:\n noise.progTimerCount -= acc_c;\n noise.accCount += acc_c;\n noise.accValue += acc_c * noise.sampleValue;\n } else {\n // Slow-step:\n while (acc_c-- > 0) {\n if (--noise.progTimerCount <= 0 && noise.progTimerMax > 0) {\n // Update noise shift register:\n noise.shiftReg <<= 1;\n noise.tmp =\n ((noise.shiftReg << (noise.randomMode === 0 ? 1 : 6)) ^\n noise.shiftReg) &\n 0x8000;\n if (noise.tmp !== 0) {\n // Sample value must be 0.\n noise.shiftReg |= 0x01;\n noise.randomBit = 0;\n noise.sampleValue = 0;\n } else {\n // Find sample value:\n noise.randomBit = 1;\n if (noise.isEnabled && noise.lengthCounter > 0) {\n noise.sampleValue = noise.masterVolume;\n } else {\n noise.sampleValue = 0;\n }\n }\n\n noise.progTimerCount += noise.progTimerMax;\n }\n\n noise.accValue += noise.sampleValue;\n noise.accCount++;\n }\n }\n\n // Frame IRQ handling:\n if (this.frameIrqEnabled && this.frameIrqActive) {\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_NORMAL);\n }\n\n // Clock frame counter at double CPU speed:\n this.masterFrameCounter += nCycles << 1;\n if (this.masterFrameCounter >= this.frameTime) {\n // 240Hz tick:\n this.masterFrameCounter -= this.frameTime;\n this.frameCounterTick();\n }\n\n // Accumulate sample value:\n this.accSample(nCycles);\n\n // Clock sample timer:\n this.sampleTimer += nCycles << 10;\n if (this.sampleTimer >= this.sampleTimerMax) {\n // Sample channels:\n this.sample();\n this.sampleTimer -= this.sampleTimerMax;\n }\n },\n\n accSample: function(cycles) {\n // Special treatment for triangle channel - need to interpolate.\n if (this.triangle.sampleCondition) {\n this.triValue = Math.floor(\n (this.triangle.progTimerCount << 4) / (this.triangle.progTimerMax + 1)\n );\n if (this.triValue > 16) {\n this.triValue = 16;\n }\n if (this.triangle.triangleCounter >= 16) {\n this.triValue = 16 - this.triValue;\n }\n\n // Add non-interpolated sample value:\n this.triValue += this.triangle.sampleValue;\n }\n\n // Now sample normally:\n if (cycles === 2) {\n this.smpTriangle += this.triValue << 1;\n this.smpDmc += this.dmc.sample << 1;\n this.smpSquare1 += this.square1.sampleValue << 1;\n this.smpSquare2 += this.square2.sampleValue << 1;\n this.accCount += 2;\n } else if (cycles === 4) {\n this.smpTriangle += this.triValue << 2;\n this.smpDmc += this.dmc.sample << 2;\n this.smpSquare1 += this.square1.sampleValue << 2;\n this.smpSquare2 += this.square2.sampleValue << 2;\n this.accCount += 4;\n } else {\n this.smpTriangle += cycles * this.triValue;\n this.smpDmc += cycles * this.dmc.sample;\n this.smpSquare1 += cycles * this.square1.sampleValue;\n this.smpSquare2 += cycles * this.square2.sampleValue;\n this.accCount += cycles;\n }\n },\n\n frameCounterTick: function() {\n this.derivedFrameCounter++;\n if (this.derivedFrameCounter >= this.frameIrqCounterMax) {\n this.derivedFrameCounter = 0;\n }\n\n if (this.derivedFrameCounter === 1 || this.derivedFrameCounter === 3) {\n // Clock length & sweep:\n this.triangle.clockLengthCounter();\n this.square1.clockLengthCounter();\n this.square2.clockLengthCounter();\n this.noise.clockLengthCounter();\n this.square1.clockSweep();\n this.square2.clockSweep();\n }\n\n if (this.derivedFrameCounter >= 0 && this.derivedFrameCounter < 4) {\n // Clock linear & decay:\n this.square1.clockEnvDecay();\n this.square2.clockEnvDecay();\n this.noise.clockEnvDecay();\n this.triangle.clockLinearCounter();\n }\n\n if (this.derivedFrameCounter === 3 && this.countSequence === 0) {\n // Enable IRQ:\n this.frameIrqActive = true;\n }\n\n // End of 240Hz tick\n },\n\n // Samples the channels, mixes the output together, then writes to buffer.\n sample: function() {\n var sq_index, tnd_index;\n\n if (this.accCount > 0) {\n this.smpSquare1 <<= 4;\n this.smpSquare1 = Math.floor(this.smpSquare1 / this.accCount);\n\n this.smpSquare2 <<= 4;\n this.smpSquare2 = Math.floor(this.smpSquare2 / this.accCount);\n\n this.smpTriangle = Math.floor(this.smpTriangle / this.accCount);\n\n this.smpDmc <<= 4;\n this.smpDmc = Math.floor(this.smpDmc / this.accCount);\n\n this.accCount = 0;\n } else {\n this.smpSquare1 = this.square1.sampleValue << 4;\n this.smpSquare2 = this.square2.sampleValue << 4;\n this.smpTriangle = this.triangle.sampleValue;\n this.smpDmc = this.dmc.sample << 4;\n }\n\n var smpNoise = Math.floor((this.noise.accValue << 4) / this.noise.accCount);\n this.noise.accValue = smpNoise >> 4;\n this.noise.accCount = 1;\n\n // Stereo sound.\n\n // Left channel:\n sq_index =\n (this.smpSquare1 * this.stereoPosLSquare1 +\n this.smpSquare2 * this.stereoPosLSquare2) >>\n 8;\n tnd_index =\n (3 * this.smpTriangle * this.stereoPosLTriangle +\n (smpNoise << 1) * this.stereoPosLNoise +\n this.smpDmc * this.stereoPosLDMC) >>\n 8;\n if (sq_index >= this.square_table.length) {\n sq_index = this.square_table.length - 1;\n }\n if (tnd_index >= this.tnd_table.length) {\n tnd_index = this.tnd_table.length - 1;\n }\n var sampleValueL =\n this.square_table[sq_index] + this.tnd_table[tnd_index] - this.dcValue;\n\n // Right channel:\n sq_index =\n (this.smpSquare1 * this.stereoPosRSquare1 +\n this.smpSquare2 * this.stereoPosRSquare2) >>\n 8;\n tnd_index =\n (3 * this.smpTriangle * this.stereoPosRTriangle +\n (smpNoise << 1) * this.stereoPosRNoise +\n this.smpDmc * this.stereoPosRDMC) >>\n 8;\n if (sq_index >= this.square_table.length) {\n sq_index = this.square_table.length - 1;\n }\n if (tnd_index >= this.tnd_table.length) {\n tnd_index = this.tnd_table.length - 1;\n }\n var sampleValueR =\n this.square_table[sq_index] + this.tnd_table[tnd_index] - this.dcValue;\n\n // Remove DC from left channel:\n var smpDiffL = sampleValueL - this.prevSampleL;\n this.prevSampleL += smpDiffL;\n this.smpAccumL += smpDiffL - (this.smpAccumL >> 10);\n sampleValueL = this.smpAccumL;\n\n // Remove DC from right channel:\n var smpDiffR = sampleValueR - this.prevSampleR;\n this.prevSampleR += smpDiffR;\n this.smpAccumR += smpDiffR - (this.smpAccumR >> 10);\n sampleValueR = this.smpAccumR;\n\n // Write:\n if (sampleValueL > this.maxSample) {\n this.maxSample = sampleValueL;\n }\n if (sampleValueL < this.minSample) {\n this.minSample = sampleValueL;\n }\n\n if (this.nes.opts.onAudioSample) {\n this.nes.opts.onAudioSample(sampleValueL / 32768, sampleValueR / 32768);\n }\n\n // Reset sampled values:\n this.smpSquare1 = 0;\n this.smpSquare2 = 0;\n this.smpTriangle = 0;\n this.smpDmc = 0;\n },\n\n getLengthMax: function(value) {\n return this.lengthLookup[value >> 3];\n },\n\n getDmcFrequency: function(value) {\n if (value >= 0 && value < 0x10) {\n return this.dmcFreqLookup[value];\n }\n return 0;\n },\n\n getNoiseWaveLength: function(value) {\n if (value >= 0 && value < 0x10) {\n return this.noiseWavelengthLookup[value];\n }\n return 0;\n },\n\n setPanning: function(pos) {\n for (var i = 0; i < 5; i++) {\n this.panning[i] = pos[i];\n }\n this.updateStereoPos();\n },\n\n setMasterVolume: function(value) {\n if (value < 0) {\n value = 0;\n }\n if (value > 256) {\n value = 256;\n }\n this.masterVolume = value;\n this.updateStereoPos();\n },\n\n updateStereoPos: function() {\n this.stereoPosLSquare1 = (this.panning[0] * this.masterVolume) >> 8;\n this.stereoPosLSquare2 = (this.panning[1] * this.masterVolume) >> 8;\n this.stereoPosLTriangle = (this.panning[2] * this.masterVolume) >> 8;\n this.stereoPosLNoise = (this.panning[3] * this.masterVolume) >> 8;\n this.stereoPosLDMC = (this.panning[4] * this.masterVolume) >> 8;\n\n this.stereoPosRSquare1 = this.masterVolume - this.stereoPosLSquare1;\n this.stereoPosRSquare2 = this.masterVolume - this.stereoPosLSquare2;\n this.stereoPosRTriangle = this.masterVolume - this.stereoPosLTriangle;\n this.stereoPosRNoise = this.masterVolume - this.stereoPosLNoise;\n this.stereoPosRDMC = this.masterVolume - this.stereoPosLDMC;\n },\n\n initLengthLookup: function() {\n // prettier-ignore\n this.lengthLookup = [\n 0x0A, 0xFE,\n 0x14, 0x02,\n 0x28, 0x04,\n 0x50, 0x06,\n 0xA0, 0x08,\n 0x3C, 0x0A,\n 0x0E, 0x0C,\n 0x1A, 0x0E,\n 0x0C, 0x10,\n 0x18, 0x12,\n 0x30, 0x14,\n 0x60, 0x16,\n 0xC0, 0x18,\n 0x48, 0x1A,\n 0x10, 0x1C,\n 0x20, 0x1E\n ];\n },\n\n initDmcFrequencyLookup: function() {\n this.dmcFreqLookup = new Array(16);\n\n this.dmcFreqLookup[0x0] = 0xd60;\n this.dmcFreqLookup[0x1] = 0xbe0;\n this.dmcFreqLookup[0x2] = 0xaa0;\n this.dmcFreqLookup[0x3] = 0xa00;\n this.dmcFreqLookup[0x4] = 0x8f0;\n this.dmcFreqLookup[0x5] = 0x7f0;\n this.dmcFreqLookup[0x6] = 0x710;\n this.dmcFreqLookup[0x7] = 0x6b0;\n this.dmcFreqLookup[0x8] = 0x5f0;\n this.dmcFreqLookup[0x9] = 0x500;\n this.dmcFreqLookup[0xa] = 0x470;\n this.dmcFreqLookup[0xb] = 0x400;\n this.dmcFreqLookup[0xc] = 0x350;\n this.dmcFreqLookup[0xd] = 0x2a0;\n this.dmcFreqLookup[0xe] = 0x240;\n this.dmcFreqLookup[0xf] = 0x1b0;\n //for(int i=0;i<16;i++)dmcFreqLookup[i]/=8;\n },\n\n initNoiseWavelengthLookup: function() {\n this.noiseWavelengthLookup = new Array(16);\n\n this.noiseWavelengthLookup[0x0] = 0x004;\n this.noiseWavelengthLookup[0x1] = 0x008;\n this.noiseWavelengthLookup[0x2] = 0x010;\n this.noiseWavelengthLookup[0x3] = 0x020;\n this.noiseWavelengthLookup[0x4] = 0x040;\n this.noiseWavelengthLookup[0x5] = 0x060;\n this.noiseWavelengthLookup[0x6] = 0x080;\n this.noiseWavelengthLookup[0x7] = 0x0a0;\n this.noiseWavelengthLookup[0x8] = 0x0ca;\n this.noiseWavelengthLookup[0x9] = 0x0fe;\n this.noiseWavelengthLookup[0xa] = 0x17c;\n this.noiseWavelengthLookup[0xb] = 0x1fc;\n this.noiseWavelengthLookup[0xc] = 0x2fa;\n this.noiseWavelengthLookup[0xd] = 0x3f8;\n this.noiseWavelengthLookup[0xe] = 0x7f2;\n this.noiseWavelengthLookup[0xf] = 0xfe4;\n },\n\n initDACtables: function() {\n var value, ival, i;\n var max_sqr = 0;\n var max_tnd = 0;\n\n this.square_table = new Array(32 * 16);\n this.tnd_table = new Array(204 * 16);\n\n for (i = 0; i < 32 * 16; i++) {\n value = 95.52 / (8128.0 / (i / 16.0) + 100.0);\n value *= 0.98411;\n value *= 50000.0;\n ival = Math.floor(value);\n\n this.square_table[i] = ival;\n if (ival > max_sqr) {\n max_sqr = ival;\n }\n }\n\n for (i = 0; i < 204 * 16; i++) {\n value = 163.67 / (24329.0 / (i / 16.0) + 100.0);\n value *= 0.98411;\n value *= 50000.0;\n ival = Math.floor(value);\n\n this.tnd_table[i] = ival;\n if (ival > max_tnd) {\n max_tnd = ival;\n }\n }\n\n this.dacRange = max_sqr + max_tnd;\n this.dcValue = this.dacRange / 2;\n }\n};\n\nvar ChannelDM = function(papu) {\n this.papu = papu;\n\n this.MODE_NORMAL = 0;\n this.MODE_LOOP = 1;\n this.MODE_IRQ = 2;\n\n this.isEnabled = null;\n this.hasSample = null;\n this.irqGenerated = false;\n\n this.playMode = null;\n this.dmaFrequency = null;\n this.dmaCounter = null;\n this.deltaCounter = null;\n this.playStartAddress = null;\n this.playAddress = null;\n this.playLength = null;\n this.playLengthCounter = null;\n this.shiftCounter = null;\n this.reg4012 = null;\n this.reg4013 = null;\n this.sample = null;\n this.dacLsb = null;\n this.data = null;\n\n this.reset();\n};\n\nChannelDM.prototype = {\n clockDmc: function() {\n // Only alter DAC value if the sample buffer has data:\n if (this.hasSample) {\n if ((this.data & 1) === 0) {\n // Decrement delta:\n if (this.deltaCounter > 0) {\n this.deltaCounter--;\n }\n } else {\n // Increment delta:\n if (this.deltaCounter < 63) {\n this.deltaCounter++;\n }\n }\n\n // Update sample value:\n this.sample = this.isEnabled ? (this.deltaCounter << 1) + this.dacLsb : 0;\n\n // Update shift register:\n this.data >>= 1;\n }\n\n this.dmaCounter--;\n if (this.dmaCounter <= 0) {\n // No more sample bits.\n this.hasSample = false;\n this.endOfSample();\n this.dmaCounter = 8;\n }\n\n if (this.irqGenerated) {\n this.papu.nes.cpu.requestIrq(this.papu.nes.cpu.IRQ_NORMAL);\n }\n },\n\n endOfSample: function() {\n if (this.playLengthCounter === 0 && this.playMode === this.MODE_LOOP) {\n // Start from beginning of sample:\n this.playAddress = this.playStartAddress;\n this.playLengthCounter = this.playLength;\n }\n\n if (this.playLengthCounter > 0) {\n // Fetch next sample:\n this.nextSample();\n\n if (this.playLengthCounter === 0) {\n // Last byte of sample fetched, generate IRQ:\n if (this.playMode === this.MODE_IRQ) {\n // Generate IRQ:\n this.irqGenerated = true;\n }\n }\n }\n },\n\n nextSample: function() {\n // Fetch byte:\n this.data = this.papu.nes.mmap.load(this.playAddress);\n this.papu.nes.cpu.haltCycles(4);\n\n this.playLengthCounter--;\n this.playAddress++;\n if (this.playAddress > 0xffff) {\n this.playAddress = 0x8000;\n }\n\n this.hasSample = true;\n },\n\n writeReg: function(address, value) {\n if (address === 0x4010) {\n // Play mode, DMA Frequency\n if (value >> 6 === 0) {\n this.playMode = this.MODE_NORMAL;\n } else if (((value >> 6) & 1) === 1) {\n this.playMode = this.MODE_LOOP;\n } else if (value >> 6 === 2) {\n this.playMode = this.MODE_IRQ;\n }\n\n if ((value & 0x80) === 0) {\n this.irqGenerated = false;\n }\n\n this.dmaFrequency = this.papu.getDmcFrequency(value & 0xf);\n } else if (address === 0x4011) {\n // Delta counter load register:\n this.deltaCounter = (value >> 1) & 63;\n this.dacLsb = value & 1;\n this.sample = (this.deltaCounter << 1) + this.dacLsb; // update sample value\n } else if (address === 0x4012) {\n // DMA address load register\n this.playStartAddress = (value << 6) | 0x0c000;\n this.playAddress = this.playStartAddress;\n this.reg4012 = value;\n } else if (address === 0x4013) {\n // Length of play code\n this.playLength = (value << 4) + 1;\n this.playLengthCounter = this.playLength;\n this.reg4013 = value;\n } else if (address === 0x4015) {\n // DMC/IRQ Status\n if (((value >> 4) & 1) === 0) {\n // Disable:\n this.playLengthCounter = 0;\n } else {\n // Restart:\n this.playAddress = this.playStartAddress;\n this.playLengthCounter = this.playLength;\n }\n this.irqGenerated = false;\n }\n },\n\n setEnabled: function(value) {\n if (!this.isEnabled && value) {\n this.playLengthCounter = this.playLength;\n }\n this.isEnabled = value;\n },\n\n getLengthStatus: function() {\n return this.playLengthCounter === 0 || !this.isEnabled ? 0 : 1;\n },\n\n getIrqStatus: function() {\n return this.irqGenerated ? 1 : 0;\n },\n\n reset: function() {\n this.isEnabled = false;\n this.irqGenerated = false;\n this.playMode = this.MODE_NORMAL;\n this.dmaFrequency = 0;\n this.dmaCounter = 0;\n this.deltaCounter = 0;\n this.playStartAddress = 0;\n this.playAddress = 0;\n this.playLength = 0;\n this.playLengthCounter = 0;\n this.sample = 0;\n this.dacLsb = 0;\n this.shiftCounter = 0;\n this.reg4012 = 0;\n this.reg4013 = 0;\n this.data = 0;\n }\n};\n\nvar ChannelNoise = function(papu) {\n this.papu = papu;\n\n this.isEnabled = null;\n this.envDecayDisable = null;\n this.envDecayLoopEnable = null;\n this.lengthCounterEnable = null;\n this.envReset = null;\n this.shiftNow = null;\n\n this.lengthCounter = null;\n this.progTimerCount = null;\n this.progTimerMax = null;\n this.envDecayRate = null;\n this.envDecayCounter = null;\n this.envVolume = null;\n this.masterVolume = null;\n this.shiftReg = 1 << 14;\n this.randomBit = null;\n this.randomMode = null;\n this.sampleValue = null;\n this.accValue = 0;\n this.accCount = 1;\n this.tmp = null;\n\n this.reset();\n};\n\nChannelNoise.prototype = {\n reset: function() {\n this.progTimerCount = 0;\n this.progTimerMax = 0;\n this.isEnabled = false;\n this.lengthCounter = 0;\n this.lengthCounterEnable = false;\n this.envDecayDisable = false;\n this.envDecayLoopEnable = false;\n this.shiftNow = false;\n this.envDecayRate = 0;\n this.envDecayCounter = 0;\n this.envVolume = 0;\n this.masterVolume = 0;\n this.shiftReg = 1;\n this.randomBit = 0;\n this.randomMode = 0;\n this.sampleValue = 0;\n this.tmp = 0;\n },\n\n clockLengthCounter: function() {\n if (this.lengthCounterEnable && this.lengthCounter > 0) {\n this.lengthCounter--;\n if (this.lengthCounter === 0) {\n this.updateSampleValue();\n }\n }\n },\n\n clockEnvDecay: function() {\n if (this.envReset) {\n // Reset envelope:\n this.envReset = false;\n this.envDecayCounter = this.envDecayRate + 1;\n this.envVolume = 0xf;\n } else if (--this.envDecayCounter <= 0) {\n // Normal handling:\n this.envDecayCounter = this.envDecayRate + 1;\n if (this.envVolume > 0) {\n this.envVolume--;\n } else {\n this.envVolume = this.envDecayLoopEnable ? 0xf : 0;\n }\n }\n if (this.envDecayDisable) {\n this.masterVolume = this.envDecayRate;\n } else {\n this.masterVolume = this.envVolume;\n }\n this.updateSampleValue();\n },\n\n updateSampleValue: function() {\n if (this.isEnabled && this.lengthCounter > 0) {\n this.sampleValue = this.randomBit * this.masterVolume;\n }\n },\n\n writeReg: function(address, value) {\n if (address === 0x400c) {\n // Volume/Envelope decay:\n this.envDecayDisable = (value & 0x10) !== 0;\n this.envDecayRate = value & 0xf;\n this.envDecayLoopEnable = (value & 0x20) !== 0;\n this.lengthCounterEnable = (value & 0x20) === 0;\n if (this.envDecayDisable) {\n this.masterVolume = this.envDecayRate;\n } else {\n this.masterVolume = this.envVolume;\n }\n } else if (address === 0x400e) {\n // Programmable timer:\n this.progTimerMax = this.papu.getNoiseWaveLength(value & 0xf);\n this.randomMode = value >> 7;\n } else if (address === 0x400f) {\n // Length counter\n this.lengthCounter = this.papu.getLengthMax(value & 248);\n this.envReset = true;\n }\n // Update:\n //updateSampleValue();\n },\n\n setEnabled: function(value) {\n this.isEnabled = value;\n if (!value) {\n this.lengthCounter = 0;\n }\n this.updateSampleValue();\n },\n\n getLengthStatus: function() {\n return this.lengthCounter === 0 || !this.isEnabled ? 0 : 1;\n }\n};\n\nvar ChannelSquare = function(papu, square1) {\n this.papu = papu;\n\n // prettier-ignore\n this.dutyLookup = [\n 0, 1, 0, 0, 0, 0, 0, 0,\n 0, 1, 1, 0, 0, 0, 0, 0,\n 0, 1, 1, 1, 1, 0, 0, 0,\n 1, 0, 0, 1, 1, 1, 1, 1\n ];\n // prettier-ignore\n this.impLookup = [\n 1,-1, 0, 0, 0, 0, 0, 0,\n 1, 0,-1, 0, 0, 0, 0, 0,\n 1, 0, 0, 0,-1, 0, 0, 0,\n -1, 0, 1, 0, 0, 0, 0, 0\n ];\n\n this.sqr1 = square1;\n this.isEnabled = null;\n this.lengthCounterEnable = null;\n this.sweepActive = null;\n this.envDecayDisable = null;\n this.envDecayLoopEnable = null;\n this.envReset = null;\n this.sweepCarry = null;\n this.updateSweepPeriod = null;\n\n this.progTimerCount = null;\n this.progTimerMax = null;\n this.lengthCounter = null;\n this.squareCounter = null;\n this.sweepCounter = null;\n this.sweepCounterMax = null;\n this.sweepMode = null;\n this.sweepShiftAmount = null;\n this.envDecayRate = null;\n this.envDecayCounter = null;\n this.envVolume = null;\n this.masterVolume = null;\n this.dutyMode = null;\n this.sweepResult = null;\n this.sampleValue = null;\n this.vol = null;\n\n this.reset();\n};\n\nChannelSquare.prototype = {\n reset: function() {\n this.progTimerCount = 0;\n this.progTimerMax = 0;\n this.lengthCounter = 0;\n this.squareCounter = 0;\n this.sweepCounter = 0;\n this.sweepCounterMax = 0;\n this.sweepMode = 0;\n this.sweepShiftAmount = 0;\n this.envDecayRate = 0;\n this.envDecayCounter = 0;\n this.envVolume = 0;\n this.masterVolume = 0;\n this.dutyMode = 0;\n this.vol = 0;\n\n this.isEnabled = false;\n this.lengthCounterEnable = false;\n this.sweepActive = false;\n this.sweepCarry = false;\n this.envDecayDisable = false;\n this.envDecayLoopEnable = false;\n },\n\n clockLengthCounter: function() {\n if (this.lengthCounterEnable && this.lengthCounter > 0) {\n this.lengthCounter--;\n if (this.lengthCounter === 0) {\n this.updateSampleValue();\n }\n }\n },\n\n clockEnvDecay: function() {\n if (this.envReset) {\n // Reset envelope:\n this.envReset = false;\n this.envDecayCounter = this.envDecayRate + 1;\n this.envVolume = 0xf;\n } else if (--this.envDecayCounter <= 0) {\n // Normal handling:\n this.envDecayCounter = this.envDecayRate + 1;\n if (this.envVolume > 0) {\n this.envVolume--;\n } else {\n this.envVolume = this.envDecayLoopEnable ? 0xf : 0;\n }\n }\n\n if (this.envDecayDisable) {\n this.masterVolume = this.envDecayRate;\n } else {\n this.masterVolume = this.envVolume;\n }\n this.updateSampleValue();\n },\n\n clockSweep: function() {\n if (--this.sweepCounter <= 0) {\n this.sweepCounter = this.sweepCounterMax + 1;\n if (\n this.sweepActive &&\n this.sweepShiftAmount > 0 &&\n this.progTimerMax > 7\n ) {\n // Calculate result from shifter:\n this.sweepCarry = false;\n if (this.sweepMode === 0) {\n this.progTimerMax += this.progTimerMax >> this.sweepShiftAmount;\n if (this.progTimerMax > 4095) {\n this.progTimerMax = 4095;\n this.sweepCarry = true;\n }\n } else {\n this.progTimerMax =\n this.progTimerMax -\n ((this.progTimerMax >> this.sweepShiftAmount) -\n (this.sqr1 ? 1 : 0));\n }\n }\n }\n\n if (this.updateSweepPeriod) {\n this.updateSweepPeriod = false;\n this.sweepCounter = this.sweepCounterMax + 1;\n }\n },\n\n updateSampleValue: function() {\n if (this.isEnabled && this.lengthCounter > 0 && this.progTimerMax > 7) {\n if (\n this.sweepMode === 0 &&\n this.progTimerMax + (this.progTimerMax >> this.sweepShiftAmount) > 4095\n ) {\n //if (this.sweepCarry) {\n this.sampleValue = 0;\n } else {\n this.sampleValue =\n this.masterVolume *\n this.dutyLookup[(this.dutyMode << 3) + this.squareCounter];\n }\n } else {\n this.sampleValue = 0;\n }\n },\n\n writeReg: function(address, value) {\n var addrAdd = this.sqr1 ? 0 : 4;\n if (address === 0x4000 + addrAdd) {\n // Volume/Envelope decay:\n this.envDecayDisable = (value & 0x10) !== 0;\n this.envDecayRate = value & 0xf;\n this.envDecayLoopEnable = (value & 0x20) !== 0;\n this.dutyMode = (value >> 6) & 0x3;\n this.lengthCounterEnable = (value & 0x20) === 0;\n if (this.envDecayDisable) {\n this.masterVolume = this.envDecayRate;\n } else {\n this.masterVolume = this.envVolume;\n }\n this.updateSampleValue();\n } else if (address === 0x4001 + addrAdd) {\n // Sweep:\n this.sweepActive = (value & 0x80) !== 0;\n this.sweepCounterMax = (value >> 4) & 7;\n this.sweepMode = (value >> 3) & 1;\n this.sweepShiftAmount = value & 7;\n this.updateSweepPeriod = true;\n } else if (address === 0x4002 + addrAdd) {\n // Programmable timer:\n this.progTimerMax &= 0x700;\n this.progTimerMax |= value;\n } else if (address === 0x4003 + addrAdd) {\n // Programmable timer, length counter\n this.progTimerMax &= 0xff;\n this.progTimerMax |= (value & 0x7) << 8;\n\n if (this.isEnabled) {\n this.lengthCounter = this.papu.getLengthMax(value & 0xf8);\n }\n\n this.envReset = true;\n }\n },\n\n setEnabled: function(value) {\n this.isEnabled = value;\n if (!value) {\n this.lengthCounter = 0;\n }\n this.updateSampleValue();\n },\n\n getLengthStatus: function() {\n return this.lengthCounter === 0 || !this.isEnabled ? 0 : 1;\n }\n};\n\nvar ChannelTriangle = function(papu) {\n this.papu = papu;\n\n this.isEnabled = null;\n this.sampleCondition = null;\n this.lengthCounterEnable = null;\n this.lcHalt = null;\n this.lcControl = null;\n\n this.progTimerCount = null;\n this.progTimerMax = null;\n this.triangleCounter = null;\n this.lengthCounter = null;\n this.linearCounter = null;\n this.lcLoadValue = null;\n this.sampleValue = null;\n this.tmp = null;\n\n this.reset();\n};\n\nChannelTriangle.prototype = {\n reset: function() {\n this.progTimerCount = 0;\n this.progTimerMax = 0;\n this.triangleCounter = 0;\n this.isEnabled = false;\n this.sampleCondition = false;\n this.lengthCounter = 0;\n this.lengthCounterEnable = false;\n this.linearCounter = 0;\n this.lcLoadValue = 0;\n this.lcHalt = true;\n this.lcControl = false;\n this.tmp = 0;\n this.sampleValue = 0xf;\n },\n\n clockLengthCounter: function() {\n if (this.lengthCounterEnable && this.lengthCounter > 0) {\n this.lengthCounter--;\n if (this.lengthCounter === 0) {\n this.updateSampleCondition();\n }\n }\n },\n\n clockLinearCounter: function() {\n if (this.lcHalt) {\n // Load:\n this.linearCounter = this.lcLoadValue;\n this.updateSampleCondition();\n } else if (this.linearCounter > 0) {\n // Decrement:\n this.linearCounter--;\n this.updateSampleCondition();\n }\n if (!this.lcControl) {\n // Clear halt flag:\n this.lcHalt = false;\n }\n },\n\n getLengthStatus: function() {\n return this.lengthCounter === 0 || !this.isEnabled ? 0 : 1;\n },\n\n readReg: function(address) {\n return 0;\n },\n\n writeReg: function(address, value) {\n if (address === 0x4008) {\n // New values for linear counter:\n this.lcControl = (value & 0x80) !== 0;\n this.lcLoadValue = value & 0x7f;\n\n // Length counter enable:\n this.lengthCounterEnable = !this.lcControl;\n } else if (address === 0x400a) {\n // Programmable timer:\n this.progTimerMax &= 0x700;\n this.progTimerMax |= value;\n } else if (address === 0x400b) {\n // Programmable timer, length counter\n this.progTimerMax &= 0xff;\n this.progTimerMax |= (value & 0x07) << 8;\n this.lengthCounter = this.papu.getLengthMax(value & 0xf8);\n this.lcHalt = true;\n }\n\n this.updateSampleCondition();\n },\n\n clockProgrammableTimer: function(nCycles) {\n if (this.progTimerMax > 0) {\n this.progTimerCount += nCycles;\n while (\n this.progTimerMax > 0 &&\n this.progTimerCount >= this.progTimerMax\n ) {\n this.progTimerCount -= this.progTimerMax;\n if (\n this.isEnabled &&\n this.lengthCounter > 0 &&\n this.linearCounter > 0\n ) {\n this.clockTriangleGenerator();\n }\n }\n }\n },\n\n clockTriangleGenerator: function() {\n this.triangleCounter++;\n this.triangleCounter &= 0x1f;\n },\n\n setEnabled: function(value) {\n this.isEnabled = value;\n if (!value) {\n this.lengthCounter = 0;\n }\n this.updateSampleCondition();\n },\n\n updateSampleCondition: function() {\n this.sampleCondition =\n this.isEnabled &&\n this.progTimerMax > 7 &&\n this.linearCounter > 0 &&\n this.lengthCounter > 0;\n }\n};\n\nmodule.exports = PAPU;\n\n\n/***/ }),\n/* 8 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar Mappers = __webpack_require__(9);\nvar Tile = __webpack_require__(2);\n\nvar ROM = function(nes) {\n this.nes = nes;\n\n this.mapperName = new Array(92);\n\n for (var i = 0; i < 92; i++) {\n this.mapperName[i] = \"Unknown Mapper\";\n }\n this.mapperName[0] = \"Direct Access\";\n this.mapperName[1] = \"Nintendo MMC1\";\n this.mapperName[2] = \"UNROM\";\n this.mapperName[3] = \"CNROM\";\n this.mapperName[4] = \"Nintendo MMC3\";\n this.mapperName[5] = \"Nintendo MMC5\";\n this.mapperName[6] = \"FFE F4xxx\";\n this.mapperName[7] = \"AOROM\";\n this.mapperName[8] = \"FFE F3xxx\";\n this.mapperName[9] = \"Nintendo MMC2\";\n this.mapperName[10] = \"Nintendo MMC4\";\n this.mapperName[11] = \"Color Dreams Chip\";\n this.mapperName[12] = \"FFE F6xxx\";\n this.mapperName[15] = \"100-in-1 switch\";\n this.mapperName[16] = \"Bandai chip\";\n this.mapperName[17] = \"FFE F8xxx\";\n this.mapperName[18] = \"Jaleco SS8806 chip\";\n this.mapperName[19] = \"Namcot 106 chip\";\n this.mapperName[20] = \"Famicom Disk System\";\n this.mapperName[21] = \"Konami VRC4a\";\n this.mapperName[22] = \"Konami VRC2a\";\n this.mapperName[23] = \"Konami VRC2a\";\n this.mapperName[24] = \"Konami VRC6\";\n this.mapperName[25] = \"Konami VRC4b\";\n this.mapperName[32] = \"Irem G-101 chip\";\n this.mapperName[33] = \"Taito TC0190/TC0350\";\n this.mapperName[34] = \"32kB ROM switch\";\n\n this.mapperName[64] = \"Tengen RAMBO-1 chip\";\n this.mapperName[65] = \"Irem H-3001 chip\";\n this.mapperName[66] = \"GNROM switch\";\n this.mapperName[67] = \"SunSoft3 chip\";\n this.mapperName[68] = \"SunSoft4 chip\";\n this.mapperName[69] = \"SunSoft5 FME-7 chip\";\n this.mapperName[71] = \"Camerica chip\";\n this.mapperName[78] = \"Irem 74HC161/32-based\";\n this.mapperName[91] = \"Pirate HK-SF3 chip\";\n};\n\nROM.prototype = {\n // Mirroring types:\n VERTICAL_MIRRORING: 0,\n HORIZONTAL_MIRRORING: 1,\n FOURSCREEN_MIRRORING: 2,\n SINGLESCREEN_MIRRORING: 3,\n SINGLESCREEN_MIRRORING2: 4,\n SINGLESCREEN_MIRRORING3: 5,\n SINGLESCREEN_MIRRORING4: 6,\n CHRROM_MIRRORING: 7,\n\n header: null,\n rom: null,\n vrom: null,\n vromTile: null,\n\n romCount: null,\n vromCount: null,\n mirroring: null,\n batteryRam: null,\n trainer: null,\n fourScreen: null,\n mapperType: null,\n valid: false,\n\n load: function(data) {\n var i, j, v;\n\n if (data.indexOf(\"NES\\x1a\") === -1) {\n throw new Error(\"Not a valid NES ROM.\");\n }\n this.header = new Array(16);\n for (i = 0; i < 16; i++) {\n this.header[i] = data.charCodeAt(i) & 0xff;\n }\n this.romCount = this.header[4];\n this.vromCount = this.header[5] * 2; // Get the number of 4kB banks, not 8kB\n this.mirroring = (this.header[6] & 1) !== 0 ? 1 : 0;\n this.batteryRam = (this.header[6] & 2) !== 0;\n this.trainer = (this.header[6] & 4) !== 0;\n this.fourScreen = (this.header[6] & 8) !== 0;\n this.mapperType = (this.header[6] >> 4) | (this.header[7] & 0xf0);\n /* TODO\n if (this.batteryRam)\n this.loadBatteryRam();*/\n // Check whether byte 8-15 are zero's:\n var foundError = false;\n for (i = 8; i < 16; i++) {\n if (this.header[i] !== 0) {\n foundError = true;\n break;\n }\n }\n if (foundError) {\n this.mapperType &= 0xf; // Ignore byte 7\n }\n // Load PRG-ROM banks:\n this.rom = new Array(this.romCount);\n var offset = 16;\n for (i = 0; i < this.romCount; i++) {\n this.rom[i] = new Array(16384);\n for (j = 0; j < 16384; j++) {\n if (offset + j >= data.length) {\n break;\n }\n this.rom[i][j] = data.charCodeAt(offset + j) & 0xff;\n }\n offset += 16384;\n }\n // Load CHR-ROM banks:\n this.vrom = new Array(this.vromCount);\n for (i = 0; i < this.vromCount; i++) {\n this.vrom[i] = new Array(4096);\n for (j = 0; j < 4096; j++) {\n if (offset + j >= data.length) {\n break;\n }\n this.vrom[i][j] = data.charCodeAt(offset + j) & 0xff;\n }\n offset += 4096;\n }\n\n // Create VROM tiles:\n this.vromTile = new Array(this.vromCount);\n for (i = 0; i < this.vromCount; i++) {\n this.vromTile[i] = new Array(256);\n for (j = 0; j < 256; j++) {\n this.vromTile[i][j] = new Tile();\n }\n }\n\n // Convert CHR-ROM banks to tiles:\n var tileIndex;\n var leftOver;\n for (v = 0; v < this.vromCount; v++) {\n for (i = 0; i < 4096; i++) {\n tileIndex = i >> 4;\n leftOver = i % 16;\n if (leftOver < 8) {\n this.vromTile[v][tileIndex].setScanline(\n leftOver,\n this.vrom[v][i],\n this.vrom[v][i + 8]\n );\n } else {\n this.vromTile[v][tileIndex].setScanline(\n leftOver - 8,\n this.vrom[v][i - 8],\n this.vrom[v][i]\n );\n }\n }\n }\n\n this.valid = true;\n },\n\n getMirroringType: function() {\n if (this.fourScreen) {\n return this.FOURSCREEN_MIRRORING;\n }\n if (this.mirroring === 0) {\n return this.HORIZONTAL_MIRRORING;\n }\n return this.VERTICAL_MIRRORING;\n },\n\n getMapperName: function() {\n if (this.mapperType >= 0 && this.mapperType < this.mapperName.length) {\n return this.mapperName[this.mapperType];\n }\n return \"Unknown Mapper, \" + this.mapperType;\n },\n\n mapperSupported: function() {\n return typeof Mappers[this.mapperType] !== \"undefined\";\n },\n\n createMapper: function() {\n if (this.mapperSupported()) {\n return new Mappers[this.mapperType](this.nes);\n } else {\n throw new Error(\n \"This ROM uses a mapper not supported by JSNES: \" +\n this.getMapperName() +\n \"(\" +\n this.mapperType +\n \")\"\n );\n }\n }\n};\n\nmodule.exports = ROM;\n\n\n/***/ }),\n/* 9 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar utils = __webpack_require__(0);\n\nvar Mappers = {};\n\nMappers[0] = function(nes) {\n this.nes = nes;\n};\n\nMappers[0].prototype = {\n reset: function() {\n this.joy1StrobeState = 0;\n this.joy2StrobeState = 0;\n this.joypadLastWrite = 0;\n\n this.zapperFired = false;\n this.zapperX = null;\n this.zapperY = null;\n },\n\n write: function(address, value) {\n if (address < 0x2000) {\n // Mirroring of RAM:\n this.nes.cpu.mem[address & 0x7ff] = value;\n } else if (address > 0x4017) {\n this.nes.cpu.mem[address] = value;\n if (address >= 0x6000 && address < 0x8000) {\n // Write to persistent RAM\n this.nes.opts.onBatteryRamWrite(address, value);\n }\n } else if (address > 0x2007 && address < 0x4000) {\n this.regWrite(0x2000 + (address & 0x7), value);\n } else {\n this.regWrite(address, value);\n }\n },\n\n writelow: function(address, value) {\n if (address < 0x2000) {\n // Mirroring of RAM:\n this.nes.cpu.mem[address & 0x7ff] = value;\n } else if (address > 0x4017) {\n this.nes.cpu.mem[address] = value;\n } else if (address > 0x2007 && address < 0x4000) {\n this.regWrite(0x2000 + (address & 0x7), value);\n } else {\n this.regWrite(address, value);\n }\n },\n\n load: function(address) {\n // Wrap around:\n address &= 0xffff;\n\n // Check address range:\n if (address > 0x4017) {\n // ROM:\n return this.nes.cpu.mem[address];\n } else if (address >= 0x2000) {\n // I/O Ports.\n return this.regLoad(address);\n } else {\n // RAM (mirrored)\n return this.nes.cpu.mem[address & 0x7ff];\n }\n },\n\n regLoad: function(address) {\n switch (address >> 12) { // use fourth nibble (0xF000)\n case 0:\n break;\n\n case 1:\n break;\n\n case 2:\n // Fall through to case 3\n case 3:\n // PPU Registers\n switch (address & 0x7) {\n case 0x0:\n // 0x2000:\n // PPU Control Register 1.\n // (the value is stored both\n // in main memory and in the\n // PPU as flags):\n // (not in the real NES)\n return this.nes.cpu.mem[0x2000];\n\n case 0x1:\n // 0x2001:\n // PPU Control Register 2.\n // (the value is stored both\n // in main memory and in the\n // PPU as flags):\n // (not in the real NES)\n return this.nes.cpu.mem[0x2001];\n\n case 0x2:\n // 0x2002:\n // PPU Status Register.\n // The value is stored in\n // main memory in addition\n // to as flags in the PPU.\n // (not in the real NES)\n return this.nes.ppu.readStatusRegister();\n\n case 0x3:\n return 0;\n\n case 0x4:\n // 0x2004:\n // Sprite Memory read.\n return this.nes.ppu.sramLoad();\n case 0x5:\n return 0;\n\n case 0x6:\n return 0;\n\n case 0x7:\n // 0x2007:\n // VRAM read:\n return this.nes.ppu.vramLoad();\n }\n break;\n case 4:\n // Sound+Joypad registers\n switch (address - 0x4015) {\n case 0:\n // 0x4015:\n // Sound channel enable, DMC Status\n return this.nes.papu.readReg(address);\n\n case 1:\n // 0x4016:\n // Joystick 1 + Strobe\n return this.joy1Read();\n\n case 2:\n // 0x4017:\n // Joystick 2 + Strobe\n // https://wiki.nesdev.com/w/index.php/Zapper\n var w;\n\n if (\n this.zapperX !== null &&\n this.zapperY !== null &&\n this.nes.ppu.isPixelWhite(this.zapperX, this.zapperY)\n ) {\n w = 0;\n } else {\n w = 0x1 << 3;\n }\n\n if (this.zapperFired) {\n w |= 0x1 << 4;\n }\n return (this.joy2Read() | w) & 0xffff;\n }\n break;\n }\n return 0;\n },\n\n regWrite: function(address, value) {\n switch (address) {\n case 0x2000:\n // PPU Control register 1\n this.nes.cpu.mem[address] = value;\n this.nes.ppu.updateControlReg1(value);\n break;\n\n case 0x2001:\n // PPU Control register 2\n this.nes.cpu.mem[address] = value;\n this.nes.ppu.updateControlReg2(value);\n break;\n\n case 0x2003:\n // Set Sprite RAM address:\n this.nes.ppu.writeSRAMAddress(value);\n break;\n\n case 0x2004:\n // Write to Sprite RAM:\n this.nes.ppu.sramWrite(value);\n break;\n\n case 0x2005:\n // Screen Scroll offsets:\n this.nes.ppu.scrollWrite(value);\n break;\n\n case 0x2006:\n // Set VRAM address:\n this.nes.ppu.writeVRAMAddress(value);\n break;\n\n case 0x2007:\n // Write to VRAM:\n this.nes.ppu.vramWrite(value);\n break;\n\n case 0x4014:\n // Sprite Memory DMA Access\n this.nes.ppu.sramDMA(value);\n break;\n\n case 0x4015:\n // Sound Channel Switch, DMC Status\n this.nes.papu.writeReg(address, value);\n break;\n\n case 0x4016:\n // Joystick 1 + Strobe\n if ((value & 1) === 0 && (this.joypadLastWrite & 1) === 1) {\n this.joy1StrobeState = 0;\n this.joy2StrobeState = 0;\n }\n this.joypadLastWrite = value;\n break;\n\n case 0x4017:\n // Sound channel frame sequencer:\n this.nes.papu.writeReg(address, value);\n break;\n\n default:\n // Sound registers\n // console.log(\"write to sound reg\");\n if (address >= 0x4000 && address <= 0x4017) {\n this.nes.papu.writeReg(address, value);\n }\n }\n },\n\n joy1Read: function() {\n var ret;\n\n switch (this.joy1StrobeState) {\n case 0:\n case 1:\n case 2:\n case 3:\n case 4:\n case 5:\n case 6:\n case 7:\n ret = this.nes.controllers[1].state[this.joy1StrobeState];\n break;\n case 8:\n case 9:\n case 10:\n case 11:\n case 12:\n case 13:\n case 14:\n case 15:\n case 16:\n case 17:\n case 18:\n ret = 0;\n break;\n case 19:\n ret = 1;\n break;\n default:\n ret = 0;\n }\n\n this.joy1StrobeState++;\n if (this.joy1StrobeState === 24) {\n this.joy1StrobeState = 0;\n }\n\n return ret;\n },\n\n joy2Read: function() {\n var ret;\n\n switch (this.joy2StrobeState) {\n case 0:\n case 1:\n case 2:\n case 3:\n case 4:\n case 5:\n case 6:\n case 7:\n ret = this.nes.controllers[2].state[this.joy2StrobeState];\n break;\n case 8:\n case 9:\n case 10:\n case 11:\n case 12:\n case 13:\n case 14:\n case 15:\n case 16:\n case 17:\n case 18:\n ret = 0;\n break;\n case 19:\n ret = 1;\n break;\n default:\n ret = 0;\n }\n\n this.joy2StrobeState++;\n if (this.joy2StrobeState === 24) {\n this.joy2StrobeState = 0;\n }\n\n return ret;\n },\n\n loadROM: function() {\n if (!this.nes.rom.valid || this.nes.rom.romCount < 1) {\n throw new Error(\"NoMapper: Invalid ROM! Unable to load.\");\n }\n\n // Load ROM into memory:\n this.loadPRGROM();\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Load Battery RAM (if present):\n this.loadBatteryRam();\n\n // Reset IRQ:\n //nes.getCpu().doResetInterrupt();\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n },\n\n loadPRGROM: function() {\n if (this.nes.rom.romCount > 1) {\n // Load the two first banks into memory.\n this.loadRomBank(0, 0x8000);\n this.loadRomBank(1, 0xc000);\n } else {\n // Load the one bank into both memory locations:\n this.loadRomBank(0, 0x8000);\n this.loadRomBank(0, 0xc000);\n }\n },\n\n loadCHRROM: function() {\n // console.log(\"Loading CHR ROM..\");\n if (this.nes.rom.vromCount > 0) {\n if (this.nes.rom.vromCount === 1) {\n this.loadVromBank(0, 0x0000);\n this.loadVromBank(0, 0x1000);\n } else {\n this.loadVromBank(0, 0x0000);\n this.loadVromBank(1, 0x1000);\n }\n } else {\n //System.out.println(\"There aren't any CHR-ROM banks..\");\n }\n },\n\n loadBatteryRam: function() {\n if (this.nes.rom.batteryRam) {\n var ram = this.nes.rom.batteryRam;\n if (ram !== null && ram.length === 0x2000) {\n // Load Battery RAM into memory:\n utils.copyArrayElements(ram, 0, this.nes.cpu.mem, 0x6000, 0x2000);\n }\n }\n },\n\n loadRomBank: function(bank, address) {\n // Loads a ROM bank into the specified address.\n bank %= this.nes.rom.romCount;\n //var data = this.nes.rom.rom[bank];\n //cpuMem.write(address,data,data.length);\n utils.copyArrayElements(\n this.nes.rom.rom[bank],\n 0,\n this.nes.cpu.mem,\n address,\n 16384\n );\n },\n\n loadVromBank: function(bank, address) {\n if (this.nes.rom.vromCount === 0) {\n return;\n }\n this.nes.ppu.triggerRendering();\n\n utils.copyArrayElements(\n this.nes.rom.vrom[bank % this.nes.rom.vromCount],\n 0,\n this.nes.ppu.vramMem,\n address,\n 4096\n );\n\n var vromTile = this.nes.rom.vromTile[bank % this.nes.rom.vromCount];\n utils.copyArrayElements(\n vromTile,\n 0,\n this.nes.ppu.ptTile,\n address >> 4,\n 256\n );\n },\n\n load32kRomBank: function(bank, address) {\n this.loadRomBank((bank * 2) % this.nes.rom.romCount, address);\n this.loadRomBank((bank * 2 + 1) % this.nes.rom.romCount, address + 16384);\n },\n\n load8kVromBank: function(bank4kStart, address) {\n if (this.nes.rom.vromCount === 0) {\n return;\n }\n this.nes.ppu.triggerRendering();\n\n this.loadVromBank(bank4kStart % this.nes.rom.vromCount, address);\n this.loadVromBank(\n (bank4kStart + 1) % this.nes.rom.vromCount,\n address + 4096\n );\n },\n\n load1kVromBank: function(bank1k, address) {\n if (this.nes.rom.vromCount === 0) {\n return;\n }\n this.nes.ppu.triggerRendering();\n\n var bank4k = Math.floor(bank1k / 4) % this.nes.rom.vromCount;\n var bankoffset = (bank1k % 4) * 1024;\n utils.copyArrayElements(\n this.nes.rom.vrom[bank4k],\n 0,\n this.nes.ppu.vramMem,\n bankoffset,\n 1024\n );\n\n // Update tiles:\n var vromTile = this.nes.rom.vromTile[bank4k];\n var baseIndex = address >> 4;\n for (var i = 0; i < 64; i++) {\n this.nes.ppu.ptTile[baseIndex + i] = vromTile[((bank1k % 4) << 6) + i];\n }\n },\n\n load2kVromBank: function(bank2k, address) {\n if (this.nes.rom.vromCount === 0) {\n return;\n }\n this.nes.ppu.triggerRendering();\n\n var bank4k = Math.floor(bank2k / 2) % this.nes.rom.vromCount;\n var bankoffset = (bank2k % 2) * 2048;\n utils.copyArrayElements(\n this.nes.rom.vrom[bank4k],\n bankoffset,\n this.nes.ppu.vramMem,\n address,\n 2048\n );\n\n // Update tiles:\n var vromTile = this.nes.rom.vromTile[bank4k];\n var baseIndex = address >> 4;\n for (var i = 0; i < 128; i++) {\n this.nes.ppu.ptTile[baseIndex + i] = vromTile[((bank2k % 2) << 7) + i];\n }\n },\n\n load8kRomBank: function(bank8k, address) {\n var bank16k = Math.floor(bank8k / 2) % this.nes.rom.romCount;\n var offset = (bank8k % 2) * 8192;\n\n //this.nes.cpu.mem.write(address,this.nes.rom.rom[bank16k],offset,8192);\n utils.copyArrayElements(\n this.nes.rom.rom[bank16k],\n offset,\n this.nes.cpu.mem,\n address,\n 8192\n );\n },\n\n clockIrqCounter: function() {\n // Does nothing. This is used by the MMC3 mapper.\n },\n\n latchAccess: function(address) {\n // Does nothing. This is used by MMC2.\n },\n\n toJSON: function() {\n return {\n joy1StrobeState: this.joy1StrobeState,\n joy2StrobeState: this.joy2StrobeState,\n joypadLastWrite: this.joypadLastWrite\n };\n },\n\n fromJSON: function(s) {\n this.joy1StrobeState = s.joy1StrobeState;\n this.joy2StrobeState = s.joy2StrobeState;\n this.joypadLastWrite = s.joypadLastWrite;\n }\n};\n\nMappers[1] = function(nes) {\n this.nes = nes;\n};\n\nMappers[1].prototype = new Mappers[0]();\n\nMappers[1].prototype.reset = function() {\n Mappers[0].prototype.reset.apply(this);\n\n // 5-bit buffer:\n this.regBuffer = 0;\n this.regBufferCounter = 0;\n\n // Register 0:\n this.mirroring = 0;\n this.oneScreenMirroring = 0;\n this.prgSwitchingArea = 1;\n this.prgSwitchingSize = 1;\n this.vromSwitchingSize = 0;\n\n // Register 1:\n this.romSelectionReg0 = 0;\n\n // Register 2:\n this.romSelectionReg1 = 0;\n\n // Register 3:\n this.romBankSelect = 0;\n};\n\nMappers[1].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n }\n\n // See what should be done with the written value:\n if ((value & 128) !== 0) {\n // Reset buffering:\n this.regBufferCounter = 0;\n this.regBuffer = 0;\n\n // Reset register:\n if (this.getRegNumber(address) === 0) {\n this.prgSwitchingArea = 1;\n this.prgSwitchingSize = 1;\n }\n } else {\n // Continue buffering:\n //regBuffer = (regBuffer & (0xFF-(1<<regBufferCounter))) | ((value & (1<<regBufferCounter))<<regBufferCounter);\n this.regBuffer =\n (this.regBuffer & (0xff - (1 << this.regBufferCounter))) |\n ((value & 1) << this.regBufferCounter);\n this.regBufferCounter++;\n\n if (this.regBufferCounter === 5) {\n // Use the buffered value:\n this.setReg(this.getRegNumber(address), this.regBuffer);\n\n // Reset buffer:\n this.regBuffer = 0;\n this.regBufferCounter = 0;\n }\n }\n};\n\nMappers[1].prototype.setReg = function(reg, value) {\n var tmp;\n\n switch (reg) {\n case 0:\n // Mirroring:\n tmp = value & 3;\n if (tmp !== this.mirroring) {\n // Set mirroring:\n this.mirroring = tmp;\n if ((this.mirroring & 2) === 0) {\n // SingleScreen mirroring overrides the other setting:\n this.nes.ppu.setMirroring(this.nes.rom.SINGLESCREEN_MIRRORING);\n } else if ((this.mirroring & 1) !== 0) {\n // Not overridden by SingleScreen mirroring.\n this.nes.ppu.setMirroring(this.nes.rom.HORIZONTAL_MIRRORING);\n } else {\n this.nes.ppu.setMirroring(this.nes.rom.VERTICAL_MIRRORING);\n }\n }\n\n // PRG Switching Area;\n this.prgSwitchingArea = (value >> 2) & 1;\n\n // PRG Switching Size:\n this.prgSwitchingSize = (value >> 3) & 1;\n\n // VROM Switching Size:\n this.vromSwitchingSize = (value >> 4) & 1;\n\n break;\n\n case 1:\n // ROM selection:\n this.romSelectionReg0 = (value >> 4) & 1;\n\n // Check whether the cart has VROM:\n if (this.nes.rom.vromCount > 0) {\n // Select VROM bank at 0x0000:\n if (this.vromSwitchingSize === 0) {\n // Swap 8kB VROM:\n if (this.romSelectionReg0 === 0) {\n this.load8kVromBank(value & 0xf, 0x0000);\n } else {\n this.load8kVromBank(\n Math.floor(this.nes.rom.vromCount / 2) + (value & 0xf),\n 0x0000\n );\n }\n } else {\n // Swap 4kB VROM:\n if (this.romSelectionReg0 === 0) {\n this.loadVromBank(value & 0xf, 0x0000);\n } else {\n this.loadVromBank(\n Math.floor(this.nes.rom.vromCount / 2) + (value & 0xf),\n 0x0000\n );\n }\n }\n }\n\n break;\n\n case 2:\n // ROM selection:\n this.romSelectionReg1 = (value >> 4) & 1;\n\n // Check whether the cart has VROM:\n if (this.nes.rom.vromCount > 0) {\n // Select VROM bank at 0x1000:\n if (this.vromSwitchingSize === 1) {\n // Swap 4kB of VROM:\n if (this.romSelectionReg1 === 0) {\n this.loadVromBank(value & 0xf, 0x1000);\n } else {\n this.loadVromBank(\n Math.floor(this.nes.rom.vromCount / 2) + (value & 0xf),\n 0x1000\n );\n }\n }\n }\n break;\n\n default:\n // Select ROM bank:\n // -------------------------\n tmp = value & 0xf;\n var bank;\n var baseBank = 0;\n\n if (this.nes.rom.romCount >= 32) {\n // 1024 kB cart\n if (this.vromSwitchingSize === 0) {\n if (this.romSelectionReg0 === 1) {\n baseBank = 16;\n }\n } else {\n baseBank =\n (this.romSelectionReg0 | (this.romSelectionReg1 << 1)) << 3;\n }\n } else if (this.nes.rom.romCount >= 16) {\n // 512 kB cart\n if (this.romSelectionReg0 === 1) {\n baseBank = 8;\n }\n }\n\n if (this.prgSwitchingSize === 0) {\n // 32kB\n bank = baseBank + (value & 0xf);\n this.load32kRomBank(bank, 0x8000);\n } else {\n // 16kB\n bank = baseBank * 2 + (value & 0xf);\n if (this.prgSwitchingArea === 0) {\n this.loadRomBank(bank, 0xc000);\n } else {\n this.loadRomBank(bank, 0x8000);\n }\n }\n }\n};\n\n// Returns the register number from the address written to:\nMappers[1].prototype.getRegNumber = function(address) {\n if (address >= 0x8000 && address <= 0x9fff) {\n return 0;\n } else if (address >= 0xa000 && address <= 0xbfff) {\n return 1;\n } else if (address >= 0xc000 && address <= 0xdfff) {\n return 2;\n } else {\n return 3;\n }\n};\n\nMappers[1].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"MMC1: Invalid ROM! Unable to load.\");\n }\n\n // Load PRG-ROM:\n this.loadRomBank(0, 0x8000); // First ROM bank..\n this.loadRomBank(this.nes.rom.romCount - 1, 0xc000); // ..and last ROM bank.\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Load Battery RAM (if present):\n this.loadBatteryRam();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\nMappers[1].prototype.switchLowHighPrgRom = function(oldSetting) {\n // not yet.\n};\n\nMappers[1].prototype.switch16to32 = function() {\n // not yet.\n};\n\nMappers[1].prototype.switch32to16 = function() {\n // not yet.\n};\n\nMappers[1].prototype.toJSON = function() {\n var s = Mappers[0].prototype.toJSON.apply(this);\n s.mirroring = this.mirroring;\n s.oneScreenMirroring = this.oneScreenMirroring;\n s.prgSwitchingArea = this.prgSwitchingArea;\n s.prgSwitchingSize = this.prgSwitchingSize;\n s.vromSwitchingSize = this.vromSwitchingSize;\n s.romSelectionReg0 = this.romSelectionReg0;\n s.romSelectionReg1 = this.romSelectionReg1;\n s.romBankSelect = this.romBankSelect;\n s.regBuffer = this.regBuffer;\n s.regBufferCounter = this.regBufferCounter;\n return s;\n};\n\nMappers[1].prototype.fromJSON = function(s) {\n Mappers[0].prototype.fromJSON.apply(this, arguments);\n this.mirroring = s.mirroring;\n this.oneScreenMirroring = s.oneScreenMirroring;\n this.prgSwitchingArea = s.prgSwitchingArea;\n this.prgSwitchingSize = s.prgSwitchingSize;\n this.vromSwitchingSize = s.vromSwitchingSize;\n this.romSelectionReg0 = s.romSelectionReg0;\n this.romSelectionReg1 = s.romSelectionReg1;\n this.romBankSelect = s.romBankSelect;\n this.regBuffer = s.regBuffer;\n this.regBufferCounter = s.regBufferCounter;\n};\n\nMappers[2] = function(nes) {\n this.nes = nes;\n};\n\nMappers[2].prototype = new Mappers[0]();\n\nMappers[2].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n // This is a ROM bank select command.\n // Swap in the given ROM bank at 0x8000:\n this.loadRomBank(value, 0x8000);\n }\n};\n\nMappers[2].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"UNROM: Invalid ROM! Unable to load.\");\n }\n\n // Load PRG-ROM:\n this.loadRomBank(0, 0x8000);\n this.loadRomBank(this.nes.rom.romCount - 1, 0xc000);\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\n/**\n * Mapper 003 (CNROM)\n *\n * @constructor\n * @example Solomon's Key, Arkanoid, Arkista's Ring, Bump 'n' Jump, Cybernoid\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_003\n */\nMappers[3] = function(nes) {\n this.nes = nes;\n};\n\nMappers[3].prototype = new Mappers[0]();\n\nMappers[3].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n // This is a ROM bank select command.\n // Swap in the given ROM bank at 0x8000:\n // This is a VROM bank select command.\n // Swap in the given VROM bank at 0x0000:\n var bank = (value % (this.nes.rom.vromCount / 2)) * 2;\n this.loadVromBank(bank, 0x0000);\n this.loadVromBank(bank + 1, 0x1000);\n this.load8kVromBank(value * 2, 0x0000);\n }\n};\n\nMappers[4] = function(nes) {\n this.nes = nes;\n\n this.CMD_SEL_2_1K_VROM_0000 = 0;\n this.CMD_SEL_2_1K_VROM_0800 = 1;\n this.CMD_SEL_1K_VROM_1000 = 2;\n this.CMD_SEL_1K_VROM_1400 = 3;\n this.CMD_SEL_1K_VROM_1800 = 4;\n this.CMD_SEL_1K_VROM_1C00 = 5;\n this.CMD_SEL_ROM_PAGE1 = 6;\n this.CMD_SEL_ROM_PAGE2 = 7;\n\n this.command = null;\n this.prgAddressSelect = null;\n this.chrAddressSelect = null;\n this.pageNumber = null;\n this.irqCounter = null;\n this.irqLatchValue = null;\n this.irqEnable = null;\n this.prgAddressChanged = false;\n};\n\nMappers[4].prototype = new Mappers[0]();\n\nMappers[4].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n }\n\n switch (address) {\n case 0x8000:\n // Command/Address Select register\n this.command = value & 7;\n var tmp = (value >> 6) & 1;\n if (tmp !== this.prgAddressSelect) {\n this.prgAddressChanged = true;\n }\n this.prgAddressSelect = tmp;\n this.chrAddressSelect = (value >> 7) & 1;\n break;\n\n case 0x8001:\n // Page number for command\n this.executeCommand(this.command, value);\n break;\n\n case 0xa000:\n // Mirroring select\n if ((value & 1) !== 0) {\n this.nes.ppu.setMirroring(this.nes.rom.HORIZONTAL_MIRRORING);\n } else {\n this.nes.ppu.setMirroring(this.nes.rom.VERTICAL_MIRRORING);\n }\n break;\n\n case 0xa001:\n // SaveRAM Toggle\n // TODO\n //nes.getRom().setSaveState((value&1)!=0);\n break;\n\n case 0xc000:\n // IRQ Counter register\n this.irqCounter = value;\n //nes.ppu.mapperIrqCounter = 0;\n break;\n\n case 0xc001:\n // IRQ Latch register\n this.irqLatchValue = value;\n break;\n\n case 0xe000:\n // IRQ Control Reg 0 (disable)\n //irqCounter = irqLatchValue;\n this.irqEnable = 0;\n break;\n\n case 0xe001:\n // IRQ Control Reg 1 (enable)\n this.irqEnable = 1;\n break;\n\n default:\n // Not a MMC3 register.\n // The game has probably crashed,\n // since it tries to write to ROM..\n // IGNORE.\n }\n};\n\nMappers[4].prototype.executeCommand = function(cmd, arg) {\n switch (cmd) {\n case this.CMD_SEL_2_1K_VROM_0000:\n // Select 2 1KB VROM pages at 0x0000:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x0000);\n this.load1kVromBank(arg + 1, 0x0400);\n } else {\n this.load1kVromBank(arg, 0x1000);\n this.load1kVromBank(arg + 1, 0x1400);\n }\n break;\n\n case this.CMD_SEL_2_1K_VROM_0800:\n // Select 2 1KB VROM pages at 0x0800:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x0800);\n this.load1kVromBank(arg + 1, 0x0c00);\n } else {\n this.load1kVromBank(arg, 0x1800);\n this.load1kVromBank(arg + 1, 0x1c00);\n }\n break;\n\n case this.CMD_SEL_1K_VROM_1000:\n // Select 1K VROM Page at 0x1000:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x1000);\n } else {\n this.load1kVromBank(arg, 0x0000);\n }\n break;\n\n case this.CMD_SEL_1K_VROM_1400:\n // Select 1K VROM Page at 0x1400:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x1400);\n } else {\n this.load1kVromBank(arg, 0x0400);\n }\n break;\n\n case this.CMD_SEL_1K_VROM_1800:\n // Select 1K VROM Page at 0x1800:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x1800);\n } else {\n this.load1kVromBank(arg, 0x0800);\n }\n break;\n\n case this.CMD_SEL_1K_VROM_1C00:\n // Select 1K VROM Page at 0x1C00:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x1c00);\n } else {\n this.load1kVromBank(arg, 0x0c00);\n }\n break;\n\n case this.CMD_SEL_ROM_PAGE1:\n if (this.prgAddressChanged) {\n // Load the two hardwired banks:\n if (this.prgAddressSelect === 0) {\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0xc000);\n } else {\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0x8000);\n }\n this.prgAddressChanged = false;\n }\n\n // Select first switchable ROM page:\n if (this.prgAddressSelect === 0) {\n this.load8kRomBank(arg, 0x8000);\n } else {\n this.load8kRomBank(arg, 0xc000);\n }\n break;\n\n case this.CMD_SEL_ROM_PAGE2:\n // Select second switchable ROM page:\n this.load8kRomBank(arg, 0xa000);\n\n // hardwire appropriate bank:\n if (this.prgAddressChanged) {\n // Load the two hardwired banks:\n if (this.prgAddressSelect === 0) {\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0xc000);\n } else {\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0x8000);\n }\n this.prgAddressChanged = false;\n }\n }\n};\n\nMappers[4].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"MMC3: Invalid ROM! Unable to load.\");\n }\n\n // Load hardwired PRG banks (0xC000 and 0xE000):\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0xc000);\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2 + 1, 0xe000);\n\n // Load swappable PRG banks (0x8000 and 0xA000):\n this.load8kRomBank(0, 0x8000);\n this.load8kRomBank(1, 0xa000);\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Load Battery RAM (if present):\n this.loadBatteryRam();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\nMappers[4].prototype.clockIrqCounter = function() {\n if (this.irqEnable === 1) {\n this.irqCounter--;\n if (this.irqCounter < 0) {\n // Trigger IRQ:\n //nes.getCpu().doIrq();\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_NORMAL);\n this.irqCounter = this.irqLatchValue;\n }\n }\n};\n\nMappers[4].prototype.toJSON = function() {\n var s = Mappers[0].prototype.toJSON.apply(this);\n s.command = this.command;\n s.prgAddressSelect = this.prgAddressSelect;\n s.chrAddressSelect = this.chrAddressSelect;\n s.pageNumber = this.pageNumber;\n s.irqCounter = this.irqCounter;\n s.irqLatchValue = this.irqLatchValue;\n s.irqEnable = this.irqEnable;\n s.prgAddressChanged = this.prgAddressChanged;\n return s;\n};\n\nMappers[4].prototype.fromJSON = function(s) {\n Mappers[0].prototype.fromJSON.apply(this, arguments);\n this.command = s.command;\n this.prgAddressSelect = s.prgAddressSelect;\n this.chrAddressSelect = s.chrAddressSelect;\n this.pageNumber = s.pageNumber;\n this.irqCounter = s.irqCounter;\n this.irqLatchValue = s.irqLatchValue;\n this.irqEnable = s.irqEnable;\n this.prgAddressChanged = s.prgAddressChanged;\n};\n\n/**\n * Mapper005 (MMC5,ExROM)\n *\n * @example Castlevania 3, Just Breed, Uncharted Waters, Romance of the 3 Kingdoms 2, Laser Invasion, Metal Slader Glory, Uchuu Keibitai SDF, Shin 4 Nin Uchi Mahjong - Yakuman Tengoku\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_005\n * @constructor\n */\nMappers[5] = function(nes) {\n this.nes = nes;\n};\n\nMappers[5].prototype = new Mappers[0]();\n\nMappers[5].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n } else {\n this.load8kVromBank(value, 0x0000);\n }\n};\n\nMappers[5].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x5000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n }\n\n switch (address) {\n case 0x5100:\n this.prg_size = value & 3;\n break;\n case 0x5101:\n this.chr_size = value & 3;\n break;\n case 0x5102:\n this.sram_we_a = value & 3;\n break;\n case 0x5103:\n this.sram_we_b = value & 3;\n break;\n case 0x5104:\n this.graphic_mode = value & 3;\n break;\n case 0x5105:\n this.nametable_mode = value;\n this.nametable_type[0] = value & 3;\n this.load1kVromBank(value & 3, 0x2000);\n value >>= 2;\n this.nametable_type[1] = value & 3;\n this.load1kVromBank(value & 3, 0x2400);\n value >>= 2;\n this.nametable_type[2] = value & 3;\n this.load1kVromBank(value & 3, 0x2800);\n value >>= 2;\n this.nametable_type[3] = value & 3;\n this.load1kVromBank(value & 3, 0x2c00);\n break;\n case 0x5106:\n this.fill_chr = value;\n break;\n case 0x5107:\n this.fill_pal = value & 3;\n break;\n case 0x5113:\n this.SetBank_SRAM(3, value & 3);\n break;\n case 0x5114:\n case 0x5115:\n case 0x5116:\n case 0x5117:\n this.SetBank_CPU(address, value);\n break;\n case 0x5120:\n case 0x5121:\n case 0x5122:\n case 0x5123:\n case 0x5124:\n case 0x5125:\n case 0x5126:\n case 0x5127:\n this.chr_mode = 0;\n this.chr_page[0][address & 7] = value;\n this.SetBank_PPU();\n break;\n case 0x5128:\n case 0x5129:\n case 0x512a:\n case 0x512b:\n this.chr_mode = 1;\n this.chr_page[1][(address & 3) + 0] = value;\n this.chr_page[1][(address & 3) + 4] = value;\n this.SetBank_PPU();\n break;\n case 0x5200:\n this.split_control = value;\n break;\n case 0x5201:\n this.split_scroll = value;\n break;\n case 0x5202:\n this.split_page = value & 0x3f;\n break;\n case 0x5203:\n this.irq_line = value;\n this.nes.cpu.ClearIRQ();\n break;\n case 0x5204:\n this.irq_enable = value;\n this.nes.cpu.ClearIRQ();\n break;\n case 0x5205:\n this.mult_a = value;\n break;\n case 0x5206:\n this.mult_b = value;\n break;\n default:\n if (address >= 0x5000 && address <= 0x5015) {\n this.nes.papu.exWrite(address, value);\n } else if (address >= 0x5c00 && address <= 0x5fff) {\n if (this.graphic_mode === 2) {\n // ExRAM\n // vram write\n } else if (this.graphic_mode !== 3) {\n // Split,ExGraphic\n if (this.irq_status & 0x40) {\n // vram write\n } else {\n // vram write\n }\n }\n } else if (address >= 0x6000 && address <= 0x7fff) {\n if (this.sram_we_a === 2 && this.sram_we_b === 1) {\n // additional ram write\n }\n }\n break;\n }\n};\n\nMappers[5].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"UNROM: Invalid ROM! Unable to load.\");\n }\n\n // Load PRG-ROM:\n this.load8kRomBank(this.nes.rom.romCount * 2 - 1, 0x8000);\n this.load8kRomBank(this.nes.rom.romCount * 2 - 1, 0xa000);\n this.load8kRomBank(this.nes.rom.romCount * 2 - 1, 0xc000);\n this.load8kRomBank(this.nes.rom.romCount * 2 - 1, 0xe000);\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\n/**\n * Mapper007 (AxROM)\n * @example Battletoads, Time Lord, Marble Madness\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_007\n * @constructor\n */\nMappers[7] = function(nes) {\n this.nes = nes;\n};\n\nMappers[7].prototype = new Mappers[0]();\n\nMappers[7].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n } else {\n this.load32kRomBank(value & 0x7, 0x8000);\n if (value & 0x10) {\n this.nes.ppu.setMirroring(this.nes.rom.SINGLESCREEN_MIRRORING2);\n } else {\n this.nes.ppu.setMirroring(this.nes.rom.SINGLESCREEN_MIRRORING);\n }\n }\n};\n\nMappers[7].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"AOROM: Invalid ROM! Unable to load.\");\n }\n\n // Load PRG-ROM:\n this.loadPRGROM();\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\n/**\n * Mapper 011 (Color Dreams)\n *\n * @description http://wiki.nesdev.com/w/index.php/Color_Dreams\n * @example Crystal Mines, Metal Fighter\n * @constructor\n */\nMappers[11] = function(nes) {\n this.nes = nes;\n};\n\nMappers[11].prototype = new Mappers[0]();\n\nMappers[11].prototype.write = function(address, value) {\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n // Swap in the given PRG-ROM bank:\n var prgbank1 = ((value & 0xf) * 2) % this.nes.rom.romCount;\n var prgbank2 = ((value & 0xf) * 2 + 1) % this.nes.rom.romCount;\n\n this.loadRomBank(prgbank1, 0x8000);\n this.loadRomBank(prgbank2, 0xc000);\n\n if (this.nes.rom.vromCount > 0) {\n // Swap in the given VROM bank at 0x0000:\n var bank = ((value >> 4) * 2) % this.nes.rom.vromCount;\n this.loadVromBank(bank, 0x0000);\n this.loadVromBank(bank + 1, 0x1000);\n }\n }\n};\n\n/**\n * Mapper 034 (BNROM, NINA-01)\n *\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_034\n * @example Darkseed, Mashou, Mission Impossible 2\n * @constructor\n */\nMappers[34] = function(nes) {\n this.nes = nes;\n};\n\nMappers[34].prototype = new Mappers[0]();\n\nMappers[34].prototype.write = function(address, value) {\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n this.load32kRomBank(value, 0x8000);\n }\n};\n\n/**\n * Mapper 066 (GxROM)\n *\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_066\n * @example Doraemon, Dragon Power, Gumshoe, Thunder & Lightning,\n * Super Mario Bros. + Duck Hunt\n * @constructor\n */\nMappers[66] = function(nes) {\n this.nes = nes;\n console.log(\"Mapper 66\");\n};\n\nMappers[66].prototype = new Mappers[0]();\n\nMappers[66].prototype.write = function(address, value) {\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n // Swap in the given PRG-ROM bank at 0x8000:\n this.load32kRomBank((value >> 4) & 3, 0x8000);\n\n // Swap in the given VROM bank at 0x0000:\n this.load8kVromBank((value & 3) * 2, 0x0000);\n }\n};\n\nmodule.exports = Mappers;\n\n\n/***/ })\n/******/ ]);\n});\n\n\n// WEBPACK FOOTER //\n// jsnes.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 3);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap be5c7600992719b4371b","module.exports = {\n copyArrayElements: function(src, srcPos, dest, destPos, length) {\n for (var i = 0; i < length; ++i) {\n dest[destPos + i] = src[srcPos + i];\n }\n },\n\n copyArray: function(src) {\n return src.slice(0);\n },\n\n fromJSON: function(obj, state) {\n for (var i = 0; i < obj.JSON_PROPERTIES.length; i++) {\n obj[obj.JSON_PROPERTIES[i]] = state[obj.JSON_PROPERTIES[i]];\n }\n },\n\n toJSON: function(obj) {\n var state = {};\n for (var i = 0; i < obj.JSON_PROPERTIES.length; i++) {\n state[obj.JSON_PROPERTIES[i]] = obj[obj.JSON_PROPERTIES[i]];\n }\n return state;\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/utils.js\n// module id = 0\n// module chunks = 0 1","var Controller = function() {\n this.state = new Array(8);\n for (var i = 0; i < this.state.length; i++) {\n this.state[i] = 0x40;\n }\n};\n\nController.BUTTON_A = 0;\nController.BUTTON_B = 1;\nController.BUTTON_SELECT = 2;\nController.BUTTON_START = 3;\nController.BUTTON_UP = 4;\nController.BUTTON_DOWN = 5;\nController.BUTTON_LEFT = 6;\nController.BUTTON_RIGHT = 7;\n\nController.prototype = {\n buttonDown: function(key) {\n this.state[key] = 0x41;\n },\n\n buttonUp: function(key) {\n this.state[key] = 0x40;\n }\n};\n\nmodule.exports = Controller;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/controller.js\n// module id = 1\n// module chunks = 0 1","var Tile = function() {\n // Tile data:\n this.pix = new Array(64);\n\n this.fbIndex = null;\n this.tIndex = null;\n this.x = null;\n this.y = null;\n this.w = null;\n this.h = null;\n this.incX = null;\n this.incY = null;\n this.palIndex = null;\n this.tpri = null;\n this.c = null;\n this.initialized = false;\n this.opaque = new Array(8);\n};\n\nTile.prototype = {\n setBuffer: function(scanline) {\n for (this.y = 0; this.y < 8; this.y++) {\n this.setScanline(this.y, scanline[this.y], scanline[this.y + 8]);\n }\n },\n\n setScanline: function(sline, b1, b2) {\n this.initialized = true;\n this.tIndex = sline << 3;\n for (this.x = 0; this.x < 8; this.x++) {\n this.pix[this.tIndex + this.x] =\n ((b1 >> (7 - this.x)) & 1) + (((b2 >> (7 - this.x)) & 1) << 1);\n if (this.pix[this.tIndex + this.x] === 0) {\n this.opaque[sline] = false;\n }\n }\n },\n\n render: function(\n buffer,\n srcx1,\n srcy1,\n srcx2,\n srcy2,\n dx,\n dy,\n palAdd,\n palette,\n flipHorizontal,\n flipVertical,\n pri,\n priTable\n ) {\n if (dx < -7 || dx >= 256 || dy < -7 || dy >= 240) {\n return;\n }\n\n this.w = srcx2 - srcx1;\n this.h = srcy2 - srcy1;\n\n if (dx < 0) {\n srcx1 -= dx;\n }\n if (dx + srcx2 >= 256) {\n srcx2 = 256 - dx;\n }\n\n if (dy < 0) {\n srcy1 -= dy;\n }\n if (dy + srcy2 >= 240) {\n srcy2 = 240 - dy;\n }\n\n if (!flipHorizontal && !flipVertical) {\n this.fbIndex = (dy << 8) + dx;\n this.tIndex = 0;\n for (this.y = 0; this.y < 8; this.y++) {\n for (this.x = 0; this.x < 8; this.x++) {\n if (\n this.x >= srcx1 &&\n this.x < srcx2 &&\n this.y >= srcy1 &&\n this.y < srcy2\n ) {\n this.palIndex = this.pix[this.tIndex];\n this.tpri = priTable[this.fbIndex];\n if (this.palIndex !== 0 && pri <= (this.tpri & 0xff)) {\n //console.log(\"Rendering upright tile to buffer\");\n buffer[this.fbIndex] = palette[this.palIndex + palAdd];\n this.tpri = (this.tpri & 0xf00) | pri;\n priTable[this.fbIndex] = this.tpri;\n }\n }\n this.fbIndex++;\n this.tIndex++;\n }\n this.fbIndex -= 8;\n this.fbIndex += 256;\n }\n } else if (flipHorizontal && !flipVertical) {\n this.fbIndex = (dy << 8) + dx;\n this.tIndex = 7;\n for (this.y = 0; this.y < 8; this.y++) {\n for (this.x = 0; this.x < 8; this.x++) {\n if (\n this.x >= srcx1 &&\n this.x < srcx2 &&\n this.y >= srcy1 &&\n this.y < srcy2\n ) {\n this.palIndex = this.pix[this.tIndex];\n this.tpri = priTable[this.fbIndex];\n if (this.palIndex !== 0 && pri <= (this.tpri & 0xff)) {\n buffer[this.fbIndex] = palette[this.palIndex + palAdd];\n this.tpri = (this.tpri & 0xf00) | pri;\n priTable[this.fbIndex] = this.tpri;\n }\n }\n this.fbIndex++;\n this.tIndex--;\n }\n this.fbIndex -= 8;\n this.fbIndex += 256;\n this.tIndex += 16;\n }\n } else if (flipVertical && !flipHorizontal) {\n this.fbIndex = (dy << 8) + dx;\n this.tIndex = 56;\n for (this.y = 0; this.y < 8; this.y++) {\n for (this.x = 0; this.x < 8; this.x++) {\n if (\n this.x >= srcx1 &&\n this.x < srcx2 &&\n this.y >= srcy1 &&\n this.y < srcy2\n ) {\n this.palIndex = this.pix[this.tIndex];\n this.tpri = priTable[this.fbIndex];\n if (this.palIndex !== 0 && pri <= (this.tpri & 0xff)) {\n buffer[this.fbIndex] = palette[this.palIndex + palAdd];\n this.tpri = (this.tpri & 0xf00) | pri;\n priTable[this.fbIndex] = this.tpri;\n }\n }\n this.fbIndex++;\n this.tIndex++;\n }\n this.fbIndex -= 8;\n this.fbIndex += 256;\n this.tIndex -= 16;\n }\n } else {\n this.fbIndex = (dy << 8) + dx;\n this.tIndex = 63;\n for (this.y = 0; this.y < 8; this.y++) {\n for (this.x = 0; this.x < 8; this.x++) {\n if (\n this.x >= srcx1 &&\n this.x < srcx2 &&\n this.y >= srcy1 &&\n this.y < srcy2\n ) {\n this.palIndex = this.pix[this.tIndex];\n this.tpri = priTable[this.fbIndex];\n if (this.palIndex !== 0 && pri <= (this.tpri & 0xff)) {\n buffer[this.fbIndex] = palette[this.palIndex + palAdd];\n this.tpri = (this.tpri & 0xf00) | pri;\n priTable[this.fbIndex] = this.tpri;\n }\n }\n this.fbIndex++;\n this.tIndex--;\n }\n this.fbIndex -= 8;\n this.fbIndex += 256;\n }\n }\n },\n\n isTransparent: function(x, y) {\n return this.pix[(y << 3) + x] === 0;\n },\n\n toJSON: function() {\n return {\n opaque: this.opaque,\n pix: this.pix\n };\n },\n\n fromJSON: function(s) {\n this.opaque = s.opaque;\n this.pix = s.pix;\n }\n};\n\nmodule.exports = Tile;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/tile.js\n// module id = 2\n// module chunks = 0 1","module.exports = {\n Controller: require(\"./controller\"),\n NES: require(\"./nes\"),\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/index.js\n// module id = 3\n// module chunks = 0 1","var CPU = require(\"./cpu\");\nvar Controller = require(\"./controller\");\nvar PPU = require(\"./ppu\");\nvar PAPU = require(\"./papu\");\nvar ROM = require(\"./rom\");\n\nvar NES = function(opts) {\n this.opts = {\n onFrame: function() {},\n onAudioSample: null,\n onStatusUpdate: function() {},\n onBatteryRamWrite: function() {},\n\n // FIXME: not actually used except for in PAPU\n preferredFrameRate: 60,\n\n emulateSound: true,\n sampleRate: 44100 // Sound sample rate in hz\n };\n if (typeof opts !== \"undefined\") {\n var key;\n for (key in this.opts) {\n if (typeof opts[key] !== \"undefined\") {\n this.opts[key] = opts[key];\n }\n }\n }\n\n this.frameTime = 1000 / this.opts.preferredFrameRate;\n\n this.ui = {\n writeFrame: this.opts.onFrame,\n updateStatus: this.opts.onStatusUpdate\n };\n this.cpu = new CPU(this);\n this.ppu = new PPU(this);\n this.papu = new PAPU(this);\n this.mmap = null; // set in loadROM()\n this.controllers = {\n 1: new Controller(),\n 2: new Controller(),\n };\n\n this.ui.updateStatus(\"Ready to load a ROM.\");\n\n this.frame = this.frame.bind(this);\n this.buttonDown = this.buttonDown.bind(this);\n this.buttonUp = this.buttonUp.bind(this);\n this.zapperMove = this.zapperMove.bind(this);\n this.zapperFireDown = this.zapperFireDown.bind(this);\n this.zapperFireUp = this.zapperFireUp.bind(this);\n};\n\nNES.prototype = {\n fpsFrameCount: 0,\n romData: null,\n\n // Resets the system\n reset: function() {\n if (this.mmap !== null) {\n this.mmap.reset();\n }\n\n this.cpu.reset();\n this.ppu.reset();\n this.papu.reset();\n\n this.lastFpsTime = null;\n this.fpsFrameCount = 0;\n },\n\n frame: function() {\n this.ppu.startFrame();\n var cycles = 0;\n var emulateSound = this.opts.emulateSound;\n var cpu = this.cpu;\n var ppu = this.ppu;\n var papu = this.papu;\n FRAMELOOP: for (;;) {\n if (cpu.cyclesToHalt === 0) {\n // Execute a CPU instruction\n cycles = cpu.emulate();\n if (emulateSound) {\n papu.clockFrameCounter(cycles);\n }\n cycles *= 3;\n } else {\n if (cpu.cyclesToHalt > 8) {\n cycles = 24;\n if (emulateSound) {\n papu.clockFrameCounter(8);\n }\n cpu.cyclesToHalt -= 8;\n } else {\n cycles = cpu.cyclesToHalt * 3;\n if (emulateSound) {\n papu.clockFrameCounter(cpu.cyclesToHalt);\n }\n cpu.cyclesToHalt = 0;\n }\n }\n\n for (; cycles > 0; cycles--) {\n if (\n ppu.curX === ppu.spr0HitX &&\n ppu.f_spVisibility === 1 &&\n ppu.scanline - 21 === ppu.spr0HitY\n ) {\n // Set sprite 0 hit flag:\n ppu.setStatusFlag(ppu.STATUS_SPRITE0HIT, true);\n }\n\n if (ppu.requestEndFrame) {\n ppu.nmiCounter--;\n if (ppu.nmiCounter === 0) {\n ppu.requestEndFrame = false;\n ppu.startVBlank();\n break FRAMELOOP;\n }\n }\n\n ppu.curX++;\n if (ppu.curX === 341) {\n ppu.curX = 0;\n ppu.endScanline();\n }\n }\n }\n this.fpsFrameCount++;\n },\n\n buttonDown: function(controller, button) {\n this.controllers[controller].buttonDown(button);\n },\n\n buttonUp: function(controller, button) {\n this.controllers[controller].buttonUp(button);\n },\n\n zapperMove: function(x, y) {\n if (!this.mmap) return;\n this.mmap.zapperX = x;\n this.mmap.zapperY = y;\n },\n\n zapperFireDown: function() {\n if (!this.mmap) return;\n this.mmap.zapperFired = true;\n },\n\n zapperFireUp: function() {\n if (!this.mmap) return;\n this.mmap.zapperFired = false;\n },\n\n getFPS: function() {\n var now = +new Date();\n var fps = null;\n if (this.lastFpsTime) {\n fps = this.fpsFrameCount / ((now - this.lastFpsTime) / 1000);\n }\n this.fpsFrameCount = 0;\n this.lastFpsTime = now;\n return fps;\n },\n\n reloadROM: function() {\n if (this.romData !== null) {\n this.loadROM(this.romData);\n }\n },\n\n // Loads a ROM file into the CPU and PPU.\n // The ROM file is validated first.\n loadROM: function(data) {\n // Load ROM file:\n this.rom = new ROM(this);\n this.rom.load(data);\n\n this.reset();\n this.mmap = this.rom.createMapper();\n this.mmap.loadROM();\n this.ppu.setMirroring(this.rom.getMirroringType());\n this.romData = data;\n },\n\n setFramerate: function(rate) {\n this.opts.preferredFrameRate = rate;\n this.frameTime = 1000 / rate;\n this.papu.setSampleRate(this.opts.sampleRate, false);\n },\n\n toJSON: function() {\n return {\n romData: this.romData,\n cpu: this.cpu.toJSON(),\n mmap: this.mmap.toJSON(),\n ppu: this.ppu.toJSON()\n };\n },\n\n fromJSON: function(s) {\n this.loadROM(s.romData);\n this.cpu.fromJSON(s.cpu);\n this.mmap.fromJSON(s.mmap);\n this.ppu.fromJSON(s.ppu);\n }\n};\n\nmodule.exports = NES;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/nes.js\n// module id = 4\n// module chunks = 0 1","var utils = require(\"./utils\");\n\nvar CPU = function(nes) {\n this.nes = nes;\n\n // Keep Chrome happy\n this.mem = null;\n this.REG_ACC = null;\n this.REG_X = null;\n this.REG_Y = null;\n this.REG_SP = null;\n this.REG_PC = null;\n this.REG_PC_NEW = null;\n this.REG_STATUS = null;\n this.F_CARRY = null;\n this.F_DECIMAL = null;\n this.F_INTERRUPT = null;\n this.F_INTERRUPT_NEW = null;\n this.F_OVERFLOW = null;\n this.F_SIGN = null;\n this.F_ZERO = null;\n this.F_NOTUSED = null;\n this.F_NOTUSED_NEW = null;\n this.F_BRK = null;\n this.F_BRK_NEW = null;\n this.opdata = null;\n this.cyclesToHalt = null;\n this.crash = null;\n this.irqRequested = null;\n this.irqType = null;\n\n this.reset();\n};\n\nCPU.prototype = {\n // IRQ Types\n IRQ_NORMAL: 0,\n IRQ_NMI: 1,\n IRQ_RESET: 2,\n\n reset: function() {\n // Main memory\n this.mem = new Array(0x10000);\n\n for (var i = 0; i < 0x2000; i++) {\n this.mem[i] = 0xff;\n }\n for (var p = 0; p < 4; p++) {\n var j = p * 0x800;\n this.mem[j + 0x008] = 0xf7;\n this.mem[j + 0x009] = 0xef;\n this.mem[j + 0x00a] = 0xdf;\n this.mem[j + 0x00f] = 0xbf;\n }\n for (var k = 0x2001; k < this.mem.length; k++) {\n this.mem[k] = 0;\n }\n\n // CPU Registers:\n this.REG_ACC = 0;\n this.REG_X = 0;\n this.REG_Y = 0;\n // Reset Stack pointer:\n this.REG_SP = 0x01ff;\n // Reset Program counter:\n this.REG_PC = 0x8000 - 1;\n this.REG_PC_NEW = 0x8000 - 1;\n // Reset Status register:\n this.REG_STATUS = 0x28;\n\n this.setStatus(0x28);\n\n // Set flags:\n this.F_CARRY = 0;\n this.F_DECIMAL = 0;\n this.F_INTERRUPT = 1;\n this.F_INTERRUPT_NEW = 1;\n this.F_OVERFLOW = 0;\n this.F_SIGN = 0;\n this.F_ZERO = 1;\n\n this.F_NOTUSED = 1;\n this.F_NOTUSED_NEW = 1;\n this.F_BRK = 1;\n this.F_BRK_NEW = 1;\n\n this.opdata = new OpData().opdata;\n this.cyclesToHalt = 0;\n\n // Reset crash flag:\n this.crash = false;\n\n // Interrupt notification:\n this.irqRequested = false;\n this.irqType = null;\n },\n\n // Emulates a single CPU instruction, returns the number of cycles\n emulate: function() {\n var temp;\n var add;\n\n // Check interrupts:\n if (this.irqRequested) {\n temp =\n this.F_CARRY |\n ((this.F_ZERO === 0 ? 1 : 0) << 1) |\n (this.F_INTERRUPT << 2) |\n (this.F_DECIMAL << 3) |\n (this.F_BRK << 4) |\n (this.F_NOTUSED << 5) |\n (this.F_OVERFLOW << 6) |\n (this.F_SIGN << 7);\n\n this.REG_PC_NEW = this.REG_PC;\n this.F_INTERRUPT_NEW = this.F_INTERRUPT;\n switch (this.irqType) {\n case 0: {\n // Normal IRQ:\n if (this.F_INTERRUPT !== 0) {\n // console.log(\"Interrupt was masked.\");\n break;\n }\n this.doIrq(temp);\n // console.log(\"Did normal IRQ. I=\"+this.F_INTERRUPT);\n break;\n }\n case 1: {\n // NMI:\n this.doNonMaskableInterrupt(temp);\n break;\n }\n case 2: {\n // Reset:\n this.doResetInterrupt();\n break;\n }\n }\n\n this.REG_PC = this.REG_PC_NEW;\n this.F_INTERRUPT = this.F_INTERRUPT_NEW;\n this.F_BRK = this.F_BRK_NEW;\n this.irqRequested = false;\n }\n\n var opinf = this.opdata[this.nes.mmap.load(this.REG_PC + 1)];\n var cycleCount = opinf >> 24;\n var cycleAdd = 0;\n\n // Find address mode:\n var addrMode = (opinf >> 8) & 0xff;\n\n // Increment PC by number of op bytes:\n var opaddr = this.REG_PC;\n this.REG_PC += (opinf >> 16) & 0xff;\n\n var addr = 0;\n switch (addrMode) {\n case 0: {\n // Zero Page mode. Use the address given after the opcode,\n // but without high byte.\n addr = this.load(opaddr + 2);\n break;\n }\n case 1: {\n // Relative mode.\n addr = this.load(opaddr + 2);\n if (addr < 0x80) {\n addr += this.REG_PC;\n } else {\n addr += this.REG_PC - 256;\n }\n break;\n }\n case 2: {\n // Ignore. Address is implied in instruction.\n break;\n }\n case 3: {\n // Absolute mode. Use the two bytes following the opcode as\n // an address.\n addr = this.load16bit(opaddr + 2);\n break;\n }\n case 4: {\n // Accumulator mode. The address is in the accumulator\n // register.\n addr = this.REG_ACC;\n break;\n }\n case 5: {\n // Immediate mode. The value is given after the opcode.\n addr = this.REG_PC;\n break;\n }\n case 6: {\n // Zero Page Indexed mode, X as index. Use the address given\n // after the opcode, then add the\n // X register to it to get the final address.\n addr = (this.load(opaddr + 2) + this.REG_X) & 0xff;\n break;\n }\n case 7: {\n // Zero Page Indexed mode, Y as index. Use the address given\n // after the opcode, then add the\n // Y register to it to get the final address.\n addr = (this.load(opaddr + 2) + this.REG_Y) & 0xff;\n break;\n }\n case 8: {\n // Absolute Indexed Mode, X as index. Same as zero page\n // indexed, but with the high byte.\n addr = this.load16bit(opaddr + 2);\n if ((addr & 0xff00) !== ((addr + this.REG_X) & 0xff00)) {\n cycleAdd = 1;\n }\n addr += this.REG_X;\n break;\n }\n case 9: {\n // Absolute Indexed Mode, Y as index. Same as zero page\n // indexed, but with the high byte.\n addr = this.load16bit(opaddr + 2);\n if ((addr & 0xff00) !== ((addr + this.REG_Y) & 0xff00)) {\n cycleAdd = 1;\n }\n addr += this.REG_Y;\n break;\n }\n case 10: {\n // Pre-indexed Indirect mode. Find the 16-bit address\n // starting at the given location plus\n // the current X register. The value is the contents of that\n // address.\n addr = this.load(opaddr + 2);\n if ((addr & 0xff00) !== ((addr + this.REG_X) & 0xff00)) {\n cycleAdd = 1;\n }\n addr += this.REG_X;\n addr &= 0xff;\n addr = this.load16bit(addr);\n break;\n }\n case 11: {\n // Post-indexed Indirect mode. Find the 16-bit address\n // contained in the given location\n // (and the one following). Add to that address the contents\n // of the Y register. Fetch the value\n // stored at that adress.\n addr = this.load16bit(this.load(opaddr + 2));\n if ((addr & 0xff00) !== ((addr + this.REG_Y) & 0xff00)) {\n cycleAdd = 1;\n }\n addr += this.REG_Y;\n break;\n }\n case 12: {\n // Indirect Absolute mode. Find the 16-bit address contained\n // at the given location.\n addr = this.load16bit(opaddr + 2); // Find op\n if (addr < 0x1fff) {\n addr =\n this.mem[addr] +\n (this.mem[(addr & 0xff00) | (((addr & 0xff) + 1) & 0xff)] << 8); // Read from address given in op\n } else {\n addr =\n this.nes.mmap.load(addr) +\n (this.nes.mmap.load(\n (addr & 0xff00) | (((addr & 0xff) + 1) & 0xff)\n ) <<\n 8);\n }\n break;\n }\n }\n // Wrap around for addresses above 0xFFFF:\n addr &= 0xffff;\n\n // ----------------------------------------------------------------------------------------------------\n // Decode & execute instruction:\n // ----------------------------------------------------------------------------------------------------\n\n // This should be compiled to a jump table.\n switch (opinf & 0xff) {\n case 0: {\n // *******\n // * ADC *\n // *******\n\n // Add with carry.\n temp = this.REG_ACC + this.load(addr) + this.F_CARRY;\n\n if (\n ((this.REG_ACC ^ this.load(addr)) & 0x80) === 0 &&\n ((this.REG_ACC ^ temp) & 0x80) !== 0\n ) {\n this.F_OVERFLOW = 1;\n } else {\n this.F_OVERFLOW = 0;\n }\n this.F_CARRY = temp > 255 ? 1 : 0;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n this.REG_ACC = temp & 255;\n cycleCount += cycleAdd;\n break;\n }\n case 1: {\n // *******\n // * AND *\n // *******\n\n // AND memory with accumulator.\n this.REG_ACC = this.REG_ACC & this.load(addr);\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n //this.REG_ACC = temp;\n if (addrMode !== 11) cycleCount += cycleAdd; // PostIdxInd = 11\n break;\n }\n case 2: {\n // *******\n // * ASL *\n // *******\n\n // Shift left one bit\n if (addrMode === 4) {\n // ADDR_ACC = 4\n\n this.F_CARRY = (this.REG_ACC >> 7) & 1;\n this.REG_ACC = (this.REG_ACC << 1) & 255;\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n } else {\n temp = this.load(addr);\n this.F_CARRY = (temp >> 7) & 1;\n temp = (temp << 1) & 255;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n this.write(addr, temp);\n }\n break;\n }\n case 3: {\n // *******\n // * BCC *\n // *******\n\n // Branch on carry clear\n if (this.F_CARRY === 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 4: {\n // *******\n // * BCS *\n // *******\n\n // Branch on carry set\n if (this.F_CARRY === 1) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 5: {\n // *******\n // * BEQ *\n // *******\n\n // Branch on zero\n if (this.F_ZERO === 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 6: {\n // *******\n // * BIT *\n // *******\n\n temp = this.load(addr);\n this.F_SIGN = (temp >> 7) & 1;\n this.F_OVERFLOW = (temp >> 6) & 1;\n temp &= this.REG_ACC;\n this.F_ZERO = temp;\n break;\n }\n case 7: {\n // *******\n // * BMI *\n // *******\n\n // Branch on negative result\n if (this.F_SIGN === 1) {\n cycleCount++;\n this.REG_PC = addr;\n }\n break;\n }\n case 8: {\n // *******\n // * BNE *\n // *******\n\n // Branch on not zero\n if (this.F_ZERO !== 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 9: {\n // *******\n // * BPL *\n // *******\n\n // Branch on positive result\n if (this.F_SIGN === 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 10: {\n // *******\n // * BRK *\n // *******\n\n this.REG_PC += 2;\n this.push((this.REG_PC >> 8) & 255);\n this.push(this.REG_PC & 255);\n this.F_BRK = 1;\n\n this.push(\n this.F_CARRY |\n ((this.F_ZERO === 0 ? 1 : 0) << 1) |\n (this.F_INTERRUPT << 2) |\n (this.F_DECIMAL << 3) |\n (this.F_BRK << 4) |\n (this.F_NOTUSED << 5) |\n (this.F_OVERFLOW << 6) |\n (this.F_SIGN << 7)\n );\n\n this.F_INTERRUPT = 1;\n //this.REG_PC = load(0xFFFE) | (load(0xFFFF) << 8);\n this.REG_PC = this.load16bit(0xfffe);\n this.REG_PC--;\n break;\n }\n case 11: {\n // *******\n // * BVC *\n // *******\n\n // Branch on overflow clear\n if (this.F_OVERFLOW === 0) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 12: {\n // *******\n // * BVS *\n // *******\n\n // Branch on overflow set\n if (this.F_OVERFLOW === 1) {\n cycleCount += (opaddr & 0xff00) !== (addr & 0xff00) ? 2 : 1;\n this.REG_PC = addr;\n }\n break;\n }\n case 13: {\n // *******\n // * CLC *\n // *******\n\n // Clear carry flag\n this.F_CARRY = 0;\n break;\n }\n case 14: {\n // *******\n // * CLD *\n // *******\n\n // Clear decimal flag\n this.F_DECIMAL = 0;\n break;\n }\n case 15: {\n // *******\n // * CLI *\n // *******\n\n // Clear interrupt flag\n this.F_INTERRUPT = 0;\n break;\n }\n case 16: {\n // *******\n // * CLV *\n // *******\n\n // Clear overflow flag\n this.F_OVERFLOW = 0;\n break;\n }\n case 17: {\n // *******\n // * CMP *\n // *******\n\n // Compare memory and accumulator:\n temp = this.REG_ACC - this.load(addr);\n this.F_CARRY = temp >= 0 ? 1 : 0;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n cycleCount += cycleAdd;\n break;\n }\n case 18: {\n // *******\n // * CPX *\n // *******\n\n // Compare memory and index X:\n temp = this.REG_X - this.load(addr);\n this.F_CARRY = temp >= 0 ? 1 : 0;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n break;\n }\n case 19: {\n // *******\n // * CPY *\n // *******\n\n // Compare memory and index Y:\n temp = this.REG_Y - this.load(addr);\n this.F_CARRY = temp >= 0 ? 1 : 0;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n break;\n }\n case 20: {\n // *******\n // * DEC *\n // *******\n\n // Decrement memory by one:\n temp = (this.load(addr) - 1) & 0xff;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n this.write(addr, temp);\n break;\n }\n case 21: {\n // *******\n // * DEX *\n // *******\n\n // Decrement index X by one:\n this.REG_X = (this.REG_X - 1) & 0xff;\n this.F_SIGN = (this.REG_X >> 7) & 1;\n this.F_ZERO = this.REG_X;\n break;\n }\n case 22: {\n // *******\n // * DEY *\n // *******\n\n // Decrement index Y by one:\n this.REG_Y = (this.REG_Y - 1) & 0xff;\n this.F_SIGN = (this.REG_Y >> 7) & 1;\n this.F_ZERO = this.REG_Y;\n break;\n }\n case 23: {\n // *******\n // * EOR *\n // *******\n\n // XOR Memory with accumulator, store in accumulator:\n this.REG_ACC = (this.load(addr) ^ this.REG_ACC) & 0xff;\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n cycleCount += cycleAdd;\n break;\n }\n case 24: {\n // *******\n // * INC *\n // *******\n\n // Increment memory by one:\n temp = (this.load(addr) + 1) & 0xff;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n this.write(addr, temp & 0xff);\n break;\n }\n case 25: {\n // *******\n // * INX *\n // *******\n\n // Increment index X by one:\n this.REG_X = (this.REG_X + 1) & 0xff;\n this.F_SIGN = (this.REG_X >> 7) & 1;\n this.F_ZERO = this.REG_X;\n break;\n }\n case 26: {\n // *******\n // * INY *\n // *******\n\n // Increment index Y by one:\n this.REG_Y++;\n this.REG_Y &= 0xff;\n this.F_SIGN = (this.REG_Y >> 7) & 1;\n this.F_ZERO = this.REG_Y;\n break;\n }\n case 27: {\n // *******\n // * JMP *\n // *******\n\n // Jump to new location:\n this.REG_PC = addr - 1;\n break;\n }\n case 28: {\n // *******\n // * JSR *\n // *******\n\n // Jump to new location, saving return address.\n // Push return address on stack:\n this.push((this.REG_PC >> 8) & 255);\n this.push(this.REG_PC & 255);\n this.REG_PC = addr - 1;\n break;\n }\n case 29: {\n // *******\n // * LDA *\n // *******\n\n // Load accumulator with memory:\n this.REG_ACC = this.load(addr);\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n cycleCount += cycleAdd;\n break;\n }\n case 30: {\n // *******\n // * LDX *\n // *******\n\n // Load index X with memory:\n this.REG_X = this.load(addr);\n this.F_SIGN = (this.REG_X >> 7) & 1;\n this.F_ZERO = this.REG_X;\n cycleCount += cycleAdd;\n break;\n }\n case 31: {\n // *******\n // * LDY *\n // *******\n\n // Load index Y with memory:\n this.REG_Y = this.load(addr);\n this.F_SIGN = (this.REG_Y >> 7) & 1;\n this.F_ZERO = this.REG_Y;\n cycleCount += cycleAdd;\n break;\n }\n case 32: {\n // *******\n // * LSR *\n // *******\n\n // Shift right one bit:\n if (addrMode === 4) {\n // ADDR_ACC\n\n temp = this.REG_ACC & 0xff;\n this.F_CARRY = temp & 1;\n temp >>= 1;\n this.REG_ACC = temp;\n } else {\n temp = this.load(addr) & 0xff;\n this.F_CARRY = temp & 1;\n temp >>= 1;\n this.write(addr, temp);\n }\n this.F_SIGN = 0;\n this.F_ZERO = temp;\n break;\n }\n case 33: {\n // *******\n // * NOP *\n // *******\n\n // No OPeration.\n // Ignore.\n break;\n }\n case 34: {\n // *******\n // * ORA *\n // *******\n\n // OR memory with accumulator, store in accumulator.\n temp = (this.load(addr) | this.REG_ACC) & 255;\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n this.REG_ACC = temp;\n if (addrMode !== 11) cycleCount += cycleAdd; // PostIdxInd = 11\n break;\n }\n case 35: {\n // *******\n // * PHA *\n // *******\n\n // Push accumulator on stack\n this.push(this.REG_ACC);\n break;\n }\n case 36: {\n // *******\n // * PHP *\n // *******\n\n // Push processor status on stack\n this.F_BRK = 1;\n this.push(\n this.F_CARRY |\n ((this.F_ZERO === 0 ? 1 : 0) << 1) |\n (this.F_INTERRUPT << 2) |\n (this.F_DECIMAL << 3) |\n (this.F_BRK << 4) |\n (this.F_NOTUSED << 5) |\n (this.F_OVERFLOW << 6) |\n (this.F_SIGN << 7)\n );\n break;\n }\n case 37: {\n // *******\n // * PLA *\n // *******\n\n // Pull accumulator from stack\n this.REG_ACC = this.pull();\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n break;\n }\n case 38: {\n // *******\n // * PLP *\n // *******\n\n // Pull processor status from stack\n temp = this.pull();\n this.F_CARRY = temp & 1;\n this.F_ZERO = ((temp >> 1) & 1) === 1 ? 0 : 1;\n this.F_INTERRUPT = (temp >> 2) & 1;\n this.F_DECIMAL = (temp >> 3) & 1;\n this.F_BRK = (temp >> 4) & 1;\n this.F_NOTUSED = (temp >> 5) & 1;\n this.F_OVERFLOW = (temp >> 6) & 1;\n this.F_SIGN = (temp >> 7) & 1;\n\n this.F_NOTUSED = 1;\n break;\n }\n case 39: {\n // *******\n // * ROL *\n // *******\n\n // Rotate one bit left\n if (addrMode === 4) {\n // ADDR_ACC = 4\n\n temp = this.REG_ACC;\n add = this.F_CARRY;\n this.F_CARRY = (temp >> 7) & 1;\n temp = ((temp << 1) & 0xff) + add;\n this.REG_ACC = temp;\n } else {\n temp = this.load(addr);\n add = this.F_CARRY;\n this.F_CARRY = (temp >> 7) & 1;\n temp = ((temp << 1) & 0xff) + add;\n this.write(addr, temp);\n }\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n break;\n }\n case 40: {\n // *******\n // * ROR *\n // *******\n\n // Rotate one bit right\n if (addrMode === 4) {\n // ADDR_ACC = 4\n\n add = this.F_CARRY << 7;\n this.F_CARRY = this.REG_ACC & 1;\n temp = (this.REG_ACC >> 1) + add;\n this.REG_ACC = temp;\n } else {\n temp = this.load(addr);\n add = this.F_CARRY << 7;\n this.F_CARRY = temp & 1;\n temp = (temp >> 1) + add;\n this.write(addr, temp);\n }\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp;\n break;\n }\n case 41: {\n // *******\n // * RTI *\n // *******\n\n // Return from interrupt. Pull status and PC from stack.\n\n temp = this.pull();\n this.F_CARRY = temp & 1;\n this.F_ZERO = ((temp >> 1) & 1) === 0 ? 1 : 0;\n this.F_INTERRUPT = (temp >> 2) & 1;\n this.F_DECIMAL = (temp >> 3) & 1;\n this.F_BRK = (temp >> 4) & 1;\n this.F_NOTUSED = (temp >> 5) & 1;\n this.F_OVERFLOW = (temp >> 6) & 1;\n this.F_SIGN = (temp >> 7) & 1;\n\n this.REG_PC = this.pull();\n this.REG_PC += this.pull() << 8;\n if (this.REG_PC === 0xffff) {\n return;\n }\n this.REG_PC--;\n this.F_NOTUSED = 1;\n break;\n }\n case 42: {\n // *******\n // * RTS *\n // *******\n\n // Return from subroutine. Pull PC from stack.\n\n this.REG_PC = this.pull();\n this.REG_PC += this.pull() << 8;\n\n if (this.REG_PC === 0xffff) {\n return; // return from NSF play routine:\n }\n break;\n }\n case 43: {\n // *******\n // * SBC *\n // *******\n\n temp = this.REG_ACC - this.load(addr) - (1 - this.F_CARRY);\n this.F_SIGN = (temp >> 7) & 1;\n this.F_ZERO = temp & 0xff;\n if (\n ((this.REG_ACC ^ temp) & 0x80) !== 0 &&\n ((this.REG_ACC ^ this.load(addr)) & 0x80) !== 0\n ) {\n this.F_OVERFLOW = 1;\n } else {\n this.F_OVERFLOW = 0;\n }\n this.F_CARRY = temp < 0 ? 0 : 1;\n this.REG_ACC = temp & 0xff;\n if (addrMode !== 11) cycleCount += cycleAdd; // PostIdxInd = 11\n break;\n }\n case 44: {\n // *******\n // * SEC *\n // *******\n\n // Set carry flag\n this.F_CARRY = 1;\n break;\n }\n case 45: {\n // *******\n // * SED *\n // *******\n\n // Set decimal mode\n this.F_DECIMAL = 1;\n break;\n }\n case 46: {\n // *******\n // * SEI *\n // *******\n\n // Set interrupt disable status\n this.F_INTERRUPT = 1;\n break;\n }\n case 47: {\n // *******\n // * STA *\n // *******\n\n // Store accumulator in memory\n this.write(addr, this.REG_ACC);\n break;\n }\n case 48: {\n // *******\n // * STX *\n // *******\n\n // Store index X in memory\n this.write(addr, this.REG_X);\n break;\n }\n case 49: {\n // *******\n // * STY *\n // *******\n\n // Store index Y in memory:\n this.write(addr, this.REG_Y);\n break;\n }\n case 50: {\n // *******\n // * TAX *\n // *******\n\n // Transfer accumulator to index X:\n this.REG_X = this.REG_ACC;\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n break;\n }\n case 51: {\n // *******\n // * TAY *\n // *******\n\n // Transfer accumulator to index Y:\n this.REG_Y = this.REG_ACC;\n this.F_SIGN = (this.REG_ACC >> 7) & 1;\n this.F_ZERO = this.REG_ACC;\n break;\n }\n case 52: {\n // *******\n // * TSX *\n // *******\n\n // Transfer stack pointer to index X:\n this.REG_X = this.REG_SP - 0x0100;\n this.F_SIGN = (this.REG_SP >> 7) & 1;\n this.F_ZERO = this.REG_X;\n break;\n }\n case 53: {\n // *******\n // * TXA *\n // *******\n\n // Transfer index X to accumulator:\n this.REG_ACC = this.REG_X;\n this.F_SIGN = (this.REG_X >> 7) & 1;\n this.F_ZERO = this.REG_X;\n break;\n }\n case 54: {\n // *******\n // * TXS *\n // *******\n\n // Transfer index X to stack pointer:\n this.REG_SP = this.REG_X + 0x0100;\n this.stackWrap();\n break;\n }\n case 55: {\n // *******\n // * TYA *\n // *******\n\n // Transfer index Y to accumulator:\n this.REG_ACC = this.REG_Y;\n this.F_SIGN = (this.REG_Y >> 7) & 1;\n this.F_ZERO = this.REG_Y;\n break;\n }\n default: {\n // *******\n // * ??? *\n // *******\n\n this.nes.stop();\n this.nes.crashMessage =\n \"Game crashed, invalid opcode at address $\" + opaddr.toString(16);\n break;\n }\n } // end of switch\n\n return cycleCount;\n },\n\n load: function(addr) {\n if (addr < 0x2000) {\n return this.mem[addr & 0x7ff];\n } else {\n return this.nes.mmap.load(addr);\n }\n },\n\n load16bit: function(addr) {\n if (addr < 0x1fff) {\n return this.mem[addr & 0x7ff] | (this.mem[(addr + 1) & 0x7ff] << 8);\n } else {\n return this.nes.mmap.load(addr) | (this.nes.mmap.load(addr + 1) << 8);\n }\n },\n\n write: function(addr, val) {\n if (addr < 0x2000) {\n this.mem[addr & 0x7ff] = val;\n } else {\n this.nes.mmap.write(addr, val);\n }\n },\n\n requestIrq: function(type) {\n if (this.irqRequested) {\n if (type === this.IRQ_NORMAL) {\n return;\n }\n // console.log(\"too fast irqs. type=\"+type);\n }\n this.irqRequested = true;\n this.irqType = type;\n },\n\n push: function(value) {\n this.nes.mmap.write(this.REG_SP, value);\n this.REG_SP--;\n this.REG_SP = 0x0100 | (this.REG_SP & 0xff);\n },\n\n stackWrap: function() {\n this.REG_SP = 0x0100 | (this.REG_SP & 0xff);\n },\n\n pull: function() {\n this.REG_SP++;\n this.REG_SP = 0x0100 | (this.REG_SP & 0xff);\n return this.nes.mmap.load(this.REG_SP);\n },\n\n pageCrossed: function(addr1, addr2) {\n return (addr1 & 0xff00) !== (addr2 & 0xff00);\n },\n\n haltCycles: function(cycles) {\n this.cyclesToHalt += cycles;\n },\n\n doNonMaskableInterrupt: function(status) {\n if ((this.nes.mmap.load(0x2000) & 128) !== 0) {\n // Check whether VBlank Interrupts are enabled\n\n this.REG_PC_NEW++;\n this.push((this.REG_PC_NEW >> 8) & 0xff);\n this.push(this.REG_PC_NEW & 0xff);\n //this.F_INTERRUPT_NEW = 1;\n this.push(status);\n\n this.REG_PC_NEW =\n this.nes.mmap.load(0xfffa) | (this.nes.mmap.load(0xfffb) << 8);\n this.REG_PC_NEW--;\n }\n },\n\n doResetInterrupt: function() {\n this.REG_PC_NEW =\n this.nes.mmap.load(0xfffc) | (this.nes.mmap.load(0xfffd) << 8);\n this.REG_PC_NEW--;\n },\n\n doIrq: function(status) {\n this.REG_PC_NEW++;\n this.push((this.REG_PC_NEW >> 8) & 0xff);\n this.push(this.REG_PC_NEW & 0xff);\n this.push(status);\n this.F_INTERRUPT_NEW = 1;\n this.F_BRK_NEW = 0;\n\n this.REG_PC_NEW =\n this.nes.mmap.load(0xfffe) | (this.nes.mmap.load(0xffff) << 8);\n this.REG_PC_NEW--;\n },\n\n getStatus: function() {\n return (\n this.F_CARRY |\n (this.F_ZERO << 1) |\n (this.F_INTERRUPT << 2) |\n (this.F_DECIMAL << 3) |\n (this.F_BRK << 4) |\n (this.F_NOTUSED << 5) |\n (this.F_OVERFLOW << 6) |\n (this.F_SIGN << 7)\n );\n },\n\n setStatus: function(st) {\n this.F_CARRY = st & 1;\n this.F_ZERO = (st >> 1) & 1;\n this.F_INTERRUPT = (st >> 2) & 1;\n this.F_DECIMAL = (st >> 3) & 1;\n this.F_BRK = (st >> 4) & 1;\n this.F_NOTUSED = (st >> 5) & 1;\n this.F_OVERFLOW = (st >> 6) & 1;\n this.F_SIGN = (st >> 7) & 1;\n },\n\n JSON_PROPERTIES: [\n \"mem\",\n \"cyclesToHalt\",\n \"irqRequested\",\n \"irqType\",\n // Registers\n \"REG_ACC\",\n \"REG_X\",\n \"REG_Y\",\n \"REG_SP\",\n \"REG_PC\",\n \"REG_PC_NEW\",\n \"REG_STATUS\",\n // Status\n \"F_CARRY\",\n \"F_DECIMAL\",\n \"F_INTERRUPT\",\n \"F_INTERRUPT_NEW\",\n \"F_OVERFLOW\",\n \"F_SIGN\",\n \"F_ZERO\",\n \"F_NOTUSED\",\n \"F_NOTUSED_NEW\",\n \"F_BRK\",\n \"F_BRK_NEW\"\n ],\n\n toJSON: function() {\n return utils.toJSON(this);\n },\n\n fromJSON: function(s) {\n utils.fromJSON(this, s);\n }\n};\n\n// Generates and provides an array of details about instructions\nvar OpData = function() {\n this.opdata = new Array(256);\n\n // Set all to invalid instruction (to detect crashes):\n for (var i = 0; i < 256; i++) this.opdata[i] = 0xff;\n\n // Now fill in all valid opcodes:\n\n // ADC:\n this.setOp(this.INS_ADC, 0x69, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_ADC, 0x65, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_ADC, 0x75, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_ADC, 0x6d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_ADC, 0x7d, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_ADC, 0x79, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_ADC, 0x61, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_ADC, 0x71, this.ADDR_POSTIDXIND, 2, 5);\n\n // AND:\n this.setOp(this.INS_AND, 0x29, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_AND, 0x25, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_AND, 0x35, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_AND, 0x2d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_AND, 0x3d, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_AND, 0x39, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_AND, 0x21, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_AND, 0x31, this.ADDR_POSTIDXIND, 2, 5);\n\n // ASL:\n this.setOp(this.INS_ASL, 0x0a, this.ADDR_ACC, 1, 2);\n this.setOp(this.INS_ASL, 0x06, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_ASL, 0x16, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_ASL, 0x0e, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_ASL, 0x1e, this.ADDR_ABSX, 3, 7);\n\n // BCC:\n this.setOp(this.INS_BCC, 0x90, this.ADDR_REL, 2, 2);\n\n // BCS:\n this.setOp(this.INS_BCS, 0xb0, this.ADDR_REL, 2, 2);\n\n // BEQ:\n this.setOp(this.INS_BEQ, 0xf0, this.ADDR_REL, 2, 2);\n\n // BIT:\n this.setOp(this.INS_BIT, 0x24, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_BIT, 0x2c, this.ADDR_ABS, 3, 4);\n\n // BMI:\n this.setOp(this.INS_BMI, 0x30, this.ADDR_REL, 2, 2);\n\n // BNE:\n this.setOp(this.INS_BNE, 0xd0, this.ADDR_REL, 2, 2);\n\n // BPL:\n this.setOp(this.INS_BPL, 0x10, this.ADDR_REL, 2, 2);\n\n // BRK:\n this.setOp(this.INS_BRK, 0x00, this.ADDR_IMP, 1, 7);\n\n // BVC:\n this.setOp(this.INS_BVC, 0x50, this.ADDR_REL, 2, 2);\n\n // BVS:\n this.setOp(this.INS_BVS, 0x70, this.ADDR_REL, 2, 2);\n\n // CLC:\n this.setOp(this.INS_CLC, 0x18, this.ADDR_IMP, 1, 2);\n\n // CLD:\n this.setOp(this.INS_CLD, 0xd8, this.ADDR_IMP, 1, 2);\n\n // CLI:\n this.setOp(this.INS_CLI, 0x58, this.ADDR_IMP, 1, 2);\n\n // CLV:\n this.setOp(this.INS_CLV, 0xb8, this.ADDR_IMP, 1, 2);\n\n // CMP:\n this.setOp(this.INS_CMP, 0xc9, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_CMP, 0xc5, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_CMP, 0xd5, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_CMP, 0xcd, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_CMP, 0xdd, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_CMP, 0xd9, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_CMP, 0xc1, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_CMP, 0xd1, this.ADDR_POSTIDXIND, 2, 5);\n\n // CPX:\n this.setOp(this.INS_CPX, 0xe0, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_CPX, 0xe4, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_CPX, 0xec, this.ADDR_ABS, 3, 4);\n\n // CPY:\n this.setOp(this.INS_CPY, 0xc0, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_CPY, 0xc4, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_CPY, 0xcc, this.ADDR_ABS, 3, 4);\n\n // DEC:\n this.setOp(this.INS_DEC, 0xc6, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_DEC, 0xd6, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_DEC, 0xce, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_DEC, 0xde, this.ADDR_ABSX, 3, 7);\n\n // DEX:\n this.setOp(this.INS_DEX, 0xca, this.ADDR_IMP, 1, 2);\n\n // DEY:\n this.setOp(this.INS_DEY, 0x88, this.ADDR_IMP, 1, 2);\n\n // EOR:\n this.setOp(this.INS_EOR, 0x49, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_EOR, 0x45, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_EOR, 0x55, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_EOR, 0x4d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_EOR, 0x5d, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_EOR, 0x59, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_EOR, 0x41, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_EOR, 0x51, this.ADDR_POSTIDXIND, 2, 5);\n\n // INC:\n this.setOp(this.INS_INC, 0xe6, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_INC, 0xf6, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_INC, 0xee, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_INC, 0xfe, this.ADDR_ABSX, 3, 7);\n\n // INX:\n this.setOp(this.INS_INX, 0xe8, this.ADDR_IMP, 1, 2);\n\n // INY:\n this.setOp(this.INS_INY, 0xc8, this.ADDR_IMP, 1, 2);\n\n // JMP:\n this.setOp(this.INS_JMP, 0x4c, this.ADDR_ABS, 3, 3);\n this.setOp(this.INS_JMP, 0x6c, this.ADDR_INDABS, 3, 5);\n\n // JSR:\n this.setOp(this.INS_JSR, 0x20, this.ADDR_ABS, 3, 6);\n\n // LDA:\n this.setOp(this.INS_LDA, 0xa9, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_LDA, 0xa5, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_LDA, 0xb5, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_LDA, 0xad, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_LDA, 0xbd, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_LDA, 0xb9, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_LDA, 0xa1, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_LDA, 0xb1, this.ADDR_POSTIDXIND, 2, 5);\n\n // LDX:\n this.setOp(this.INS_LDX, 0xa2, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_LDX, 0xa6, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_LDX, 0xb6, this.ADDR_ZPY, 2, 4);\n this.setOp(this.INS_LDX, 0xae, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_LDX, 0xbe, this.ADDR_ABSY, 3, 4);\n\n // LDY:\n this.setOp(this.INS_LDY, 0xa0, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_LDY, 0xa4, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_LDY, 0xb4, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_LDY, 0xac, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_LDY, 0xbc, this.ADDR_ABSX, 3, 4);\n\n // LSR:\n this.setOp(this.INS_LSR, 0x4a, this.ADDR_ACC, 1, 2);\n this.setOp(this.INS_LSR, 0x46, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_LSR, 0x56, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_LSR, 0x4e, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_LSR, 0x5e, this.ADDR_ABSX, 3, 7);\n\n // NOP:\n this.setOp(this.INS_NOP, 0xea, this.ADDR_IMP, 1, 2);\n\n // ORA:\n this.setOp(this.INS_ORA, 0x09, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_ORA, 0x05, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_ORA, 0x15, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_ORA, 0x0d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_ORA, 0x1d, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_ORA, 0x19, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_ORA, 0x01, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_ORA, 0x11, this.ADDR_POSTIDXIND, 2, 5);\n\n // PHA:\n this.setOp(this.INS_PHA, 0x48, this.ADDR_IMP, 1, 3);\n\n // PHP:\n this.setOp(this.INS_PHP, 0x08, this.ADDR_IMP, 1, 3);\n\n // PLA:\n this.setOp(this.INS_PLA, 0x68, this.ADDR_IMP, 1, 4);\n\n // PLP:\n this.setOp(this.INS_PLP, 0x28, this.ADDR_IMP, 1, 4);\n\n // ROL:\n this.setOp(this.INS_ROL, 0x2a, this.ADDR_ACC, 1, 2);\n this.setOp(this.INS_ROL, 0x26, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_ROL, 0x36, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_ROL, 0x2e, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_ROL, 0x3e, this.ADDR_ABSX, 3, 7);\n\n // ROR:\n this.setOp(this.INS_ROR, 0x6a, this.ADDR_ACC, 1, 2);\n this.setOp(this.INS_ROR, 0x66, this.ADDR_ZP, 2, 5);\n this.setOp(this.INS_ROR, 0x76, this.ADDR_ZPX, 2, 6);\n this.setOp(this.INS_ROR, 0x6e, this.ADDR_ABS, 3, 6);\n this.setOp(this.INS_ROR, 0x7e, this.ADDR_ABSX, 3, 7);\n\n // RTI:\n this.setOp(this.INS_RTI, 0x40, this.ADDR_IMP, 1, 6);\n\n // RTS:\n this.setOp(this.INS_RTS, 0x60, this.ADDR_IMP, 1, 6);\n\n // SBC:\n this.setOp(this.INS_SBC, 0xe9, this.ADDR_IMM, 2, 2);\n this.setOp(this.INS_SBC, 0xe5, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_SBC, 0xf5, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_SBC, 0xed, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_SBC, 0xfd, this.ADDR_ABSX, 3, 4);\n this.setOp(this.INS_SBC, 0xf9, this.ADDR_ABSY, 3, 4);\n this.setOp(this.INS_SBC, 0xe1, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_SBC, 0xf1, this.ADDR_POSTIDXIND, 2, 5);\n\n // SEC:\n this.setOp(this.INS_SEC, 0x38, this.ADDR_IMP, 1, 2);\n\n // SED:\n this.setOp(this.INS_SED, 0xf8, this.ADDR_IMP, 1, 2);\n\n // SEI:\n this.setOp(this.INS_SEI, 0x78, this.ADDR_IMP, 1, 2);\n\n // STA:\n this.setOp(this.INS_STA, 0x85, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_STA, 0x95, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_STA, 0x8d, this.ADDR_ABS, 3, 4);\n this.setOp(this.INS_STA, 0x9d, this.ADDR_ABSX, 3, 5);\n this.setOp(this.INS_STA, 0x99, this.ADDR_ABSY, 3, 5);\n this.setOp(this.INS_STA, 0x81, this.ADDR_PREIDXIND, 2, 6);\n this.setOp(this.INS_STA, 0x91, this.ADDR_POSTIDXIND, 2, 6);\n\n // STX:\n this.setOp(this.INS_STX, 0x86, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_STX, 0x96, this.ADDR_ZPY, 2, 4);\n this.setOp(this.INS_STX, 0x8e, this.ADDR_ABS, 3, 4);\n\n // STY:\n this.setOp(this.INS_STY, 0x84, this.ADDR_ZP, 2, 3);\n this.setOp(this.INS_STY, 0x94, this.ADDR_ZPX, 2, 4);\n this.setOp(this.INS_STY, 0x8c, this.ADDR_ABS, 3, 4);\n\n // TAX:\n this.setOp(this.INS_TAX, 0xaa, this.ADDR_IMP, 1, 2);\n\n // TAY:\n this.setOp(this.INS_TAY, 0xa8, this.ADDR_IMP, 1, 2);\n\n // TSX:\n this.setOp(this.INS_TSX, 0xba, this.ADDR_IMP, 1, 2);\n\n // TXA:\n this.setOp(this.INS_TXA, 0x8a, this.ADDR_IMP, 1, 2);\n\n // TXS:\n this.setOp(this.INS_TXS, 0x9a, this.ADDR_IMP, 1, 2);\n\n // TYA:\n this.setOp(this.INS_TYA, 0x98, this.ADDR_IMP, 1, 2);\n\n // prettier-ignore\n this.cycTable = new Array(\n /*0x00*/ 7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,\n /*0x10*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0x20*/ 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,\n /*0x30*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0x40*/ 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,\n /*0x50*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0x60*/ 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,\n /*0x70*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0x80*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,\n /*0x90*/ 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,\n /*0xA0*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,\n /*0xB0*/ 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,\n /*0xC0*/ 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,\n /*0xD0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,\n /*0xE0*/ 2,6,3,8,3,3,5,5,2,2,2,2,4,4,6,6,\n /*0xF0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7\n );\n\n this.instname = new Array(56);\n\n // Instruction Names:\n this.instname[0] = \"ADC\";\n this.instname[1] = \"AND\";\n this.instname[2] = \"ASL\";\n this.instname[3] = \"BCC\";\n this.instname[4] = \"BCS\";\n this.instname[5] = \"BEQ\";\n this.instname[6] = \"BIT\";\n this.instname[7] = \"BMI\";\n this.instname[8] = \"BNE\";\n this.instname[9] = \"BPL\";\n this.instname[10] = \"BRK\";\n this.instname[11] = \"BVC\";\n this.instname[12] = \"BVS\";\n this.instname[13] = \"CLC\";\n this.instname[14] = \"CLD\";\n this.instname[15] = \"CLI\";\n this.instname[16] = \"CLV\";\n this.instname[17] = \"CMP\";\n this.instname[18] = \"CPX\";\n this.instname[19] = \"CPY\";\n this.instname[20] = \"DEC\";\n this.instname[21] = \"DEX\";\n this.instname[22] = \"DEY\";\n this.instname[23] = \"EOR\";\n this.instname[24] = \"INC\";\n this.instname[25] = \"INX\";\n this.instname[26] = \"INY\";\n this.instname[27] = \"JMP\";\n this.instname[28] = \"JSR\";\n this.instname[29] = \"LDA\";\n this.instname[30] = \"LDX\";\n this.instname[31] = \"LDY\";\n this.instname[32] = \"LSR\";\n this.instname[33] = \"NOP\";\n this.instname[34] = \"ORA\";\n this.instname[35] = \"PHA\";\n this.instname[36] = \"PHP\";\n this.instname[37] = \"PLA\";\n this.instname[38] = \"PLP\";\n this.instname[39] = \"ROL\";\n this.instname[40] = \"ROR\";\n this.instname[41] = \"RTI\";\n this.instname[42] = \"RTS\";\n this.instname[43] = \"SBC\";\n this.instname[44] = \"SEC\";\n this.instname[45] = \"SED\";\n this.instname[46] = \"SEI\";\n this.instname[47] = \"STA\";\n this.instname[48] = \"STX\";\n this.instname[49] = \"STY\";\n this.instname[50] = \"TAX\";\n this.instname[51] = \"TAY\";\n this.instname[52] = \"TSX\";\n this.instname[53] = \"TXA\";\n this.instname[54] = \"TXS\";\n this.instname[55] = \"TYA\";\n\n this.addrDesc = new Array(\n \"Zero Page \",\n \"Relative \",\n \"Implied \",\n \"Absolute \",\n \"Accumulator \",\n \"Immediate \",\n \"Zero Page,X \",\n \"Zero Page,Y \",\n \"Absolute,X \",\n \"Absolute,Y \",\n \"Preindexed Indirect \",\n \"Postindexed Indirect\",\n \"Indirect Absolute \"\n );\n};\n\nOpData.prototype = {\n INS_ADC: 0,\n INS_AND: 1,\n INS_ASL: 2,\n\n INS_BCC: 3,\n INS_BCS: 4,\n INS_BEQ: 5,\n INS_BIT: 6,\n INS_BMI: 7,\n INS_BNE: 8,\n INS_BPL: 9,\n INS_BRK: 10,\n INS_BVC: 11,\n INS_BVS: 12,\n\n INS_CLC: 13,\n INS_CLD: 14,\n INS_CLI: 15,\n INS_CLV: 16,\n INS_CMP: 17,\n INS_CPX: 18,\n INS_CPY: 19,\n\n INS_DEC: 20,\n INS_DEX: 21,\n INS_DEY: 22,\n\n INS_EOR: 23,\n\n INS_INC: 24,\n INS_INX: 25,\n INS_INY: 26,\n\n INS_JMP: 27,\n INS_JSR: 28,\n\n INS_LDA: 29,\n INS_LDX: 30,\n INS_LDY: 31,\n INS_LSR: 32,\n\n INS_NOP: 33,\n\n INS_ORA: 34,\n\n INS_PHA: 35,\n INS_PHP: 36,\n INS_PLA: 37,\n INS_PLP: 38,\n\n INS_ROL: 39,\n INS_ROR: 40,\n INS_RTI: 41,\n INS_RTS: 42,\n\n INS_SBC: 43,\n INS_SEC: 44,\n INS_SED: 45,\n INS_SEI: 46,\n INS_STA: 47,\n INS_STX: 48,\n INS_STY: 49,\n\n INS_TAX: 50,\n INS_TAY: 51,\n INS_TSX: 52,\n INS_TXA: 53,\n INS_TXS: 54,\n INS_TYA: 55,\n\n INS_DUMMY: 56, // dummy instruction used for 'halting' the processor some cycles\n\n // -------------------------------- //\n\n // Addressing modes:\n ADDR_ZP: 0,\n ADDR_REL: 1,\n ADDR_IMP: 2,\n ADDR_ABS: 3,\n ADDR_ACC: 4,\n ADDR_IMM: 5,\n ADDR_ZPX: 6,\n ADDR_ZPY: 7,\n ADDR_ABSX: 8,\n ADDR_ABSY: 9,\n ADDR_PREIDXIND: 10,\n ADDR_POSTIDXIND: 11,\n ADDR_INDABS: 12,\n\n setOp: function(inst, op, addr, size, cycles) {\n this.opdata[op] =\n (inst & 0xff) |\n ((addr & 0xff) << 8) |\n ((size & 0xff) << 16) |\n ((cycles & 0xff) << 24);\n }\n};\n\nmodule.exports = CPU;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/cpu.js\n// module id = 5\n// module chunks = 0 1","var Tile = require('./tile');\nvar utils = require('./utils');\n\nvar PPU = function(nes) {\n this.nes = nes;\n\n // Keep Chrome happy\n this.vramMem = null;\n this.spriteMem = null;\n this.vramAddress = null;\n this.vramTmpAddress = null;\n this.vramBufferedReadValue = null;\n this.firstWrite = null;\n this.sramAddress = null;\n this.currentMirroring = null;\n this.requestEndFrame = null;\n this.nmiOk = null;\n this.dummyCycleToggle = null;\n this.validTileData = null;\n this.nmiCounter = null;\n this.scanlineAlreadyRendered = null;\n this.f_nmiOnVblank = null;\n this.f_spriteSize = null;\n this.f_bgPatternTable = null;\n this.f_spPatternTable = null;\n this.f_addrInc = null;\n this.f_nTblAddress = null;\n this.f_color = null;\n this.f_spVisibility = null;\n this.f_bgVisibility = null;\n this.f_spClipping = null;\n this.f_bgClipping = null;\n this.f_dispType = null;\n this.cntFV = null;\n this.cntV = null;\n this.cntH = null;\n this.cntVT = null;\n this.cntHT = null;\n this.regFV = null;\n this.regV = null;\n this.regH = null;\n this.regVT = null;\n this.regHT = null;\n this.regFH = null;\n this.regS = null;\n this.curNt = null;\n this.attrib = null;\n this.buffer = null;\n this.bgbuffer = null;\n this.pixrendered = null;\n\n this.validTileData = null;\n this.scantile = null;\n this.scanline = null;\n this.lastRenderedScanline = null;\n this.curX = null;\n this.sprX = null;\n this.sprY = null;\n this.sprTile = null;\n this.sprCol = null;\n this.vertFlip = null;\n this.horiFlip = null;\n this.bgPriority = null;\n this.spr0HitX = null;\n this.spr0HitY = null;\n this.hitSpr0 = null;\n this.sprPalette = null;\n this.imgPalette = null;\n this.ptTile = null;\n this.ntable1 = null;\n this.currentMirroring = null;\n this.nameTable = null;\n this.vramMirrorTable = null;\n this.palTable = null;\n\n // Rendering Options:\n this.showSpr0Hit = false;\n this.clipToTvSize = true;\n\n this.reset();\n};\n\nPPU.prototype = {\n // Status flags:\n STATUS_VRAMWRITE: 4,\n STATUS_SLSPRITECOUNT: 5,\n STATUS_SPRITE0HIT: 6,\n STATUS_VBLANK: 7,\n\n reset: function() {\n var i;\n\n // Memory\n this.vramMem = new Array(0x8000);\n this.spriteMem = new Array(0x100);\n for (i = 0; i < this.vramMem.length; i++) {\n this.vramMem[i] = 0;\n }\n for (i = 0; i < this.spriteMem.length; i++) {\n this.spriteMem[i] = 0;\n }\n\n // VRAM I/O:\n this.vramAddress = null;\n this.vramTmpAddress = null;\n this.vramBufferedReadValue = 0;\n this.firstWrite = true; // VRAM/Scroll Hi/Lo latch\n\n // SPR-RAM I/O:\n this.sramAddress = 0; // 8-bit only.\n\n this.currentMirroring = -1;\n this.requestEndFrame = false;\n this.nmiOk = false;\n this.dummyCycleToggle = false;\n this.validTileData = false;\n this.nmiCounter = 0;\n this.scanlineAlreadyRendered = null;\n\n // Control Flags Register 1:\n this.f_nmiOnVblank = 0; // NMI on VBlank. 0=disable, 1=enable\n this.f_spriteSize = 0; // Sprite size. 0=8x8, 1=8x16\n this.f_bgPatternTable = 0; // Background Pattern Table address. 0=0x0000,1=0x1000\n this.f_spPatternTable = 0; // Sprite Pattern Table address. 0=0x0000,1=0x1000\n this.f_addrInc = 0; // PPU Address Increment. 0=1,1=32\n this.f_nTblAddress = 0; // Name Table Address. 0=0x2000,1=0x2400,2=0x2800,3=0x2C00\n\n // Control Flags Register 2:\n this.f_color = 0; // Background color. 0=black, 1=blue, 2=green, 4=red\n this.f_spVisibility = 0; // Sprite visibility. 0=not displayed,1=displayed\n this.f_bgVisibility = 0; // Background visibility. 0=Not Displayed,1=displayed\n this.f_spClipping = 0; // Sprite clipping. 0=Sprites invisible in left 8-pixel column,1=No clipping\n this.f_bgClipping = 0; // Background clipping. 0=BG invisible in left 8-pixel column, 1=No clipping\n this.f_dispType = 0; // Display type. 0=color, 1=monochrome\n\n // Counters:\n this.cntFV = 0;\n this.cntV = 0;\n this.cntH = 0;\n this.cntVT = 0;\n this.cntHT = 0;\n\n // Registers:\n this.regFV = 0;\n this.regV = 0;\n this.regH = 0;\n this.regVT = 0;\n this.regHT = 0;\n this.regFH = 0;\n this.regS = 0;\n\n // These are temporary variables used in rendering and sound procedures.\n // Their states outside of those procedures can be ignored.\n // TODO: the use of this is a bit weird, investigate\n this.curNt = null;\n\n // Variables used when rendering:\n this.attrib = new Array(32);\n this.buffer = new Array(256 * 240);\n this.bgbuffer = new Array(256 * 240);\n this.pixrendered = new Array(256 * 240);\n\n this.validTileData = null;\n\n this.scantile = new Array(32);\n\n // Initialize misc vars:\n this.scanline = 0;\n this.lastRenderedScanline = -1;\n this.curX = 0;\n\n // Sprite data:\n this.sprX = new Array(64); // X coordinate\n this.sprY = new Array(64); // Y coordinate\n this.sprTile = new Array(64); // Tile Index (into pattern table)\n this.sprCol = new Array(64); // Upper two bits of color\n this.vertFlip = new Array(64); // Vertical Flip\n this.horiFlip = new Array(64); // Horizontal Flip\n this.bgPriority = new Array(64); // Background priority\n this.spr0HitX = 0; // Sprite #0 hit X coordinate\n this.spr0HitY = 0; // Sprite #0 hit Y coordinate\n this.hitSpr0 = false;\n\n // Palette data:\n this.sprPalette = new Array(16);\n this.imgPalette = new Array(16);\n\n // Create pattern table tile buffers:\n this.ptTile = new Array(512);\n for (i = 0; i < 512; i++) {\n this.ptTile[i] = new Tile();\n }\n\n // Create nametable buffers:\n // Name table data:\n this.ntable1 = new Array(4);\n this.currentMirroring = -1;\n this.nameTable = new Array(4);\n for (i = 0; i < 4; i++) {\n this.nameTable[i] = new NameTable(32, 32, \"Nt\" + i);\n }\n\n // Initialize mirroring lookup table:\n this.vramMirrorTable = new Array(0x8000);\n for (i = 0; i < 0x8000; i++) {\n this.vramMirrorTable[i] = i;\n }\n\n this.palTable = new PaletteTable();\n this.palTable.loadNTSCPalette();\n //this.palTable.loadDefaultPalette();\n\n this.updateControlReg1(0);\n this.updateControlReg2(0);\n },\n\n // Sets Nametable mirroring.\n setMirroring: function(mirroring) {\n if (mirroring === this.currentMirroring) {\n return;\n }\n\n this.currentMirroring = mirroring;\n this.triggerRendering();\n\n // Remove mirroring:\n if (this.vramMirrorTable === null) {\n this.vramMirrorTable = new Array(0x8000);\n }\n for (var i = 0; i < 0x8000; i++) {\n this.vramMirrorTable[i] = i;\n }\n\n // Palette mirroring:\n this.defineMirrorRegion(0x3f20, 0x3f00, 0x20);\n this.defineMirrorRegion(0x3f40, 0x3f00, 0x20);\n this.defineMirrorRegion(0x3f80, 0x3f00, 0x20);\n this.defineMirrorRegion(0x3fc0, 0x3f00, 0x20);\n\n // Additional mirroring:\n this.defineMirrorRegion(0x3000, 0x2000, 0xf00);\n this.defineMirrorRegion(0x4000, 0x0000, 0x4000);\n\n if (mirroring === this.nes.rom.HORIZONTAL_MIRRORING) {\n // Horizontal mirroring.\n\n this.ntable1[0] = 0;\n this.ntable1[1] = 0;\n this.ntable1[2] = 1;\n this.ntable1[3] = 1;\n\n this.defineMirrorRegion(0x2400, 0x2000, 0x400);\n this.defineMirrorRegion(0x2c00, 0x2800, 0x400);\n } else if (mirroring === this.nes.rom.VERTICAL_MIRRORING) {\n // Vertical mirroring.\n\n this.ntable1[0] = 0;\n this.ntable1[1] = 1;\n this.ntable1[2] = 0;\n this.ntable1[3] = 1;\n\n this.defineMirrorRegion(0x2800, 0x2000, 0x400);\n this.defineMirrorRegion(0x2c00, 0x2400, 0x400);\n } else if (mirroring === this.nes.rom.SINGLESCREEN_MIRRORING) {\n // Single Screen mirroring\n\n this.ntable1[0] = 0;\n this.ntable1[1] = 0;\n this.ntable1[2] = 0;\n this.ntable1[3] = 0;\n\n this.defineMirrorRegion(0x2400, 0x2000, 0x400);\n this.defineMirrorRegion(0x2800, 0x2000, 0x400);\n this.defineMirrorRegion(0x2c00, 0x2000, 0x400);\n } else if (mirroring === this.nes.rom.SINGLESCREEN_MIRRORING2) {\n this.ntable1[0] = 1;\n this.ntable1[1] = 1;\n this.ntable1[2] = 1;\n this.ntable1[3] = 1;\n\n this.defineMirrorRegion(0x2400, 0x2400, 0x400);\n this.defineMirrorRegion(0x2800, 0x2400, 0x400);\n this.defineMirrorRegion(0x2c00, 0x2400, 0x400);\n } else {\n // Assume Four-screen mirroring.\n\n this.ntable1[0] = 0;\n this.ntable1[1] = 1;\n this.ntable1[2] = 2;\n this.ntable1[3] = 3;\n }\n },\n\n // Define a mirrored area in the address lookup table.\n // Assumes the regions don't overlap.\n // The 'to' region is the region that is physically in memory.\n defineMirrorRegion: function(fromStart, toStart, size) {\n for (var i = 0; i < size; i++) {\n this.vramMirrorTable[fromStart + i] = toStart + i;\n }\n },\n\n startVBlank: function() {\n // Do NMI:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_NMI);\n\n // Make sure everything is rendered:\n if (this.lastRenderedScanline < 239) {\n this.renderFramePartially(\n this.lastRenderedScanline + 1,\n 240 - this.lastRenderedScanline\n );\n }\n\n // End frame:\n this.endFrame();\n\n // Reset scanline counter:\n this.lastRenderedScanline = -1;\n },\n\n endScanline: function() {\n switch (this.scanline) {\n case 19:\n // Dummy scanline.\n // May be variable length:\n if (this.dummyCycleToggle) {\n // Remove dead cycle at end of scanline,\n // for next scanline:\n this.curX = 1;\n this.dummyCycleToggle = !this.dummyCycleToggle;\n }\n break;\n\n case 20:\n // Clear VBlank flag:\n this.setStatusFlag(this.STATUS_VBLANK, false);\n\n // Clear Sprite #0 hit flag:\n this.setStatusFlag(this.STATUS_SPRITE0HIT, false);\n this.hitSpr0 = false;\n this.spr0HitX = -1;\n this.spr0HitY = -1;\n\n if (this.f_bgVisibility === 1 || this.f_spVisibility === 1) {\n // Update counters:\n this.cntFV = this.regFV;\n this.cntV = this.regV;\n this.cntH = this.regH;\n this.cntVT = this.regVT;\n this.cntHT = this.regHT;\n\n if (this.f_bgVisibility === 1) {\n // Render dummy scanline:\n this.renderBgScanline(false, 0);\n }\n }\n\n if (this.f_bgVisibility === 1 && this.f_spVisibility === 1) {\n // Check sprite 0 hit for first scanline:\n this.checkSprite0(0);\n }\n\n if (this.f_bgVisibility === 1 || this.f_spVisibility === 1) {\n // Clock mapper IRQ Counter:\n this.nes.mmap.clockIrqCounter();\n }\n break;\n\n case 261:\n // Dead scanline, no rendering.\n // Set VINT:\n this.setStatusFlag(this.STATUS_VBLANK, true);\n this.requestEndFrame = true;\n this.nmiCounter = 9;\n\n // Wrap around:\n this.scanline = -1; // will be incremented to 0\n\n break;\n\n default:\n if (this.scanline >= 21 && this.scanline <= 260) {\n // Render normally:\n if (this.f_bgVisibility === 1) {\n if (!this.scanlineAlreadyRendered) {\n // update scroll:\n this.cntHT = this.regHT;\n this.cntH = this.regH;\n this.renderBgScanline(true, this.scanline + 1 - 21);\n }\n this.scanlineAlreadyRendered = false;\n\n // Check for sprite 0 (next scanline):\n if (!this.hitSpr0 && this.f_spVisibility === 1) {\n if (\n this.sprX[0] >= -7 &&\n this.sprX[0] < 256 &&\n this.sprY[0] + 1 <= this.scanline - 20 &&\n this.sprY[0] + 1 + (this.f_spriteSize === 0 ? 8 : 16) >=\n this.scanline - 20\n ) {\n if (this.checkSprite0(this.scanline - 20)) {\n this.hitSpr0 = true;\n }\n }\n }\n }\n\n if (this.f_bgVisibility === 1 || this.f_spVisibility === 1) {\n // Clock mapper IRQ Counter:\n this.nes.mmap.clockIrqCounter();\n }\n }\n }\n\n this.scanline++;\n this.regsToAddress();\n this.cntsToAddress();\n },\n\n startFrame: function() {\n // Set background color:\n var bgColor = 0;\n\n if (this.f_dispType === 0) {\n // Color display.\n // f_color determines color emphasis.\n // Use first entry of image palette as BG color.\n bgColor = this.imgPalette[0];\n } else {\n // Monochrome display.\n // f_color determines the bg color.\n switch (this.f_color) {\n case 0:\n // Black\n bgColor = 0x00000;\n break;\n case 1:\n // Green\n bgColor = 0x00ff00;\n break;\n case 2:\n // Blue\n bgColor = 0xff0000;\n break;\n case 3:\n // Invalid. Use black.\n bgColor = 0x000000;\n break;\n case 4:\n // Red\n bgColor = 0x0000ff;\n break;\n default:\n // Invalid. Use black.\n bgColor = 0x0;\n }\n }\n\n var buffer = this.buffer;\n var i;\n for (i = 0; i < 256 * 240; i++) {\n buffer[i] = bgColor;\n }\n var pixrendered = this.pixrendered;\n for (i = 0; i < pixrendered.length; i++) {\n pixrendered[i] = 65;\n }\n },\n\n endFrame: function() {\n var i, x, y;\n var buffer = this.buffer;\n\n // Draw spr#0 hit coordinates:\n if (this.showSpr0Hit) {\n // Spr 0 position:\n if (\n this.sprX[0] >= 0 &&\n this.sprX[0] < 256 &&\n this.sprY[0] >= 0 &&\n this.sprY[0] < 240\n ) {\n for (i = 0; i < 256; i++) {\n buffer[(this.sprY[0] << 8) + i] = 0xff5555;\n }\n for (i = 0; i < 240; i++) {\n buffer[(i << 8) + this.sprX[0]] = 0xff5555;\n }\n }\n // Hit position:\n if (\n this.spr0HitX >= 0 &&\n this.spr0HitX < 256 &&\n this.spr0HitY >= 0 &&\n this.spr0HitY < 240\n ) {\n for (i = 0; i < 256; i++) {\n buffer[(this.spr0HitY << 8) + i] = 0x55ff55;\n }\n for (i = 0; i < 240; i++) {\n buffer[(i << 8) + this.spr0HitX] = 0x55ff55;\n }\n }\n }\n\n // This is a bit lazy..\n // if either the sprites or the background should be clipped,\n // both are clipped after rendering is finished.\n if (\n this.clipToTvSize ||\n this.f_bgClipping === 0 ||\n this.f_spClipping === 0\n ) {\n // Clip left 8-pixels column:\n for (y = 0; y < 240; y++) {\n for (x = 0; x < 8; x++) {\n buffer[(y << 8) + x] = 0;\n }\n }\n }\n\n if (this.clipToTvSize) {\n // Clip right 8-pixels column too:\n for (y = 0; y < 240; y++) {\n for (x = 0; x < 8; x++) {\n buffer[(y << 8) + 255 - x] = 0;\n }\n }\n }\n\n // Clip top and bottom 8 pixels:\n if (this.clipToTvSize) {\n for (y = 0; y < 8; y++) {\n for (x = 0; x < 256; x++) {\n buffer[(y << 8) + x] = 0;\n buffer[((239 - y) << 8) + x] = 0;\n }\n }\n }\n\n this.nes.ui.writeFrame(buffer);\n },\n\n updateControlReg1: function(value) {\n this.triggerRendering();\n\n this.f_nmiOnVblank = (value >> 7) & 1;\n this.f_spriteSize = (value >> 5) & 1;\n this.f_bgPatternTable = (value >> 4) & 1;\n this.f_spPatternTable = (value >> 3) & 1;\n this.f_addrInc = (value >> 2) & 1;\n this.f_nTblAddress = value & 3;\n\n this.regV = (value >> 1) & 1;\n this.regH = value & 1;\n this.regS = (value >> 4) & 1;\n },\n\n updateControlReg2: function(value) {\n this.triggerRendering();\n\n this.f_color = (value >> 5) & 7;\n this.f_spVisibility = (value >> 4) & 1;\n this.f_bgVisibility = (value >> 3) & 1;\n this.f_spClipping = (value >> 2) & 1;\n this.f_bgClipping = (value >> 1) & 1;\n this.f_dispType = value & 1;\n\n if (this.f_dispType === 0) {\n this.palTable.setEmphasis(this.f_color);\n }\n this.updatePalettes();\n },\n\n setStatusFlag: function(flag, value) {\n var n = 1 << flag;\n this.nes.cpu.mem[0x2002] =\n (this.nes.cpu.mem[0x2002] & (255 - n)) | (value ? n : 0);\n },\n\n // CPU Register $2002:\n // Read the Status Register.\n readStatusRegister: function() {\n var tmp = this.nes.cpu.mem[0x2002];\n\n // Reset scroll & VRAM Address toggle:\n this.firstWrite = true;\n\n // Clear VBlank flag:\n this.setStatusFlag(this.STATUS_VBLANK, false);\n\n // Fetch status data:\n return tmp;\n },\n\n // CPU Register $2003:\n // Write the SPR-RAM address that is used for sramWrite (Register 0x2004 in CPU memory map)\n writeSRAMAddress: function(address) {\n this.sramAddress = address;\n },\n\n // CPU Register $2004 (R):\n // Read from SPR-RAM (Sprite RAM).\n // The address should be set first.\n sramLoad: function() {\n /*short tmp = sprMem.load(sramAddress);\n sramAddress++; // Increment address\n sramAddress%=0x100;\n return tmp;*/\n return this.spriteMem[this.sramAddress];\n },\n\n // CPU Register $2004 (W):\n // Write to SPR-RAM (Sprite RAM).\n // The address should be set first.\n sramWrite: function(value) {\n this.spriteMem[this.sramAddress] = value;\n this.spriteRamWriteUpdate(this.sramAddress, value);\n this.sramAddress++; // Increment address\n this.sramAddress %= 0x100;\n },\n\n // CPU Register $2005:\n // Write to scroll registers.\n // The first write is the vertical offset, the second is the\n // horizontal offset:\n scrollWrite: function(value) {\n this.triggerRendering();\n\n if (this.firstWrite) {\n // First write, horizontal scroll:\n this.regHT = (value >> 3) & 31;\n this.regFH = value & 7;\n } else {\n // Second write, vertical scroll:\n this.regFV = value & 7;\n this.regVT = (value >> 3) & 31;\n }\n this.firstWrite = !this.firstWrite;\n },\n\n // CPU Register $2006:\n // Sets the adress used when reading/writing from/to VRAM.\n // The first write sets the high byte, the second the low byte.\n writeVRAMAddress: function(address) {\n if (this.firstWrite) {\n this.regFV = (address >> 4) & 3;\n this.regV = (address >> 3) & 1;\n this.regH = (address >> 2) & 1;\n this.regVT = (this.regVT & 7) | ((address & 3) << 3);\n } else {\n this.triggerRendering();\n\n this.regVT = (this.regVT & 24) | ((address >> 5) & 7);\n this.regHT = address & 31;\n\n this.cntFV = this.regFV;\n this.cntV = this.regV;\n this.cntH = this.regH;\n this.cntVT = this.regVT;\n this.cntHT = this.regHT;\n\n this.checkSprite0(this.scanline - 20);\n }\n\n this.firstWrite = !this.firstWrite;\n\n // Invoke mapper latch:\n this.cntsToAddress();\n if (this.vramAddress < 0x2000) {\n this.nes.mmap.latchAccess(this.vramAddress);\n }\n },\n\n // CPU Register $2007(R):\n // Read from PPU memory. The address should be set first.\n vramLoad: function() {\n var tmp;\n\n this.cntsToAddress();\n this.regsToAddress();\n\n // If address is in range 0x0000-0x3EFF, return buffered values:\n if (this.vramAddress <= 0x3eff) {\n tmp = this.vramBufferedReadValue;\n\n // Update buffered value:\n if (this.vramAddress < 0x2000) {\n this.vramBufferedReadValue = this.vramMem[this.vramAddress];\n } else {\n this.vramBufferedReadValue = this.mirroredLoad(this.vramAddress);\n }\n\n // Mapper latch access:\n if (this.vramAddress < 0x2000) {\n this.nes.mmap.latchAccess(this.vramAddress);\n }\n\n // Increment by either 1 or 32, depending on d2 of Control Register 1:\n this.vramAddress += this.f_addrInc === 1 ? 32 : 1;\n\n this.cntsFromAddress();\n this.regsFromAddress();\n\n return tmp; // Return the previous buffered value.\n }\n\n // No buffering in this mem range. Read normally.\n tmp = this.mirroredLoad(this.vramAddress);\n\n // Increment by either 1 or 32, depending on d2 of Control Register 1:\n this.vramAddress += this.f_addrInc === 1 ? 32 : 1;\n\n this.cntsFromAddress();\n this.regsFromAddress();\n\n return tmp;\n },\n\n // CPU Register $2007(W):\n // Write to PPU memory. The address should be set first.\n vramWrite: function(value) {\n this.triggerRendering();\n this.cntsToAddress();\n this.regsToAddress();\n\n if (this.vramAddress >= 0x2000) {\n // Mirroring is used.\n this.mirroredWrite(this.vramAddress, value);\n } else {\n // Write normally.\n this.writeMem(this.vramAddress, value);\n\n // Invoke mapper latch:\n this.nes.mmap.latchAccess(this.vramAddress);\n }\n\n // Increment by either 1 or 32, depending on d2 of Control Register 1:\n this.vramAddress += this.f_addrInc === 1 ? 32 : 1;\n this.regsFromAddress();\n this.cntsFromAddress();\n },\n\n // CPU Register $4014:\n // Write 256 bytes of main memory\n // into Sprite RAM.\n sramDMA: function(value) {\n var baseAddress = value * 0x100;\n var data;\n for (var i = this.sramAddress; i < 256; i++) {\n data = this.nes.cpu.mem[baseAddress + i];\n this.spriteMem[i] = data;\n this.spriteRamWriteUpdate(i, data);\n }\n\n this.nes.cpu.haltCycles(513);\n },\n\n // Updates the scroll registers from a new VRAM address.\n regsFromAddress: function() {\n var address = (this.vramTmpAddress >> 8) & 0xff;\n this.regFV = (address >> 4) & 7;\n this.regV = (address >> 3) & 1;\n this.regH = (address >> 2) & 1;\n this.regVT = (this.regVT & 7) | ((address & 3) << 3);\n\n address = this.vramTmpAddress & 0xff;\n this.regVT = (this.regVT & 24) | ((address >> 5) & 7);\n this.regHT = address & 31;\n },\n\n // Updates the scroll registers from a new VRAM address.\n cntsFromAddress: function() {\n var address = (this.vramAddress >> 8) & 0xff;\n this.cntFV = (address >> 4) & 3;\n this.cntV = (address >> 3) & 1;\n this.cntH = (address >> 2) & 1;\n this.cntVT = (this.cntVT & 7) | ((address & 3) << 3);\n\n address = this.vramAddress & 0xff;\n this.cntVT = (this.cntVT & 24) | ((address >> 5) & 7);\n this.cntHT = address & 31;\n },\n\n regsToAddress: function() {\n var b1 = (this.regFV & 7) << 4;\n b1 |= (this.regV & 1) << 3;\n b1 |= (this.regH & 1) << 2;\n b1 |= (this.regVT >> 3) & 3;\n\n var b2 = (this.regVT & 7) << 5;\n b2 |= this.regHT & 31;\n\n this.vramTmpAddress = ((b1 << 8) | b2) & 0x7fff;\n },\n\n cntsToAddress: function() {\n var b1 = (this.cntFV & 7) << 4;\n b1 |= (this.cntV & 1) << 3;\n b1 |= (this.cntH & 1) << 2;\n b1 |= (this.cntVT >> 3) & 3;\n\n var b2 = (this.cntVT & 7) << 5;\n b2 |= this.cntHT & 31;\n\n this.vramAddress = ((b1 << 8) | b2) & 0x7fff;\n },\n\n incTileCounter: function(count) {\n for (var i = count; i !== 0; i--) {\n this.cntHT++;\n if (this.cntHT === 32) {\n this.cntHT = 0;\n this.cntVT++;\n if (this.cntVT >= 30) {\n this.cntH++;\n if (this.cntH === 2) {\n this.cntH = 0;\n this.cntV++;\n if (this.cntV === 2) {\n this.cntV = 0;\n this.cntFV++;\n this.cntFV &= 0x7;\n }\n }\n }\n }\n }\n },\n\n // Reads from memory, taking into account\n // mirroring/mapping of address ranges.\n mirroredLoad: function(address) {\n return this.vramMem[this.vramMirrorTable[address]];\n },\n\n // Writes to memory, taking into account\n // mirroring/mapping of address ranges.\n mirroredWrite: function(address, value) {\n if (address >= 0x3f00 && address < 0x3f20) {\n // Palette write mirroring.\n if (address === 0x3f00 || address === 0x3f10) {\n this.writeMem(0x3f00, value);\n this.writeMem(0x3f10, value);\n } else if (address === 0x3f04 || address === 0x3f14) {\n this.writeMem(0x3f04, value);\n this.writeMem(0x3f14, value);\n } else if (address === 0x3f08 || address === 0x3f18) {\n this.writeMem(0x3f08, value);\n this.writeMem(0x3f18, value);\n } else if (address === 0x3f0c || address === 0x3f1c) {\n this.writeMem(0x3f0c, value);\n this.writeMem(0x3f1c, value);\n } else {\n this.writeMem(address, value);\n }\n } else {\n // Use lookup table for mirrored address:\n if (address < this.vramMirrorTable.length) {\n this.writeMem(this.vramMirrorTable[address], value);\n } else {\n throw new Error(\"Invalid VRAM address: \" + address.toString(16));\n }\n }\n },\n\n triggerRendering: function() {\n if (this.scanline >= 21 && this.scanline <= 260) {\n // Render sprites, and combine:\n this.renderFramePartially(\n this.lastRenderedScanline + 1,\n this.scanline - 21 - this.lastRenderedScanline\n );\n\n // Set last rendered scanline:\n this.lastRenderedScanline = this.scanline - 21;\n }\n },\n\n renderFramePartially: function(startScan, scanCount) {\n if (this.f_spVisibility === 1) {\n this.renderSpritesPartially(startScan, scanCount, true);\n }\n\n if (this.f_bgVisibility === 1) {\n var si = startScan << 8;\n var ei = (startScan + scanCount) << 8;\n if (ei > 0xf000) {\n ei = 0xf000;\n }\n var buffer = this.buffer;\n var bgbuffer = this.bgbuffer;\n var pixrendered = this.pixrendered;\n for (var destIndex = si; destIndex < ei; destIndex++) {\n if (pixrendered[destIndex] > 0xff) {\n buffer[destIndex] = bgbuffer[destIndex];\n }\n }\n }\n\n if (this.f_spVisibility === 1) {\n this.renderSpritesPartially(startScan, scanCount, false);\n }\n\n this.validTileData = false;\n },\n\n renderBgScanline: function(bgbuffer, scan) {\n var baseTile = this.regS === 0 ? 0 : 256;\n var destIndex = (scan << 8) - this.regFH;\n\n this.curNt = this.ntable1[this.cntV + this.cntV + this.cntH];\n\n this.cntHT = this.regHT;\n this.cntH = this.regH;\n this.curNt = this.ntable1[this.cntV + this.cntV + this.cntH];\n\n if (scan < 240 && scan - this.cntFV >= 0) {\n var tscanoffset = this.cntFV << 3;\n var scantile = this.scantile;\n var attrib = this.attrib;\n var ptTile = this.ptTile;\n var nameTable = this.nameTable;\n var imgPalette = this.imgPalette;\n var pixrendered = this.pixrendered;\n var targetBuffer = bgbuffer ? this.bgbuffer : this.buffer;\n\n var t, tpix, att, col;\n\n for (var tile = 0; tile < 32; tile++) {\n if (scan >= 0) {\n // Fetch tile & attrib data:\n if (this.validTileData) {\n // Get data from array:\n t = scantile[tile];\n if (typeof t === \"undefined\") {\n continue;\n }\n tpix = t.pix;\n att = attrib[tile];\n } else {\n // Fetch data:\n t =\n ptTile[\n baseTile +\n nameTable[this.curNt].getTileIndex(this.cntHT, this.cntVT)\n ];\n if (typeof t === \"undefined\") {\n continue;\n }\n tpix = t.pix;\n att = nameTable[this.curNt].getAttrib(this.cntHT, this.cntVT);\n scantile[tile] = t;\n attrib[tile] = att;\n }\n\n // Render tile scanline:\n var sx = 0;\n var x = (tile << 3) - this.regFH;\n\n if (x > -8) {\n if (x < 0) {\n destIndex -= x;\n sx = -x;\n }\n if (t.opaque[this.cntFV]) {\n for (; sx < 8; sx++) {\n targetBuffer[destIndex] =\n imgPalette[tpix[tscanoffset + sx] + att];\n pixrendered[destIndex] |= 256;\n destIndex++;\n }\n } else {\n for (; sx < 8; sx++) {\n col = tpix[tscanoffset + sx];\n if (col !== 0) {\n targetBuffer[destIndex] = imgPalette[col + att];\n pixrendered[destIndex] |= 256;\n }\n destIndex++;\n }\n }\n }\n }\n\n // Increase Horizontal Tile Counter:\n if (++this.cntHT === 32) {\n this.cntHT = 0;\n this.cntH++;\n this.cntH %= 2;\n this.curNt = this.ntable1[(this.cntV << 1) + this.cntH];\n }\n }\n\n // Tile data for one row should now have been fetched,\n // so the data in the array is valid.\n this.validTileData = true;\n }\n\n // update vertical scroll:\n this.cntFV++;\n if (this.cntFV === 8) {\n this.cntFV = 0;\n this.cntVT++;\n if (this.cntVT === 30) {\n this.cntVT = 0;\n this.cntV++;\n this.cntV %= 2;\n this.curNt = this.ntable1[(this.cntV << 1) + this.cntH];\n } else if (this.cntVT === 32) {\n this.cntVT = 0;\n }\n\n // Invalidate fetched data:\n this.validTileData = false;\n }\n },\n\n renderSpritesPartially: function(startscan, scancount, bgPri) {\n if (this.f_spVisibility === 1) {\n for (var i = 0; i < 64; i++) {\n if (\n this.bgPriority[i] === bgPri &&\n this.sprX[i] >= 0 &&\n this.sprX[i] < 256 &&\n this.sprY[i] + 8 >= startscan &&\n this.sprY[i] < startscan + scancount\n ) {\n // Show sprite.\n if (this.f_spriteSize === 0) {\n // 8x8 sprites\n\n this.srcy1 = 0;\n this.srcy2 = 8;\n\n if (this.sprY[i] < startscan) {\n this.srcy1 = startscan - this.sprY[i] - 1;\n }\n\n if (this.sprY[i] + 8 > startscan + scancount) {\n this.srcy2 = startscan + scancount - this.sprY[i] + 1;\n }\n\n if (this.f_spPatternTable === 0) {\n this.ptTile[this.sprTile[i]].render(\n this.buffer,\n 0,\n this.srcy1,\n 8,\n this.srcy2,\n this.sprX[i],\n this.sprY[i] + 1,\n this.sprCol[i],\n this.sprPalette,\n this.horiFlip[i],\n this.vertFlip[i],\n i,\n this.pixrendered\n );\n } else {\n this.ptTile[this.sprTile[i] + 256].render(\n this.buffer,\n 0,\n this.srcy1,\n 8,\n this.srcy2,\n this.sprX[i],\n this.sprY[i] + 1,\n this.sprCol[i],\n this.sprPalette,\n this.horiFlip[i],\n this.vertFlip[i],\n i,\n this.pixrendered\n );\n }\n } else {\n // 8x16 sprites\n var top = this.sprTile[i];\n if ((top & 1) !== 0) {\n top = this.sprTile[i] - 1 + 256;\n }\n\n var srcy1 = 0;\n var srcy2 = 8;\n\n if (this.sprY[i] < startscan) {\n srcy1 = startscan - this.sprY[i] - 1;\n }\n\n if (this.sprY[i] + 8 > startscan + scancount) {\n srcy2 = startscan + scancount - this.sprY[i];\n }\n\n this.ptTile[top + (this.vertFlip[i] ? 1 : 0)].render(\n this.buffer,\n 0,\n srcy1,\n 8,\n srcy2,\n this.sprX[i],\n this.sprY[i] + 1,\n this.sprCol[i],\n this.sprPalette,\n this.horiFlip[i],\n this.vertFlip[i],\n i,\n this.pixrendered\n );\n\n srcy1 = 0;\n srcy2 = 8;\n\n if (this.sprY[i] + 8 < startscan) {\n srcy1 = startscan - (this.sprY[i] + 8 + 1);\n }\n\n if (this.sprY[i] + 16 > startscan + scancount) {\n srcy2 = startscan + scancount - (this.sprY[i] + 8);\n }\n\n this.ptTile[top + (this.vertFlip[i] ? 0 : 1)].render(\n this.buffer,\n 0,\n srcy1,\n 8,\n srcy2,\n this.sprX[i],\n this.sprY[i] + 1 + 8,\n this.sprCol[i],\n this.sprPalette,\n this.horiFlip[i],\n this.vertFlip[i],\n i,\n this.pixrendered\n );\n }\n }\n }\n }\n },\n\n checkSprite0: function(scan) {\n this.spr0HitX = -1;\n this.spr0HitY = -1;\n\n var toffset;\n var tIndexAdd = this.f_spPatternTable === 0 ? 0 : 256;\n var x, y, t, i;\n var bufferIndex;\n var col;\n var bgPri;\n\n x = this.sprX[0];\n y = this.sprY[0] + 1;\n\n if (this.f_spriteSize === 0) {\n // 8x8 sprites.\n\n // Check range:\n if (y <= scan && y + 8 > scan && x >= -7 && x < 256) {\n // Sprite is in range.\n // Draw scanline:\n t = this.ptTile[this.sprTile[0] + tIndexAdd];\n col = this.sprCol[0];\n bgPri = this.bgPriority[0];\n\n if (this.vertFlip[0]) {\n toffset = 7 - (scan - y);\n } else {\n toffset = scan - y;\n }\n toffset *= 8;\n\n bufferIndex = scan * 256 + x;\n if (this.horiFlip[0]) {\n for (i = 7; i >= 0; i--) {\n if (x >= 0 && x < 256) {\n if (\n bufferIndex >= 0 &&\n bufferIndex < 61440 &&\n this.pixrendered[bufferIndex] !== 0\n ) {\n if (t.pix[toffset + i] !== 0) {\n this.spr0HitX = bufferIndex % 256;\n this.spr0HitY = scan;\n return true;\n }\n }\n }\n x++;\n bufferIndex++;\n }\n } else {\n for (i = 0; i < 8; i++) {\n if (x >= 0 && x < 256) {\n if (\n bufferIndex >= 0 &&\n bufferIndex < 61440 &&\n this.pixrendered[bufferIndex] !== 0\n ) {\n if (t.pix[toffset + i] !== 0) {\n this.spr0HitX = bufferIndex % 256;\n this.spr0HitY = scan;\n return true;\n }\n }\n }\n x++;\n bufferIndex++;\n }\n }\n }\n } else {\n // 8x16 sprites:\n\n // Check range:\n if (y <= scan && y + 16 > scan && x >= -7 && x < 256) {\n // Sprite is in range.\n // Draw scanline:\n\n if (this.vertFlip[0]) {\n toffset = 15 - (scan - y);\n } else {\n toffset = scan - y;\n }\n\n if (toffset < 8) {\n // first half of sprite.\n t = this.ptTile[\n this.sprTile[0] +\n (this.vertFlip[0] ? 1 : 0) +\n ((this.sprTile[0] & 1) !== 0 ? 255 : 0)\n ];\n } else {\n // second half of sprite.\n t = this.ptTile[\n this.sprTile[0] +\n (this.vertFlip[0] ? 0 : 1) +\n ((this.sprTile[0] & 1) !== 0 ? 255 : 0)\n ];\n if (this.vertFlip[0]) {\n toffset = 15 - toffset;\n } else {\n toffset -= 8;\n }\n }\n toffset *= 8;\n col = this.sprCol[0];\n bgPri = this.bgPriority[0];\n\n bufferIndex = scan * 256 + x;\n if (this.horiFlip[0]) {\n for (i = 7; i >= 0; i--) {\n if (x >= 0 && x < 256) {\n if (\n bufferIndex >= 0 &&\n bufferIndex < 61440 &&\n this.pixrendered[bufferIndex] !== 0\n ) {\n if (t.pix[toffset + i] !== 0) {\n this.spr0HitX = bufferIndex % 256;\n this.spr0HitY = scan;\n return true;\n }\n }\n }\n x++;\n bufferIndex++;\n }\n } else {\n for (i = 0; i < 8; i++) {\n if (x >= 0 && x < 256) {\n if (\n bufferIndex >= 0 &&\n bufferIndex < 61440 &&\n this.pixrendered[bufferIndex] !== 0\n ) {\n if (t.pix[toffset + i] !== 0) {\n this.spr0HitX = bufferIndex % 256;\n this.spr0HitY = scan;\n return true;\n }\n }\n }\n x++;\n bufferIndex++;\n }\n }\n }\n }\n\n return false;\n },\n\n // This will write to PPU memory, and\n // update internally buffered data\n // appropriately.\n writeMem: function(address, value) {\n this.vramMem[address] = value;\n\n // Update internally buffered data:\n if (address < 0x2000) {\n this.vramMem[address] = value;\n this.patternWrite(address, value);\n } else if (address >= 0x2000 && address < 0x23c0) {\n this.nameTableWrite(this.ntable1[0], address - 0x2000, value);\n } else if (address >= 0x23c0 && address < 0x2400) {\n this.attribTableWrite(this.ntable1[0], address - 0x23c0, value);\n } else if (address >= 0x2400 && address < 0x27c0) {\n this.nameTableWrite(this.ntable1[1], address - 0x2400, value);\n } else if (address >= 0x27c0 && address < 0x2800) {\n this.attribTableWrite(this.ntable1[1], address - 0x27c0, value);\n } else if (address >= 0x2800 && address < 0x2bc0) {\n this.nameTableWrite(this.ntable1[2], address - 0x2800, value);\n } else if (address >= 0x2bc0 && address < 0x2c00) {\n this.attribTableWrite(this.ntable1[2], address - 0x2bc0, value);\n } else if (address >= 0x2c00 && address < 0x2fc0) {\n this.nameTableWrite(this.ntable1[3], address - 0x2c00, value);\n } else if (address >= 0x2fc0 && address < 0x3000) {\n this.attribTableWrite(this.ntable1[3], address - 0x2fc0, value);\n } else if (address >= 0x3f00 && address < 0x3f20) {\n this.updatePalettes();\n }\n },\n\n // Reads data from $3f00 to $f20\n // into the two buffered palettes.\n updatePalettes: function() {\n var i;\n\n for (i = 0; i < 16; i++) {\n if (this.f_dispType === 0) {\n this.imgPalette[i] = this.palTable.getEntry(\n this.vramMem[0x3f00 + i] & 63\n );\n } else {\n this.imgPalette[i] = this.palTable.getEntry(\n this.vramMem[0x3f00 + i] & 32\n );\n }\n }\n for (i = 0; i < 16; i++) {\n if (this.f_dispType === 0) {\n this.sprPalette[i] = this.palTable.getEntry(\n this.vramMem[0x3f10 + i] & 63\n );\n } else {\n this.sprPalette[i] = this.palTable.getEntry(\n this.vramMem[0x3f10 + i] & 32\n );\n }\n }\n },\n\n // Updates the internal pattern\n // table buffers with this new byte.\n // In vNES, there is a version of this with 4 arguments which isn't used.\n patternWrite: function(address, value) {\n var tileIndex = Math.floor(address / 16);\n var leftOver = address % 16;\n if (leftOver < 8) {\n this.ptTile[tileIndex].setScanline(\n leftOver,\n value,\n this.vramMem[address + 8]\n );\n } else {\n this.ptTile[tileIndex].setScanline(\n leftOver - 8,\n this.vramMem[address - 8],\n value\n );\n }\n },\n\n // Updates the internal name table buffers\n // with this new byte.\n nameTableWrite: function(index, address, value) {\n this.nameTable[index].tile[address] = value;\n\n // Update Sprite #0 hit:\n //updateSpr0Hit();\n this.checkSprite0(this.scanline - 20);\n },\n\n // Updates the internal pattern\n // table buffers with this new attribute\n // table byte.\n attribTableWrite: function(index, address, value) {\n this.nameTable[index].writeAttrib(address, value);\n },\n\n // Updates the internally buffered sprite\n // data with this new byte of info.\n spriteRamWriteUpdate: function(address, value) {\n var tIndex = Math.floor(address / 4);\n\n if (tIndex === 0) {\n //updateSpr0Hit();\n this.checkSprite0(this.scanline - 20);\n }\n\n if (address % 4 === 0) {\n // Y coordinate\n this.sprY[tIndex] = value;\n } else if (address % 4 === 1) {\n // Tile index\n this.sprTile[tIndex] = value;\n } else if (address % 4 === 2) {\n // Attributes\n this.vertFlip[tIndex] = (value & 0x80) !== 0;\n this.horiFlip[tIndex] = (value & 0x40) !== 0;\n this.bgPriority[tIndex] = (value & 0x20) !== 0;\n this.sprCol[tIndex] = (value & 3) << 2;\n } else if (address % 4 === 3) {\n // X coordinate\n this.sprX[tIndex] = value;\n }\n },\n\n doNMI: function() {\n // Set VBlank flag:\n this.setStatusFlag(this.STATUS_VBLANK, true);\n //nes.getCpu().doNonMaskableInterrupt();\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_NMI);\n },\n\n isPixelWhite: function(x, y) {\n this.triggerRendering();\n return this.nes.ppu.buffer[(y << 8) + x] === 0xffffff;\n },\n\n JSON_PROPERTIES: [\n // Memory\n \"vramMem\",\n \"spriteMem\",\n // Counters\n \"cntFV\",\n \"cntV\",\n \"cntH\",\n \"cntVT\",\n \"cntHT\",\n // Registers\n \"regFV\",\n \"regV\",\n \"regH\",\n \"regVT\",\n \"regHT\",\n \"regFH\",\n \"regS\",\n // VRAM addr\n \"vramAddress\",\n \"vramTmpAddress\",\n // Control/Status registers\n \"f_nmiOnVblank\",\n \"f_spriteSize\",\n \"f_bgPatternTable\",\n \"f_spPatternTable\",\n \"f_addrInc\",\n \"f_nTblAddress\",\n \"f_color\",\n \"f_spVisibility\",\n \"f_bgVisibility\",\n \"f_spClipping\",\n \"f_bgClipping\",\n \"f_dispType\",\n // VRAM I/O\n \"vramBufferedReadValue\",\n \"firstWrite\",\n // Mirroring\n \"currentMirroring\",\n \"vramMirrorTable\",\n \"ntable1\",\n // SPR-RAM I/O\n \"sramAddress\",\n // Sprites. Most sprite data is rebuilt from spriteMem\n \"hitSpr0\",\n // Palettes\n \"sprPalette\",\n \"imgPalette\",\n // Rendering progression\n \"curX\",\n \"scanline\",\n \"lastRenderedScanline\",\n \"curNt\",\n \"scantile\",\n // Used during rendering\n \"attrib\",\n \"buffer\",\n \"bgbuffer\",\n \"pixrendered\",\n // Misc\n \"requestEndFrame\",\n \"nmiOk\",\n \"dummyCycleToggle\",\n \"nmiCounter\",\n \"validTileData\",\n \"scanlineAlreadyRendered\"\n ],\n\n toJSON: function() {\n var i;\n var state = utils.toJSON(this);\n\n state.nameTable = [];\n for (i = 0; i < this.nameTable.length; i++) {\n state.nameTable[i] = this.nameTable[i].toJSON();\n }\n\n state.ptTile = [];\n for (i = 0; i < this.ptTile.length; i++) {\n state.ptTile[i] = this.ptTile[i].toJSON();\n }\n\n return state;\n },\n\n fromJSON: function(state) {\n var i;\n\n utils.fromJSON(this, state);\n\n for (i = 0; i < this.nameTable.length; i++) {\n this.nameTable[i].fromJSON(state.nameTable[i]);\n }\n\n for (i = 0; i < this.ptTile.length; i++) {\n this.ptTile[i].fromJSON(state.ptTile[i]);\n }\n\n // Sprite data:\n for (i = 0; i < this.spriteMem.length; i++) {\n this.spriteRamWriteUpdate(i, this.spriteMem[i]);\n }\n }\n};\n\nvar NameTable = function(width, height, name) {\n this.width = width;\n this.height = height;\n this.name = name;\n\n this.tile = new Array(width * height);\n this.attrib = new Array(width * height);\n for (var i = 0; i < width * height; i++) {\n this.tile[i] = 0;\n this.attrib[i] = 0;\n }\n};\n\nNameTable.prototype = {\n getTileIndex: function(x, y) {\n return this.tile[y * this.width + x];\n },\n\n getAttrib: function(x, y) {\n return this.attrib[y * this.width + x];\n },\n\n writeAttrib: function(index, value) {\n var basex = (index % 8) * 4;\n var basey = Math.floor(index / 8) * 4;\n var add;\n var tx, ty;\n var attindex;\n\n for (var sqy = 0; sqy < 2; sqy++) {\n for (var sqx = 0; sqx < 2; sqx++) {\n add = (value >> (2 * (sqy * 2 + sqx))) & 3;\n for (var y = 0; y < 2; y++) {\n for (var x = 0; x < 2; x++) {\n tx = basex + sqx * 2 + x;\n ty = basey + sqy * 2 + y;\n attindex = ty * this.width + tx;\n this.attrib[ty * this.width + tx] = (add << 2) & 12;\n }\n }\n }\n }\n },\n\n toJSON: function() {\n return {\n tile: this.tile,\n attrib: this.attrib\n };\n },\n\n fromJSON: function(s) {\n this.tile = s.tile;\n this.attrib = s.attrib;\n }\n};\n\nvar PaletteTable = function() {\n this.curTable = new Array(64);\n this.emphTable = new Array(8);\n this.currentEmph = -1;\n};\n\nPaletteTable.prototype = {\n reset: function() {\n this.setEmphasis(0);\n },\n\n loadNTSCPalette: function() {\n // prettier-ignore\n this.curTable = [0x525252, 0xB40000, 0xA00000, 0xB1003D, 0x740069, 0x00005B, 0x00005F, 0x001840, 0x002F10, 0x084A08, 0x006700, 0x124200, 0x6D2800, 0x000000, 0x000000, 0x000000, 0xC4D5E7, 0xFF4000, 0xDC0E22, 0xFF476B, 0xD7009F, 0x680AD7, 0x0019BC, 0x0054B1, 0x006A5B, 0x008C03, 0x00AB00, 0x2C8800, 0xA47200, 0x000000, 0x000000, 0x000000, 0xF8F8F8, 0xFFAB3C, 0xFF7981, 0xFF5BC5, 0xFF48F2, 0xDF49FF, 0x476DFF, 0x00B4F7, 0x00E0FF, 0x00E375, 0x03F42B, 0x78B82E, 0xE5E218, 0x787878, 0x000000, 0x000000, 0xFFFFFF, 0xFFF2BE, 0xF8B8B8, 0xF8B8D8, 0xFFB6FF, 0xFFC3FF, 0xC7D1FF, 0x9ADAFF, 0x88EDF8, 0x83FFDD, 0xB8F8B8, 0xF5F8AC, 0xFFFFB0, 0xF8D8F8, 0x000000, 0x000000];\n this.makeTables();\n this.setEmphasis(0);\n },\n\n loadPALPalette: function() {\n // prettier-ignore\n this.curTable = [0x525252, 0xB40000, 0xA00000, 0xB1003D, 0x740069, 0x00005B, 0x00005F, 0x001840, 0x002F10, 0x084A08, 0x006700, 0x124200, 0x6D2800, 0x000000, 0x000000, 0x000000, 0xC4D5E7, 0xFF4000, 0xDC0E22, 0xFF476B, 0xD7009F, 0x680AD7, 0x0019BC, 0x0054B1, 0x006A5B, 0x008C03, 0x00AB00, 0x2C8800, 0xA47200, 0x000000, 0x000000, 0x000000, 0xF8F8F8, 0xFFAB3C, 0xFF7981, 0xFF5BC5, 0xFF48F2, 0xDF49FF, 0x476DFF, 0x00B4F7, 0x00E0FF, 0x00E375, 0x03F42B, 0x78B82E, 0xE5E218, 0x787878, 0x000000, 0x000000, 0xFFFFFF, 0xFFF2BE, 0xF8B8B8, 0xF8B8D8, 0xFFB6FF, 0xFFC3FF, 0xC7D1FF, 0x9ADAFF, 0x88EDF8, 0x83FFDD, 0xB8F8B8, 0xF5F8AC, 0xFFFFB0, 0xF8D8F8, 0x000000, 0x000000];\n this.makeTables();\n this.setEmphasis(0);\n },\n\n makeTables: function() {\n var r, g, b, col, i, rFactor, gFactor, bFactor;\n\n // Calculate a table for each possible emphasis setting:\n for (var emph = 0; emph < 8; emph++) {\n // Determine color component factors:\n rFactor = 1.0;\n gFactor = 1.0;\n bFactor = 1.0;\n\n if ((emph & 1) !== 0) {\n rFactor = 0.75;\n bFactor = 0.75;\n }\n if ((emph & 2) !== 0) {\n rFactor = 0.75;\n gFactor = 0.75;\n }\n if ((emph & 4) !== 0) {\n gFactor = 0.75;\n bFactor = 0.75;\n }\n\n this.emphTable[emph] = new Array(64);\n\n // Calculate table:\n for (i = 0; i < 64; i++) {\n col = this.curTable[i];\n r = Math.floor(this.getRed(col) * rFactor);\n g = Math.floor(this.getGreen(col) * gFactor);\n b = Math.floor(this.getBlue(col) * bFactor);\n this.emphTable[emph][i] = this.getRgb(r, g, b);\n }\n }\n },\n\n setEmphasis: function(emph) {\n if (emph !== this.currentEmph) {\n this.currentEmph = emph;\n for (var i = 0; i < 64; i++) {\n this.curTable[i] = this.emphTable[emph][i];\n }\n }\n },\n\n getEntry: function(yiq) {\n return this.curTable[yiq];\n },\n\n getRed: function(rgb) {\n return (rgb >> 16) & 0xff;\n },\n\n getGreen: function(rgb) {\n return (rgb >> 8) & 0xff;\n },\n\n getBlue: function(rgb) {\n return rgb & 0xff;\n },\n\n getRgb: function(r, g, b) {\n return (r << 16) | (g << 8) | b;\n },\n\n loadDefaultPalette: function() {\n this.curTable[0] = this.getRgb(117, 117, 117);\n this.curTable[1] = this.getRgb(39, 27, 143);\n this.curTable[2] = this.getRgb(0, 0, 171);\n this.curTable[3] = this.getRgb(71, 0, 159);\n this.curTable[4] = this.getRgb(143, 0, 119);\n this.curTable[5] = this.getRgb(171, 0, 19);\n this.curTable[6] = this.getRgb(167, 0, 0);\n this.curTable[7] = this.getRgb(127, 11, 0);\n this.curTable[8] = this.getRgb(67, 47, 0);\n this.curTable[9] = this.getRgb(0, 71, 0);\n this.curTable[10] = this.getRgb(0, 81, 0);\n this.curTable[11] = this.getRgb(0, 63, 23);\n this.curTable[12] = this.getRgb(27, 63, 95);\n this.curTable[13] = this.getRgb(0, 0, 0);\n this.curTable[14] = this.getRgb(0, 0, 0);\n this.curTable[15] = this.getRgb(0, 0, 0);\n this.curTable[16] = this.getRgb(188, 188, 188);\n this.curTable[17] = this.getRgb(0, 115, 239);\n this.curTable[18] = this.getRgb(35, 59, 239);\n this.curTable[19] = this.getRgb(131, 0, 243);\n this.curTable[20] = this.getRgb(191, 0, 191);\n this.curTable[21] = this.getRgb(231, 0, 91);\n this.curTable[22] = this.getRgb(219, 43, 0);\n this.curTable[23] = this.getRgb(203, 79, 15);\n this.curTable[24] = this.getRgb(139, 115, 0);\n this.curTable[25] = this.getRgb(0, 151, 0);\n this.curTable[26] = this.getRgb(0, 171, 0);\n this.curTable[27] = this.getRgb(0, 147, 59);\n this.curTable[28] = this.getRgb(0, 131, 139);\n this.curTable[29] = this.getRgb(0, 0, 0);\n this.curTable[30] = this.getRgb(0, 0, 0);\n this.curTable[31] = this.getRgb(0, 0, 0);\n this.curTable[32] = this.getRgb(255, 255, 255);\n this.curTable[33] = this.getRgb(63, 191, 255);\n this.curTable[34] = this.getRgb(95, 151, 255);\n this.curTable[35] = this.getRgb(167, 139, 253);\n this.curTable[36] = this.getRgb(247, 123, 255);\n this.curTable[37] = this.getRgb(255, 119, 183);\n this.curTable[38] = this.getRgb(255, 119, 99);\n this.curTable[39] = this.getRgb(255, 155, 59);\n this.curTable[40] = this.getRgb(243, 191, 63);\n this.curTable[41] = this.getRgb(131, 211, 19);\n this.curTable[42] = this.getRgb(79, 223, 75);\n this.curTable[43] = this.getRgb(88, 248, 152);\n this.curTable[44] = this.getRgb(0, 235, 219);\n this.curTable[45] = this.getRgb(0, 0, 0);\n this.curTable[46] = this.getRgb(0, 0, 0);\n this.curTable[47] = this.getRgb(0, 0, 0);\n this.curTable[48] = this.getRgb(255, 255, 255);\n this.curTable[49] = this.getRgb(171, 231, 255);\n this.curTable[50] = this.getRgb(199, 215, 255);\n this.curTable[51] = this.getRgb(215, 203, 255);\n this.curTable[52] = this.getRgb(255, 199, 255);\n this.curTable[53] = this.getRgb(255, 199, 219);\n this.curTable[54] = this.getRgb(255, 191, 179);\n this.curTable[55] = this.getRgb(255, 219, 171);\n this.curTable[56] = this.getRgb(255, 231, 163);\n this.curTable[57] = this.getRgb(227, 255, 163);\n this.curTable[58] = this.getRgb(171, 243, 191);\n this.curTable[59] = this.getRgb(179, 255, 207);\n this.curTable[60] = this.getRgb(159, 255, 243);\n this.curTable[61] = this.getRgb(0, 0, 0);\n this.curTable[62] = this.getRgb(0, 0, 0);\n this.curTable[63] = this.getRgb(0, 0, 0);\n\n this.makeTables();\n this.setEmphasis(0);\n }\n};\n\nmodule.exports = PPU;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/ppu.js\n// module id = 6\n// module chunks = 0 1","var CPU_FREQ_NTSC = 1789772.5; //1789772.72727272d;\n// var CPU_FREQ_PAL = 1773447.4;\n\nvar PAPU = function(nes) {\n this.nes = nes;\n\n this.square1 = new ChannelSquare(this, true);\n this.square2 = new ChannelSquare(this, false);\n this.triangle = new ChannelTriangle(this);\n this.noise = new ChannelNoise(this);\n this.dmc = new ChannelDM(this);\n\n this.frameIrqCounter = null;\n this.frameIrqCounterMax = 4;\n this.initCounter = 2048;\n this.channelEnableValue = null;\n\n this.sampleRate = 44100;\n\n this.lengthLookup = null;\n this.dmcFreqLookup = null;\n this.noiseWavelengthLookup = null;\n this.square_table = null;\n this.tnd_table = null;\n\n this.frameIrqEnabled = false;\n this.frameIrqActive = null;\n this.frameClockNow = null;\n this.startedPlaying = false;\n this.recordOutput = false;\n this.initingHardware = false;\n\n this.masterFrameCounter = null;\n this.derivedFrameCounter = null;\n this.countSequence = null;\n this.sampleTimer = null;\n this.frameTime = null;\n this.sampleTimerMax = null;\n this.sampleCount = null;\n this.triValue = 0;\n\n this.smpSquare1 = null;\n this.smpSquare2 = null;\n this.smpTriangle = null;\n this.smpDmc = null;\n this.accCount = null;\n\n // DC removal vars:\n this.prevSampleL = 0;\n this.prevSampleR = 0;\n this.smpAccumL = 0;\n this.smpAccumR = 0;\n\n // DAC range:\n this.dacRange = 0;\n this.dcValue = 0;\n\n // Master volume:\n this.masterVolume = 256;\n\n // Stereo positioning:\n this.stereoPosLSquare1 = null;\n this.stereoPosLSquare2 = null;\n this.stereoPosLTriangle = null;\n this.stereoPosLNoise = null;\n this.stereoPosLDMC = null;\n this.stereoPosRSquare1 = null;\n this.stereoPosRSquare2 = null;\n this.stereoPosRTriangle = null;\n this.stereoPosRNoise = null;\n this.stereoPosRDMC = null;\n\n this.extraCycles = null;\n\n this.maxSample = null;\n this.minSample = null;\n\n // Panning:\n this.panning = [80, 170, 100, 150, 128];\n this.setPanning(this.panning);\n\n // Initialize lookup tables:\n this.initLengthLookup();\n this.initDmcFrequencyLookup();\n this.initNoiseWavelengthLookup();\n this.initDACtables();\n\n // Init sound registers:\n for (var i = 0; i < 0x14; i++) {\n if (i === 0x10) {\n this.writeReg(0x4010, 0x10);\n } else {\n this.writeReg(0x4000 + i, 0);\n }\n }\n\n this.reset();\n};\n\nPAPU.prototype = {\n reset: function() {\n this.sampleRate = this.nes.opts.sampleRate;\n this.sampleTimerMax = Math.floor(\n 1024.0 *\n CPU_FREQ_NTSC *\n this.nes.opts.preferredFrameRate /\n (this.sampleRate * 60.0)\n );\n\n this.frameTime = Math.floor(\n 14915.0 * this.nes.opts.preferredFrameRate / 60.0\n );\n\n this.sampleTimer = 0;\n\n this.updateChannelEnable(0);\n this.masterFrameCounter = 0;\n this.derivedFrameCounter = 0;\n this.countSequence = 0;\n this.sampleCount = 0;\n this.initCounter = 2048;\n this.frameIrqEnabled = false;\n this.initingHardware = false;\n\n this.resetCounter();\n\n this.square1.reset();\n this.square2.reset();\n this.triangle.reset();\n this.noise.reset();\n this.dmc.reset();\n\n this.accCount = 0;\n this.smpSquare1 = 0;\n this.smpSquare2 = 0;\n this.smpTriangle = 0;\n this.smpDmc = 0;\n\n this.frameIrqEnabled = false;\n this.frameIrqCounterMax = 4;\n\n this.channelEnableValue = 0xff;\n this.startedPlaying = false;\n this.prevSampleL = 0;\n this.prevSampleR = 0;\n this.smpAccumL = 0;\n this.smpAccumR = 0;\n\n this.maxSample = -500000;\n this.minSample = 500000;\n },\n\n readReg: function(address) {\n // Read 0x4015:\n var tmp = 0;\n tmp |= this.square1.getLengthStatus();\n tmp |= this.square2.getLengthStatus() << 1;\n tmp |= this.triangle.getLengthStatus() << 2;\n tmp |= this.noise.getLengthStatus() << 3;\n tmp |= this.dmc.getLengthStatus() << 4;\n tmp |= (this.frameIrqActive && this.frameIrqEnabled ? 1 : 0) << 6;\n tmp |= this.dmc.getIrqStatus() << 7;\n\n this.frameIrqActive = false;\n this.dmc.irqGenerated = false;\n\n return tmp & 0xffff;\n },\n\n writeReg: function(address, value) {\n if (address >= 0x4000 && address < 0x4004) {\n // Square Wave 1 Control\n this.square1.writeReg(address, value);\n // console.log(\"Square Write\");\n } else if (address >= 0x4004 && address < 0x4008) {\n // Square 2 Control\n this.square2.writeReg(address, value);\n } else if (address >= 0x4008 && address < 0x400c) {\n // Triangle Control\n this.triangle.writeReg(address, value);\n } else if (address >= 0x400c && address <= 0x400f) {\n // Noise Control\n this.noise.writeReg(address, value);\n } else if (address === 0x4010) {\n // DMC Play mode & DMA frequency\n this.dmc.writeReg(address, value);\n } else if (address === 0x4011) {\n // DMC Delta Counter\n this.dmc.writeReg(address, value);\n } else if (address === 0x4012) {\n // DMC Play code starting address\n this.dmc.writeReg(address, value);\n } else if (address === 0x4013) {\n // DMC Play code length\n this.dmc.writeReg(address, value);\n } else if (address === 0x4015) {\n // Channel enable\n this.updateChannelEnable(value);\n\n if (value !== 0 && this.initCounter > 0) {\n // Start hardware initialization\n this.initingHardware = true;\n }\n\n // DMC/IRQ Status\n this.dmc.writeReg(address, value);\n } else if (address === 0x4017) {\n // Frame counter control\n this.countSequence = (value >> 7) & 1;\n this.masterFrameCounter = 0;\n this.frameIrqActive = false;\n\n if (((value >> 6) & 0x1) === 0) {\n this.frameIrqEnabled = true;\n } else {\n this.frameIrqEnabled = false;\n }\n\n if (this.countSequence === 0) {\n // NTSC:\n this.frameIrqCounterMax = 4;\n this.derivedFrameCounter = 4;\n } else {\n // PAL:\n this.frameIrqCounterMax = 5;\n this.derivedFrameCounter = 0;\n this.frameCounterTick();\n }\n }\n },\n\n resetCounter: function() {\n if (this.countSequence === 0) {\n this.derivedFrameCounter = 4;\n } else {\n this.derivedFrameCounter = 0;\n }\n },\n\n // Updates channel enable status.\n // This is done on writes to the\n // channel enable register (0x4015),\n // and when the user enables/disables channels\n // in the GUI.\n updateChannelEnable: function(value) {\n this.channelEnableValue = value & 0xffff;\n this.square1.setEnabled((value & 1) !== 0);\n this.square2.setEnabled((value & 2) !== 0);\n this.triangle.setEnabled((value & 4) !== 0);\n this.noise.setEnabled((value & 8) !== 0);\n this.dmc.setEnabled((value & 16) !== 0);\n },\n\n // Clocks the frame counter. It should be clocked at\n // twice the cpu speed, so the cycles will be\n // divided by 2 for those counters that are\n // clocked at cpu speed.\n clockFrameCounter: function(nCycles) {\n if (this.initCounter > 0) {\n if (this.initingHardware) {\n this.initCounter -= nCycles;\n if (this.initCounter <= 0) {\n this.initingHardware = false;\n }\n return;\n }\n }\n\n // Don't process ticks beyond next sampling:\n nCycles += this.extraCycles;\n var maxCycles = this.sampleTimerMax - this.sampleTimer;\n if (nCycles << 10 > maxCycles) {\n this.extraCycles = ((nCycles << 10) - maxCycles) >> 10;\n nCycles -= this.extraCycles;\n } else {\n this.extraCycles = 0;\n }\n\n var dmc = this.dmc;\n var triangle = this.triangle;\n var square1 = this.square1;\n var square2 = this.square2;\n var noise = this.noise;\n\n // Clock DMC:\n if (dmc.isEnabled) {\n dmc.shiftCounter -= nCycles << 3;\n while (dmc.shiftCounter <= 0 && dmc.dmaFrequency > 0) {\n dmc.shiftCounter += dmc.dmaFrequency;\n dmc.clockDmc();\n }\n }\n\n // Clock Triangle channel Prog timer:\n if (triangle.progTimerMax > 0) {\n triangle.progTimerCount -= nCycles;\n while (triangle.progTimerCount <= 0) {\n triangle.progTimerCount += triangle.progTimerMax + 1;\n if (triangle.linearCounter > 0 && triangle.lengthCounter > 0) {\n triangle.triangleCounter++;\n triangle.triangleCounter &= 0x1f;\n\n if (triangle.isEnabled) {\n if (triangle.triangleCounter >= 0x10) {\n // Normal value.\n triangle.sampleValue = triangle.triangleCounter & 0xf;\n } else {\n // Inverted value.\n triangle.sampleValue = 0xf - (triangle.triangleCounter & 0xf);\n }\n triangle.sampleValue <<= 4;\n }\n }\n }\n }\n\n // Clock Square channel 1 Prog timer:\n square1.progTimerCount -= nCycles;\n if (square1.progTimerCount <= 0) {\n square1.progTimerCount += (square1.progTimerMax + 1) << 1;\n\n square1.squareCounter++;\n square1.squareCounter &= 0x7;\n square1.updateSampleValue();\n }\n\n // Clock Square channel 2 Prog timer:\n square2.progTimerCount -= nCycles;\n if (square2.progTimerCount <= 0) {\n square2.progTimerCount += (square2.progTimerMax + 1) << 1;\n\n square2.squareCounter++;\n square2.squareCounter &= 0x7;\n square2.updateSampleValue();\n }\n\n // Clock noise channel Prog timer:\n var acc_c = nCycles;\n if (noise.progTimerCount - acc_c > 0) {\n // Do all cycles at once:\n noise.progTimerCount -= acc_c;\n noise.accCount += acc_c;\n noise.accValue += acc_c * noise.sampleValue;\n } else {\n // Slow-step:\n while (acc_c-- > 0) {\n if (--noise.progTimerCount <= 0 && noise.progTimerMax > 0) {\n // Update noise shift register:\n noise.shiftReg <<= 1;\n noise.tmp =\n ((noise.shiftReg << (noise.randomMode === 0 ? 1 : 6)) ^\n noise.shiftReg) &\n 0x8000;\n if (noise.tmp !== 0) {\n // Sample value must be 0.\n noise.shiftReg |= 0x01;\n noise.randomBit = 0;\n noise.sampleValue = 0;\n } else {\n // Find sample value:\n noise.randomBit = 1;\n if (noise.isEnabled && noise.lengthCounter > 0) {\n noise.sampleValue = noise.masterVolume;\n } else {\n noise.sampleValue = 0;\n }\n }\n\n noise.progTimerCount += noise.progTimerMax;\n }\n\n noise.accValue += noise.sampleValue;\n noise.accCount++;\n }\n }\n\n // Frame IRQ handling:\n if (this.frameIrqEnabled && this.frameIrqActive) {\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_NORMAL);\n }\n\n // Clock frame counter at double CPU speed:\n this.masterFrameCounter += nCycles << 1;\n if (this.masterFrameCounter >= this.frameTime) {\n // 240Hz tick:\n this.masterFrameCounter -= this.frameTime;\n this.frameCounterTick();\n }\n\n // Accumulate sample value:\n this.accSample(nCycles);\n\n // Clock sample timer:\n this.sampleTimer += nCycles << 10;\n if (this.sampleTimer >= this.sampleTimerMax) {\n // Sample channels:\n this.sample();\n this.sampleTimer -= this.sampleTimerMax;\n }\n },\n\n accSample: function(cycles) {\n // Special treatment for triangle channel - need to interpolate.\n if (this.triangle.sampleCondition) {\n this.triValue = Math.floor(\n (this.triangle.progTimerCount << 4) / (this.triangle.progTimerMax + 1)\n );\n if (this.triValue > 16) {\n this.triValue = 16;\n }\n if (this.triangle.triangleCounter >= 16) {\n this.triValue = 16 - this.triValue;\n }\n\n // Add non-interpolated sample value:\n this.triValue += this.triangle.sampleValue;\n }\n\n // Now sample normally:\n if (cycles === 2) {\n this.smpTriangle += this.triValue << 1;\n this.smpDmc += this.dmc.sample << 1;\n this.smpSquare1 += this.square1.sampleValue << 1;\n this.smpSquare2 += this.square2.sampleValue << 1;\n this.accCount += 2;\n } else if (cycles === 4) {\n this.smpTriangle += this.triValue << 2;\n this.smpDmc += this.dmc.sample << 2;\n this.smpSquare1 += this.square1.sampleValue << 2;\n this.smpSquare2 += this.square2.sampleValue << 2;\n this.accCount += 4;\n } else {\n this.smpTriangle += cycles * this.triValue;\n this.smpDmc += cycles * this.dmc.sample;\n this.smpSquare1 += cycles * this.square1.sampleValue;\n this.smpSquare2 += cycles * this.square2.sampleValue;\n this.accCount += cycles;\n }\n },\n\n frameCounterTick: function() {\n this.derivedFrameCounter++;\n if (this.derivedFrameCounter >= this.frameIrqCounterMax) {\n this.derivedFrameCounter = 0;\n }\n\n if (this.derivedFrameCounter === 1 || this.derivedFrameCounter === 3) {\n // Clock length & sweep:\n this.triangle.clockLengthCounter();\n this.square1.clockLengthCounter();\n this.square2.clockLengthCounter();\n this.noise.clockLengthCounter();\n this.square1.clockSweep();\n this.square2.clockSweep();\n }\n\n if (this.derivedFrameCounter >= 0 && this.derivedFrameCounter < 4) {\n // Clock linear & decay:\n this.square1.clockEnvDecay();\n this.square2.clockEnvDecay();\n this.noise.clockEnvDecay();\n this.triangle.clockLinearCounter();\n }\n\n if (this.derivedFrameCounter === 3 && this.countSequence === 0) {\n // Enable IRQ:\n this.frameIrqActive = true;\n }\n\n // End of 240Hz tick\n },\n\n // Samples the channels, mixes the output together, then writes to buffer.\n sample: function() {\n var sq_index, tnd_index;\n\n if (this.accCount > 0) {\n this.smpSquare1 <<= 4;\n this.smpSquare1 = Math.floor(this.smpSquare1 / this.accCount);\n\n this.smpSquare2 <<= 4;\n this.smpSquare2 = Math.floor(this.smpSquare2 / this.accCount);\n\n this.smpTriangle = Math.floor(this.smpTriangle / this.accCount);\n\n this.smpDmc <<= 4;\n this.smpDmc = Math.floor(this.smpDmc / this.accCount);\n\n this.accCount = 0;\n } else {\n this.smpSquare1 = this.square1.sampleValue << 4;\n this.smpSquare2 = this.square2.sampleValue << 4;\n this.smpTriangle = this.triangle.sampleValue;\n this.smpDmc = this.dmc.sample << 4;\n }\n\n var smpNoise = Math.floor((this.noise.accValue << 4) / this.noise.accCount);\n this.noise.accValue = smpNoise >> 4;\n this.noise.accCount = 1;\n\n // Stereo sound.\n\n // Left channel:\n sq_index =\n (this.smpSquare1 * this.stereoPosLSquare1 +\n this.smpSquare2 * this.stereoPosLSquare2) >>\n 8;\n tnd_index =\n (3 * this.smpTriangle * this.stereoPosLTriangle +\n (smpNoise << 1) * this.stereoPosLNoise +\n this.smpDmc * this.stereoPosLDMC) >>\n 8;\n if (sq_index >= this.square_table.length) {\n sq_index = this.square_table.length - 1;\n }\n if (tnd_index >= this.tnd_table.length) {\n tnd_index = this.tnd_table.length - 1;\n }\n var sampleValueL =\n this.square_table[sq_index] + this.tnd_table[tnd_index] - this.dcValue;\n\n // Right channel:\n sq_index =\n (this.smpSquare1 * this.stereoPosRSquare1 +\n this.smpSquare2 * this.stereoPosRSquare2) >>\n 8;\n tnd_index =\n (3 * this.smpTriangle * this.stereoPosRTriangle +\n (smpNoise << 1) * this.stereoPosRNoise +\n this.smpDmc * this.stereoPosRDMC) >>\n 8;\n if (sq_index >= this.square_table.length) {\n sq_index = this.square_table.length - 1;\n }\n if (tnd_index >= this.tnd_table.length) {\n tnd_index = this.tnd_table.length - 1;\n }\n var sampleValueR =\n this.square_table[sq_index] + this.tnd_table[tnd_index] - this.dcValue;\n\n // Remove DC from left channel:\n var smpDiffL = sampleValueL - this.prevSampleL;\n this.prevSampleL += smpDiffL;\n this.smpAccumL += smpDiffL - (this.smpAccumL >> 10);\n sampleValueL = this.smpAccumL;\n\n // Remove DC from right channel:\n var smpDiffR = sampleValueR - this.prevSampleR;\n this.prevSampleR += smpDiffR;\n this.smpAccumR += smpDiffR - (this.smpAccumR >> 10);\n sampleValueR = this.smpAccumR;\n\n // Write:\n if (sampleValueL > this.maxSample) {\n this.maxSample = sampleValueL;\n }\n if (sampleValueL < this.minSample) {\n this.minSample = sampleValueL;\n }\n\n if (this.nes.opts.onAudioSample) {\n this.nes.opts.onAudioSample(sampleValueL / 32768, sampleValueR / 32768);\n }\n\n // Reset sampled values:\n this.smpSquare1 = 0;\n this.smpSquare2 = 0;\n this.smpTriangle = 0;\n this.smpDmc = 0;\n },\n\n getLengthMax: function(value) {\n return this.lengthLookup[value >> 3];\n },\n\n getDmcFrequency: function(value) {\n if (value >= 0 && value < 0x10) {\n return this.dmcFreqLookup[value];\n }\n return 0;\n },\n\n getNoiseWaveLength: function(value) {\n if (value >= 0 && value < 0x10) {\n return this.noiseWavelengthLookup[value];\n }\n return 0;\n },\n\n setPanning: function(pos) {\n for (var i = 0; i < 5; i++) {\n this.panning[i] = pos[i];\n }\n this.updateStereoPos();\n },\n\n setMasterVolume: function(value) {\n if (value < 0) {\n value = 0;\n }\n if (value > 256) {\n value = 256;\n }\n this.masterVolume = value;\n this.updateStereoPos();\n },\n\n updateStereoPos: function() {\n this.stereoPosLSquare1 = (this.panning[0] * this.masterVolume) >> 8;\n this.stereoPosLSquare2 = (this.panning[1] * this.masterVolume) >> 8;\n this.stereoPosLTriangle = (this.panning[2] * this.masterVolume) >> 8;\n this.stereoPosLNoise = (this.panning[3] * this.masterVolume) >> 8;\n this.stereoPosLDMC = (this.panning[4] * this.masterVolume) >> 8;\n\n this.stereoPosRSquare1 = this.masterVolume - this.stereoPosLSquare1;\n this.stereoPosRSquare2 = this.masterVolume - this.stereoPosLSquare2;\n this.stereoPosRTriangle = this.masterVolume - this.stereoPosLTriangle;\n this.stereoPosRNoise = this.masterVolume - this.stereoPosLNoise;\n this.stereoPosRDMC = this.masterVolume - this.stereoPosLDMC;\n },\n\n initLengthLookup: function() {\n // prettier-ignore\n this.lengthLookup = [\n 0x0A, 0xFE,\n 0x14, 0x02,\n 0x28, 0x04,\n 0x50, 0x06,\n 0xA0, 0x08,\n 0x3C, 0x0A,\n 0x0E, 0x0C,\n 0x1A, 0x0E,\n 0x0C, 0x10,\n 0x18, 0x12,\n 0x30, 0x14,\n 0x60, 0x16,\n 0xC0, 0x18,\n 0x48, 0x1A,\n 0x10, 0x1C,\n 0x20, 0x1E\n ];\n },\n\n initDmcFrequencyLookup: function() {\n this.dmcFreqLookup = new Array(16);\n\n this.dmcFreqLookup[0x0] = 0xd60;\n this.dmcFreqLookup[0x1] = 0xbe0;\n this.dmcFreqLookup[0x2] = 0xaa0;\n this.dmcFreqLookup[0x3] = 0xa00;\n this.dmcFreqLookup[0x4] = 0x8f0;\n this.dmcFreqLookup[0x5] = 0x7f0;\n this.dmcFreqLookup[0x6] = 0x710;\n this.dmcFreqLookup[0x7] = 0x6b0;\n this.dmcFreqLookup[0x8] = 0x5f0;\n this.dmcFreqLookup[0x9] = 0x500;\n this.dmcFreqLookup[0xa] = 0x470;\n this.dmcFreqLookup[0xb] = 0x400;\n this.dmcFreqLookup[0xc] = 0x350;\n this.dmcFreqLookup[0xd] = 0x2a0;\n this.dmcFreqLookup[0xe] = 0x240;\n this.dmcFreqLookup[0xf] = 0x1b0;\n //for(int i=0;i<16;i++)dmcFreqLookup[i]/=8;\n },\n\n initNoiseWavelengthLookup: function() {\n this.noiseWavelengthLookup = new Array(16);\n\n this.noiseWavelengthLookup[0x0] = 0x004;\n this.noiseWavelengthLookup[0x1] = 0x008;\n this.noiseWavelengthLookup[0x2] = 0x010;\n this.noiseWavelengthLookup[0x3] = 0x020;\n this.noiseWavelengthLookup[0x4] = 0x040;\n this.noiseWavelengthLookup[0x5] = 0x060;\n this.noiseWavelengthLookup[0x6] = 0x080;\n this.noiseWavelengthLookup[0x7] = 0x0a0;\n this.noiseWavelengthLookup[0x8] = 0x0ca;\n this.noiseWavelengthLookup[0x9] = 0x0fe;\n this.noiseWavelengthLookup[0xa] = 0x17c;\n this.noiseWavelengthLookup[0xb] = 0x1fc;\n this.noiseWavelengthLookup[0xc] = 0x2fa;\n this.noiseWavelengthLookup[0xd] = 0x3f8;\n this.noiseWavelengthLookup[0xe] = 0x7f2;\n this.noiseWavelengthLookup[0xf] = 0xfe4;\n },\n\n initDACtables: function() {\n var value, ival, i;\n var max_sqr = 0;\n var max_tnd = 0;\n\n this.square_table = new Array(32 * 16);\n this.tnd_table = new Array(204 * 16);\n\n for (i = 0; i < 32 * 16; i++) {\n value = 95.52 / (8128.0 / (i / 16.0) + 100.0);\n value *= 0.98411;\n value *= 50000.0;\n ival = Math.floor(value);\n\n this.square_table[i] = ival;\n if (ival > max_sqr) {\n max_sqr = ival;\n }\n }\n\n for (i = 0; i < 204 * 16; i++) {\n value = 163.67 / (24329.0 / (i / 16.0) + 100.0);\n value *= 0.98411;\n value *= 50000.0;\n ival = Math.floor(value);\n\n this.tnd_table[i] = ival;\n if (ival > max_tnd) {\n max_tnd = ival;\n }\n }\n\n this.dacRange = max_sqr + max_tnd;\n this.dcValue = this.dacRange / 2;\n }\n};\n\nvar ChannelDM = function(papu) {\n this.papu = papu;\n\n this.MODE_NORMAL = 0;\n this.MODE_LOOP = 1;\n this.MODE_IRQ = 2;\n\n this.isEnabled = null;\n this.hasSample = null;\n this.irqGenerated = false;\n\n this.playMode = null;\n this.dmaFrequency = null;\n this.dmaCounter = null;\n this.deltaCounter = null;\n this.playStartAddress = null;\n this.playAddress = null;\n this.playLength = null;\n this.playLengthCounter = null;\n this.shiftCounter = null;\n this.reg4012 = null;\n this.reg4013 = null;\n this.sample = null;\n this.dacLsb = null;\n this.data = null;\n\n this.reset();\n};\n\nChannelDM.prototype = {\n clockDmc: function() {\n // Only alter DAC value if the sample buffer has data:\n if (this.hasSample) {\n if ((this.data & 1) === 0) {\n // Decrement delta:\n if (this.deltaCounter > 0) {\n this.deltaCounter--;\n }\n } else {\n // Increment delta:\n if (this.deltaCounter < 63) {\n this.deltaCounter++;\n }\n }\n\n // Update sample value:\n this.sample = this.isEnabled ? (this.deltaCounter << 1) + this.dacLsb : 0;\n\n // Update shift register:\n this.data >>= 1;\n }\n\n this.dmaCounter--;\n if (this.dmaCounter <= 0) {\n // No more sample bits.\n this.hasSample = false;\n this.endOfSample();\n this.dmaCounter = 8;\n }\n\n if (this.irqGenerated) {\n this.papu.nes.cpu.requestIrq(this.papu.nes.cpu.IRQ_NORMAL);\n }\n },\n\n endOfSample: function() {\n if (this.playLengthCounter === 0 && this.playMode === this.MODE_LOOP) {\n // Start from beginning of sample:\n this.playAddress = this.playStartAddress;\n this.playLengthCounter = this.playLength;\n }\n\n if (this.playLengthCounter > 0) {\n // Fetch next sample:\n this.nextSample();\n\n if (this.playLengthCounter === 0) {\n // Last byte of sample fetched, generate IRQ:\n if (this.playMode === this.MODE_IRQ) {\n // Generate IRQ:\n this.irqGenerated = true;\n }\n }\n }\n },\n\n nextSample: function() {\n // Fetch byte:\n this.data = this.papu.nes.mmap.load(this.playAddress);\n this.papu.nes.cpu.haltCycles(4);\n\n this.playLengthCounter--;\n this.playAddress++;\n if (this.playAddress > 0xffff) {\n this.playAddress = 0x8000;\n }\n\n this.hasSample = true;\n },\n\n writeReg: function(address, value) {\n if (address === 0x4010) {\n // Play mode, DMA Frequency\n if (value >> 6 === 0) {\n this.playMode = this.MODE_NORMAL;\n } else if (((value >> 6) & 1) === 1) {\n this.playMode = this.MODE_LOOP;\n } else if (value >> 6 === 2) {\n this.playMode = this.MODE_IRQ;\n }\n\n if ((value & 0x80) === 0) {\n this.irqGenerated = false;\n }\n\n this.dmaFrequency = this.papu.getDmcFrequency(value & 0xf);\n } else if (address === 0x4011) {\n // Delta counter load register:\n this.deltaCounter = (value >> 1) & 63;\n this.dacLsb = value & 1;\n this.sample = (this.deltaCounter << 1) + this.dacLsb; // update sample value\n } else if (address === 0x4012) {\n // DMA address load register\n this.playStartAddress = (value << 6) | 0x0c000;\n this.playAddress = this.playStartAddress;\n this.reg4012 = value;\n } else if (address === 0x4013) {\n // Length of play code\n this.playLength = (value << 4) + 1;\n this.playLengthCounter = this.playLength;\n this.reg4013 = value;\n } else if (address === 0x4015) {\n // DMC/IRQ Status\n if (((value >> 4) & 1) === 0) {\n // Disable:\n this.playLengthCounter = 0;\n } else {\n // Restart:\n this.playAddress = this.playStartAddress;\n this.playLengthCounter = this.playLength;\n }\n this.irqGenerated = false;\n }\n },\n\n setEnabled: function(value) {\n if (!this.isEnabled && value) {\n this.playLengthCounter = this.playLength;\n }\n this.isEnabled = value;\n },\n\n getLengthStatus: function() {\n return this.playLengthCounter === 0 || !this.isEnabled ? 0 : 1;\n },\n\n getIrqStatus: function() {\n return this.irqGenerated ? 1 : 0;\n },\n\n reset: function() {\n this.isEnabled = false;\n this.irqGenerated = false;\n this.playMode = this.MODE_NORMAL;\n this.dmaFrequency = 0;\n this.dmaCounter = 0;\n this.deltaCounter = 0;\n this.playStartAddress = 0;\n this.playAddress = 0;\n this.playLength = 0;\n this.playLengthCounter = 0;\n this.sample = 0;\n this.dacLsb = 0;\n this.shiftCounter = 0;\n this.reg4012 = 0;\n this.reg4013 = 0;\n this.data = 0;\n }\n};\n\nvar ChannelNoise = function(papu) {\n this.papu = papu;\n\n this.isEnabled = null;\n this.envDecayDisable = null;\n this.envDecayLoopEnable = null;\n this.lengthCounterEnable = null;\n this.envReset = null;\n this.shiftNow = null;\n\n this.lengthCounter = null;\n this.progTimerCount = null;\n this.progTimerMax = null;\n this.envDecayRate = null;\n this.envDecayCounter = null;\n this.envVolume = null;\n this.masterVolume = null;\n this.shiftReg = 1 << 14;\n this.randomBit = null;\n this.randomMode = null;\n this.sampleValue = null;\n this.accValue = 0;\n this.accCount = 1;\n this.tmp = null;\n\n this.reset();\n};\n\nChannelNoise.prototype = {\n reset: function() {\n this.progTimerCount = 0;\n this.progTimerMax = 0;\n this.isEnabled = false;\n this.lengthCounter = 0;\n this.lengthCounterEnable = false;\n this.envDecayDisable = false;\n this.envDecayLoopEnable = false;\n this.shiftNow = false;\n this.envDecayRate = 0;\n this.envDecayCounter = 0;\n this.envVolume = 0;\n this.masterVolume = 0;\n this.shiftReg = 1;\n this.randomBit = 0;\n this.randomMode = 0;\n this.sampleValue = 0;\n this.tmp = 0;\n },\n\n clockLengthCounter: function() {\n if (this.lengthCounterEnable && this.lengthCounter > 0) {\n this.lengthCounter--;\n if (this.lengthCounter === 0) {\n this.updateSampleValue();\n }\n }\n },\n\n clockEnvDecay: function() {\n if (this.envReset) {\n // Reset envelope:\n this.envReset = false;\n this.envDecayCounter = this.envDecayRate + 1;\n this.envVolume = 0xf;\n } else if (--this.envDecayCounter <= 0) {\n // Normal handling:\n this.envDecayCounter = this.envDecayRate + 1;\n if (this.envVolume > 0) {\n this.envVolume--;\n } else {\n this.envVolume = this.envDecayLoopEnable ? 0xf : 0;\n }\n }\n if (this.envDecayDisable) {\n this.masterVolume = this.envDecayRate;\n } else {\n this.masterVolume = this.envVolume;\n }\n this.updateSampleValue();\n },\n\n updateSampleValue: function() {\n if (this.isEnabled && this.lengthCounter > 0) {\n this.sampleValue = this.randomBit * this.masterVolume;\n }\n },\n\n writeReg: function(address, value) {\n if (address === 0x400c) {\n // Volume/Envelope decay:\n this.envDecayDisable = (value & 0x10) !== 0;\n this.envDecayRate = value & 0xf;\n this.envDecayLoopEnable = (value & 0x20) !== 0;\n this.lengthCounterEnable = (value & 0x20) === 0;\n if (this.envDecayDisable) {\n this.masterVolume = this.envDecayRate;\n } else {\n this.masterVolume = this.envVolume;\n }\n } else if (address === 0x400e) {\n // Programmable timer:\n this.progTimerMax = this.papu.getNoiseWaveLength(value & 0xf);\n this.randomMode = value >> 7;\n } else if (address === 0x400f) {\n // Length counter\n this.lengthCounter = this.papu.getLengthMax(value & 248);\n this.envReset = true;\n }\n // Update:\n //updateSampleValue();\n },\n\n setEnabled: function(value) {\n this.isEnabled = value;\n if (!value) {\n this.lengthCounter = 0;\n }\n this.updateSampleValue();\n },\n\n getLengthStatus: function() {\n return this.lengthCounter === 0 || !this.isEnabled ? 0 : 1;\n }\n};\n\nvar ChannelSquare = function(papu, square1) {\n this.papu = papu;\n\n // prettier-ignore\n this.dutyLookup = [\n 0, 1, 0, 0, 0, 0, 0, 0,\n 0, 1, 1, 0, 0, 0, 0, 0,\n 0, 1, 1, 1, 1, 0, 0, 0,\n 1, 0, 0, 1, 1, 1, 1, 1\n ];\n // prettier-ignore\n this.impLookup = [\n 1,-1, 0, 0, 0, 0, 0, 0,\n 1, 0,-1, 0, 0, 0, 0, 0,\n 1, 0, 0, 0,-1, 0, 0, 0,\n -1, 0, 1, 0, 0, 0, 0, 0\n ];\n\n this.sqr1 = square1;\n this.isEnabled = null;\n this.lengthCounterEnable = null;\n this.sweepActive = null;\n this.envDecayDisable = null;\n this.envDecayLoopEnable = null;\n this.envReset = null;\n this.sweepCarry = null;\n this.updateSweepPeriod = null;\n\n this.progTimerCount = null;\n this.progTimerMax = null;\n this.lengthCounter = null;\n this.squareCounter = null;\n this.sweepCounter = null;\n this.sweepCounterMax = null;\n this.sweepMode = null;\n this.sweepShiftAmount = null;\n this.envDecayRate = null;\n this.envDecayCounter = null;\n this.envVolume = null;\n this.masterVolume = null;\n this.dutyMode = null;\n this.sweepResult = null;\n this.sampleValue = null;\n this.vol = null;\n\n this.reset();\n};\n\nChannelSquare.prototype = {\n reset: function() {\n this.progTimerCount = 0;\n this.progTimerMax = 0;\n this.lengthCounter = 0;\n this.squareCounter = 0;\n this.sweepCounter = 0;\n this.sweepCounterMax = 0;\n this.sweepMode = 0;\n this.sweepShiftAmount = 0;\n this.envDecayRate = 0;\n this.envDecayCounter = 0;\n this.envVolume = 0;\n this.masterVolume = 0;\n this.dutyMode = 0;\n this.vol = 0;\n\n this.isEnabled = false;\n this.lengthCounterEnable = false;\n this.sweepActive = false;\n this.sweepCarry = false;\n this.envDecayDisable = false;\n this.envDecayLoopEnable = false;\n },\n\n clockLengthCounter: function() {\n if (this.lengthCounterEnable && this.lengthCounter > 0) {\n this.lengthCounter--;\n if (this.lengthCounter === 0) {\n this.updateSampleValue();\n }\n }\n },\n\n clockEnvDecay: function() {\n if (this.envReset) {\n // Reset envelope:\n this.envReset = false;\n this.envDecayCounter = this.envDecayRate + 1;\n this.envVolume = 0xf;\n } else if (--this.envDecayCounter <= 0) {\n // Normal handling:\n this.envDecayCounter = this.envDecayRate + 1;\n if (this.envVolume > 0) {\n this.envVolume--;\n } else {\n this.envVolume = this.envDecayLoopEnable ? 0xf : 0;\n }\n }\n\n if (this.envDecayDisable) {\n this.masterVolume = this.envDecayRate;\n } else {\n this.masterVolume = this.envVolume;\n }\n this.updateSampleValue();\n },\n\n clockSweep: function() {\n if (--this.sweepCounter <= 0) {\n this.sweepCounter = this.sweepCounterMax + 1;\n if (\n this.sweepActive &&\n this.sweepShiftAmount > 0 &&\n this.progTimerMax > 7\n ) {\n // Calculate result from shifter:\n this.sweepCarry = false;\n if (this.sweepMode === 0) {\n this.progTimerMax += this.progTimerMax >> this.sweepShiftAmount;\n if (this.progTimerMax > 4095) {\n this.progTimerMax = 4095;\n this.sweepCarry = true;\n }\n } else {\n this.progTimerMax =\n this.progTimerMax -\n ((this.progTimerMax >> this.sweepShiftAmount) -\n (this.sqr1 ? 1 : 0));\n }\n }\n }\n\n if (this.updateSweepPeriod) {\n this.updateSweepPeriod = false;\n this.sweepCounter = this.sweepCounterMax + 1;\n }\n },\n\n updateSampleValue: function() {\n if (this.isEnabled && this.lengthCounter > 0 && this.progTimerMax > 7) {\n if (\n this.sweepMode === 0 &&\n this.progTimerMax + (this.progTimerMax >> this.sweepShiftAmount) > 4095\n ) {\n //if (this.sweepCarry) {\n this.sampleValue = 0;\n } else {\n this.sampleValue =\n this.masterVolume *\n this.dutyLookup[(this.dutyMode << 3) + this.squareCounter];\n }\n } else {\n this.sampleValue = 0;\n }\n },\n\n writeReg: function(address, value) {\n var addrAdd = this.sqr1 ? 0 : 4;\n if (address === 0x4000 + addrAdd) {\n // Volume/Envelope decay:\n this.envDecayDisable = (value & 0x10) !== 0;\n this.envDecayRate = value & 0xf;\n this.envDecayLoopEnable = (value & 0x20) !== 0;\n this.dutyMode = (value >> 6) & 0x3;\n this.lengthCounterEnable = (value & 0x20) === 0;\n if (this.envDecayDisable) {\n this.masterVolume = this.envDecayRate;\n } else {\n this.masterVolume = this.envVolume;\n }\n this.updateSampleValue();\n } else if (address === 0x4001 + addrAdd) {\n // Sweep:\n this.sweepActive = (value & 0x80) !== 0;\n this.sweepCounterMax = (value >> 4) & 7;\n this.sweepMode = (value >> 3) & 1;\n this.sweepShiftAmount = value & 7;\n this.updateSweepPeriod = true;\n } else if (address === 0x4002 + addrAdd) {\n // Programmable timer:\n this.progTimerMax &= 0x700;\n this.progTimerMax |= value;\n } else if (address === 0x4003 + addrAdd) {\n // Programmable timer, length counter\n this.progTimerMax &= 0xff;\n this.progTimerMax |= (value & 0x7) << 8;\n\n if (this.isEnabled) {\n this.lengthCounter = this.papu.getLengthMax(value & 0xf8);\n }\n\n this.envReset = true;\n }\n },\n\n setEnabled: function(value) {\n this.isEnabled = value;\n if (!value) {\n this.lengthCounter = 0;\n }\n this.updateSampleValue();\n },\n\n getLengthStatus: function() {\n return this.lengthCounter === 0 || !this.isEnabled ? 0 : 1;\n }\n};\n\nvar ChannelTriangle = function(papu) {\n this.papu = papu;\n\n this.isEnabled = null;\n this.sampleCondition = null;\n this.lengthCounterEnable = null;\n this.lcHalt = null;\n this.lcControl = null;\n\n this.progTimerCount = null;\n this.progTimerMax = null;\n this.triangleCounter = null;\n this.lengthCounter = null;\n this.linearCounter = null;\n this.lcLoadValue = null;\n this.sampleValue = null;\n this.tmp = null;\n\n this.reset();\n};\n\nChannelTriangle.prototype = {\n reset: function() {\n this.progTimerCount = 0;\n this.progTimerMax = 0;\n this.triangleCounter = 0;\n this.isEnabled = false;\n this.sampleCondition = false;\n this.lengthCounter = 0;\n this.lengthCounterEnable = false;\n this.linearCounter = 0;\n this.lcLoadValue = 0;\n this.lcHalt = true;\n this.lcControl = false;\n this.tmp = 0;\n this.sampleValue = 0xf;\n },\n\n clockLengthCounter: function() {\n if (this.lengthCounterEnable && this.lengthCounter > 0) {\n this.lengthCounter--;\n if (this.lengthCounter === 0) {\n this.updateSampleCondition();\n }\n }\n },\n\n clockLinearCounter: function() {\n if (this.lcHalt) {\n // Load:\n this.linearCounter = this.lcLoadValue;\n this.updateSampleCondition();\n } else if (this.linearCounter > 0) {\n // Decrement:\n this.linearCounter--;\n this.updateSampleCondition();\n }\n if (!this.lcControl) {\n // Clear halt flag:\n this.lcHalt = false;\n }\n },\n\n getLengthStatus: function() {\n return this.lengthCounter === 0 || !this.isEnabled ? 0 : 1;\n },\n\n readReg: function(address) {\n return 0;\n },\n\n writeReg: function(address, value) {\n if (address === 0x4008) {\n // New values for linear counter:\n this.lcControl = (value & 0x80) !== 0;\n this.lcLoadValue = value & 0x7f;\n\n // Length counter enable:\n this.lengthCounterEnable = !this.lcControl;\n } else if (address === 0x400a) {\n // Programmable timer:\n this.progTimerMax &= 0x700;\n this.progTimerMax |= value;\n } else if (address === 0x400b) {\n // Programmable timer, length counter\n this.progTimerMax &= 0xff;\n this.progTimerMax |= (value & 0x07) << 8;\n this.lengthCounter = this.papu.getLengthMax(value & 0xf8);\n this.lcHalt = true;\n }\n\n this.updateSampleCondition();\n },\n\n clockProgrammableTimer: function(nCycles) {\n if (this.progTimerMax > 0) {\n this.progTimerCount += nCycles;\n while (\n this.progTimerMax > 0 &&\n this.progTimerCount >= this.progTimerMax\n ) {\n this.progTimerCount -= this.progTimerMax;\n if (\n this.isEnabled &&\n this.lengthCounter > 0 &&\n this.linearCounter > 0\n ) {\n this.clockTriangleGenerator();\n }\n }\n }\n },\n\n clockTriangleGenerator: function() {\n this.triangleCounter++;\n this.triangleCounter &= 0x1f;\n },\n\n setEnabled: function(value) {\n this.isEnabled = value;\n if (!value) {\n this.lengthCounter = 0;\n }\n this.updateSampleCondition();\n },\n\n updateSampleCondition: function() {\n this.sampleCondition =\n this.isEnabled &&\n this.progTimerMax > 7 &&\n this.linearCounter > 0 &&\n this.lengthCounter > 0;\n }\n};\n\nmodule.exports = PAPU;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/papu.js\n// module id = 7\n// module chunks = 0 1","var Mappers = require(\"./mappers\");\nvar Tile = require(\"./tile\");\n\nvar ROM = function(nes) {\n this.nes = nes;\n\n this.mapperName = new Array(92);\n\n for (var i = 0; i < 92; i++) {\n this.mapperName[i] = \"Unknown Mapper\";\n }\n this.mapperName[0] = \"Direct Access\";\n this.mapperName[1] = \"Nintendo MMC1\";\n this.mapperName[2] = \"UNROM\";\n this.mapperName[3] = \"CNROM\";\n this.mapperName[4] = \"Nintendo MMC3\";\n this.mapperName[5] = \"Nintendo MMC5\";\n this.mapperName[6] = \"FFE F4xxx\";\n this.mapperName[7] = \"AOROM\";\n this.mapperName[8] = \"FFE F3xxx\";\n this.mapperName[9] = \"Nintendo MMC2\";\n this.mapperName[10] = \"Nintendo MMC4\";\n this.mapperName[11] = \"Color Dreams Chip\";\n this.mapperName[12] = \"FFE F6xxx\";\n this.mapperName[15] = \"100-in-1 switch\";\n this.mapperName[16] = \"Bandai chip\";\n this.mapperName[17] = \"FFE F8xxx\";\n this.mapperName[18] = \"Jaleco SS8806 chip\";\n this.mapperName[19] = \"Namcot 106 chip\";\n this.mapperName[20] = \"Famicom Disk System\";\n this.mapperName[21] = \"Konami VRC4a\";\n this.mapperName[22] = \"Konami VRC2a\";\n this.mapperName[23] = \"Konami VRC2a\";\n this.mapperName[24] = \"Konami VRC6\";\n this.mapperName[25] = \"Konami VRC4b\";\n this.mapperName[32] = \"Irem G-101 chip\";\n this.mapperName[33] = \"Taito TC0190/TC0350\";\n this.mapperName[34] = \"32kB ROM switch\";\n\n this.mapperName[64] = \"Tengen RAMBO-1 chip\";\n this.mapperName[65] = \"Irem H-3001 chip\";\n this.mapperName[66] = \"GNROM switch\";\n this.mapperName[67] = \"SunSoft3 chip\";\n this.mapperName[68] = \"SunSoft4 chip\";\n this.mapperName[69] = \"SunSoft5 FME-7 chip\";\n this.mapperName[71] = \"Camerica chip\";\n this.mapperName[78] = \"Irem 74HC161/32-based\";\n this.mapperName[91] = \"Pirate HK-SF3 chip\";\n};\n\nROM.prototype = {\n // Mirroring types:\n VERTICAL_MIRRORING: 0,\n HORIZONTAL_MIRRORING: 1,\n FOURSCREEN_MIRRORING: 2,\n SINGLESCREEN_MIRRORING: 3,\n SINGLESCREEN_MIRRORING2: 4,\n SINGLESCREEN_MIRRORING3: 5,\n SINGLESCREEN_MIRRORING4: 6,\n CHRROM_MIRRORING: 7,\n\n header: null,\n rom: null,\n vrom: null,\n vromTile: null,\n\n romCount: null,\n vromCount: null,\n mirroring: null,\n batteryRam: null,\n trainer: null,\n fourScreen: null,\n mapperType: null,\n valid: false,\n\n load: function(data) {\n var i, j, v;\n\n if (data.indexOf(\"NES\\x1a\") === -1) {\n throw new Error(\"Not a valid NES ROM.\");\n }\n this.header = new Array(16);\n for (i = 0; i < 16; i++) {\n this.header[i] = data.charCodeAt(i) & 0xff;\n }\n this.romCount = this.header[4];\n this.vromCount = this.header[5] * 2; // Get the number of 4kB banks, not 8kB\n this.mirroring = (this.header[6] & 1) !== 0 ? 1 : 0;\n this.batteryRam = (this.header[6] & 2) !== 0;\n this.trainer = (this.header[6] & 4) !== 0;\n this.fourScreen = (this.header[6] & 8) !== 0;\n this.mapperType = (this.header[6] >> 4) | (this.header[7] & 0xf0);\n /* TODO\n if (this.batteryRam)\n this.loadBatteryRam();*/\n // Check whether byte 8-15 are zero's:\n var foundError = false;\n for (i = 8; i < 16; i++) {\n if (this.header[i] !== 0) {\n foundError = true;\n break;\n }\n }\n if (foundError) {\n this.mapperType &= 0xf; // Ignore byte 7\n }\n // Load PRG-ROM banks:\n this.rom = new Array(this.romCount);\n var offset = 16;\n for (i = 0; i < this.romCount; i++) {\n this.rom[i] = new Array(16384);\n for (j = 0; j < 16384; j++) {\n if (offset + j >= data.length) {\n break;\n }\n this.rom[i][j] = data.charCodeAt(offset + j) & 0xff;\n }\n offset += 16384;\n }\n // Load CHR-ROM banks:\n this.vrom = new Array(this.vromCount);\n for (i = 0; i < this.vromCount; i++) {\n this.vrom[i] = new Array(4096);\n for (j = 0; j < 4096; j++) {\n if (offset + j >= data.length) {\n break;\n }\n this.vrom[i][j] = data.charCodeAt(offset + j) & 0xff;\n }\n offset += 4096;\n }\n\n // Create VROM tiles:\n this.vromTile = new Array(this.vromCount);\n for (i = 0; i < this.vromCount; i++) {\n this.vromTile[i] = new Array(256);\n for (j = 0; j < 256; j++) {\n this.vromTile[i][j] = new Tile();\n }\n }\n\n // Convert CHR-ROM banks to tiles:\n var tileIndex;\n var leftOver;\n for (v = 0; v < this.vromCount; v++) {\n for (i = 0; i < 4096; i++) {\n tileIndex = i >> 4;\n leftOver = i % 16;\n if (leftOver < 8) {\n this.vromTile[v][tileIndex].setScanline(\n leftOver,\n this.vrom[v][i],\n this.vrom[v][i + 8]\n );\n } else {\n this.vromTile[v][tileIndex].setScanline(\n leftOver - 8,\n this.vrom[v][i - 8],\n this.vrom[v][i]\n );\n }\n }\n }\n\n this.valid = true;\n },\n\n getMirroringType: function() {\n if (this.fourScreen) {\n return this.FOURSCREEN_MIRRORING;\n }\n if (this.mirroring === 0) {\n return this.HORIZONTAL_MIRRORING;\n }\n return this.VERTICAL_MIRRORING;\n },\n\n getMapperName: function() {\n if (this.mapperType >= 0 && this.mapperType < this.mapperName.length) {\n return this.mapperName[this.mapperType];\n }\n return \"Unknown Mapper, \" + this.mapperType;\n },\n\n mapperSupported: function() {\n return typeof Mappers[this.mapperType] !== \"undefined\";\n },\n\n createMapper: function() {\n if (this.mapperSupported()) {\n return new Mappers[this.mapperType](this.nes);\n } else {\n throw new Error(\n \"This ROM uses a mapper not supported by JSNES: \" +\n this.getMapperName() +\n \"(\" +\n this.mapperType +\n \")\"\n );\n }\n }\n};\n\nmodule.exports = ROM;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/rom.js\n// module id = 8\n// module chunks = 0 1","var utils = require(\"./utils\");\n\nvar Mappers = {};\n\nMappers[0] = function(nes) {\n this.nes = nes;\n};\n\nMappers[0].prototype = {\n reset: function() {\n this.joy1StrobeState = 0;\n this.joy2StrobeState = 0;\n this.joypadLastWrite = 0;\n\n this.zapperFired = false;\n this.zapperX = null;\n this.zapperY = null;\n },\n\n write: function(address, value) {\n if (address < 0x2000) {\n // Mirroring of RAM:\n this.nes.cpu.mem[address & 0x7ff] = value;\n } else if (address > 0x4017) {\n this.nes.cpu.mem[address] = value;\n if (address >= 0x6000 && address < 0x8000) {\n // Write to persistent RAM\n this.nes.opts.onBatteryRamWrite(address, value);\n }\n } else if (address > 0x2007 && address < 0x4000) {\n this.regWrite(0x2000 + (address & 0x7), value);\n } else {\n this.regWrite(address, value);\n }\n },\n\n writelow: function(address, value) {\n if (address < 0x2000) {\n // Mirroring of RAM:\n this.nes.cpu.mem[address & 0x7ff] = value;\n } else if (address > 0x4017) {\n this.nes.cpu.mem[address] = value;\n } else if (address > 0x2007 && address < 0x4000) {\n this.regWrite(0x2000 + (address & 0x7), value);\n } else {\n this.regWrite(address, value);\n }\n },\n\n load: function(address) {\n // Wrap around:\n address &= 0xffff;\n\n // Check address range:\n if (address > 0x4017) {\n // ROM:\n return this.nes.cpu.mem[address];\n } else if (address >= 0x2000) {\n // I/O Ports.\n return this.regLoad(address);\n } else {\n // RAM (mirrored)\n return this.nes.cpu.mem[address & 0x7ff];\n }\n },\n\n regLoad: function(address) {\n switch (address >> 12) { // use fourth nibble (0xF000)\n case 0:\n break;\n\n case 1:\n break;\n\n case 2:\n // Fall through to case 3\n case 3:\n // PPU Registers\n switch (address & 0x7) {\n case 0x0:\n // 0x2000:\n // PPU Control Register 1.\n // (the value is stored both\n // in main memory and in the\n // PPU as flags):\n // (not in the real NES)\n return this.nes.cpu.mem[0x2000];\n\n case 0x1:\n // 0x2001:\n // PPU Control Register 2.\n // (the value is stored both\n // in main memory and in the\n // PPU as flags):\n // (not in the real NES)\n return this.nes.cpu.mem[0x2001];\n\n case 0x2:\n // 0x2002:\n // PPU Status Register.\n // The value is stored in\n // main memory in addition\n // to as flags in the PPU.\n // (not in the real NES)\n return this.nes.ppu.readStatusRegister();\n\n case 0x3:\n return 0;\n\n case 0x4:\n // 0x2004:\n // Sprite Memory read.\n return this.nes.ppu.sramLoad();\n case 0x5:\n return 0;\n\n case 0x6:\n return 0;\n\n case 0x7:\n // 0x2007:\n // VRAM read:\n return this.nes.ppu.vramLoad();\n }\n break;\n case 4:\n // Sound+Joypad registers\n switch (address - 0x4015) {\n case 0:\n // 0x4015:\n // Sound channel enable, DMC Status\n return this.nes.papu.readReg(address);\n\n case 1:\n // 0x4016:\n // Joystick 1 + Strobe\n return this.joy1Read();\n\n case 2:\n // 0x4017:\n // Joystick 2 + Strobe\n // https://wiki.nesdev.com/w/index.php/Zapper\n var w;\n\n if (\n this.zapperX !== null &&\n this.zapperY !== null &&\n this.nes.ppu.isPixelWhite(this.zapperX, this.zapperY)\n ) {\n w = 0;\n } else {\n w = 0x1 << 3;\n }\n\n if (this.zapperFired) {\n w |= 0x1 << 4;\n }\n return (this.joy2Read() | w) & 0xffff;\n }\n break;\n }\n return 0;\n },\n\n regWrite: function(address, value) {\n switch (address) {\n case 0x2000:\n // PPU Control register 1\n this.nes.cpu.mem[address] = value;\n this.nes.ppu.updateControlReg1(value);\n break;\n\n case 0x2001:\n // PPU Control register 2\n this.nes.cpu.mem[address] = value;\n this.nes.ppu.updateControlReg2(value);\n break;\n\n case 0x2003:\n // Set Sprite RAM address:\n this.nes.ppu.writeSRAMAddress(value);\n break;\n\n case 0x2004:\n // Write to Sprite RAM:\n this.nes.ppu.sramWrite(value);\n break;\n\n case 0x2005:\n // Screen Scroll offsets:\n this.nes.ppu.scrollWrite(value);\n break;\n\n case 0x2006:\n // Set VRAM address:\n this.nes.ppu.writeVRAMAddress(value);\n break;\n\n case 0x2007:\n // Write to VRAM:\n this.nes.ppu.vramWrite(value);\n break;\n\n case 0x4014:\n // Sprite Memory DMA Access\n this.nes.ppu.sramDMA(value);\n break;\n\n case 0x4015:\n // Sound Channel Switch, DMC Status\n this.nes.papu.writeReg(address, value);\n break;\n\n case 0x4016:\n // Joystick 1 + Strobe\n if ((value & 1) === 0 && (this.joypadLastWrite & 1) === 1) {\n this.joy1StrobeState = 0;\n this.joy2StrobeState = 0;\n }\n this.joypadLastWrite = value;\n break;\n\n case 0x4017:\n // Sound channel frame sequencer:\n this.nes.papu.writeReg(address, value);\n break;\n\n default:\n // Sound registers\n // console.log(\"write to sound reg\");\n if (address >= 0x4000 && address <= 0x4017) {\n this.nes.papu.writeReg(address, value);\n }\n }\n },\n\n joy1Read: function() {\n var ret;\n\n switch (this.joy1StrobeState) {\n case 0:\n case 1:\n case 2:\n case 3:\n case 4:\n case 5:\n case 6:\n case 7:\n ret = this.nes.controllers[1].state[this.joy1StrobeState];\n break;\n case 8:\n case 9:\n case 10:\n case 11:\n case 12:\n case 13:\n case 14:\n case 15:\n case 16:\n case 17:\n case 18:\n ret = 0;\n break;\n case 19:\n ret = 1;\n break;\n default:\n ret = 0;\n }\n\n this.joy1StrobeState++;\n if (this.joy1StrobeState === 24) {\n this.joy1StrobeState = 0;\n }\n\n return ret;\n },\n\n joy2Read: function() {\n var ret;\n\n switch (this.joy2StrobeState) {\n case 0:\n case 1:\n case 2:\n case 3:\n case 4:\n case 5:\n case 6:\n case 7:\n ret = this.nes.controllers[2].state[this.joy2StrobeState];\n break;\n case 8:\n case 9:\n case 10:\n case 11:\n case 12:\n case 13:\n case 14:\n case 15:\n case 16:\n case 17:\n case 18:\n ret = 0;\n break;\n case 19:\n ret = 1;\n break;\n default:\n ret = 0;\n }\n\n this.joy2StrobeState++;\n if (this.joy2StrobeState === 24) {\n this.joy2StrobeState = 0;\n }\n\n return ret;\n },\n\n loadROM: function() {\n if (!this.nes.rom.valid || this.nes.rom.romCount < 1) {\n throw new Error(\"NoMapper: Invalid ROM! Unable to load.\");\n }\n\n // Load ROM into memory:\n this.loadPRGROM();\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Load Battery RAM (if present):\n this.loadBatteryRam();\n\n // Reset IRQ:\n //nes.getCpu().doResetInterrupt();\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n },\n\n loadPRGROM: function() {\n if (this.nes.rom.romCount > 1) {\n // Load the two first banks into memory.\n this.loadRomBank(0, 0x8000);\n this.loadRomBank(1, 0xc000);\n } else {\n // Load the one bank into both memory locations:\n this.loadRomBank(0, 0x8000);\n this.loadRomBank(0, 0xc000);\n }\n },\n\n loadCHRROM: function() {\n // console.log(\"Loading CHR ROM..\");\n if (this.nes.rom.vromCount > 0) {\n if (this.nes.rom.vromCount === 1) {\n this.loadVromBank(0, 0x0000);\n this.loadVromBank(0, 0x1000);\n } else {\n this.loadVromBank(0, 0x0000);\n this.loadVromBank(1, 0x1000);\n }\n } else {\n //System.out.println(\"There aren't any CHR-ROM banks..\");\n }\n },\n\n loadBatteryRam: function() {\n if (this.nes.rom.batteryRam) {\n var ram = this.nes.rom.batteryRam;\n if (ram !== null && ram.length === 0x2000) {\n // Load Battery RAM into memory:\n utils.copyArrayElements(ram, 0, this.nes.cpu.mem, 0x6000, 0x2000);\n }\n }\n },\n\n loadRomBank: function(bank, address) {\n // Loads a ROM bank into the specified address.\n bank %= this.nes.rom.romCount;\n //var data = this.nes.rom.rom[bank];\n //cpuMem.write(address,data,data.length);\n utils.copyArrayElements(\n this.nes.rom.rom[bank],\n 0,\n this.nes.cpu.mem,\n address,\n 16384\n );\n },\n\n loadVromBank: function(bank, address) {\n if (this.nes.rom.vromCount === 0) {\n return;\n }\n this.nes.ppu.triggerRendering();\n\n utils.copyArrayElements(\n this.nes.rom.vrom[bank % this.nes.rom.vromCount],\n 0,\n this.nes.ppu.vramMem,\n address,\n 4096\n );\n\n var vromTile = this.nes.rom.vromTile[bank % this.nes.rom.vromCount];\n utils.copyArrayElements(\n vromTile,\n 0,\n this.nes.ppu.ptTile,\n address >> 4,\n 256\n );\n },\n\n load32kRomBank: function(bank, address) {\n this.loadRomBank((bank * 2) % this.nes.rom.romCount, address);\n this.loadRomBank((bank * 2 + 1) % this.nes.rom.romCount, address + 16384);\n },\n\n load8kVromBank: function(bank4kStart, address) {\n if (this.nes.rom.vromCount === 0) {\n return;\n }\n this.nes.ppu.triggerRendering();\n\n this.loadVromBank(bank4kStart % this.nes.rom.vromCount, address);\n this.loadVromBank(\n (bank4kStart + 1) % this.nes.rom.vromCount,\n address + 4096\n );\n },\n\n load1kVromBank: function(bank1k, address) {\n if (this.nes.rom.vromCount === 0) {\n return;\n }\n this.nes.ppu.triggerRendering();\n\n var bank4k = Math.floor(bank1k / 4) % this.nes.rom.vromCount;\n var bankoffset = (bank1k % 4) * 1024;\n utils.copyArrayElements(\n this.nes.rom.vrom[bank4k],\n 0,\n this.nes.ppu.vramMem,\n bankoffset,\n 1024\n );\n\n // Update tiles:\n var vromTile = this.nes.rom.vromTile[bank4k];\n var baseIndex = address >> 4;\n for (var i = 0; i < 64; i++) {\n this.nes.ppu.ptTile[baseIndex + i] = vromTile[((bank1k % 4) << 6) + i];\n }\n },\n\n load2kVromBank: function(bank2k, address) {\n if (this.nes.rom.vromCount === 0) {\n return;\n }\n this.nes.ppu.triggerRendering();\n\n var bank4k = Math.floor(bank2k / 2) % this.nes.rom.vromCount;\n var bankoffset = (bank2k % 2) * 2048;\n utils.copyArrayElements(\n this.nes.rom.vrom[bank4k],\n bankoffset,\n this.nes.ppu.vramMem,\n address,\n 2048\n );\n\n // Update tiles:\n var vromTile = this.nes.rom.vromTile[bank4k];\n var baseIndex = address >> 4;\n for (var i = 0; i < 128; i++) {\n this.nes.ppu.ptTile[baseIndex + i] = vromTile[((bank2k % 2) << 7) + i];\n }\n },\n\n load8kRomBank: function(bank8k, address) {\n var bank16k = Math.floor(bank8k / 2) % this.nes.rom.romCount;\n var offset = (bank8k % 2) * 8192;\n\n //this.nes.cpu.mem.write(address,this.nes.rom.rom[bank16k],offset,8192);\n utils.copyArrayElements(\n this.nes.rom.rom[bank16k],\n offset,\n this.nes.cpu.mem,\n address,\n 8192\n );\n },\n\n clockIrqCounter: function() {\n // Does nothing. This is used by the MMC3 mapper.\n },\n\n latchAccess: function(address) {\n // Does nothing. This is used by MMC2.\n },\n\n toJSON: function() {\n return {\n joy1StrobeState: this.joy1StrobeState,\n joy2StrobeState: this.joy2StrobeState,\n joypadLastWrite: this.joypadLastWrite\n };\n },\n\n fromJSON: function(s) {\n this.joy1StrobeState = s.joy1StrobeState;\n this.joy2StrobeState = s.joy2StrobeState;\n this.joypadLastWrite = s.joypadLastWrite;\n }\n};\n\nMappers[1] = function(nes) {\n this.nes = nes;\n};\n\nMappers[1].prototype = new Mappers[0]();\n\nMappers[1].prototype.reset = function() {\n Mappers[0].prototype.reset.apply(this);\n\n // 5-bit buffer:\n this.regBuffer = 0;\n this.regBufferCounter = 0;\n\n // Register 0:\n this.mirroring = 0;\n this.oneScreenMirroring = 0;\n this.prgSwitchingArea = 1;\n this.prgSwitchingSize = 1;\n this.vromSwitchingSize = 0;\n\n // Register 1:\n this.romSelectionReg0 = 0;\n\n // Register 2:\n this.romSelectionReg1 = 0;\n\n // Register 3:\n this.romBankSelect = 0;\n};\n\nMappers[1].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n }\n\n // See what should be done with the written value:\n if ((value & 128) !== 0) {\n // Reset buffering:\n this.regBufferCounter = 0;\n this.regBuffer = 0;\n\n // Reset register:\n if (this.getRegNumber(address) === 0) {\n this.prgSwitchingArea = 1;\n this.prgSwitchingSize = 1;\n }\n } else {\n // Continue buffering:\n //regBuffer = (regBuffer & (0xFF-(1<<regBufferCounter))) | ((value & (1<<regBufferCounter))<<regBufferCounter);\n this.regBuffer =\n (this.regBuffer & (0xff - (1 << this.regBufferCounter))) |\n ((value & 1) << this.regBufferCounter);\n this.regBufferCounter++;\n\n if (this.regBufferCounter === 5) {\n // Use the buffered value:\n this.setReg(this.getRegNumber(address), this.regBuffer);\n\n // Reset buffer:\n this.regBuffer = 0;\n this.regBufferCounter = 0;\n }\n }\n};\n\nMappers[1].prototype.setReg = function(reg, value) {\n var tmp;\n\n switch (reg) {\n case 0:\n // Mirroring:\n tmp = value & 3;\n if (tmp !== this.mirroring) {\n // Set mirroring:\n this.mirroring = tmp;\n if ((this.mirroring & 2) === 0) {\n // SingleScreen mirroring overrides the other setting:\n this.nes.ppu.setMirroring(this.nes.rom.SINGLESCREEN_MIRRORING);\n } else if ((this.mirroring & 1) !== 0) {\n // Not overridden by SingleScreen mirroring.\n this.nes.ppu.setMirroring(this.nes.rom.HORIZONTAL_MIRRORING);\n } else {\n this.nes.ppu.setMirroring(this.nes.rom.VERTICAL_MIRRORING);\n }\n }\n\n // PRG Switching Area;\n this.prgSwitchingArea = (value >> 2) & 1;\n\n // PRG Switching Size:\n this.prgSwitchingSize = (value >> 3) & 1;\n\n // VROM Switching Size:\n this.vromSwitchingSize = (value >> 4) & 1;\n\n break;\n\n case 1:\n // ROM selection:\n this.romSelectionReg0 = (value >> 4) & 1;\n\n // Check whether the cart has VROM:\n if (this.nes.rom.vromCount > 0) {\n // Select VROM bank at 0x0000:\n if (this.vromSwitchingSize === 0) {\n // Swap 8kB VROM:\n if (this.romSelectionReg0 === 0) {\n this.load8kVromBank(value & 0xf, 0x0000);\n } else {\n this.load8kVromBank(\n Math.floor(this.nes.rom.vromCount / 2) + (value & 0xf),\n 0x0000\n );\n }\n } else {\n // Swap 4kB VROM:\n if (this.romSelectionReg0 === 0) {\n this.loadVromBank(value & 0xf, 0x0000);\n } else {\n this.loadVromBank(\n Math.floor(this.nes.rom.vromCount / 2) + (value & 0xf),\n 0x0000\n );\n }\n }\n }\n\n break;\n\n case 2:\n // ROM selection:\n this.romSelectionReg1 = (value >> 4) & 1;\n\n // Check whether the cart has VROM:\n if (this.nes.rom.vromCount > 0) {\n // Select VROM bank at 0x1000:\n if (this.vromSwitchingSize === 1) {\n // Swap 4kB of VROM:\n if (this.romSelectionReg1 === 0) {\n this.loadVromBank(value & 0xf, 0x1000);\n } else {\n this.loadVromBank(\n Math.floor(this.nes.rom.vromCount / 2) + (value & 0xf),\n 0x1000\n );\n }\n }\n }\n break;\n\n default:\n // Select ROM bank:\n // -------------------------\n tmp = value & 0xf;\n var bank;\n var baseBank = 0;\n\n if (this.nes.rom.romCount >= 32) {\n // 1024 kB cart\n if (this.vromSwitchingSize === 0) {\n if (this.romSelectionReg0 === 1) {\n baseBank = 16;\n }\n } else {\n baseBank =\n (this.romSelectionReg0 | (this.romSelectionReg1 << 1)) << 3;\n }\n } else if (this.nes.rom.romCount >= 16) {\n // 512 kB cart\n if (this.romSelectionReg0 === 1) {\n baseBank = 8;\n }\n }\n\n if (this.prgSwitchingSize === 0) {\n // 32kB\n bank = baseBank + (value & 0xf);\n this.load32kRomBank(bank, 0x8000);\n } else {\n // 16kB\n bank = baseBank * 2 + (value & 0xf);\n if (this.prgSwitchingArea === 0) {\n this.loadRomBank(bank, 0xc000);\n } else {\n this.loadRomBank(bank, 0x8000);\n }\n }\n }\n};\n\n// Returns the register number from the address written to:\nMappers[1].prototype.getRegNumber = function(address) {\n if (address >= 0x8000 && address <= 0x9fff) {\n return 0;\n } else if (address >= 0xa000 && address <= 0xbfff) {\n return 1;\n } else if (address >= 0xc000 && address <= 0xdfff) {\n return 2;\n } else {\n return 3;\n }\n};\n\nMappers[1].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"MMC1: Invalid ROM! Unable to load.\");\n }\n\n // Load PRG-ROM:\n this.loadRomBank(0, 0x8000); // First ROM bank..\n this.loadRomBank(this.nes.rom.romCount - 1, 0xc000); // ..and last ROM bank.\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Load Battery RAM (if present):\n this.loadBatteryRam();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\nMappers[1].prototype.switchLowHighPrgRom = function(oldSetting) {\n // not yet.\n};\n\nMappers[1].prototype.switch16to32 = function() {\n // not yet.\n};\n\nMappers[1].prototype.switch32to16 = function() {\n // not yet.\n};\n\nMappers[1].prototype.toJSON = function() {\n var s = Mappers[0].prototype.toJSON.apply(this);\n s.mirroring = this.mirroring;\n s.oneScreenMirroring = this.oneScreenMirroring;\n s.prgSwitchingArea = this.prgSwitchingArea;\n s.prgSwitchingSize = this.prgSwitchingSize;\n s.vromSwitchingSize = this.vromSwitchingSize;\n s.romSelectionReg0 = this.romSelectionReg0;\n s.romSelectionReg1 = this.romSelectionReg1;\n s.romBankSelect = this.romBankSelect;\n s.regBuffer = this.regBuffer;\n s.regBufferCounter = this.regBufferCounter;\n return s;\n};\n\nMappers[1].prototype.fromJSON = function(s) {\n Mappers[0].prototype.fromJSON.apply(this, arguments);\n this.mirroring = s.mirroring;\n this.oneScreenMirroring = s.oneScreenMirroring;\n this.prgSwitchingArea = s.prgSwitchingArea;\n this.prgSwitchingSize = s.prgSwitchingSize;\n this.vromSwitchingSize = s.vromSwitchingSize;\n this.romSelectionReg0 = s.romSelectionReg0;\n this.romSelectionReg1 = s.romSelectionReg1;\n this.romBankSelect = s.romBankSelect;\n this.regBuffer = s.regBuffer;\n this.regBufferCounter = s.regBufferCounter;\n};\n\nMappers[2] = function(nes) {\n this.nes = nes;\n};\n\nMappers[2].prototype = new Mappers[0]();\n\nMappers[2].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n // This is a ROM bank select command.\n // Swap in the given ROM bank at 0x8000:\n this.loadRomBank(value, 0x8000);\n }\n};\n\nMappers[2].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"UNROM: Invalid ROM! Unable to load.\");\n }\n\n // Load PRG-ROM:\n this.loadRomBank(0, 0x8000);\n this.loadRomBank(this.nes.rom.romCount - 1, 0xc000);\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\n/**\n * Mapper 003 (CNROM)\n *\n * @constructor\n * @example Solomon's Key, Arkanoid, Arkista's Ring, Bump 'n' Jump, Cybernoid\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_003\n */\nMappers[3] = function(nes) {\n this.nes = nes;\n};\n\nMappers[3].prototype = new Mappers[0]();\n\nMappers[3].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n // This is a ROM bank select command.\n // Swap in the given ROM bank at 0x8000:\n // This is a VROM bank select command.\n // Swap in the given VROM bank at 0x0000:\n var bank = (value % (this.nes.rom.vromCount / 2)) * 2;\n this.loadVromBank(bank, 0x0000);\n this.loadVromBank(bank + 1, 0x1000);\n this.load8kVromBank(value * 2, 0x0000);\n }\n};\n\nMappers[4] = function(nes) {\n this.nes = nes;\n\n this.CMD_SEL_2_1K_VROM_0000 = 0;\n this.CMD_SEL_2_1K_VROM_0800 = 1;\n this.CMD_SEL_1K_VROM_1000 = 2;\n this.CMD_SEL_1K_VROM_1400 = 3;\n this.CMD_SEL_1K_VROM_1800 = 4;\n this.CMD_SEL_1K_VROM_1C00 = 5;\n this.CMD_SEL_ROM_PAGE1 = 6;\n this.CMD_SEL_ROM_PAGE2 = 7;\n\n this.command = null;\n this.prgAddressSelect = null;\n this.chrAddressSelect = null;\n this.pageNumber = null;\n this.irqCounter = null;\n this.irqLatchValue = null;\n this.irqEnable = null;\n this.prgAddressChanged = false;\n};\n\nMappers[4].prototype = new Mappers[0]();\n\nMappers[4].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n }\n\n switch (address) {\n case 0x8000:\n // Command/Address Select register\n this.command = value & 7;\n var tmp = (value >> 6) & 1;\n if (tmp !== this.prgAddressSelect) {\n this.prgAddressChanged = true;\n }\n this.prgAddressSelect = tmp;\n this.chrAddressSelect = (value >> 7) & 1;\n break;\n\n case 0x8001:\n // Page number for command\n this.executeCommand(this.command, value);\n break;\n\n case 0xa000:\n // Mirroring select\n if ((value & 1) !== 0) {\n this.nes.ppu.setMirroring(this.nes.rom.HORIZONTAL_MIRRORING);\n } else {\n this.nes.ppu.setMirroring(this.nes.rom.VERTICAL_MIRRORING);\n }\n break;\n\n case 0xa001:\n // SaveRAM Toggle\n // TODO\n //nes.getRom().setSaveState((value&1)!=0);\n break;\n\n case 0xc000:\n // IRQ Counter register\n this.irqCounter = value;\n //nes.ppu.mapperIrqCounter = 0;\n break;\n\n case 0xc001:\n // IRQ Latch register\n this.irqLatchValue = value;\n break;\n\n case 0xe000:\n // IRQ Control Reg 0 (disable)\n //irqCounter = irqLatchValue;\n this.irqEnable = 0;\n break;\n\n case 0xe001:\n // IRQ Control Reg 1 (enable)\n this.irqEnable = 1;\n break;\n\n default:\n // Not a MMC3 register.\n // The game has probably crashed,\n // since it tries to write to ROM..\n // IGNORE.\n }\n};\n\nMappers[4].prototype.executeCommand = function(cmd, arg) {\n switch (cmd) {\n case this.CMD_SEL_2_1K_VROM_0000:\n // Select 2 1KB VROM pages at 0x0000:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x0000);\n this.load1kVromBank(arg + 1, 0x0400);\n } else {\n this.load1kVromBank(arg, 0x1000);\n this.load1kVromBank(arg + 1, 0x1400);\n }\n break;\n\n case this.CMD_SEL_2_1K_VROM_0800:\n // Select 2 1KB VROM pages at 0x0800:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x0800);\n this.load1kVromBank(arg + 1, 0x0c00);\n } else {\n this.load1kVromBank(arg, 0x1800);\n this.load1kVromBank(arg + 1, 0x1c00);\n }\n break;\n\n case this.CMD_SEL_1K_VROM_1000:\n // Select 1K VROM Page at 0x1000:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x1000);\n } else {\n this.load1kVromBank(arg, 0x0000);\n }\n break;\n\n case this.CMD_SEL_1K_VROM_1400:\n // Select 1K VROM Page at 0x1400:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x1400);\n } else {\n this.load1kVromBank(arg, 0x0400);\n }\n break;\n\n case this.CMD_SEL_1K_VROM_1800:\n // Select 1K VROM Page at 0x1800:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x1800);\n } else {\n this.load1kVromBank(arg, 0x0800);\n }\n break;\n\n case this.CMD_SEL_1K_VROM_1C00:\n // Select 1K VROM Page at 0x1C00:\n if (this.chrAddressSelect === 0) {\n this.load1kVromBank(arg, 0x1c00);\n } else {\n this.load1kVromBank(arg, 0x0c00);\n }\n break;\n\n case this.CMD_SEL_ROM_PAGE1:\n if (this.prgAddressChanged) {\n // Load the two hardwired banks:\n if (this.prgAddressSelect === 0) {\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0xc000);\n } else {\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0x8000);\n }\n this.prgAddressChanged = false;\n }\n\n // Select first switchable ROM page:\n if (this.prgAddressSelect === 0) {\n this.load8kRomBank(arg, 0x8000);\n } else {\n this.load8kRomBank(arg, 0xc000);\n }\n break;\n\n case this.CMD_SEL_ROM_PAGE2:\n // Select second switchable ROM page:\n this.load8kRomBank(arg, 0xa000);\n\n // hardwire appropriate bank:\n if (this.prgAddressChanged) {\n // Load the two hardwired banks:\n if (this.prgAddressSelect === 0) {\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0xc000);\n } else {\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0x8000);\n }\n this.prgAddressChanged = false;\n }\n }\n};\n\nMappers[4].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"MMC3: Invalid ROM! Unable to load.\");\n }\n\n // Load hardwired PRG banks (0xC000 and 0xE000):\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2, 0xc000);\n this.load8kRomBank((this.nes.rom.romCount - 1) * 2 + 1, 0xe000);\n\n // Load swappable PRG banks (0x8000 and 0xA000):\n this.load8kRomBank(0, 0x8000);\n this.load8kRomBank(1, 0xa000);\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Load Battery RAM (if present):\n this.loadBatteryRam();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\nMappers[4].prototype.clockIrqCounter = function() {\n if (this.irqEnable === 1) {\n this.irqCounter--;\n if (this.irqCounter < 0) {\n // Trigger IRQ:\n //nes.getCpu().doIrq();\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_NORMAL);\n this.irqCounter = this.irqLatchValue;\n }\n }\n};\n\nMappers[4].prototype.toJSON = function() {\n var s = Mappers[0].prototype.toJSON.apply(this);\n s.command = this.command;\n s.prgAddressSelect = this.prgAddressSelect;\n s.chrAddressSelect = this.chrAddressSelect;\n s.pageNumber = this.pageNumber;\n s.irqCounter = this.irqCounter;\n s.irqLatchValue = this.irqLatchValue;\n s.irqEnable = this.irqEnable;\n s.prgAddressChanged = this.prgAddressChanged;\n return s;\n};\n\nMappers[4].prototype.fromJSON = function(s) {\n Mappers[0].prototype.fromJSON.apply(this, arguments);\n this.command = s.command;\n this.prgAddressSelect = s.prgAddressSelect;\n this.chrAddressSelect = s.chrAddressSelect;\n this.pageNumber = s.pageNumber;\n this.irqCounter = s.irqCounter;\n this.irqLatchValue = s.irqLatchValue;\n this.irqEnable = s.irqEnable;\n this.prgAddressChanged = s.prgAddressChanged;\n};\n\n/**\n * Mapper005 (MMC5,ExROM)\n *\n * @example Castlevania 3, Just Breed, Uncharted Waters, Romance of the 3 Kingdoms 2, Laser Invasion, Metal Slader Glory, Uchuu Keibitai SDF, Shin 4 Nin Uchi Mahjong - Yakuman Tengoku\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_005\n * @constructor\n */\nMappers[5] = function(nes) {\n this.nes = nes;\n};\n\nMappers[5].prototype = new Mappers[0]();\n\nMappers[5].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n } else {\n this.load8kVromBank(value, 0x0000);\n }\n};\n\nMappers[5].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x5000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n }\n\n switch (address) {\n case 0x5100:\n this.prg_size = value & 3;\n break;\n case 0x5101:\n this.chr_size = value & 3;\n break;\n case 0x5102:\n this.sram_we_a = value & 3;\n break;\n case 0x5103:\n this.sram_we_b = value & 3;\n break;\n case 0x5104:\n this.graphic_mode = value & 3;\n break;\n case 0x5105:\n this.nametable_mode = value;\n this.nametable_type[0] = value & 3;\n this.load1kVromBank(value & 3, 0x2000);\n value >>= 2;\n this.nametable_type[1] = value & 3;\n this.load1kVromBank(value & 3, 0x2400);\n value >>= 2;\n this.nametable_type[2] = value & 3;\n this.load1kVromBank(value & 3, 0x2800);\n value >>= 2;\n this.nametable_type[3] = value & 3;\n this.load1kVromBank(value & 3, 0x2c00);\n break;\n case 0x5106:\n this.fill_chr = value;\n break;\n case 0x5107:\n this.fill_pal = value & 3;\n break;\n case 0x5113:\n this.SetBank_SRAM(3, value & 3);\n break;\n case 0x5114:\n case 0x5115:\n case 0x5116:\n case 0x5117:\n this.SetBank_CPU(address, value);\n break;\n case 0x5120:\n case 0x5121:\n case 0x5122:\n case 0x5123:\n case 0x5124:\n case 0x5125:\n case 0x5126:\n case 0x5127:\n this.chr_mode = 0;\n this.chr_page[0][address & 7] = value;\n this.SetBank_PPU();\n break;\n case 0x5128:\n case 0x5129:\n case 0x512a:\n case 0x512b:\n this.chr_mode = 1;\n this.chr_page[1][(address & 3) + 0] = value;\n this.chr_page[1][(address & 3) + 4] = value;\n this.SetBank_PPU();\n break;\n case 0x5200:\n this.split_control = value;\n break;\n case 0x5201:\n this.split_scroll = value;\n break;\n case 0x5202:\n this.split_page = value & 0x3f;\n break;\n case 0x5203:\n this.irq_line = value;\n this.nes.cpu.ClearIRQ();\n break;\n case 0x5204:\n this.irq_enable = value;\n this.nes.cpu.ClearIRQ();\n break;\n case 0x5205:\n this.mult_a = value;\n break;\n case 0x5206:\n this.mult_b = value;\n break;\n default:\n if (address >= 0x5000 && address <= 0x5015) {\n this.nes.papu.exWrite(address, value);\n } else if (address >= 0x5c00 && address <= 0x5fff) {\n if (this.graphic_mode === 2) {\n // ExRAM\n // vram write\n } else if (this.graphic_mode !== 3) {\n // Split,ExGraphic\n if (this.irq_status & 0x40) {\n // vram write\n } else {\n // vram write\n }\n }\n } else if (address >= 0x6000 && address <= 0x7fff) {\n if (this.sram_we_a === 2 && this.sram_we_b === 1) {\n // additional ram write\n }\n }\n break;\n }\n};\n\nMappers[5].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"UNROM: Invalid ROM! Unable to load.\");\n }\n\n // Load PRG-ROM:\n this.load8kRomBank(this.nes.rom.romCount * 2 - 1, 0x8000);\n this.load8kRomBank(this.nes.rom.romCount * 2 - 1, 0xa000);\n this.load8kRomBank(this.nes.rom.romCount * 2 - 1, 0xc000);\n this.load8kRomBank(this.nes.rom.romCount * 2 - 1, 0xe000);\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\n/**\n * Mapper007 (AxROM)\n * @example Battletoads, Time Lord, Marble Madness\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_007\n * @constructor\n */\nMappers[7] = function(nes) {\n this.nes = nes;\n};\n\nMappers[7].prototype = new Mappers[0]();\n\nMappers[7].prototype.write = function(address, value) {\n // Writes to addresses other than MMC registers are handled by NoMapper.\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n } else {\n this.load32kRomBank(value & 0x7, 0x8000);\n if (value & 0x10) {\n this.nes.ppu.setMirroring(this.nes.rom.SINGLESCREEN_MIRRORING2);\n } else {\n this.nes.ppu.setMirroring(this.nes.rom.SINGLESCREEN_MIRRORING);\n }\n }\n};\n\nMappers[7].prototype.loadROM = function() {\n if (!this.nes.rom.valid) {\n throw new Error(\"AOROM: Invalid ROM! Unable to load.\");\n }\n\n // Load PRG-ROM:\n this.loadPRGROM();\n\n // Load CHR-ROM:\n this.loadCHRROM();\n\n // Do Reset-Interrupt:\n this.nes.cpu.requestIrq(this.nes.cpu.IRQ_RESET);\n};\n\n/**\n * Mapper 011 (Color Dreams)\n *\n * @description http://wiki.nesdev.com/w/index.php/Color_Dreams\n * @example Crystal Mines, Metal Fighter\n * @constructor\n */\nMappers[11] = function(nes) {\n this.nes = nes;\n};\n\nMappers[11].prototype = new Mappers[0]();\n\nMappers[11].prototype.write = function(address, value) {\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n // Swap in the given PRG-ROM bank:\n var prgbank1 = ((value & 0xf) * 2) % this.nes.rom.romCount;\n var prgbank2 = ((value & 0xf) * 2 + 1) % this.nes.rom.romCount;\n\n this.loadRomBank(prgbank1, 0x8000);\n this.loadRomBank(prgbank2, 0xc000);\n\n if (this.nes.rom.vromCount > 0) {\n // Swap in the given VROM bank at 0x0000:\n var bank = ((value >> 4) * 2) % this.nes.rom.vromCount;\n this.loadVromBank(bank, 0x0000);\n this.loadVromBank(bank + 1, 0x1000);\n }\n }\n};\n\n/**\n * Mapper 034 (BNROM, NINA-01)\n *\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_034\n * @example Darkseed, Mashou, Mission Impossible 2\n * @constructor\n */\nMappers[34] = function(nes) {\n this.nes = nes;\n};\n\nMappers[34].prototype = new Mappers[0]();\n\nMappers[34].prototype.write = function(address, value) {\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n this.load32kRomBank(value, 0x8000);\n }\n};\n\n/**\n * Mapper 066 (GxROM)\n *\n * @description http://wiki.nesdev.com/w/index.php/INES_Mapper_066\n * @example Doraemon, Dragon Power, Gumshoe, Thunder & Lightning,\n * Super Mario Bros. + Duck Hunt\n * @constructor\n */\nMappers[66] = function(nes) {\n this.nes = nes;\n console.log(\"Mapper 66\");\n};\n\nMappers[66].prototype = new Mappers[0]();\n\nMappers[66].prototype.write = function(address, value) {\n if (address < 0x8000) {\n Mappers[0].prototype.write.apply(this, arguments);\n return;\n } else {\n // Swap in the given PRG-ROM bank at 0x8000:\n this.load32kRomBank((value >> 4) & 3, 0x8000);\n\n // Swap in the given VROM bank at 0x0000:\n this.load8kVromBank((value & 3) * 2, 0x0000);\n }\n};\n\nmodule.exports = Mappers;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/mappers.js\n// module id = 9\n// module chunks = 0 1"],"sourceRoot":""}