ソースを参照

Memory class is now being treated as an interface. Bank takes the place of Memory and Bank extends Memory. MMC also extends Memory.

master
Bryan Miller 5年前
コミット
99c67da1bf
3個のファイルの変更90行の追加71行の削除
  1. +60
    -0
      src/bank.js
  2. +6
    -48
      src/memory.js
  3. +24
    -23
      src/mmc.js

+ 60
- 0
src/bank.js ファイルの表示

@@ -0,0 +1,60 @@

var Memory = require('src/memory');

class Bank extends Memory{
constructor(size, ro){
super();
this.__ro = (ro === true);
this.__map = null;
this.__addr = 0;
if (size > 0){
this.__map = new Uint8Array(size);
}
this.__listeners = {};
}

get size(){return (this.__map) ? this.__map.length : 0;}

get address(){return this.__addr;}
set address(a){
if (this.__map)
this.__addr = Math.min(this.__map.length, Math.max(0, a));
}

get byte(){return (this.__map) ? this.__map[this.__addr] : -1;}
set byte(b){
if (!this.__ro && this.__map){
this.__map[this.__addr] = b;
if (this.__addr in this.__listeners)
this.__listeners[this.__addr].forEach((fn)=>{fn(b);});
}
}

onAddressWrite(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
if (typeof(fn) !== 'function')
throw new TypeErrpr("Expected a callback function.");
if (!(addr in this.__listeners))
this.__listeners[addr] = [];
// WARNING: Not testing to see if using the same function more than once.
this.__listeners[addr].push(fn);
}

// This method is intended for the emulator to fill a Read-Only memory module with data prior to
// the start of execution. This method should never be used in a running system.
sysStore(address, data){
if (this.__map){
let dc = data;
if (address < 0 || address >= this.__map.length)
throw new RangeError("Memory address out of range.");
if (this.__map.length - address < dc.length)
dc = dc.slice(0, this.__map.length - address);
this.__map.set(address, dc);
return dc.length;
}
}
}


module.exports = Bank;

+ 6
- 48
src/memory.js ファイルの表示

@@ -1,57 +1,15 @@


class Memory{
constructor(size, ro){
this.__ro = (ro === true);
this.__map = null;
this.__addr = 0;
if (size > 0){
this.__map = new Uint8Array(size);
}
this.__listeners = {};
}
constructor(){}

get size(){return (this.__map) ? this.__map.length : 0;}
get size(){return 0;}

get address(){return this.__addr;}
set address(a){
if (this.__map)
this.__addr = Math.min(this.__map.length, Math.max(0, a));
}
get address(){return 0;}
set address(a){}

get byte(){return (this.__map) ? this.__map[this.__addr] : -1;}
set byte(b){
if (!this.__ro && this.__map){
this.__map[this.__addr] = b;
if (this.__addr in this.__listeners)
this.__listeners[this.__addr].forEach((fn)=>{fn(b);});
}
}

onAddressWrite(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
if (typeof(fn) !== 'function')
throw new TypeErrpr("Expected a callback function.");
if (!(addr in this.__listeners))
this.__listeners[addr] = [];
// WARNING: Not testing to see if using the same function more than once.
this.__listeners[addr].push(fn);
}

// This method is intended for the emulator to fill a Read-Only memory module with data prior to
// the start of execution. This method should never be used in a running system.
sysStore(address, data){
if (this.__map){
let dc = data;
if (address < 0 || address >= this.__map.length)
throw new RangeError("Memory address out of range.");
if (this.__map.length - address < dc.length)
dc = dc.slice(0, this.__map.length - address);
this.__map.set(address, dc);
return dc.length;
}
}
get byte(){return -1;}
set byte(b){}
}



+ 24
- 23
src/mmc.js ファイルの表示

@@ -1,7 +1,7 @@

var Memory = require('chip/memory');
var Memory = require('src/memory');

class Bank{
class Switch{
constructor(mem){
this.__mem = [mem];
this.__idx = 0;
@@ -28,60 +28,61 @@ class Bank{



class MMC{
class MMC extends Memory{
constructor(){
this.__banks = [];
super();
this.__switches = [];
this.__addr = 0;
this.__bnkidx = 0;
this.__sidx = 0;
}

get size(){
return this.__banks.reduce((acc, b)=>{
acc += b.mem.size;
return this.__switches.reduce((acc, s)=>{
acc += s.mem.size;
}, 0);
}

get banks(){return this.__banks.length;}
get switches(){return this.__switches.length;}

get address(){return this.__addr;}
set address(a){
if (a >= 0 && a < this.size){
this.__addr = a;
offset = 0;
for (let b=0; b < this.__banks.length; b++){
if (a >= offset && a < offset + this.__banks[b].mem.size){
this.__bnkidx = b;
this.__banks[b].mem.address = a - offset;
for (let s=0; s < this.__switches.length; s++){
if (a >= offset && a < offset + this.__switches[s].mem.size){
this.__sidx = b;
this.__switches[s].mem.address = a - offset;
break;
} else {
offset += this.__banks[b].mem.size;
offset += this.__switches[s].mem.size;
}
}
}
}

get byte(){return (this.__banks.length > 0) ? this.__banks[this.__bnkidx].mem.byte : -1;}
get byte(){return (this.__switches.length > 0) ? this.__switches[this.__sidx].mem.byte : -1;}
set byte(b){
if (this.__banks.length > 0){
this.__banks[this.__bnkidx].mem.byte = b;
if (this.__switches.length > 0){
this.__switches[this.__sidx].mem.byte = b;
}
}

connectMemory(mem, addroff){
addroff = (typeof(addroff) === 'number' && addroff >= 0) ? addroff : -1;
if (addroff < 0 || addroff === this.size){
this.__banks.push(new Bank(mem));
this.__switches.push(new Switch(mem));
} else {
offset = 0;
for (let b=0; b < this.__banks.length; b++){
for (let s=0; s < this.__switches.length; s++){
if (addroff === offset){
if (this.__banks[b].mem.size !== mem.size)
if (this.__switches[s].mem.size !== mem.size)
throw new RangeError("Memory modules assigned to the same bank must be the same byte size.");
this.__banks[b].addMemModule(mem);
this.__switches[s].addMemModule(mem);
offset = -1;
break;
} else {
offset += this.__banks[b].mem.size;
offset += this.__switches[s].mem.size;
}
}
if (offset >= 0)
@@ -93,8 +94,8 @@ class MMC{
mmSwitchRegister(){
return (function(byte){
let mmcidx = (byte & 0xF0) >> 4;
if (mmcidx < this.__banks.length){
this.__banks[mmcidx].idx = (byte & 0x0F);
if (mmcidx < this.__switches.length){
this.__switches[mmcidx].idx = (byte & 0x0F);
}
}).bind(this);
}

読み込み中…
キャンセル
保存