| break; | break; | ||||
| case NESBank.ACCESSMODE_2K: | case NESBank.ACCESSMODE_2K: | ||||
| res.side = Math.floor(off * 0.5); | res.side = Math.floor(off * 0.5); | ||||
| res.tileidx = (res.side*32) + ((Math.floor(y/8) * 16) + Math.floor(x / 8)); | |||||
| off -= (off > 1) ? 2 : 0; | |||||
| res.tileidx = (off*128) + ((Math.floor(y/8) * 16) + Math.floor(x / 8)); | |||||
| break; | break; | ||||
| case NESBank.ACCESSMODE_1K: | case NESBank.ACCESSMODE_1K: | ||||
| res.side = Math.floor(off * 0.25); | res.side = Math.floor(off * 0.25); | ||||
| off -= (off > 3) ? 4 : 0; | off -= (off > 3) ? 4 : 0; | ||||
| res.tileidx = (off * 16) + ((Math.floor(y/8) * 16) + Math.floor(x / 8)); | |||||
| res.tileidx = (off * 64) + ((Math.floor(y/8) * 16) + Math.floor(x / 8)); | |||||
| break; | break; | ||||
| } | } | ||||
| return res; | return res; | ||||
| } | } | ||||
| function LRIdx2TileIdxCo(index, lid){ | |||||
| if (isNaN(lid) || lid < 0 || lid > 2){ | |||||
| lid = 2; | |||||
| } | |||||
| var res = { | |||||
| lid: 0, | |||||
| index: 0, | |||||
| x: 0, | |||||
| y: 0 | |||||
| }; | |||||
| var w = (lid == 2) ? 256 : 128; | |||||
| var x = Math.floor(index % w); | |||||
| var y = Math.floor(index / w); | |||||
| if (x < 128){ | |||||
| res.index = (Math.floor(y/8) * 16) + Math.floor(x / 8); | |||||
| if (lid !== 2) | |||||
| res.lid = lid; | |||||
| } else { | |||||
| res.index = (Math.floor(y/8) * 16) + Math.floor((x - 128) / 8); | |||||
| res.lid = 1; | |||||
| function AdjOffsetToNewMode(nmode, omode, ooff){ | |||||
| // NOTE: 8K never shows up because it will ALWAYS return an offset of 0, so it's easier to just let it all fall through | |||||
| // to the default return value. | |||||
| switch(nmode){ | |||||
| case NESBank.ACCESSMODE_4K: | |||||
| if (ooff > 1){ | |||||
| switch(omode){ | |||||
| case NESBank.ACCESSMODE_2K: | |||||
| return Math.floor(ooff * 0.5); | |||||
| case NESBank.ACCESSMODE_1K: | |||||
| return Math.floor(ooff * 0.25); | |||||
| } | |||||
| } | |||||
| return ooff; | |||||
| case NESBank.ACCESSMODE_2K: | |||||
| switch(omode){ | |||||
| case NESBank.ACCESSMODE_4K: | |||||
| return ooff * 2; | |||||
| case NESBank.ACCESSMODE_1K: | |||||
| return Math.floor(ooff * 0.5); | |||||
| } | |||||
| break; | |||||
| case NESBank.ACCESSMODE_1K: | |||||
| switch(omode){ | |||||
| case NESBank.ACCESSMODE_4K: | |||||
| return ooff * 4; | |||||
| case NESBank.ACCESSMODE_2K: | |||||
| return ooff * 2; | |||||
| } | |||||
| break; | |||||
| } | } | ||||
| res.x = x % 8; | |||||
| res.y = y % 8; | |||||
| return res; | |||||
| return 0; | |||||
| } | } | ||||
| set access_mode(m){ | set access_mode(m){ | ||||
| if (!Utils.isInt(m)) | if (!Utils.isInt(m)) | ||||
| throw new TypeError("Access mode expected to be integer."); | throw new TypeError("Access mode expected to be integer."); | ||||
| var oam = this.__AccessMode; | |||||
| switch(m){ | switch(m){ | ||||
| case NESBank.ACCESSMODE_8K: | case NESBank.ACCESSMODE_8K: | ||||
| this.__AccessMode = NESBank.ACCESSMODE_8K; | this.__AccessMode = NESBank.ACCESSMODE_8K; | ||||
| this.__AccessOffset = 0; | |||||
| break; | break; | ||||
| case NESBank.ACCESSMODE_4K: | |||||
| if (this.__AccessOffset > 1){ | |||||
| switch(this.__AccessMode){ | |||||
| case NESBank.ACCESSMODE_2K: | |||||
| this.__AccessOffset = Math.floor(this.__AccessOffset * 0.5); | |||||
| break; | |||||
| case NESBank.ACCESSMODE_1K: | |||||
| this.__AccessOffset = Math.floor(this.__AccessOffset * 0.25); | |||||
| break; | |||||
| } | |||||
| } | |||||
| case NESBank.ACCESSMODE_4K: | |||||
| this.__AccessMode = NESBank.ACCESSMODE_4K | this.__AccessMode = NESBank.ACCESSMODE_4K | ||||
| break; | break; | ||||
| case NESBank.ACCESSMODE_2K: | |||||
| switch(this.__AccessMode){ | |||||
| case NESBank.ACCESSMODE_8K: | |||||
| this.__AccessOffset = 0; | |||||
| break; | |||||
| case NESBank.ACCESSMODE_4K: | |||||
| this.__AccessOffset *= 2; | |||||
| break; | |||||
| case NESBank.ACCESSMODE_1K: | |||||
| this.__AccessOffset = Math.floor(this.__AccessOffset * 0.5); | |||||
| break; | |||||
| } | |||||
| case NESBank.ACCESSMODE_2K: | |||||
| this.__AccessMode = NESBank.ACCESSMODE_2K; | this.__AccessMode = NESBank.ACCESSMODE_2K; | ||||
| break; | break; | ||||
| case NESBank.ACCESSMODE_1K: | case NESBank.ACCESSMODE_1K: | ||||
| switch(this.__AccessMode){ | |||||
| case NESBank.ACCESSMODE_8K: | |||||
| this.__AccessOffset = 0; | |||||
| break; | |||||
| case NESBank.ACCESSMODE_4K: | |||||
| this.__AccessOffset *= 4; | |||||
| break; | |||||
| case NESBank.ACCESSMODE_2K: | |||||
| this.__AccessOffset *= 2; | |||||
| break; | |||||
| } | |||||
| this.__AccessMode = NESBank.ACCESSMODE_1K; | this.__AccessMode = NESBank.ACCESSMODE_1K; | ||||
| break; | break; | ||||
| default: | default: | ||||
| throw new ValueError("Unknown Access Mode."); | throw new ValueError("Unknown Access Mode."); | ||||
| } | } | ||||
| this.__AccessOffset = AdjOffsetToNewMode(m, oam, this.__AccessOffset); | |||||
| if (this.__emitsEnabled) | if (this.__emitsEnabled) | ||||
| this.emit("data_changed"); | this.emit("data_changed"); | ||||
| } | } | ||||
| get access_offset(){return this.__AccessOffset;} | get access_offset(){return this.__AccessOffset;} | ||||
| set access_offset(o){ | set access_offset(o){ | ||||
| if (!Utils.isInt(m)) | |||||
| if (!Utils.isInt(o)) | |||||
| throw new TypeError("Access offset expected to be integer."); | throw new TypeError("Access offset expected to be integer."); | ||||
| switch (this.__AccessMode){ | switch (this.__AccessMode){ | ||||
| case NESBank.ACCESSMODE_8K: | case NESBank.ACCESSMODE_8K: | ||||
| break; | break; | ||||
| } | } | ||||
| this.__AccessOffset = m; | |||||
| this.__AccessOffset = o; | |||||
| if (this.__emitsEnabled) | if (this.__emitsEnabled) | ||||
| this.emit("data_changed"); | this.emit("data_changed"); | ||||
| } | } | ||||
| return buff; | return buff; | ||||
| } | } | ||||
| /*set chr(buff){ | |||||
| set chr(buff){ | |||||
| if (!(buff instanceof Uint8Array)) | if (!(buff instanceof Uint8Array)) | ||||
| throw new TypeError("Expected Uint8Array buffer."); | throw new TypeError("Expected Uint8Array buffer."); | ||||
| if (buff.length !== 8192) | |||||
| throw new RangeError("Data buffer has invalid byte length."); | |||||
| var offset = 0; | |||||
| this.__LP.forEach((i) => { | |||||
| i.chr = buff.slice(offset, offset+15); | |||||
| offset += 16; | |||||
| }); | |||||
| this.__RP.forEach((i) => { | |||||
| i.chr = buff.slice(offset, offset+15); | |||||
| offset += 16; | |||||
| }); | |||||
| }*/ | |||||
| this.setCHR(buff); | |||||
| } | |||||
| get base64(){ | get base64(){ | ||||
| var b = ""; | var b = ""; | ||||
| } | } | ||||
| setCHR(buff, offset){ | setCHR(buff, offset){ | ||||
| if (!Utils.isInt(offset) || offset < 0) | |||||
| offset = 0; | |||||
| if (!Utils.isInt(offset)) | |||||
| offset = -1; | |||||
| var idx = 0; | var idx = 0; | ||||
| switch(buff.length){ | switch(buff.length){ | ||||
| case 8192: | case 8192: | ||||
| if (offset < 0) | |||||
| offset = AdjOffsetToNewMode(NESBank.ACCESSMODE_8K, this.__AccessMode, this.__AccessOffset); | |||||
| this.__LP.forEach((i) => { | this.__LP.forEach((i) => { | ||||
| i.chr = buff.slice(idx, idx+15); | |||||
| i.chr = buff.slice(idx, idx+16); | |||||
| idx += 16; | idx += 16; | ||||
| }); | }); | ||||
| this.__RP.forEach((i) => { | this.__RP.forEach((i) => { | ||||
| i.chr = buff.slice(idx, idx+15); | |||||
| i.chr = buff.slice(idx, idx+16); | |||||
| idx += 16; | idx += 16; | ||||
| }); | }); | ||||
| break; | break; | ||||
| case 4096: | case 4096: | ||||
| if (offset < 0) | |||||
| offset = AdjOffsetToNewMode(NESBank.ACCESSMODE_4K, this.__AccessMode, this.__AccessOffset); | |||||
| if (offset >= 2) | if (offset >= 2) | ||||
| throw new RangeError("Offset mismatch based on Buffer length."); | throw new RangeError("Offset mismatch based on Buffer length."); | ||||
| var list = (offset === 0) ? this.__LP : this.__RP; | var list = (offset === 0) ? this.__LP : this.__RP; | ||||
| list.forEach((i) => { | list.forEach((i) => { | ||||
| i.chr = buff.slice(idx, idx+15); | |||||
| i.chr = buff.slice(idx, idx+16); | |||||
| idx += 16; | idx += 16; | ||||
| }); | }); | ||||
| break; | break; | ||||
| case 2048: | case 2048: | ||||
| if (offset < 0) | |||||
| offset = AdjOffsetToNewMode(NESBank.ACCESSMODE_2K, this.__AccessMode, this.__AccessOffset); | |||||
| if (offset >= 4) | if (offset >= 4) | ||||
| throw new RangeError("Offset mismatch based on Buffer length."); | throw new RangeError("Offset mismatch based on Buffer length."); | ||||
| var list = (offset < 2) ? this.__LP : this.__RP; | var list = (offset < 2) ? this.__LP : this.__RP; | ||||
| var s = Math.floor(offset * 0.5) * 128; | var s = Math.floor(offset * 0.5) * 128; | ||||
| var e = s + 128; | var e = s + 128; | ||||
| for (let i=s; i < e; i++){ | for (let i=s; i < e; i++){ | ||||
| list[i].chr = buff.slice(idx, idx+15); | |||||
| list[i].chr = buff.slice(idx, idx+16); | |||||
| idx += 16; | idx += 16; | ||||
| } | } | ||||
| break; | break; | ||||
| case 1024: | case 1024: | ||||
| if (offset < 0) | |||||
| offset = AdjOffsetToNewMode(NESBank.ACCESSMODE_1K, this.__AccessMode, this.__AccessOffset); | |||||
| if (offset >= 8) | if (offset >= 8) | ||||
| throw new RangeError("Offset mismatch based on Buffer length."); | throw new RangeError("Offset mismatch based on Buffer length."); | ||||
| var list = (offset < 4) ? this.__LP : this.__RP; | var list = (offset < 4) ? this.__LP : this.__RP; | ||||
| var s = Math.floor(this.__AccessOffset * 0.25) * 64; | var s = Math.floor(this.__AccessOffset * 0.25) * 64; | ||||
| var e = s + 64; | var e = s + 64; | ||||
| for (let i=s; i < e; i++){ | for (let i=s; i < e; i++){ | ||||
| list[i].chr = buff.slice(idx, idx+15); | |||||
| list[i].chr = buff.slice(idx, idx+16); | |||||
| idx += 16; | idx += 16; | ||||
| } | } | ||||
| break; | break; |