mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-04-07 23:37:22 +00:00
converted everything to new Z80, debugging broken
This commit is contained in:
parent
3b4d2b5f82
commit
d8421fee7f
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user