UNPKG

broken-neees

Version:

A really broken NEEES emulator that introduces glitches and random bugs on purpose!

298 lines (297 loc) 13.1 kB
"use strict"; function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _InMemoryRegister = _interopRequireDefault(require("../lib/InMemoryRegister")); var _byte = _interopRequireDefault(require("../lib/byte")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } var PPUCtrl = /*#__PURE__*/function (_InMemoryRegister$PPU) { _inherits(PPUCtrl, _InMemoryRegister$PPU); var _super = _createSuper(PPUCtrl); function PPUCtrl() { _classCallCheck(this, PPUCtrl); return _super.apply(this, arguments); } _createClass(PPUCtrl, [{ key: "onLoad", value: function onLoad() { this.addField("vramAddressIncrement32", 2).addField("sprite8x8PatternTableId", 3).addField("backgroundPatternTableId", 4).addField("spriteSize", 5).addField("generateNMIOnVBlank", 7); } }, { key: "onWrite", value: function onWrite(value) { this.setValue(value); this.ppu.loopy.onPPUCtrlWrite(value); } }]); return PPUCtrl; }(_InMemoryRegister.default.PPU); var PPUMask = /*#__PURE__*/function (_InMemoryRegister$PPU2) { _inherits(PPUMask, _InMemoryRegister$PPU2); var _super2 = _createSuper(PPUMask); function PPUMask() { _classCallCheck(this, PPUMask); return _super2.apply(this, arguments); } _createClass(PPUMask, [{ key: "onLoad", value: function onLoad() { this.addField("grayscale", 0).addField("showBackgroundInFirst8Pixels", 1).addField("showSpritesInFirst8Pixels", 2).addField("showBackground", 3).addField("showSprites", 4).addField("emphasizeRed", 5).addField("emphasizeGreen", 6).addField("emphasizeBlue", 7); } }, { key: "isRenderingEnabled", value: function isRenderingEnabled() { return this.showBackground || this.showSprites; } }, { key: "transform", value: function transform(color) { var r = color >> 0 & 0xff; var g = color >> 8 & 0xff; var b = color >> 16 & 0xff; if (this.grayscale) { r = g = b = Math.floor((r + g + b) / 3); } if (this.emphasizeRed || this.emphasizeGreen || this.emphasizeBlue) { var all = this.emphasizeRed && this.emphasizeGreen && this.emphasizeBlue; if (!this.emphasizeRed || all) r = Math.floor(r * 0.75); if (!this.emphasizeGreen || all) g = Math.floor(g * 0.75); if (!this.emphasizeBlue || all) b = Math.floor(b * 0.75); } return 0xff000000 | r << 0 | g << 8 | b << 16; } }, { key: "onWrite", value: function onWrite(value) { this.setValue(value); } }]); return PPUMask; }(_InMemoryRegister.default.PPU); var PPUStatus = /*#__PURE__*/function (_InMemoryRegister$PPU3) { _inherits(PPUStatus, _InMemoryRegister$PPU3); var _super3 = _createSuper(PPUStatus); function PPUStatus() { _classCallCheck(this, PPUStatus); return _super3.apply(this, arguments); } _createClass(PPUStatus, [{ key: "onLoad", value: function onLoad() { this.addWritableField("spriteOverflow", 5).addWritableField("sprite0Hit", 6).addWritableField("isInVBlankInterval", 7); this.setValue(128); } }, { key: "onRead", value: function onRead() { if (this.ppu.isDebugging) return this.value; var value = this.value; this.isInVBlankInterval = 0; this.ppu.loopy.onPPUStatusRead(); return value; } }]); return PPUStatus; }(_InMemoryRegister.default.PPU); var OAMAddr = /*#__PURE__*/function (_InMemoryRegister$PPU4) { _inherits(OAMAddr, _InMemoryRegister$PPU4); var _super4 = _createSuper(OAMAddr); function OAMAddr() { _classCallCheck(this, OAMAddr); return _super4.apply(this, arguments); } _createClass(OAMAddr, [{ key: "onWrite", value: function onWrite(value) { this.setValue(value); } }]); return OAMAddr; }(_InMemoryRegister.default.PPU); var OAMData = /*#__PURE__*/function (_InMemoryRegister$PPU5) { _inherits(OAMData, _InMemoryRegister$PPU5); var _super5 = _createSuper(OAMData); function OAMData() { _classCallCheck(this, OAMData); return _super5.apply(this, arguments); } _createClass(OAMData, [{ key: "onRead", value: function onRead() { var oamAddress = this.ppu.registers.oamAddr; return this.ppu.memory.oamRam[oamAddress.value]; } }, { key: "onWrite", value: function onWrite(value) { var oamAddress = this.ppu.registers.oamAddr; this.ppu.memory.oamRam[oamAddress.value] = value; this._incrementAddress(); } }, { key: "_incrementAddress", value: function _incrementAddress() { var oamAddress = this.ppu.registers.oamAddr; oamAddress.setValue(oamAddress.value + 1); } }]); return OAMData; }(_InMemoryRegister.default.PPU); var PPUScroll = /*#__PURE__*/function (_InMemoryRegister$PPU6) { _inherits(PPUScroll, _InMemoryRegister$PPU6); var _super6 = _createSuper(PPUScroll); function PPUScroll() { _classCallCheck(this, PPUScroll); return _super6.apply(this, arguments); } _createClass(PPUScroll, [{ key: "onWrite", value: function onWrite(value) { this.ppu.loopy.onPPUScrollWrite(value); } }]); return PPUScroll; }(_InMemoryRegister.default.PPU); var PPUAddr = /*#__PURE__*/function (_InMemoryRegister$PPU7) { _inherits(PPUAddr, _InMemoryRegister$PPU7); var _super7 = _createSuper(PPUAddr); function PPUAddr() { _classCallCheck(this, PPUAddr); return _super7.apply(this, arguments); } _createClass(PPUAddr, [{ key: "onWrite", value: function onWrite(value) { this.ppu.loopy.onPPUAddrWrite(value); } }]); return PPUAddr; }(_InMemoryRegister.default.PPU); var PPUData = /*#__PURE__*/function (_InMemoryRegister$PPU8) { _inherits(PPUData, _InMemoryRegister$PPU8); var _super8 = _createSuper(PPUData); function PPUData() { _classCallCheck(this, PPUData); return _super8.apply(this, arguments); } _createClass(PPUData, [{ key: "onLoad", value: function onLoad() { this.buffer = 0; } }, { key: "onRead", value: function onRead() { if (this.ppu.isDebugging) return this.buffer; var data = this.buffer; var ppuAddress = this.ppu.loopy.vAddress.getValue(); this.buffer = this.ppu.memory.read(ppuAddress); if (ppuAddress >= 0x3f00) data = this.buffer; this._incrementAddress(); return data; } }, { key: "onWrite", value: function onWrite(value) { var ppuAddress = this.ppu.loopy.vAddress.getValue(); this.ppu.memory.write(ppuAddress, value); this._incrementAddress(); } }, { key: "_incrementAddress", value: function _incrementAddress() { var ppuCtrl = this.ppu.registers.ppuCtrl; var ppuAddress = this.ppu.loopy.vAddress.getValue(); this.ppu.loopy.vAddress.setValue(_byte.default.toU16(ppuAddress + (ppuCtrl.vramAddressIncrement32 ? 32 : 1))); } }]); return PPUData; }(_InMemoryRegister.default.PPU); var OAMDMA = /*#__PURE__*/function (_InMemoryRegister$PPU9) { _inherits(OAMDMA, _InMemoryRegister$PPU9); var _super9 = _createSuper(OAMDMA); function OAMDMA() { _classCallCheck(this, OAMDMA); return _super9.apply(this, arguments); } _createClass(OAMDMA, [{ key: "onWrite", value: function onWrite(value) { for (var i = 0; i < 256; i++) { var address = _byte.default.buildU16(value, i); var data = this.ppu.cpu.memory.read(address); this.ppu.memory.oamRam[i] = data; } this.ppu.cpu.extraCycles += 513; } }]); return OAMDMA; }(_InMemoryRegister.default.PPU); var VideoRegisters = /*#__PURE__*/function () { function VideoRegisters(ppu) { _classCallCheck(this, VideoRegisters); this.ppuCtrl = new PPUCtrl(ppu); // $2000 this.ppuMask = new PPUMask(ppu); // $2001 this.ppuStatus = new PPUStatus(ppu); // $2002 this.oamAddr = new OAMAddr(ppu); // $2003 this.oamData = new OAMData(ppu); // $2004 this.ppuScroll = new PPUScroll(ppu); // $2005 this.ppuAddr = new PPUAddr(ppu); // $2006 this.ppuData = new PPUData(ppu); // $2007 this.oamDma = new OAMDMA(ppu); // $4014 } _createClass(VideoRegisters, [{ key: "read", value: function read(address) { var _this$_getRegister; return (_this$_getRegister = this._getRegister(address)) === null || _this$_getRegister === void 0 ? void 0 : _this$_getRegister.onRead(); } }, { key: "write", value: function write(address, value) { var _this$_getRegister2; (_this$_getRegister2 = this._getRegister(address)) === null || _this$_getRegister2 === void 0 ? void 0 : _this$_getRegister2.onWrite(value); } }, { key: "_getRegister", value: function _getRegister(address) { switch (address) { case 0x2000: return this.ppuCtrl; case 0x2001: return this.ppuMask; case 0x2002: return this.ppuStatus; case 0x2003: return this.oamAddr; case 0x2004: return this.oamData; case 0x2005: return this.ppuScroll; case 0x2006: return this.ppuAddr; case 0x2007: return this.ppuData; case 0x4014: return this.oamDma; default: } } }]); return VideoRegisters; }(); exports.default = VideoRegisters;