浏览代码

Broke up the src/memory/memory.js file into rom, ram, and shadow. Updated src/memory/index.js and tests as needed.

master
Bryan Miller 5 年前
父节点
当前提交
2784031e8a
共有 7 个文件被更改,包括 250 次插入231 次删除
  1. +3
    -1
      src/memory/index.js
  2. +0
    -219
      src/memory/memory.js
  3. +51
    -0
      src/memory/ram.js
  4. +80
    -0
      src/memory/rom.js
  5. +105
    -0
      src/memory/shadow.js
  6. +1
    -1
      test/unit.src.MOS.6502.cpu.spec.js
  7. +10
    -10
      test/unit.src.memory.spec.js

+ 3
- 1
src/memory/index.js 查看文件

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


module.exports = Object.freeze({
Memory: require("./memory.js"),
ROM: require("./rom.js"),
RAM: require("./ram.js"),
Shadow: require("./shadow.js"),
MMC: require("./mmc.js"),
IMem: require("./imem.js")
});

+ 0
- 219
src/memory/memory.js 查看文件

@@ -1,219 +0,0 @@

const IO = require('../io.js');
const IMem = require('./imem');


class ROM extends IMem{
constructor(pages){
if (pages < 1)
throw new RangeError("Memory requires positive page values.");
super();
this.__addr = 0;
this.__map = new Uint8Array(pages * 256);
// Allow writable events because RAM will inherit ROM and use the same
// __io object.
this.__io = new IO([], []);
}

get pages(){return this.__map.length / 256;}
get size(){return this.__map.length;}

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

get byte(){
this.__io.triggerRead(this.__addr);
return this.__map[this.__addr];
}
set byte(b){}


onAddressRead(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
this.__io.onRead(addr, fn);
return this;
}


peek(a){
a = Math.min(this.__map.length - 1, Math.max(0, a));
return this.__map[a];
}


load(address, data){
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(dc, address);
return dc.length;
}


clearPage(page){
let addr = (page << 8) & 0xFF00;
if (addr < 0 || addr >= this.__map.length)
throw new RangeError("Memory address out of range.");
this.__map.fill(0, addr, addr + 256);
return this;
}


clear(){
this.__map.fill(0);
return this;
}
}



class RAM extends ROM {
constructor(pages){
super(pages);
}

get pages(){return this.__map.length/256;}
get size(){return this.__map.length;}
get writable(){return true;}


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

get byte(){
this.__io.triggerRead(this.__addr);
return this.__map[this.__addr];
}
set byte(b){
this.__map[this.__addr] = b & 0xFF;
this.__io.triggerWrite(this.__addr, b & 0xFF);
}

onAddressWrite(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
this.__io.onWrite(addr, fn);
return this;
}

poke(a, b){
a = Math.min(this.__map.length - 1, Math.max(0, a));
this.__map[a] = b & 0xFF;
return this;
}
}


class Shadow extends IMem {
constructor(pages, rbc){
if (rbc > (pages * 256))
throw RangeError("Register Byte Count exceeds available pages defined.");
super();
this.__map = new Uint8Array(rbc);
this.__addr = 0;
this.__size = pages * 256;

this.__io = new IO([], []);
}

get pages(){return this.__size/256;}
get size(){return this.__size;}
get registers(){return this.__map.length;}
get writable(){return true;}

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

get byte(){
let a = this.__addr % this.__map.length;
this.__io.triggerRead(this.__addr);
return this.__map[a];
}
set byte(b){
if (this.__addr >= 0 && this.__addr < this.__map.length){
this.__map[this.__addr] = b & 0xFF;
this.__io.triggerWrite(this.__addr, b & 0xFF);
}
}

onAddressRead(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
this.__io.onRead(addr, fn);
return this;
}

onAddressWrite(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
let a = this.__addr % this.__map.length;
this.__io.onWrite(a, fn);
return this;
}

peek(a){
a = Math.min(this.__size - 1, Math.max(0, a)) % this.__map.length;
return this.__map[a];
}

poke(a, b){
if (a >= 0 && a < this.__map.length)
this.__map[a] = b & 0xFF;
return this;
}

load(addr, data){
let dc = data;
if (addr < 0 || addr >= this.__size)
throw new RangeError("Memory address out of range.");
// We simply quit here because, while it's legal to try to write,
// there's actually no memory at this point. We're playing pretend :p
if (addr >= this.__map.length){return 0;}

if (this.__map.length - addr < dc.length)
dc = dc.slice(0, this.__map.length - addr);
this.__map.set(dc, addr);
return dc.length;
}


clearPage(page){
let addr = (page << 8) & 0xFF00;
if (addr < 0 || addr >= this.__size)
throw new RangeError("Memory address out of range.");
if (addr < this.__map.length){
let end = (addr + 256 <= this.__map.length) ? 256 : this.__map.length - addr;
this.__map.fill(0, addr, end);
}
return this;
}


clear(){
if (this.__map)
this.__map.fill(0);
return this;
}
}


