diff --git a/index.html b/index.html
index bf8271c6..31c70de9 100644
--- a/index.html
+++ b/index.html
@@ -273,6 +273,12 @@ canvas.pixelated {
+
+
+
+
+
+
diff --git a/src/platform/galaxian.js b/src/platform/galaxian.js
index 36d17f40..052afda9 100644
--- a/src/platform/galaxian.js
+++ b/src/platform/galaxian.js
@@ -12,7 +12,7 @@ var GalaxianPlatform = function(mainElement) {
this.__proto__ = new BaseZ80Platform();
var cpu, ram, vram, oram, membus, iobus, rom, palette, outlatches;
- var video, audio, timer, pixels, displayPCs;
+ var video, audio, timer, pixels;
var inputs = [0xe,0x8,0x0];
var interruptEnabled = 0;
var starsEnabled = 0;
diff --git a/src/platform/konamisound.js b/src/platform/konamisound.js
new file mode 100644
index 00000000..89fef5db
--- /dev/null
+++ b/src/platform/konamisound.js
@@ -0,0 +1,153 @@
+"use strict";
+var KONAMISOUND_PRESETS = [
+];
+
+// TODO: global???
+window.buildZ80({
+ applyContention: false
+});
+
+var KonamiSoundPlatform = function(mainElement) {
+ var self = this;
+ this.__proto__ = new BaseZ80Platform();
+
+ var cpu, ram, rom, membus, iobus;
+ var audio, master;
+ var video, timer;
+ var interruptPending = 0;
+ var psgRegister = 0;
+ var psg;
+
+ var cpuFrequency = 14318000/8;
+ var ioTimerFrequency = 1789750 / 1280;
+ var cpuCyclesPerFrame = cpuFrequency/60;
+ var cpuCyclesPerTimer = cpuFrequency/ioTimerFrequency;
+
+ this.getPresets = function() {
+ return KONAMISOUND_PRESETS;
+ }
+
+ this.start = function() {
+ ram = new RAM(0x400);
+ membus = {
+ read: new AddressDecoder([
+ [0x0000, 0x3fff, 0x1fff, function(a) { return rom ? rom[a] : null; }],
+ [0x4000, 0x5fff, 0x3ff, function(a) { return ram.mem[a]; }]
+ ]),
+ write: new AddressDecoder([
+ [0x4000, 0x5fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
+ [0x6000, 0x6fff, 0, function(a,v) { }],
+ ]),
+ isContended: function() { return false; },
+ };
+ iobus = {
+ read: function(addr) {
+ if (addr & 0x40) {
+ if (psgRegister == 0xf) { // timer
+ var bit = (cpu.getTstates() / cpuCyclesPerTimer) & 1;
+ return bit << 3;
+ }
+ return psg.readRegister(psgRegister) & 0xff;
+ }
+ return 0;
+ },
+ write: function(addr, val) {
+ if (addr & 0x80) {
+ psgRegister = val & 0xf;
+ //console.log('PSG reg', psgRegister);
+ }
+ if (addr & 0x40) {
+ psg.writeRegisterAY(psgRegister, val & 0xff);
+ //console.log('PSG write', psgRegister, val);
+ }
+ }
+ };
+ cpu = window.Z80({
+ display: {},
+ memory: membus,
+ ioBus: iobus
+ });
+ psg = new PsgDeviceChannel();
+ master = new MasterChannel();
+ psg.setMode(PsgDeviceChannel.MODE_SIGNED);
+ psg.setDevice(PsgDeviceChannel.DEVICE_AY_3_8910);
+ master.addChannel(psg);
+ audio = new AudioLooper(512);
+ audio.setChannel(master);
+ //audio = new SampleAudio(psg.sampleRate);
+ video = new RasterVideo(mainElement,256,256);
+ video.create();
+ video.setKeyboardEvents(function(key,code,flags) {
+ var intr = (key-49);
+ if (intr >= 0 && (flags & 1)) {
+ psg.writeRegister(14, intr);
+ psg.writeRegister(15, 0x80);
+ cpu.setIFF1(1);
+ cpu.requestInterrupt(0x38);
+ /*
+ console.log(cpu.saveState());
+ console.log(hex(intr * 8), cpu.getIFF1(), cpu.getIM());
+ cpu.runFrame(cpu.getTstates() + 1);
+ console.log(cpu.saveState());
+ */
+ }
+ });
+ timer = new AnimationTimer(60, function() {
+ if (!self.isRunning())
+ return;
+ var debugCond = self.getDebugCallback();
+ var targetTstates = cpu.getTstates() + cpuCyclesPerFrame;
+ if (debugCond) {
+ while (cpu.getTstates() < targetTstates) {
+ if (debugCond && debugCond()) { debugCond = null; }
+ cpu.runFrame(cpu.getTstates() + 1);
+ }
+ } else {
+ cpu.runFrame(targetTstates);
+ }
+ });
+ }
+
+ this.loadROM = function(title, data) {
+ rom = padBytes(data, 0x4000);
+ cpu.reset();
+ }
+
+ this.loadState = function(state) {
+ cpu.loadState(state.c);
+ ram.mem.set(state.b);
+ }
+ this.saveState = function() {
+ return {
+ c:self.getCPUState(),
+ b:ram.mem.slice(0),
+ };
+ }
+ this.getRAMForState = function(state) {
+ return ram.mem;
+ }
+ this.getCPUState = function() {
+ return cpu.saveState();
+ }
+
+ this.isRunning = function() {
+ return timer.isRunning();
+ }
+ this.pause = function() {
+ timer.stop();
+ //audio.stop();
+ }
+ this.resume = function() {
+ timer.start();
+ audio.activate();
+ }
+ this.reset = function() {
+ cpu.reset();
+ if (!this.getDebugCallback()) cpu.setTstates(0); // TODO?
+ }
+ this.readAddress = function(addr) {
+ return membus.read(addr); // TODO?
+ }
+}
+
+PLATFORMS['konamisound'] = KonamiSoundPlatform;
diff --git a/test/cli/testdecoder.js b/test/cli/testdecoder.js
index 44308fa7..5c3c42ca 100644
--- a/test/cli/testdecoder.js
+++ b/test/cli/testdecoder.js
@@ -15,7 +15,7 @@ function assertEquals(a,b) {
assert(a==b, a + " != " + b);
}
-describe('Test address decoder', function() {
+describe('Address decoder', function() {
it('Should work empty', function() {
var decoder = new AddressDecoder([]);
assertEquals(0, decoder(0x1234));
diff --git a/test/cli/worker.js b/test/cli/worker.js
deleted file mode 100644
index a4c56c7f..00000000
--- a/test/cli/worker.js
+++ /dev/null
@@ -1,107 +0,0 @@
-
-var assert = require('assert');
-var fs = require('fs');
-var vm = require('vm');
-var worker = {};
-
-var includeInThisContext = function(path) {
- var code = fs.readFileSync(path);
- vm.runInThisContext(code, path);
-};
-
-global.importScripts = function(path) {
- includeInThisContext('src/worker/'+path);
-}
-
-function Blob(blob) {
- this.size = blob.length;
- this.length = blob.length;
- this.slice = function(a,b) {
- var data = blob.slice(a,b);
- var b = new Blob(data);
- //console.log(a, b, data.length, data.slice(0,64));
- //console.log(new Error().stack);
- return b;
- }
- this.asArrayBuffer = function() {
- var buf = new ArrayBuffer(blob.length);
- var arr = new Uint8Array(buf);
- for (var i=0; i\nint main() {\nint x=1;\nprintf("%d",x);\nreturn x+2;\n}', 'apple2', done, 2947, 4);
- });
- it('should NOT assemble Z80ASM', function(done) {
- compile('z80asm', 'ddwiuweq', 'none', done, 0, 0, 1);
- });
- it('should assemble Z80ASM', function(done) {
- compile('z80asm', '\tMODULE test\n\tXREF _puts\n\tld hl,$0000\n\tret\n', 'spaceinv', done, 4, 2, 0);
- });
- it('should NOT compile SDCC', function(done) {
- compile('sdcc', 'foobar', 'spaceinv', done, 0, 0, 1);
- });
- it('should assemble SDASZ80', function(done) {
- compile('sdcc', '\tMODULE test\n\tXREF _puts\n\tld hl,$0000\n\tret\n', 'spaceinv', done, 8192, 2, 1);
- });
- it('should compile SDCC', function(done) {
- compile('sdcc', 'int foo=0;\nint main(int argc) {\nint x=1;\nint y=2+argc;\nreturn x+y+argc;\n}', 'spaceinv', done, 8192, 3, 0);
- });
-});
diff --git a/test/cli/z80/z80test.js b/test/cli/z80/z80test.js
index 1975968b..1ae33d8f 100644
--- a/test/cli/z80/z80test.js
+++ b/test/cli/z80/z80test.js
@@ -1,9 +1,10 @@
"use strict";
+global.window = global;
+
require('../../../src/cpu/z80.js');
var _global = window;
-
_global.buildZ80({
applyContention: true
});
@@ -200,13 +201,36 @@ var testsIn = fs.readFileSync('test/cli/z80/tests.in', {encoding:'utf8'}).split(
var testsExpected = fs.readFileSync('test/cli/z80/tests.expected', {encoding:'utf8'}).split('\n\n');
assert(testsIn.length == testsExpected.length);
-describe('Z80 CPU', function() {
- it('should execute test cases', function() {
- for (var iter=0; iter