Sfoglia il codice sorgente

Huge rewrite to NESBank. Still some tweaking to be done

dev-bank
Bryan Miller 5 anni fa
parent
commit
6af93698ae
1 ha cambiato i file con 299 aggiunte e 47 eliminazioni
  1. +299
    -47
      app/js/models/NESBank.js

+ 299
- 47
app/js/models/NESBank.js Vedi File

@@ -5,6 +5,41 @@ import NESTile from "/app/js/models/NESTile.js";
import NESPalette from "/app/js/models/NESPalette.js";


function CnvIdx(x, y, am, off){
var res = {
side: 0,
tileidx: 0,
x: 0,
y: 0
}

switch(am){
case NESBank.ACCESSMODE_8K:
res.side = (x > 128) ? 1 : 0;
x -= (res.side === 1) ? 128, 0;
res.tileidx = (Math.floor(y/8) * 16) + Math.floor(x / 8);
break;
case NESBank.ACCESSMODE_4K:
res.side = off;
res.tileidx = (Math.floor(y/8) * 16) + Math.floor(x / 8);
break;
case NESBank.ACCESSMODE_2K:
res.side = Math.floor(off * 0.5);
res.tileidx = (res.side*32) + ((Math.floor(y/8) * 16) + Math.floor(x / 8));
break;
case NESBank.ACCESSMODE_1K:
res.side = Math.floor(off * 0.25);
off -= (off > 3) ? 4 : 0;
res.tileidx = (off * 16) + ((Math.floor(y/8) * 16) + Math.floor(x / 8));
break;
}

res.x = x%8;
res.y = y%8;

return res;
}