module.exports = Object.freeze({
RAM: RAM,
ROM: ROM,
Shadow: Shadow
});






+ 51
- 0
src/memory/ram.js 查看文件

@@ -0,0 +1,51 @@

const IO = require('../io.js');
const IMem = require('./imem.js');
const ROM = require('./rom.js');


class RAM extends ROM {
constructor(pages){
super(pages);
}

get pages(){return this.__map.length/256;}
get size(){return this.__map.length;}
get writable(){return true;}


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

get byte(){
this.__io.triggerRead(this.__addr);
return this.__map[this.__addr];
}
set byte(b){
this.__map[this.__addr] = b & 0xFF;
this.__io.triggerWrite(this.__addr, b & 0xFF);
}

onAddressWrite(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
this.__io.onWrite(addr, fn);
return this;
}

poke(a, b){
a = Math.min(this.__map.length - 1, Math.max(0, a));
this.__map[a] = b & 0xFF;
return this;
}
}



module.exports = RAM;





+ 80
- 0
src/memory/rom.js 查看文件

@@ -0,0 +1,80 @@

const IO = require('../io.js');
const IMem = require('./imem.js');


class ROM extends IMem{
constructor(pages){
if (pages < 1)
throw new RangeError("Memory requires positive page values.");
super();
this.__addr = 0;
this.__map = new Uint8Array(pages * 256);
// Allow writable events because RAM will inherit ROM and use the same
// __io object.
this.__io = new IO([], []);
}

get pages(){return this.__map.length / 256;}
get size(){return this.__map.length;}

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

get byte(){
this.__io.triggerRead(this.__addr);
return this.__map[this.__addr];
}
set byte(b){}


onAddressRead(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
this.__io.onRead(addr, fn);
return this;
}


peek(a){
a = Math.min(this.__map.length - 1, Math.max(0, a));
return this.__map[a];
}


load(address, data){
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(dc, address);
return dc.length;
}


clearPage(page){
let addr = (page << 8) & 0xFF00;
if (addr < 0 || addr >= this.__map.length)
throw new RangeError("Memory address out of range.");
this.__map.fill(0, addr, addr + 256);
return this;
}


clear(){
this.__map.fill(0);
return this;
}
}



module.exports = ROM;






+ 105
- 0
src/memory/shadow.js 查看文件

@@ -0,0 +1,105 @@

const IO = require('../io.js');
const IMem = require('./imem.js');


class Shadow extends IMem {
constructor(pages, rbc){
if (rbc > (pages * 256))
throw RangeError("Register Byte Count exceeds available pages defined.");
super();
this.__map = new Uint8Array(rbc);
this.__addr = 0;
this.__size = pages * 256;

this.__io = new IO([], []);
}

get pages(){return this.__size/256;}
get size(){return this.__size;}
get registers(){return this.__map.length;}
get writable(){return true;}

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

get byte(){
let a = this.__addr % this.__map.length;
this.__io.triggerRead(this.__addr);
return this.__map[a];
}
set byte(b){
if (this.__addr >= 0 && this.__addr < this.__map.length){
this.__map[this.__addr] = b & 0xFF;
this.__io.triggerWrite(this.__addr, b & 0xFF);
}
}

onAddressRead(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
this.__io.onRead(addr, fn);
return this;
}

onAddressWrite(addr, fn){
if (addr < 0 || addr >= this.size)
throw new RangeError("Memory address is out of bounds.");
let a = this.__addr % this.__map.length;
this.__io.onWrite(a, fn);
return this;
}

peek(a){
a = Math.min(this.__size - 1, Math.max(0, a)) % this.__map.length;
return this.__map[a];
}

poke(a, b){
if (a >= 0 && a < this.__map.length)
this.__map[a] = b & 0xFF;
return this;
}

load(addr, data){
let dc = data;
if (addr < 0 || addr >= this.__size)
throw new RangeError("Memory address out of range.");
// We simply quit here because, while it's legal to try to write,
// there's actually no memory at this point. We're playing pretend :p
if (addr >= this.__map.length){return 0;}

if (this.__map.length - addr < dc.length)
dc = dc.slice(0, this.__map.length - addr);
this.__map.set(dc, addr);
return dc.length;
}


clearPage(page){
let addr = (page << 8) & 0xFF00;
if (addr < 0 || addr >= this.__size)
throw new RangeError("Memory address out of range.");
if (addr < this.__map.length){
let end = (addr + 256 <= this.__map.length) ? 256 : this.__map.length - addr;
this.__map.fill(0, addr, end);
}
return this;
}


clear(){
if (this.__map)
this.__map.fill(0);
return this;
}
}


