mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-16 17:30:27 +00:00
AddressDecoder
This commit is contained in:
parent
f649f0ec03
commit
dfbd584207
22
src/emu.js
22
src/emu.js
@ -643,3 +643,25 @@ function padBytes(data, len) {
|
|||||||
r.mem.set(data);
|
r.mem.set(data);
|
||||||
return r.mem;
|
return r.mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: better performance, check values
|
||||||
|
function AddressDecoder(table) {
|
||||||
|
var self = this;
|
||||||
|
function makeFunction(lo, hi) {
|
||||||
|
var s = "";
|
||||||
|
for (var i=0; i<table.length; i++) {
|
||||||
|
var entry = table[i];
|
||||||
|
var start = entry[0];
|
||||||
|
var end = entry[1];
|
||||||
|
var mask = entry[2];
|
||||||
|
var func = entry[3];
|
||||||
|
self['__fn'+i] = func;
|
||||||
|
s += "if (a>=" + start + " && a<="+end + "){";
|
||||||
|
s += "a&="+(mask?mask:0xffff)+";";
|
||||||
|
s += "return this.__fn"+i+"(a,v)&0xff;}\n";
|
||||||
|
}
|
||||||
|
s += "return 0;"; // TODO: noise()?
|
||||||
|
return new Function('a', 'v', s);
|
||||||
|
}
|
||||||
|
return makeFunction(0x0, 0xffff).bind(self);
|
||||||
|
}
|
||||||
|
@ -150,72 +150,24 @@ var GalaxianPlatform = function(mainElement) {
|
|||||||
oram = new RAM(0x100);
|
oram = new RAM(0x100);
|
||||||
outlatches = new RAM(0x8);
|
outlatches = new RAM(0x8);
|
||||||
membus = {
|
membus = {
|
||||||
read: function(address) {
|
read: new AddressDecoder([
|
||||||
if (address < 0x4000) {
|
[0x0000, 0x3fff, 0, function(a) { return rom ? rom[a] : null; }],
|
||||||
return (rom ? rom[address] : 0) & 0xff;
|
[0x4000, 0x47ff, 0x3ff, function(a) { return ram.mem[a]; }],
|
||||||
} else if (address < 0x4800) {
|
[0x5000, 0x57ff, 0x3ff, function(a) { return vram.mem[a]; }],
|
||||||
address &= 0x3ff;
|
[0x5800, 0x5fff, 0xff, function(a) { return oram.mem[a]; }],
|
||||||
return ram.mem[address] & 0xff;
|
[0x6000, 0x6000, 0, function(a) { return inputs[0]; }],
|
||||||
} else if (address >= 0x5000 && address < 0x5800) {
|
[0x6800, 0x6800, 0, function(a) { return inputs[1]; }],
|
||||||
address &= 0x3ff;
|
[0x7000, 0x7000, 0, function(a) { return inputs[2]; }],
|
||||||
return vram.mem[address] & 0xff;
|
[0x7800, 0x7800, 0, function(a) { watchdog_counter = INITIAL_WATCHDOG; }],
|
||||||
} else if (address >= 0x5800 && address < 0x6000) {
|
]),
|
||||||
address &= 0xff;
|
write: new AddressDecoder([
|
||||||
return oram.mem[address] & 0xff;
|
[0x4000, 0x47ff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
|
||||||
} else if (address >= 0x6000 && address < 0x6800) {
|
[0x5000, 0x57ff, 0x3ff, function(a,v) { vram.mem[a] = v; }],
|
||||||
address &= 0x7;
|
[0x5800, 0x5fff, 0xff, function(a,v) { oram.mem[a] = v; }],
|
||||||
switch (address) {
|
[0x6000, 0x67ff, 0x7, function(a,v) { outlatches.mem[a] = v; }],
|
||||||
case 0:
|
[0x7001, 0x7001, 0, function(a,v) { interruptEnabled = v; }],
|
||||||
return inputs[0];
|
[0x7004, 0x7004, 0, function(a,v) { starsEnabled = v; }],
|
||||||
}
|
]),
|
||||||
} else if (address >= 0x6800 && address < 0x7000) {
|
|
||||||
return inputs[1];
|
|
||||||
} else if (address >= 0x7000 && address < 0x7800) {
|
|
||||||
address &= 0x7;
|
|
||||||
switch (address) {
|
|
||||||
case 0:
|
|
||||||
return inputs[2];
|
|
||||||
}
|
|
||||||
} else if (address >= 0x7800 && address < 0x8000) {
|
|
||||||
watchdog_counter = INITIAL_WATCHDOG;
|
|
||||||
} else {
|
|
||||||
console.log("read", hex(address));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
write: function(address, value) {
|
|
||||||
//console.log("write", hex(address,4), hex(value,2));
|
|
||||||
if (address >= 0x4000 && address < 0x4800) {
|
|
||||||
address &= 0x3ff;
|
|
||||||
ram.mem[address] = value;
|
|
||||||
} else if (address >= 0x5000 && address < 0x5800) {
|
|
||||||
address &= 0x3ff;
|
|
||||||
vram.mem[address] = value;
|
|
||||||
} else if (address >= 0x5800 && address < 0x6000) {
|
|
||||||
address &= 0xff;
|
|
||||||
oram.mem[address] = value;
|
|
||||||
} else if (address >= 0x6000 && address < 0x6800) {
|
|
||||||
address &= 0x7;
|
|
||||||
outlatches.mem[address] = value;
|
|
||||||
} else if (address >= 0x6800 && address < 0x7000) {
|
|
||||||
address &= 0x7;
|
|
||||||
// TODO: sound
|
|
||||||
} else if (address >= 0x7000 && address < 0x7800) {
|
|
||||||
address &= 0x7;
|
|
||||||
switch (address) {
|
|
||||||
case 1:
|
|
||||||
interruptEnabled = value;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
starsEnabled = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (address >= 0x7800 && address < 0x8000) {
|
|
||||||
// TODO: sound
|
|
||||||
} else {
|
|
||||||
console.log("write", hex(address), hex(value));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isContended: function() { return false; },
|
isContended: function() { return false; },
|
||||||
};
|
};
|
||||||
iobus = {
|
iobus = {
|
||||||
@ -323,7 +275,7 @@ var GalaxianPlatform = function(mainElement) {
|
|||||||
watchdog_counter = state.wdc;
|
watchdog_counter = state.wdc;
|
||||||
interruptEnabled = state.ie;
|
interruptEnabled = state.ie;
|
||||||
starsEnabled = state.se;
|
starsEnabled = state.se;
|
||||||
frameCounter = fc;
|
frameCounter = state.fc;
|
||||||
inputs[0] = state.in0;
|
inputs[0] = state.in0;
|
||||||
inputs[1] = state.in1;
|
inputs[1] = state.in1;
|
||||||
inputs[2] = state.in2;
|
inputs[2] = state.in2;
|
||||||
@ -356,7 +308,6 @@ var GalaxianPlatform = function(mainElement) {
|
|||||||
this.pause = function() {
|
this.pause = function() {
|
||||||
timer.stop();
|
timer.stop();
|
||||||
audio.stop();
|
audio.stop();
|
||||||
console.log(JSON.stringify(this.saveState()));
|
|
||||||
}
|
}
|
||||||
this.resume = function() {
|
this.resume = function() {
|
||||||
timer.start();
|
timer.start();
|
||||||
|
@ -46,29 +46,20 @@ var SpaceInvadersPlatform = function(mainElement) {
|
|||||||
ram = new RAM(0x2000);
|
ram = new RAM(0x2000);
|
||||||
displayPCs = new Uint16Array(new ArrayBuffer(0x2000*2));
|
displayPCs = new Uint16Array(new ArrayBuffer(0x2000*2));
|
||||||
membus = {
|
membus = {
|
||||||
read: function(address) {
|
read: new AddressDecoder([
|
||||||
if (address < 0x2000) {
|
[0x0000, 0x1fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }],
|
||||||
return (rom ? rom[address] : 0) & 0xff;
|
[0x2000, 0x3fff, 0x1fff, function(a) { return ram.mem[a]; }],
|
||||||
} else {
|
]),
|
||||||
address &= 0x1fff;
|
write: new AddressDecoder([
|
||||||
return ram.mem[address] & 0xff;
|
[0x2000, 0x23ff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
|
||||||
}
|
[0x2400, 0x3fff, 0x1fff, function(a,v) {
|
||||||
},
|
ram.mem[a] = v;
|
||||||
write: function(address, value) {
|
var ofs = (a - 0x400)<<3;
|
||||||
//console.log("write", hex(address,4), hex(value,2));
|
for (var i=0; i<8; i++)
|
||||||
if (address >= 0x2000) {
|
pixels[ofs+i] = (v & (1<<i)) ? PIXEL_ON : PIXEL_OFF;
|
||||||
address &= 0x1fff;
|
displayPCs[a] = cpu.getPC(); // save program counter
|
||||||
value &= 0xff;
|
}],
|
||||||
ram.mem[address] = value;
|
]),
|
||||||
if (address >= 0x400) {
|
|
||||||
// TODO: dirty flags
|
|
||||||
var ofs = (address - 0x400)*8;
|
|
||||||
for (var i=0; i<8; i++)
|
|
||||||
pixels[ofs+i] = (value & (1<<i)) ? PIXEL_ON : PIXEL_OFF;
|
|
||||||
displayPCs[address] = cpu.getPC(); // save program counter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isContended: function() { return false; },
|
isContended: function() { return false; },
|
||||||
};
|
};
|
||||||
iobus = {
|
iobus = {
|
||||||
|
@ -381,6 +381,7 @@ worker.onmessage = function(e) {
|
|||||||
}
|
}
|
||||||
if (rom_changed || trace_pending_at_pc) {
|
if (rom_changed || trace_pending_at_pc) {
|
||||||
// update editor annotations
|
// update editor annotations
|
||||||
|
// TODO: do incrementally for performance
|
||||||
editor.clearGutter("gutter-info");
|
editor.clearGutter("gutter-info");
|
||||||
editor.clearGutter("gutter-bytes");
|
editor.clearGutter("gutter-bytes");
|
||||||
editor.clearGutter("gutter-offset");
|
editor.clearGutter("gutter-offset");
|
||||||
|
33
test/cli/testdecoder.js
Normal file
33
test/cli/testdecoder.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
var vm = require('vm');
|
||||||
|
var fs = require('fs');
|
||||||
|
var includeInThisContext = function(path) {
|
||||||
|
var code = fs.readFileSync(path);
|
||||||
|
vm.runInThisContext(code, path);
|
||||||
|
};
|
||||||
|
|
||||||
|
includeInThisContext("src/emu.js");
|
||||||
|
|
||||||
|
function assert(b, msg) {
|
||||||
|
if (!b) { throw new Error(msg); }
|
||||||
|
}
|
||||||
|
function assertEquals(a,b) {
|
||||||
|
assert(a==b, a + " != " + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Test address decoder', function() {
|
||||||
|
it('Should work empty', function() {
|
||||||
|
var decoder = new AddressDecoder([]);
|
||||||
|
assertEquals(0, decoder(0x1234));
|
||||||
|
assertEquals(0, decoder(0x123456));
|
||||||
|
});
|
||||||
|
it('Should work with 1 range', function() {
|
||||||
|
var decoder = new AddressDecoder([
|
||||||
|
[0x1000, 0x7fff, 0xff, function(a) { return a+2; }]
|
||||||
|
]);
|
||||||
|
assertEquals(0, decoder(0xfff));
|
||||||
|
assertEquals(2, decoder(0x1000));
|
||||||
|
assertEquals(1, decoder(0x7fff));
|
||||||
|
assertEquals(0, decoder(0x8000));
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user