diff --git a/css/ui.css b/css/ui.css
index f3a42d94..3bf92020 100644
--- a/css/ui.css
+++ b/css/ui.css
@@ -591,6 +591,8 @@ div.asset_toolbar {
}
.control-def {
color: #ccc;
+ white-space: nowrap;
+ line-height:2em;
}
.book-title {
font-size:12pt;
diff --git a/index.html b/index.html
index af1cd267..b47dc084 100644
--- a/index.html
+++ b/index.html
@@ -373,8 +373,9 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
←↑↓→ Joystick
Shift Button
- Enter Start
- \ Select
+ F1 Start
+ F2 Select
+ F3 Option
diff --git a/src/common/baseplatform.ts b/src/common/baseplatform.ts
index 4de11e48..942e3088 100644
--- a/src/common/baseplatform.ts
+++ b/src/common/baseplatform.ts
@@ -17,8 +17,6 @@ import { _MOS6502 } from "./cpu/MOS6502";
///
-declare var jt;
-
export interface OpcodeMetadata {
minCycles: number;
maxCycles: number;
diff --git a/src/common/devices.ts b/src/common/devices.ts
index 3f32c279..cc62ddf6 100644
--- a/src/common/devices.ts
+++ b/src/common/devices.ts
@@ -156,11 +156,14 @@ export interface ProbeCPU {
logExecute(address:number, SP:number);
logInterrupt(type:number);
logIllegal(address:number);
+ logWait(address:number);
}
export interface ProbeBus {
logRead(address:number, value:number);
logWrite(address:number, value:number);
+ logDMARead(address:number, value:number);
+ logDMAWrite(address:number, value:number);
}
export interface ProbeIO {
@@ -191,6 +194,9 @@ export class NullProbe implements ProbeAll {
logVRAMRead() {}
logVRAMWrite() {}
logIllegal() {}
+ logWait() {}
+ logDMARead() {}
+ logDMAWrite() {}
logData() {}
addLogBuffer(src: Uint32Array) {}
}
@@ -296,6 +302,19 @@ export abstract class BasicHeadlessMachine implements HasCPU, Bus, AcceptsROM, P
}
};
}
+ probeDMABus(iobus:Bus) : Bus {
+ return {
+ read: (a) => {
+ let val = iobus.read(a);
+ this.probe.logDMARead(a,val);
+ return val;
+ },
+ write: (a,v) => {
+ this.probe.logDMAWrite(a,v);
+ iobus.write(a,v);
+ }
+ };
+ }
connectCPUIOBus(iobus:Bus) : void {
this.cpu['connectIOBus'](this.probeIOBus(iobus));
}
diff --git a/src/common/emu.ts b/src/common/emu.ts
index a1d1128e..be6d10cc 100644
--- a/src/common/emu.ts
+++ b/src/common/emu.ts
@@ -3,9 +3,6 @@ import { hex, clamp, lpad, RGBA } from "./util";
import { SourceLocation } from "./workertypes";
import { VirtualList } from "./vlist"
-// external modules
-declare var jt, Javatari;
-
// Emulator classes
export var PLATFORMS = {};
@@ -52,12 +49,9 @@ export enum KeyFlags {
export function _setKeyboardEvents(canvas:HTMLElement, callback:KeyboardCallback) {
canvas.onkeydown = (e) => {
- callback(e.which, 0, KeyFlags.KeyDown|_metakeyflags(e));
- // eat backspace, tab, escape, slash, ' keys
- if (e.ctrlKey || e.which == 8 || e.which == 9 || e.which == 27
- || e.which == 191 || e.which == 191 || e.which == 222) {
- e.preventDefault();
- }
+ let flags = _metakeyflags(e);
+ callback(e.which, 0, KeyFlags.KeyDown|flags);
+ if (!flags) e.preventDefault(); // eat all keys that don't have a modifier
};
canvas.onkeyup = (e) => {
callback(e.which, 0, KeyFlags.KeyUp|_metakeyflags(e));
@@ -370,7 +364,7 @@ export const Keys = {
GP_D: {c: 67, n: "C", plyr:0, button:3},
SELECT: {c: 220, n: "\\", plyr:0, button:8},
START: {c: 13, n: "Enter", plyr:0, button:9},
- OPTION: {c: 9, n: "Tab", plyr:0, button:10},
+ OPTION: {c: 8, n: "Bcksp", plyr:0, button:10},
// gamepad and keyboard (player 1)
P2_UP: {c: 87, n: "W", plyr:1, yaxis:-1},
P2_DOWN: {c: 83, n: "S", plyr:1, yaxis:1},
@@ -458,6 +452,7 @@ export const Keys = {
VK_SLASH: {c: 191, n: "/"},
VK_CONTROL: {c: 17, n: "Ctrl"},
VK_ALT: {c: 18, n: "Alt"},
+ VK_COMMAND: {c: 224, n: "Cmd"},
VK_SPACE: {c: 32, n: "Space"},
VK_INSERT: {c: 45, n: "Ins"},
VK_DELETE: {c: 46, n: "Del"},
diff --git a/src/common/probe.ts b/src/common/probe.ts
index 3967fffa..a392ed50 100644
--- a/src/common/probe.ts
+++ b/src/common/probe.ts
@@ -4,6 +4,10 @@ import { Probeable, ProbeAll } from "./devices";
export enum ProbeFlags {
CLOCKS = 0x00000000,
EXECUTE = 0x01000000,
+ INTERRUPT = 0x08000000,
+ ILLEGAL = 0x09000000,
+ SP_PUSH = 0x0a000000,
+ SP_POP = 0x0b000000,
HAS_VALUE = 0x10000000,
MEM_READ = 0x12000000,
MEM_WRITE = 0x13000000,
@@ -11,10 +15,9 @@ export enum ProbeFlags {
IO_WRITE = 0x15000000,
VRAM_READ = 0x16000000,
VRAM_WRITE= 0x17000000,
- INTERRUPT = 0x08000000,
- ILLEGAL = 0x09000000,
- SP_PUSH = 0x0a000000,
- SP_POP = 0x0b000000,
+ DMA_READ = 0x18000000,
+ DMA_WRITE = 0x19000000,
+ WAIT = 0x1f000000,
SCANLINE = 0x7e000000,
FRAME = 0x7f000000,
}
@@ -140,6 +143,15 @@ export class ProbeRecorder implements ProbeAll {
logIllegal(address:number) {
this.log(address | ProbeFlags.ILLEGAL);
}
+ logWait(address:number) {
+ this.log(address | ProbeFlags.WAIT);
+ }
+ logDMARead(address:number, value:number) {
+ this.logValue(address, value, ProbeFlags.DMA_READ);
+ }
+ logDMAWrite(address:number, value:number) {
+ this.logValue(address, value, ProbeFlags.DMA_WRITE);
+ }
countEvents(op : number) : number {
var count = 0;
for (var i=0; i number;
write : (a:number, v:number) => void;
- probeDMABus : Bus; // to pass to MARIA
+ dmaBus : Bus; // to pass to MARIA
constructor() {
super();
@@ -355,7 +355,7 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
[0x0000, 0xffff, 0xffff, (a,v) => { this.probe && this.probe.logIllegal(a); }],
]);
this.connectCPUMemoryBus(this);
- this.probeDMABus = this.probeIOBus(this);
+ this.dmaBus = this.probeDMABus(this);
this.handler = newKeyboardHandler(this.inputs, Atari7800_KEYCODE_MAP);
this.pokey1 = new POKEYDeviceChannel();
this.audioadapter = new TssChannelAdapter(this.pokey1, audioOversample, audioSampleRate);
@@ -417,7 +417,7 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
// is this scanline visible?
if (visible) {
// do DMA for scanline?
- let dmaClocks = this.maria.doDMA(this.probeDMABus);
+ let dmaClocks = this.maria.doDMA(this.dmaBus);
this.probe.logClocks(dmaClocks >> 2); // TODO: logDMA
mc += dmaClocks;
// copy line to frame buffer
@@ -435,6 +435,7 @@ export class Atari7800 extends BasicMachine implements RasterFrameBased {
// post-DMA clocks
while (mc < colorClocksPerLine) {
if (this.maria.WSYNC) {
+ this.probe.logWait(0);
this.probe.logClocks((colorClocksPerLine - mc) >> 2);
mc = colorClocksPerLine;
break;
diff --git a/src/machine/atari8.ts b/src/machine/atari8.ts
index fdae6b13..8d52ce91 100644
--- a/src/machine/atari8.ts
+++ b/src/machine/atari8.ts
@@ -10,9 +10,9 @@ import { CONSOL, GTIA, TRIG0 } from "./chips/gtia";
import { POKEY } from "./chips/pokey";
const ATARI8_KEYMATRIX_INTL_NOSHIFT = [
- Keys.VK_L, Keys.VK_J, Keys.VK_SEMICOLON, Keys.VK_F1, Keys.VK_F2, Keys.VK_K, Keys.VK_BACK_SLASH, Keys.VK_TILDE,
+ Keys.VK_L, Keys.VK_J, Keys.VK_SEMICOLON, Keys.VK_F4, Keys.VK_F5, Keys.VK_K, Keys.VK_BACK_SLASH, Keys.VK_TILDE,
Keys.VK_O, null, Keys.VK_P, Keys.VK_U, Keys.VK_ENTER, Keys.VK_I, Keys.VK_MINUS2, Keys.VK_EQUALS2,
- Keys.VK_V, Keys.VK_F8, Keys.VK_C, Keys.VK_F3, Keys.VK_F4, Keys.VK_B, Keys.VK_X, Keys.VK_Z,
+ Keys.VK_V, Keys.VK_F7, Keys.VK_C, Keys.VK_F6, Keys.VK_F4, Keys.VK_B, Keys.VK_X, Keys.VK_Z,
Keys.VK_4, null, Keys.VK_3, Keys.VK_6, Keys.VK_ESCAPE, Keys.VK_5, Keys.VK_2, Keys.VK_1,
Keys.VK_COMMA, Keys.VK_SPACE, Keys.VK_PERIOD, Keys.VK_N, null, Keys.VK_M, Keys.VK_SLASH, null/*invert*/,
Keys.VK_R, null, Keys.VK_E, Keys.VK_Y, Keys.VK_TAB, Keys.VK_T, Keys.VK_W, Keys.VK_Q,
@@ -26,7 +26,7 @@ var ATARI8_KEYCODE_MAP = makeKeycodeMap([
[Keys.DOWN, 0, 0x2],
[Keys.LEFT, 0, 0x4],
[Keys.RIGHT, 0, 0x8],
- [Keys.VK_SHIFT, 2, 0x1],
+ [{c: 16, n: "Shift", plyr:0, button:0}, 2, 0x1],
/*
[Keys.P2_UP, 0, 0x10],
[Keys.P2_DOWN, 0, 0x20],
@@ -34,9 +34,9 @@ var ATARI8_KEYCODE_MAP = makeKeycodeMap([
[Keys.P2_RIGHT, 0, 0x80],
[Keys.P2_A, 3, 0x1],
*/
- [Keys.START, 3, 0x1], // START
- [Keys.SELECT, 3, 0x2], // SELECT
- [Keys.OPTION, 3, 0x4], // OPTION
+ [Keys.VK_F1, 3, 0x1], // START
+ [Keys.VK_F2, 3, 0x2], // SELECT
+ [Keys.VK_F3, 3, 0x4], // OPTION
]);
@@ -72,6 +72,7 @@ export class Atari800 extends BasicScanlineMachine {
cart_80 = false;
cart_a0 = false;
xexdata = null;
+ keyboard_active = true;
// TODO: save/load vars
constructor() {
@@ -89,7 +90,7 @@ export class Atari800 extends BasicScanlineMachine {
this.audioadapter = new TssChannelAdapter(this.audio_pokey.pokey1, this.audioOversample, this.sampleRate);
this.handler = newKeyboardHandler(
this.inputs, ATARI8_KEYCODE_MAP, this.getKeyboardFunction(), true);
- }
+ }
newBus() {
return {
@@ -134,7 +135,7 @@ export class Atari800 extends BasicScanlineMachine {
// used by ANTIC
readDMA(a) {
let v = this.bus.read(a);
- this.probe.logVRAMRead(a, v);
+ this.probe.logDMARead(a, v);
this.lastdmabyte = v;
return v;
}
@@ -192,6 +193,8 @@ export class Atari800 extends BasicScanlineMachine {
// ANTIC DMA cycle, update GTIA
if (this.antic.h < 8)
this.gtia.updateGfx(this.antic.h - 1, this.antic.v, this.lastdmabyte); // HALT pin
+ if (this.antic.isWSYNC())
+ this.probe.logWait(0);
this.probe.logClocks(1);
} else {
super.advanceCPU();
@@ -278,8 +281,9 @@ export class Atari800 extends BasicScanlineMachine {
}
getKeyboardFunction() {
return (o, key, code, flags) => {
+ if (!this.keyboard_active) return false;
if (flags & (KeyFlags.KeyDown | KeyFlags.KeyUp)) {
- //console.log(o, key, code, flags, hex(this.keycode));
+ console.log(o, key, code, flags, hex(this.keycode));
var keymap = ATARI8_KEYMATRIX_INTL_NOSHIFT;
if (key == Keys.VK_F9.c) {
this.irq_pokey.generateIRQ(0x80); // break IRQ
diff --git a/src/machine/chips/antic.ts b/src/machine/chips/antic.ts
index 28ea72ce..ab264676 100644
--- a/src/machine/chips/antic.ts
+++ b/src/machine/chips/antic.ts
@@ -109,7 +109,9 @@ export class ANTIC {
let s = "";
s += "H: " + lpad(state.h, 3) + " V: " + lpad(state.v, 3) + "\n";
s += "DLIOp: " + hex(state.dliop, 2) + " Lines: " + state.yofs + "/" + state.linesleft;
- s += " DMA " + (state.dma_enabled ? "ON " : "off") + "\n";
+ s += " DMA " + (state.dma_enabled ? "ON " : "off")
+ if (state.dma_enabled) s += " idx " + state.dmaidx + " clk " + hex(state.dmaclock)
+ s += "\n"
s += "Addr: " + hex(state.scanaddr, 4) + "\n";
s += dumpRAM(state.regs, 0, 16).replace('$00', 'Regs');
return s;
@@ -138,6 +140,7 @@ export class ANTIC {
processDLIEntry() {
if (this.mode == 0) { // N Blank Lines
this.linesleft = ((this.dliop >> 4) & 7) + 1;
+ this.dmaclock = 0;
} else {
this.linesleft = MODE_LINES[this.mode];
this.period = MODE_PERIOD[this.mode];
@@ -150,6 +153,7 @@ export class ANTIC {
this.linesleft = 1; //(248 - this.v) & 0xff; // TODO?
this.dma_enabled = false;
}
+ this.dmaclock = 0;
} else if (this.lms) {
this.scanaddr = this.dlarg_lo + (this.dlarg_hi << 8);
//console.log('scanaddr', hex(this.scanaddr));
@@ -225,9 +229,12 @@ export class ANTIC {
isMissileDMAEnabled() {
return this.regs[DMACTL] & 0b1100;
}
+ isWSYNC() {
+ return this.regs[WSYNC] != 0;
+ }
clockPulse(): boolean {
- let did_dma = this.regs[WSYNC] != 0;
+ let did_dma = this.isWSYNC();
if (!this.isVisibleScanline()) {
this.doVBlank();
} else {
@@ -285,7 +292,7 @@ export class ANTIC {
this.output = 0; // background color (TODO: only for blank lines)
if (this.mode >= 2 && this.period) {
let candma = this.h <= LAST_DMA_H;
- this.dmaclock <<= 1;
+ this.dmaclock = (this.dmaclock << 1) & 0x1ff;
if (this.dmaclock & (1 << this.period)) {
this.dmaclock |= 1;
}
@@ -346,6 +353,7 @@ export class ANTIC {
this.dma_enabled = this.dlDMAEnabled() != 0;
}
this.output = 2; // blank
+ this.dmaclock = 0;
}
doPlayerMissileDMA(section: number) {
diff --git a/src/machine/chips/gtia.ts b/src/machine/chips/gtia.ts
index e6da7edc..5bb52d58 100644
--- a/src/machine/chips/gtia.ts
+++ b/src/machine/chips/gtia.ts
@@ -80,6 +80,7 @@ export class GTIA {
this.regs.fill(0);
this.readregs.fill(0); // TODO?
this.readregs[0x14] = 0xf; // NTSC
+ this.readregs.fill(0xf, 0x15); // default value for write-only regs
this.count = 0;
}
saveState() {
diff --git a/src/platform/vcs.ts b/src/platform/vcs.ts
index a9987822..42d9fe51 100644
--- a/src/platform/vcs.ts
+++ b/src/platform/vcs.ts
@@ -397,7 +397,7 @@ class VCSPlatform extends BasePlatform {
bus.oldWrite = bus.write;
bus.write = function(a,v) {
this.oldWrite(a,v);
- if (a == 0x02) probe.logIllegal(a); // WSYNC
+ if (a == 0x02) probe.logWait(a); // WSYNC
else if (a < 0x80) probe.logIOWrite(a,v);
else if (a > 0x280 && a < 0x300) probe.logIOWrite(a,v);
else probe.logWrite(a,v);
diff --git a/test/cli/testplatforms.js b/test/cli/testplatforms.js
index 23108c61..e28129d9 100644
--- a/test/cli/testplatforms.js
+++ b/test/cli/testplatforms.js
@@ -367,16 +367,16 @@ describe('Platform Replay', () => {
});
});
it('Should run atari5200', async () => {
- await testPlatform('atari8-5200', 'acid5200.rom', 1100, (platform, frameno) => {
- if (frameno == 999) {
+ await testPlatform('atari8-5200', 'acid5200.rom', 1200, (platform, frameno) => {
+ if (frameno == 1199) {
let s = '';
for (let i=0; i<40; i++) {
- let c = platform.readAddress(0x722+i) & 0x7f;
+ let c = platform.readAddress(0x722+i-40) & 0x7f;
if (c < 0x40) c += 0x20;
s += String.fromCharCode(c);
}
s = s.trim();
- assert.equal(s, "Passed: 12 Failed: 34 Skipped: 1");
+ assert.equal(s, "Passed: 13 Failed: 33 Skipped: 1");
}
});
});