broken-neees
Version:
A really broken NEEES emulator that introduces glitches and random bugs on purpose!
99 lines (97 loc) • 4.45 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _byte = _interopRequireDefault(require("./lib/byte"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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); }
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); }
var KB = 1024;
var HEADER_SIZE = 16;
var PRG_PAGE_SIZE = 16 * KB;
var CHR_PAGE_SIZE = 8 * KB;
var Cartridge = /*#__PURE__*/function () {
function Cartridge(bytes) {
_classCallCheck(this, Cartridge);
this.bytes = bytes;
this._checkMagicConstant();
this.header = this._buildHeader();
}
// [!!!]
_createClass(Cartridge, [{
key: "isBroken",
get: function get() {
return !this.unbroken;
}
}, {
key: "prg",
value: function prg() {
return this.bytes.slice(this._prgOffset(), this._prgOffset() + this._prgSize());
}
}, {
key: "chr",
value: function chr() {
if (this.header.usesChrRam) return new Uint8Array(CHR_PAGE_SIZE);
if (this.unbroken) {
return this.bytes.slice(this._chrOffset(), this._chrOffset() + this._chrSize());
} else {
// [!!!]
var size = this._chrSize();
var bytes = new Uint8Array(size + 3);
bytes.set(this.bytes.slice(this._chrOffset(), this._chrOffset() + size), 3);
return bytes;
}
}
}, {
key: "_prgOffset",
value: function _prgOffset() {
return HEADER_SIZE + (this.header.has512BytePadding ? 512 : 0);
}
}, {
key: "_prgSize",
value: function _prgSize() {
return this.header.prgRomPages * PRG_PAGE_SIZE;
}
}, {
key: "_chrOffset",
value: function _chrOffset() {
return this._prgOffset() + this._prgSize();
}
}, {
key: "_chrSize",
value: function _chrSize() {
return this.header.chrRomPages * CHR_PAGE_SIZE;
}
}, {
key: "_buildHeader",
value: function _buildHeader() {
var prgRomPages = this.bytes[4];
var chrRomPages = this.bytes[5];
var flags6 = this.bytes[6];
var flags7 = this.bytes[7];
return {
prgRomPages: prgRomPages,
chrRomPages: chrRomPages,
usesChrRam: chrRomPages === 0,
has512BytePadding: _byte.default.getFlag(flags6, 2),
hasPrgRam: _byte.default.getFlag(flags6, 1),
mirroringId: _byte.default.getFlag(flags6, 3) ? "FOUR_SCREEN" : _byte.default.getFlag(flags6, 0) ? "VERTICAL" : "HORIZONTAL",
mapperId: _byte.default.buildU8(_byte.default.highNybbleOf(flags7), _byte.default.highNybbleOf(flags6))
};
}
}, {
key: "_checkMagicConstant",
value: function _checkMagicConstant() {
if (this.bytes[0] !== 0x4e || this.bytes[1] !== 0x45 || this.bytes[2] !== 0x53 || this.bytes[3] !== 0x1a) {
throw new Error("Invalid ROM.");
}
}
}]);
return Cartridge;
}();
exports.default = Cartridge;