module.exports = Shadow;




+ 1
- 1
test/unit.src.MOS.6502.cpu.spec.js 查看文件

@@ -7,7 +7,7 @@ describe("Testing MOS6502 CPU...", function(){
var asm = new MOS6502.Assembler();
var cpu = new MOS6502.CPU();
var tick = cpu.clk();
cpu.memory = new Mem.Memory.RAM(256);
cpu.memory = new Mem.RAM(256);
cpu.memory.load(0xFFFC, [0x00, 0x00]);
it("Resetting (IRQ Disabled flag must be on", function(){

+ 10
- 10
test/unit.src.memory.spec.js 查看文件

@@ -5,8 +5,8 @@ const Mem = require('../src/memory');
describe("Testing Memory Module", function(){
describe("Core Memory Classes...", function(){
describe("ROM Class", function(){
var m1 = new Mem.Memory.ROM(1);
var m2 = new Mem.Memory.ROM(4);
var m1 = new Mem.ROM(1);
var m2 = new Mem.ROM(4);

it("Bytes match 256 byte page sizes", function(){
expect(m1.size).to.equal(256);
@@ -108,8 +108,8 @@ describe("Testing Memory Module", function(){
});

describe("RAM Class", function(){
var m1 = new Mem.Memory.RAM(1);
var m2 = new Mem.Memory.RAM(4);
var m1 = new Mem.RAM(1);
var m2 = new Mem.RAM(4);

it("Bytes match 256 byte page sizes", function(){
expect(m1.size).to.equal(256);
@@ -251,7 +251,7 @@ describe("Testing Memory Module", function(){
});

describe("Shadow Class", function(){
var sm = new Mem.Memory.Shadow(1, 4);
var sm = new Mem.Shadow(1, 4);

it("Bytes Match 256 Size", function(){
expect(sm.size).to.equal(256);
@@ -364,12 +364,12 @@ describe("Testing Memory Module", function(){
var mmc = new Mem.MMC();
var rcb = sinon.fake();
var wcb = sinon.fake();
let m1 = new Mem.Memory.RAM(1);
let m1 = new Mem.RAM(1);
m1.onAddressRead(0x31, rcb);
m1.onAddressWrite(0x31, wcb);
mmc.connectMemory(m1);
mmc.connectMemory(new Mem.Memory.RAM(2));
mmc.connectMemory(new Mem.Memory.RAM(1));
mmc.connectMemory(new Mem.RAM(2));
mmc.connectMemory(new Mem.RAM(1));

it("Reports 4 pages", function(){
expect(mmc.pages).to.equal(4);
@@ -402,7 +402,7 @@ describe("Testing Memory Module", function(){
});

it("Adding Switchable Banks", function(){
let b2 = new Mem.Memory.ROM(1);
let b2 = new Mem.ROM(1);
expect(function(){
mmc.connectMemory(b2, 0x0100);
}).to.throw("Memory modules assigned to the same bank must be the same byte size.");
@@ -417,7 +417,7 @@ describe("Testing Memory Module", function(){
mmc.switchBank(0x00);
expect(mmc.read(0x01)).to.equal(0x02);

mmc.connectMemory(new Mem.Memory.ROM(2), 0x0100);
mmc.connectMemory(new Mem.ROM(2), 0x0100);
expect(mmc.read(0x0115)).to.equal(0x15);
mmc.switchBank(0x11);
expect(mmc.read(0x0115)).to.equal(0x00);

正在加载...
取消
保存