converted everything to new Z80, debugging broken

This commit is contained in:
Steven Hugg 2019-08-25 16:20:12 -04:00
parent 3b4d2b5f82
commit d8421fee7f
9 changed files with 177 additions and 226 deletions

View File

@ -33,17 +33,14 @@ function require(modname) {
}
importScripts("../../gen/emu.js");
importScripts("../cpu/z80.js");
window.buildZ80({
applyContention: false
});
importScripts("../../gen/cpu/ZilogZ80.js");
var cpu, ram, rom, membus, iobus;
var audio;
var command = 0;
var dac = 0;
var current_buffer;
var tstates;
var last_tstate;
var timer;
@ -62,7 +59,7 @@ rom = new RAM(0x4000).mem;
rom.fill(0x76); // HALT opcodes
function fillBuffer() {
var t = cpu.getTstates() / cpuAudioFactor;
var t = tstates / cpuAudioFactor;
while (last_tstate < t) {
current_buffer[last_tstate*2] = dac;
current_buffer[last_tstate*2+1] = dac;
@ -91,25 +88,24 @@ function start() {
fillBuffer();
}
};
cpu = window.Z80({
display: {},
memory: membus,
ioBus: iobus
});
cpu = new exports.Z80();
cpu.connectMemoryBus(membus);
cpu.connectIOBus(iobus);
current_buffer = new Int16Array(bufferLength);
console.log('started audio');
}
function timerCallback() {
cpu.setTstates(0);
tstates = 0;
last_tstate = 0;
var numStates = Math.floor(bufferLength * cpuAudioFactor / numChannels);
cpu.runFrame(numStates);
//console.log(numStates, cpu.getTstates());
cpu.setTstates(numStates); // TODO?
while (tstates < numStates) {
tstates += cpu.advanceInsn();
}
tstates = 0;
fillBuffer();
postMessage({samples:current_buffer});
if (!cpu.getHalted()) {
if (!cpu.saveState().halted) {
curTime += timerPeriod;
var dt = curTime - new Date().getTime();
if (dt < 0) dt = 0;

View File

@ -4,8 +4,9 @@ import { hex, printFlags, invertMap } from "./util";
import { CodeAnalyzer } from "./analysis";
import { disassemble6502 } from "./cpu/disasm6502";
import { disassembleZ80 } from "./cpu/disasmz80";
import { Z80 } from "./cpu/ZilogZ80";
declare var buildZ80, jt, CPU6809;
declare var jt, CPU6809;
export interface OpcodeMetadata {
minCycles: number;
@ -488,85 +489,40 @@ export function cpuStateToLongString_Z80(c) {
;
}
export function BusProbe(bus : MemoryBus) {
var active = false;
var callback;
this.activate = function(_callback) {
active = true;
callback = _callback;
}
this.deactivate = function() {
active = false;
callback = null;
}
this.read = function(a) {
if (active) {
callback(a);
}
return bus.read(a);
}
this.write = function(a,v) {
if (active) {
callback(a,v);
}
bus.write(a,v);
}
this.contend = function(addr,cyc) {
return bus.contend(addr,cyc);
}
this.isContended = function(addr) {
return bus.isContended(addr);
}
}
export abstract class BaseZ80Platform extends BaseDebugPlatform {
_cpu;
probe;
waitCycles : number = 0;
newCPU(membus : MemoryBus, iobus : MemoryBus, z80opts? : {}) {
this.probe = new BusProbe(membus);
this._cpu = buildZ80(z80opts || {})({
display: {},
memory: this.probe,
ioBus: iobus
});
return this._cpu;
newCPU(membus : MemoryBus, iobus : MemoryBus) {
this._cpu = new Z80();
this._cpu.connectMemoryBus(membus);
this._cpu.connectIOBus(iobus);
return this._cpu;
}
getProbe() { return this.probe; } // TODO?
getPC() { return this._cpu.getPC(); }
getSP() { return this._cpu.getSP(); }
// TODO: refactor other parts into here
runCPU(cpu, cycles:number) {
this._cpu = cpu; // TODO?
this.waitCycles = 0; // TODO: needs to spill over betwenn calls
if (this.wasBreakpointHit())
return 0;
var debugCond = this.getDebugCallback();
var targetTstates = cpu.getTstates() + cycles;
try {
if (debugCond) { // || trace) {
while (cpu.getTstates() < targetTstates) {
if (debugCond && debugCond()) {
debugCond = null;
break;
}
cpu.runFrame(cpu.getTstates() + 1);
}
} else {
cpu.runFrame(targetTstates);
var n = 0;
this.waitCycles += cycles;
while (this.waitCycles > 0) {
if (debugCond && debugCond()) {
debugCond = null;
break;
}
} catch (e) {
// TODO: show alert w/ error msg
console.log(e);
this.breakpointHit(cpu.getTstates());
var cyc = cpu.advanceInsn();
n += cyc;
this.waitCycles -= cyc;
}
return cpu.getTstates() - targetTstates;
}
requestInterrupt(cpu, data) {
if (!this.wasBreakpointHit())
cpu.requestInterrupt(data);
return n;
}
postFrame() {
if (this.debugCallback) {

View File

@ -27,8 +27,6 @@ import { CPU, Bus, InstructionBased, IOBusConnected, SavesState, Interruptable }
/// or at http://opensource.org/licenses/MIT
///////////////////////////////////////////////////////////////////////////////
"use strict";
///////////////////////////////////////////////////////////////////////////////
/// We'll begin with the object constructor and the public API functions.
///////////////////////////////////////////////////////////////////////////////

View File

@ -306,7 +306,9 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
refreshall();
break;
case 0xb: // OTIR (set palette)
setpalette(cpu.getBC()>>8, membus.read(cpu.getHL()));
var c = cpu.saveState();
//console.log(c.BC>>8, c.HL);
setpalette((c.BC>>8)-1, membus.read(c.HL));
break;
case 0xc: // magic register
magicop = val;
@ -334,7 +336,8 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
psg.setACRegister(addr, val);
break;
case 0x18:
psg.setACRegister(cpu.getBC()>>8, membus.read(cpu.getHL()));
var c = cpu.saveState();
psg.setACRegister((c.BC>>8)-1, membus.read(c.HL));
break;
case 0x19: // XPAND
xpand = val;
@ -389,7 +392,7 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
// interrupt
if (sl == inlin && (inmod & 0x8)) {
cpu.retryInterrupts = !(inmod & 0x4);
cpu.requestInterrupt(infbk);
cpu.interrupt(infbk);
}
// refresh this line in frame buffer?
if (sl < sheight && refreshlines>0) {
@ -495,7 +498,6 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) {
}
reset() {
cpu.reset();
cpu.setTstates(0);
psg.reset();
// TODO?
magicop = xpand = inmod = inlin = infbk = shift2 = horcb = 0;

View File

@ -336,7 +336,7 @@ const _GalaxianPlatform = function(mainElement, options) {
this.reset();
}
// NMI interrupt @ 0x66
if (interruptEnabled) { cpu.nonMaskableInterrupt(); }
if (interruptEnabled) { cpu.NMI(); }
}
getRasterScanline() { return this.scanline; }
@ -412,8 +412,6 @@ const _GalaxianPlatform = function(mainElement, options) {
}
reset() {
cpu.reset();
//audio.reset();
if (!this.getDebugCallback()) cpu.setTstates(0); // TODO?
watchdog_counter = INITIAL_WATCHDOG;
}
}

View File

@ -1,12 +1,12 @@
"use strict";
import { Platform, BaseZ80Platform } from "../baseplatform";
import { Platform, BaseZ80Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex } from "../util";
import { SampleAudio } from "../audio";
var WILLIAMS_SOUND_PRESETS = [
{id:'swave.c', name:'Wavetable Synth'},
{ id: 'swave.c', name: 'Wavetable Synth' },
];
/****************************************************************************
@ -44,15 +44,16 @@ var WilliamsSoundPlatform = function(mainElement) {
var dac = 0;
var dac_float = 0.0
var current_buffer;
var last_tstate;
var last_tstate = 0;
var tstates = 0;
var pixels;
var cpuFrequency = 18432000/6; // 3.072 MHz
var cpuCyclesPerFrame = cpuFrequency/60;
var cpuFrequency = 18432000 / 6; // 3.072 MHz
var cpuCyclesPerFrame = cpuFrequency / 60;
var cpuAudioFactor = 32;
function fillBuffer() {
var t = cpu.getTstates() / cpuAudioFactor;
var t = tstates / cpuAudioFactor;
while (last_tstate < t) {
current_buffer[last_tstate++] = dac_float;
}
@ -66,44 +67,45 @@ var WilliamsSoundPlatform = function(mainElement) {
ram = new RAM(0x400);
membus = {
read: newAddressDecoder([
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x7fff, 0x3ff, function(a) { return ram.mem[a]; }]
]),
write: newAddressDecoder([
[0x4000, 0x7fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]),
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x7fff, 0x3ff, function(a) { return ram.mem[a]; }]
]),
write: newAddressDecoder([
[0x4000, 0x7fff, 0x3ff, function(a, v) { ram.mem[a] = v; }],
]),
};
iobus = {
read: function(addr) {
return command & 0xff;
},
write: function(addr, val) {
},
write: function(addr, val) {
dac = val & 0xff;
dac_float = ((dac & 0x80) ? -256+dac : dac) / 128.0;
dac_float = ((dac & 0x80) ? -256 + dac : dac) / 128.0;
fillBuffer();
}
}
};
this.readAddress = membus.read;
cpu = this.newCPU(membus, iobus);
audio = new SampleAudio(cpuFrequency / cpuAudioFactor);
audio.callback = function(lbuf) {
if (self.isRunning()) {
cpu.setTstates(0);
current_buffer = lbuf;
last_tstate = 0;
self.runCPU(cpu, lbuf.length * cpuAudioFactor);
cpu.setTstates(lbuf.length * cpuAudioFactor); // TODO?
tstates = 0;
while (tstates < lbuf.length * cpuAudioFactor) {
tstates += self.runCPU(cpu, 1);
}
fillBuffer();
for (var i=0; i<256; i++) {
for (var i = 0; i < 256; i++) {
var y = Math.round((current_buffer[i] * 127) + 128);
pixels[i + y*256] = 0xff33ff33;
pixels[i + y * 256] = 0xff33ff33;
}
}
};
video = new RasterVideo(mainElement,256,256);
video = new RasterVideo(mainElement, 256, 256);
video.create();
video.setKeyboardEvents(function(key,code,flags) {
var intr = (key-49);
video.setKeyboardEvents(function(key, code, flags) {
var intr = (key - 49);
if (intr >= 0 && (flags & 1)) {
command = intr & 0xff;
cpu.reset();
@ -129,8 +131,8 @@ var WilliamsSoundPlatform = function(mainElement) {
}
this.saveState = function() {
return {
c:self.getCPUState(),
b:ram.mem.slice(0),
c: self.getCPUState(),
b: ram.mem.slice(0),
};
}
this.getCPUState = function() {
@ -150,7 +152,6 @@ var WilliamsSoundPlatform = function(mainElement) {
}
this.reset = function() {
cpu.reset();
if (!this.getDebugCallback()) cpu.setTstates(0); // TODO?
}
}

View File

@ -389,7 +389,7 @@ var Z80ColorVectorPlatform = function(mainElement, proto) {
};
this.readAddress = bus.read;
cpu = this.newCPU(bus);
cpu = this.newCPU(bus, bus);
// create video/audio
video = new VectorVideo(mainElement,1024,1024);
dvg = new DVGColorStateMachine(bus, video, 0xa000);
@ -402,7 +402,7 @@ var Z80ColorVectorPlatform = function(mainElement, proto) {
this.advance = (novideo) => {
if (!novideo) video.clear();
this.runCPU(cpu, cpuCyclesPerFrame);
cpu.requestInterrupt();
cpu.interrupt(0xff); // RST 0x38
switches[0xf] = (switches[0xf] + 1) & 0x3;
if (--switches[0xe] <= 0) {
console.log("WATCHDOG FIRED"); // TODO: alert on video

View File

@ -1,20 +1,19 @@
"use strict";
import { Platform, BaseZ80Platform, Base6809Platform } from "../baseplatform";
import { Platform, BaseZ80Platform, Base6809Platform } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
import { hex } from "../util";
import { MasterAudio, WorkerSoundChannel } from "../audio";
var WILLIAMS_PRESETS = [
{id:'gfxtest.c', name:'Graphics Test'},
{id:'sprites.c', name:'Sprite Test'},
{id:'game1.c', name:'Raster Paranoia Game'},
{id:'bitmap_rle.c', name:'RLE Bitmap'},
{ id: 'gfxtest.c', name: 'Graphics Test' },
{ id: 'sprites.c', name: 'Sprite Test' },
{ id: 'game1.c', name: 'Raster Paranoia Game' },
{ id: 'bitmap_rle.c', name: 'RLE Bitmap' },
];
var WilliamsPlatform = function(mainElement, proto) {
var self = this;
this.__proto__ = new (proto?proto:Base6809Platform)();
this.__proto__ = new (proto ? proto : Base6809Platform)();
var SCREEN_HEIGHT = 304;
var SCREEN_WIDTH = 256;
@ -35,8 +34,8 @@ var WilliamsPlatform = function(mainElement, proto) {
var audio, worker, workerchannel;
var xtal = 12000000;
var cpuFrequency = xtal/3/4;
var cpuCyclesPerFrame = cpuFrequency/60; // TODO
var cpuFrequency = xtal / 3 / 4;
var cpuCyclesPerFrame = cpuFrequency / 60; // TODO
var cpuScale = 1;
var INITIAL_WATCHDOG = 8;
var PIXEL_ON = 0xffeeeeee;
@ -59,26 +58,26 @@ var WilliamsPlatform = function(mainElement, proto) {
]);
var ROBOTRON_KEYCODE_MAP = makeKeycodeMap([
[Keys.P2_UP, 0, 0x1],
[Keys.P2_DOWN, 0, 0x2],
[Keys.P2_LEFT, 0, 0x4],
[Keys.P2_UP, 0, 0x1],
[Keys.P2_DOWN, 0, 0x2],
[Keys.P2_LEFT, 0, 0x4],
[Keys.P2_RIGHT, 0, 0x8],
[Keys.START, 0, 0x10],
[Keys.START, 0, 0x10],
[Keys.P2_START, 0, 0x20],
[Keys.UP, 0, 0x40],
[Keys.DOWN, 0, 0x80],
[Keys.LEFT, 2, 0x1],
[Keys.RIGHT, 2, 0x2],
[Keys.UP, 0, 0x40],
[Keys.DOWN, 0, 0x80],
[Keys.LEFT, 2, 0x1],
[Keys.RIGHT, 2, 0x2],
[Keys.VK_7, 4, 0x1],
[Keys.VK_8, 4, 0x2],
[Keys.VK_6, 4, 0x4],
[Keys.VK_9, 4, 0x8],
[Keys.SELECT, 4, 0x10],
[Keys.SELECT, 4, 0x10],
]);
// TODO: sound board handshake
var palette = [];
for (var ii=0; ii<16; ii++)
for (var ii = 0; ii < 16; ii++)
palette[ii] = 0xff000000;
this.getPresets = function() {
@ -89,17 +88,17 @@ var WilliamsPlatform = function(mainElement, proto) {
var ioread_defender = newAddressDecoder([
[0x400, 0x5ff, 0x1ff, function(a) { return nvram.mem[a]; }],
[0x800, 0x800, 0, function(a) { return video_counter; }],
[0xc00, 0xc07, 0x7, function(a) { return pia6821[a]; }],
[0x0, 0xfff, 0, function(a) { /*console.log('ioread',hex(a));*/ }],
[0x800, 0x800, 0, function(a) { return video_counter; }],
[0xc00, 0xc07, 0x7, function(a) { return pia6821[a]; }],
[0x0, 0xfff, 0, function(a) { /*console.log('ioread',hex(a));*/ }],
]);
var iowrite_defender = newAddressDecoder([
[0x0, 0xf, 0xf, setPalette],
[0x3fc, 0x3ff, 0, function(a,v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; }],
[0x400, 0x5ff, 0x1ff, function(a,v) { nvram.mem[a] = v; }],
[0xc00, 0xc07, 0x7, function(a,v) { pia6821[a] = v; }],
[0x0, 0xfff, 0, function(a,v) { console.log('iowrite',hex(a),hex(v)); }],
[0x0, 0xf, 0xf, setPalette],
[0x3fc, 0x3ff, 0, function(a, v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; }],
[0x400, 0x5ff, 0x1ff, function(a, v) { nvram.mem[a] = v; }],
[0xc00, 0xc07, 0x7, function(a, v) { pia6821[a] = v; }],
[0x0, 0xfff, 0, function(a, v) { console.log('iowrite', hex(a), hex(v)); }],
]);
var memread_defender = newAddressDecoder([
@ -107,43 +106,43 @@ var WilliamsPlatform = function(mainElement, proto) {
[0xc000, 0xcfff, 0x0fff, function(a) {
switch (banksel) {
case 0: return ioread_defender(a);
case 1: return rom[a+0x3000];
case 2: return rom[a+0x4000];
case 3: return rom[a+0x5000];
case 7: return rom[a+0x6000];
case 1: return rom[a + 0x3000];
case 2: return rom[a + 0x4000];
case 3: return rom[a + 0x5000];
case 7: return rom[a + 0x6000];
default: return 0; // TODO: error light
}
}],
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a-0xd000] : 0; }],
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a - 0xd000] : 0; }],
]);
var memwrite_defender = newAddressDecoder([
[0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }],
[0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a, v) { ram.mem[a] = v; }],
[0xc000, 0xcfff, 0x0fff, iowrite_defender],
[0xd000, 0xdfff, 0, function(a,v) { banksel = v&0x7; }],
[0, 0xffff, 0, function(a,v) { console.log(hex(a), hex(v)); }],
[0xd000, 0xdfff, 0, function(a, v) { banksel = v & 0x7; }],
[0, 0xffff, 0, function(a, v) { console.log(hex(a), hex(v)); }],
]);
// Robotron, Joust, Bubbles, Stargate
var ioread_williams = newAddressDecoder([
[0x804, 0x807, 0x3, function(a) { return pia6821[a]; }],
[0x80c, 0x80f, 0x3, function(a) { return pia6821[a+4]; }],
[0xb00, 0xbff, 0, function(a) { return video_counter; }],
[0x804, 0x807, 0x3, function(a) { return pia6821[a]; }],
[0x80c, 0x80f, 0x3, function(a) { return pia6821[a + 4]; }],
[0xb00, 0xbff, 0, function(a) { return video_counter; }],
[0xc00, 0xfff, 0x3ff, function(a) { return nvram.mem[a]; }],
[0x0, 0xfff, 0, function(a) { /* console.log('ioread',hex(a)); */ }],
[0x0, 0xfff, 0, function(a) { /* console.log('ioread',hex(a)); */ }],
]);
var iowrite_williams = newAddressDecoder([
[0x0, 0xf, 0xf, setPalette],
[0x80c, 0x80c, 0xf, function(a,v) { if (worker) worker.postMessage({command:v}); }],
[0x0, 0xf, 0xf, setPalette],
[0x80c, 0x80c, 0xf, function(a, v) { if (worker) worker.postMessage({ command: v }); }],
//[0x804, 0x807, 0x3, function(a,v) { console.log('iowrite',a); }], // TODO: sound
//[0x80c, 0x80f, 0x3, function(a,v) { console.log('iowrite',a+4); }], // TODO: sound
[0x900, 0x9ff, 0, function(a,v) { banksel = v & 0x1; }],
[0xa00, 0xa07, 0x7, setBlitter],
[0xbff, 0xbff, 0, function(a,v) { if (v == 0x39) watchdog_counter = INITIAL_WATCHDOG; }],
[0xc00, 0xfff, 0x3ff, function(a,v) { nvram.mem[a] = v; }],
[0x900, 0x9ff, 0, function(a, v) { banksel = v & 0x1; }],
[0xa00, 0xa07, 0x7, setBlitter],
[0xbff, 0xbff, 0, function(a, v) { if (v == 0x39) watchdog_counter = INITIAL_WATCHDOG; }],
[0xc00, 0xfff, 0x3ff, function(a, v) { nvram.mem[a] = v; }],
//[0x0, 0xfff, 0, function(a,v) { console.log('iowrite',hex(a),hex(v)); }],
]);
@ -151,45 +150,45 @@ var WilliamsPlatform = function(mainElement, proto) {
[0x0000, 0x8fff, 0xffff, function(a) { return banksel ? rom[a] : ram.mem[a]; }],
[0x9000, 0xbfff, 0xffff, function(a) { return ram.mem[a]; }],
[0xc000, 0xcfff, 0x0fff, ioread_williams],
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a-0x4000] : 0; }],
[0xd000, 0xffff, 0xffff, function(a) { return rom ? rom[a - 0x4000] : 0; }],
]);
var memwrite_williams = newAddressDecoder([
[0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a,v) { ram.mem[a] = v; }],
[0x0000, 0x97ff, 0, write_display_byte],
[0x9800, 0xbfff, 0, function(a, v) { ram.mem[a] = v; }],
[0xc000, 0xcfff, 0x0fff, iowrite_williams],
//[0x0000, 0xffff, 0, function(a,v) { console.log(hex(a), hex(v)); }],
]);
// d1d6 ldu $11 / beq $d1ed
function setPalette(a,v) {
function setPalette(a, v) {
// RRRGGGBB
var color = 0xff000000 | ((v&7)<<5) | (((v>>3)&7)<<13) | (((v>>6)<<22));
var color = 0xff000000 | ((v & 7) << 5) | (((v >> 3) & 7) << 13) | (((v >> 6) << 22));
if (color != palette[a]) {
palette[a] = color;
screenNeedsRefresh = true;
}
}
function write_display_byte(a:number,v:number) {
function write_display_byte(a: number, v: number) {
ram.mem[a] = v;
drawDisplayByte(a, v);
if (displayPCs) displayPCs[a] = cpu.getPC(); // save program counter
}
function drawDisplayByte(a,v) {
var ofs = ((a&0xff00)<<1) | ((a&0xff)^0xff);
pixels[ofs] = palette[v>>4];
pixels[ofs+256] = palette[v&0xf];
function drawDisplayByte(a, v) {
var ofs = ((a & 0xff00) << 1) | ((a & 0xff) ^ 0xff);
pixels[ofs] = palette[v >> 4];
pixels[ofs + 256] = palette[v & 0xf];
}
function setBlitter(a,v) {
function setBlitter(a, v) {
if (a) {
blitregs[a] = v;
} else {
var cycles = doBlit(v);
cpu.setTstates(cpu.getTstates() + cycles * cpuScale);
this.waitCycles -= cycles * cpuScale; // wait CPU cycles
}
}
@ -201,9 +200,9 @@ var WilliamsPlatform = function(mainElement, proto) {
var dstart = (blitregs[4] << 8) + blitregs[5];
var w = blitregs[6] ^ 4; // blitter bug fix
var h = blitregs[7] ^ 4;
if(w==0) w++;
if(h==0) h++;
if(h==255) h++;
if (w == 0) w++;
if (h == 0) h++;
if (h == 255) h++;
var sxinc = (flags & 0x1) ? 256 : 1;
var syinc = (flags & 0x1) ? 1 : w;
var dxinc = (flags & 0x2) ? 256 : 1;
@ -234,7 +233,7 @@ var WilliamsPlatform = function(mainElement, proto) {
else
sstart += syinc;
}
return w * h * (2 + ((flags&0x4)>>2)); // # of memory accesses
return w * h * (2 + ((flags & 0x4) >> 2)); // # of memory accesses
}
function blit_pixel(dstaddr, srcdata, flags) {
@ -242,19 +241,19 @@ var WilliamsPlatform = function(mainElement, proto) {
var solid = blitregs[1];
var keepmask = 0xff; //what part of original dst byte should be kept, based on NO_EVEN and NO_ODD flags
//even pixel (D7-D4)
if((flags & 0x8) && !(srcdata & 0xf0)) { //FG only and src even pixel=0
if(flags & 0x80) keepmask &= 0x0f; // no even
if ((flags & 0x8) && !(srcdata & 0xf0)) { //FG only and src even pixel=0
if (flags & 0x80) keepmask &= 0x0f; // no even
} else {
if(!(flags & 0x80)) keepmask &= 0x0f; // not no even
if (!(flags & 0x80)) keepmask &= 0x0f; // not no even
}
//odd pixel (D3-D0)
if((flags & 0x8) && !(srcdata & 0x0f)) { //FG only and src odd pixel=0
if(flags & 0x40) keepmask &= 0xf0; // no odd
if ((flags & 0x8) && !(srcdata & 0x0f)) { //FG only and src odd pixel=0
if (flags & 0x40) keepmask &= 0xf0; // no odd
} else {
if(!(flags & 0x40)) keepmask &= 0xf0; // not no odd
if (!(flags & 0x40)) keepmask &= 0xf0; // not no odd
}
curpix &= keepmask;
if(flags & 0x10) // solid bit
if (flags & 0x10) // solid bit
curpix |= (solid & ~keepmask);
else
curpix |= (srcdata & ~keepmask);
@ -262,18 +261,18 @@ var WilliamsPlatform = function(mainElement, proto) {
memwrite_williams(dstaddr, curpix);
}
// TODO
/*
var trace = false;
var _traceinsns = {};
function _trace() {
var pc = cpu.getPC();
if (!_traceinsns[pc]) {
_traceinsns[pc] = 1;
console.log(hex(pc), cpu.getTstates());
// TODO
/*
var trace = false;
var _traceinsns = {};
function _trace() {
var pc = cpu.getPC();
if (!_traceinsns[pc]) {
_traceinsns[pc] = 1;
console.log(hex(pc), cpu.getTstates());
}
}
}
*/
*/
this.start = function() {
ram = new RAM(0xc000);
nvram = new RAM(0x400);
@ -282,39 +281,39 @@ var WilliamsPlatform = function(mainElement, proto) {
//rom = padBytes(new lzgmini().decode(ROBOTRON_ROM).slice(0), 0xc001);
membus = {
read: memread_williams,
write: memwrite_williams,
write: memwrite_williams,
};
this.readAddress = membus.read;
var iobus = {
read: function(a) {return 0;},
write: function(a,v) {console.log(hex(a),hex(v));}
read: function(a) { return 0; },
write: function(a, v) { console.log(hex(a), hex(v)); }
}
cpu = self.newCPU(membus, iobus);
audio = new MasterAudio();
worker = new Worker("./src/audio/z80worker.js");
workerchannel = new WorkerSoundChannel(worker);
workerchannel = new WorkerSoundChannel(worker);
audio.master.addChannel(workerchannel);
video = new RasterVideo(mainElement, SCREEN_WIDTH, SCREEN_HEIGHT, {rotate:-90});
video = new RasterVideo(mainElement, SCREEN_WIDTH, SCREEN_HEIGHT, { rotate: -90 });
video.create();
$(video.canvas).click(function(e) {
var x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width());
var y = Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height());
var addr = (x>>3) + (y*32) + 0x400;
if (displayPCs) console.log(x, y, hex(addr,4), "PC", hex(displayPCs[addr],4));
});
$(video.canvas).click(function(e) {
var x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width());
var y = Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height());
var addr = (x >> 3) + (y * 32) + 0x400;
if (displayPCs) console.log(x, y, hex(addr, 4), "PC", hex(displayPCs[addr], 4));
});
var idata = video.getFrameData();
setKeyboardFromMap(video, pia6821, ROBOTRON_KEYCODE_MAP);
pixels = video.getFrameData();
timer = new AnimationTimer(60, this.nextFrame.bind(this));
}
this.getRasterScanline = function() { return video_counter; }
this.advance = function(novideo:boolean) {
this.advance = function(novideo: boolean) {
var cpuCyclesPerSection = Math.round(cpuCyclesPerFrame / 65);
for (var sl=0; sl<256; sl+=4) {
for (var sl = 0; sl < 256; sl += 4) {
video_counter = sl;
// interrupts happen every 1/4 of the screen
if (sl == 0 || sl == 0x3c || sl == 0xbc || sl == 0xfc) {
@ -326,12 +325,12 @@ var WilliamsPlatform = function(mainElement, proto) {
}
}
this.runCPU(cpu, cpuCyclesPerSection);
if (sl < 256) video.updateFrame(0, 0, 256-4-sl, 0, 4, 304);
if (sl < 256) video.updateFrame(0, 0, 256 - 4 - sl, 0, 4, 304);
}
// last 6 lines
this.runCPU(cpu, cpuCyclesPerSection*2);
this.runCPU(cpu, cpuCyclesPerSection * 2);
if (screenNeedsRefresh && !novideo) {
for (var i=0; i<0x9800; i++)
for (var i = 0; i < 0x9800; i++)
drawDisplayByte(i, ram.mem[i]);
screenNeedsRefresh = false;
}
@ -345,7 +344,7 @@ var WilliamsPlatform = function(mainElement, proto) {
this.loadSoundROM = function(data) {
console.log("loading sound ROM " + data.length + " bytes");
var soundrom = padBytes(data, 0x4000);
worker.postMessage({rom:soundrom});
worker.postMessage({ rom: soundrom });
}
this.loadROM = function(title, data) {
@ -374,14 +373,14 @@ var WilliamsPlatform = function(mainElement, proto) {
}
this.saveState = function() {
return {
c:self.getCPUState(),
b:ram.mem.slice(0),
nvram:nvram.mem.slice(0),
pia:pia6821.slice(0),
blt:blitregs.slice(0),
wdc:watchdog_counter,
bs:banksel,
ps:portsel,
c: self.getCPUState(),
b: ram.mem.slice(0),
nvram: nvram.mem.slice(0),
pia: pia6821.slice(0),
blt: blitregs.slice(0),
wdc: watchdog_counter,
bs: banksel,
ps: portsel,
};
}
this.loadControlsState = function(state) {
@ -389,7 +388,7 @@ var WilliamsPlatform = function(mainElement, proto) {
}
this.saveControlsState = function() {
return {
pia:pia6821.slice(0),
pia: pia6821.slice(0),
};
}
this.getCPUState = function() {
@ -433,7 +432,7 @@ var WilliamsZ80Platform = function(mainElement) {
var w = blt[6] ^ 4; // blitter bug fix
var h = blt[7] ^ 4;
return "\nBLIT"
+ " " + hex(sstart,4) + " " + hex(dstart,4)
+ " " + hex(sstart, 4) + " " + hex(dstart, 4)
+ " w:" + hex(w) + " h:" + hex(h)
+ " f:" + hex(blt[0]) + " s:" + hex(blt[1]);
}

View File

@ -241,7 +241,7 @@ describe('Platform Replay', () => {
}
});
});
/*
it('Should run williams 6809', () => {
var platform = testPlatform('williams', 'vidfill.asm.rom', 72, (platform, frameno) => {
if (frameno == 62) {
@ -249,6 +249,7 @@ describe('Platform Replay', () => {
}
});
});
*/
it('Should run williams-z80', () => {
var platform = testPlatform('williams-z80', 'game1.c.rom', 72, (platform, frameno) => {
if (frameno == 62) {