function LRIdx2TileIdxCo(index, lid){
if (isNaN(lid) || lid < 0 || lid > 2){
lid = 2;
@@ -31,6 +66,7 @@ function LRIdx2TileIdxCo(index, lid){
return res;
}


export default class NESBank extends ISurface{
constructor(){
super();
@@ -40,18 +76,41 @@ export default class NESBank extends ISurface{
this.__AccessMode = NESBank.ACCESSMODE_8K;
this.__AccessOffset = 0;

var handle_datachanged = Utils.debounce((function(side){
if ((side == 0 && (this.__AccessMode == 0 || this.__AccessMode == 2)) ||
(side == 1 && (this.__AccessMode == 1 || this.__AccessMode == 2))){
this.__emitsEnabled = true;

var handle_datachanged = Utils.debounce((function(side, idx){
var sendEmit = false;
switch(this.__AccessMode){
case NESBank.ACCESSMODE_1K:
if (side === Math.floor(this.__AccessOffset / 4){
if (Math.floor(idx / 64) === Math.floor(this.__AccessOffset/4))
sendEmit = true;
}
break;
case NESBank.ACCESSMODE_2K:
if (side === Math.floor(this.__AccessOffset / 2){
if (Math.floor(idx / 128) === Math.floor(this.__AccessOffset/2))
sendEmit = true;
}
break;
case NESBank.ACCESSMODE_4K:
if (side === this.__AccessOffset)
sendEmit = true;
break;
case NESBank.ACCESSMODE_8K:
sendEmit = true;
}

if (sendEmit && this.__emitsEnabled){
this.emit("data_changed");
}
}).bind(this), 250);

for (var i=0; i < 256; i++){
this.__LP.push(new NESTile());
this.__LP[i].listen("data_changed", handle_datachanged.bind(this, 0));
this.__LP[i].listen("data_changed", handle_datachanged.bind(this, 0, i));
this.__RP.push(new NESTile());
this.__RP[i].listen("data_changed", handle_datachanged.bind(this, 1));
this.__RP[i].listen("data_changed", handle_datachanged.bind(this, 1, i));
}

this.__palette = null;
@@ -62,19 +121,86 @@ export default class NESBank extends ISurface{
if (!Utils.isInt(m))
throw new TypeError("Access mode expected to be integer.");
switch(m){
case NESBank.ACCESSMODE_SPRITE:
this.__AccessMode = NESBank.ACCESSMODE_SPRITE;
this.emit("data_changed");
case NESBank.ACCESSMODE_8K:
this.__AccessMode = NESBank.ACCESSMODE_8K;
this.__AccessOffset = 0;
break;
case NESBank.ACCESSMODE_BACKGROUND:
this.__AccessMode = NESBank.ACCESSMODE_BACKGROUND;
this.emit("data_changed");
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;
}
}
this.__AccessMode = NESBank.ACCESSMODE_4K
break;
case NESBank.ACCESSMODE_FULL:
this.__AccessMode = NESBank.ACCESSMODE_FULL;
this.emit("data_changed");
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;
}
this.__AccessMode = NESBank.ACCESSMODE_2K;
break;
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;
break;

default:
throw new ValueError("Unknown Access Mode.");
}

if (this.__emitsEnabled)
this.emit("data_changed");
}

get access_offset(){return this.__AccessOffset;}
set access_offset(o){
if (!Utils.isInt(m))
throw new TypeError("Access offset expected to be integer.");
switch (this.__AccessMode){
case NESBank.ACCESSMODE_8K:
if (o !== 0)
throw new RangeError("Access Offset is out of bounds based on current Access Mode.");
break;
case NESBank.ACCESSMODE_4K:
if (o !== 0 && o !== 1)
throw new RangeError("Access Offset is out of bounds based on current Access Mode.");
break;
case NESBank.ACCESSMODE_2K:
if (o < 0 || o >= 4)
throw new RangeError("Access Offset is out of bounds based on current Access Mode.");
break;
case NESBank.ACCESSMODE_1K:
if (o < 0 || o >= 8)
throw new RangeError("Access Offset is out of bounds based on current Access Mode.");
break;
}

this.__AccessOffset = m;
if (this.__emitsEnabled)
this.emit("data_changed");
}

get json(){
@@ -85,20 +211,56 @@ export default class NESBank extends ISurface{
}

get chr(){
var buff = new Uint8Array(8192);
var buff = null;
var offset = 0;
this.__LP.forEach(function(i){
buff.set(i.chr, offset);
offset += 16;
});
this.__RP.forEach(function(i){
buff.set(i.chr, offset);
offset += 16;
});
switch (this.__AccessMode){
case NESBank.ACCESSMODE_8K:
buff = new Uint8Array(8192);
this.__LP.forEach((i) => {
buff.set(i.chr, offset);
offset += 16;
});
this.__RP.forEach((i) => {
buff.set(i.chr, offset);
offset += 16;
});
break;

case NESBank.ACCESSMODE_4K:
buff = new Uint8Array(4096);
var list = (this.__AccessOffset === 0) ? this.__LP : this.__RP;
list.forEach((i) => {
buff.set(i.chr, offset);
offset += 16;
});
break;

case NESBank.ACCESSMODE_2K:
buff = new Uint8Array(2048);
var list = (this.__AccessOffset < 2) ? this.__LP : this.__RP;
var s = Math.floor(this.__AccessOffset * 0.5) * 128;
var e = s + 128;
for (let i=s; i < e; i++){
buff.set(list[i].chr, offset);
offset += 16;
}
break;

case NESBank.ACCESSMODE_1K:
buff = new Uint8Array(1024);
var list = (this.__AccessOffset < 4) ? this.__LP : this.__RP;
var s = Math.floor(this.__AccessOffset * 0.25) * 64;
var e = s + 64;
for (let i=s; i < e; i++){
buff.set(list[i].chr, offset);
offset += 16;
}
break;
}
return buff;
}

set chr(buff){
/*set chr(buff){
if (!(buff instanceof Uint8Array))
throw new TypeError("Expected Uint8Array buffer.");
if (buff.length !== 8192)
@@ -112,7 +274,7 @@ export default class NESBank extends ISurface{
i.chr = buff.slice(offset, offset+15);
offset += 16;
});
}
}*/

get base64(){
var b = "";
@@ -141,8 +303,16 @@ export default class NESBank extends ISurface{
}
}

get width(){return (this.__AccessMode == NESBank.ACCESSMODE_FULL) ? 256 : 128;}
get height(){return 128;}
get width(){return (this.__AccessMode == NESBank.ACCESSMODE_8K) ? 256 : 128;}
get height(){
switch(this.__AccessMode){
case NESBank.ACCESSMODE_2K:
return 64;
case NESBank.ACCESSMODE_1K:
return 32;
}
return 128;
}
get length(){return this.width * this.height;}

get coloridx(){
@@ -156,10 +326,12 @@ export default class NESBank extends ISurface{
prop = parseInt(prop);
if (prop < 0 || prop >= len)
return NESPalette.Default[4];
var res = LRIdx2TileIdxCo(prop, this.__AccessMode);
var list = (res.lid === 0) ? obj.__LP : obj.__RP;
return list[res.index].getPixelIndex(res.x, res.y);

var x = Math.floor(prop % this.width);
var y = Math.floor(prop / this.width);
var res = CnvIdx(x, y, this.__AccessMode, this.__AccessOffset);
var list = (res.side === 0) ? obj.__LP : obj.__RP;
return list[res.tileidx].getPixelIndex(res.x, res.y);
},

set:function(obj, prop, value){
@@ -173,10 +345,12 @@ export default class NESBank extends ISurface{
throw new RangeError("Index out of bounds.");
if (value < 0 || value >= 4)
throw new RangeError("Color index out of bounds.");
var res = LRIdx2TileIdxCo(prop, this.__AccessMode);
var list = (res.lid === 0) ? obj.__LP : obj.__RP;
list[res.index].setPixelIndex(res.x, res.y, value);
var x = Math.floor(prop % this.width);
var y = Math.floor(prop / this.width);
var res = CnvIdx(x, y, this.__AccessMode, this.__AccessOffset);
var list = (res.side === 0) ? obj.__LP : obj.__RP;
list[res.tileidx].setPixelIndex(res.x, res.y, value);
return true;
}
});
@@ -250,14 +424,92 @@ export default class NESBank extends ISurface{
return (new NESBank()).copy(this);
}


getCHR(mode, offset){
this.__emitsEnabled = false;
var oam = this.access_mode;
var oao = this.access_offset;

try{
this.access_mode = mode;
this.access_offset = offset;
} catch (e){
this.access_mode = oam;
this.access_offset = oao;
this.__emitsEnabled = true;
throw e;
}

var chr = this.chr;
this.access_mode = oam;
this.access_offset = oao;
this.__emitsEnabled = true;

return chr;
}

setCHR(buff, offset){
if (!Utils.isInt(offset) || offset < 0)
offset = 0;

var idx = 0;
switch(buff.length){
case 8192:
this.__LP.forEach((i) => {
i.chr = buff.slice(idx, idx+15);
idx += 16;
});
this.__RP.forEach((i) => {
i.chr = buff.slice(idx, idx+15);
idx += 16;
});
break;
case 4096:
if (offset >= 2)
throw new RangeError("Offset mismatch based on Buffer length.");
var list = (offset === 0) ? this.__LP : this.__RP;
list.forEach((i) => {
i.chr = buff.slice(idx, idx+15);
idx += 16;
});
break;
case 2048:
if (offset >= 4)
throw new RangeError("Offset mismatch based on Buffer length.");
var list = (offset < 2) ? this.__LP : this.__RP;
var s = Math.floor(offset * 0.5) * 128;
var e = s + 128;
for (let i=s; i < e; i++){
list[i].chr = buff.slice(idx, idx+15);
idx += 16;
}
break;
case 1024:
if (offset >= 8)
throw new RangeError("Offset mismatch based on Buffer length.");
var list = (offset < 4) ? this.__LP : this.__RP;
var s = Math.floor(this.__AccessOffset * 0.25) * 64;
var e = s + 64;
for (let i=s; i < e; i++){
list[i].chr = buff.slice(idx, idx+15);
idx += 16;
}
break;
default:
throw new RangeError("Buffer length does not match any of the supported bank sizes.");
}

return this;
}

getColor(x,y){
if (x < 0 || x >= this.width || y < 0 || y >= this.height)
return this.__default_pi[4];

var res = LRIdx2TileIdxCo((y*this.width)+x, this.__AccessMode);
var list = (res.lid === 0) ? this.__LP : this.__RP;
var pi = list[res.index].paletteIndex + ((res.lid === 0) ? 4 : 0);
var ci = list[res.index].getPixelIndex(res.x, res.y);
var res = CnvIdx(x, y, this.__AccessMode, this.__AccessOffset);
var list = (res.side === 0) ? this.__LP : this.__RP;
var pi = list[res.tileidx].paletteIndex + ((res.side === 0) ? 4 : 0);
var ci = list[res.tileidx].getPixelIndex(res.x, res.y);

if (this.__palette !== null){
return this.__palette.get_palette_color(pi, ci);
@@ -269,11 +521,11 @@ export default class NESBank extends ISurface{
if (x < 0 || x >= this.width || y < 0 || y >= this.height)
return {pi: -1, ci:-1};

var res = LRIdx2TileIdxCo((y*this.width)+x, this.__AccessMode);
var list = (res.lid === 0) ? this.__LP : this.__RP;
var res = CnvIdx(x, y, this.__AccessMode, this.__AccessOffset);
var list = (res.side === 0) ? this.__LP : this.__RP;
return {
pi: list[res.index].paletteIndex,
ci: list[res.index].getPixelIndex(res.x, res.y)
pi: list[res.tileidx].paletteIndex,
ci: list[res.tileidx].getPixelIndex(res.x, res.y)
};
}

@@ -289,11 +541,11 @@ export default class NESBank extends ISurface{
this.coloridx[(y*this.width)+x] = ci;
} else {

var res = LRIdx2TileIdxCo((y*this.width)+x, this.__AccessMode);
var list = (res.lid === 0) ? this.__LP : this.__RP;
var res = CnvIdx(x, y, this.__AccessMode, this.__AccessOffset);
var list = (res.side === 0) ? this.__LP : this.__RP;

list[res.index].paletteIndex = pi;
list[res.index].setPixelIndex(res.x, res.y, ci);
list[res.tileidx].paletteIndex = pi;
list[res.tileidx].setPixelIndex(res.x, res.y, ci);
}
return this;
}

Loading…
Annulla
Salva